75 lines
4.3 KiB
Markdown
75 lines
4.3 KiB
Markdown
# CLAUDE.md
|
||
|
||
Laravel 12 + Inertia/Vue, mandantenfähig (custom `tenant`-Scoping über `app('tenant')`, gesetzt in
|
||
`app/Middleware/IdentifyTenant.php`). PHP 8.5 — Tests/Artisan laufen im Container:
|
||
`docker exec mareike-mareike-app-1 php artisan test`.
|
||
|
||
## Projektkonventionen (verbindlich)
|
||
|
||
Die verbindlichen Konventionen (Actions/Request-Command-Response, Controller, Repositories, Models/Resources, Tenant,
|
||
Routing, Mails) stehen in `.ai/conventions.md` und werden hier eingebunden — **immer beachten**:
|
||
|
||
@.ai/conventions.md
|
||
|
||
## Bereichs-Dokumentation
|
||
|
||
- [Zahlungsmodule](app/EventPaymentModules/CLAUDE.md) — interface-gesteuerte Zahlungsarten (Optionen, Config,
|
||
Anmelde-Zusammenfassung, GiroCode/Fähigkeits-Interfaces, neues Modul hinzufügen).
|
||
|
||
## Umsatzsteuer / Steuerinformationen
|
||
|
||
Rechtlich korrekter Begriff ist **Umsatzsteuer (USt)**, nicht MwSt. Ziel: tagesbasierte Anmelde-Rechnungen („Teilnahme
|
||
Veranstaltung X in Gruppe Y" × Anwesenheitstage × Beitrag/Tag). Grundlage ist gebaut, die Rechnungs-PDF/-berechnung
|
||
folgt noch.
|
||
|
||
### Tenant-Einstellungen (Tab „Steuerinformationen")
|
||
|
||
Felder auf `tenants` (Self-Service `TenantData.vue` + verwaltet `TenantEdit.vue`, Partial `TenantTaxInfo.vue`,
|
||
Controller `TenantTax*` / `ManagedTenantTax*`, Action `UpdateTenantTax`):
|
||
|
||
- `tax_liable` (bool) — ob USt-Pflicht besteht.
|
||
- `vat_rate` (int, %) — USt-Satz, nur relevant wenn `tax_liable` (0–100, geclamped).
|
||
- `vat_pricing_mode` (Enum `App\Enumerations\VatPricingMode`, natives PHP-Enum: `inclusive` | `add_on`).
|
||
- `tax_exemption_reason` (FK → `tax_exemption_reasons.slug`, nullable) — Grund wenn **nicht** steuerpflichtig.
|
||
DB-Default neuer Tenants: `ustg_4_25a` (Jugendhilfe).
|
||
- `tax_exemption_note` (text, nullable) — Freitext, nur bei Grund `custom` (`requires_note`).
|
||
|
||
### Preismodus — **das Kernverhalten**
|
||
|
||
Es wird **immer der finale Brutto-Beitrag** pro Anmeldung gespeichert (`EventParticipant.amount`, keine USt-Spalten am
|
||
Teilnehmer). Der Modus wirkt **nur bei der Preisermittlung im Anmeldeprozess**:
|
||
|
||
- **`inclusive`** (Brutto / „zusammenfassen", Supermarkt-Prinzip, Default): der konfigurierte Beitrag **ist** der
|
||
Endpreis, USt ist bereits enthalten → Preis bleibt gleich; die USt wird erst **auf der Rechnung herausgerechnet**:
|
||
`USt = brutto × Satz / (100 + Satz)`, `netto = brutto − USt`.
|
||
- **`add_on`** (Netto / „aufaddieren"): der konfigurierte Beitrag ist netto → Endpreis = `Beitrag × (1 + Satz/100)`. Die
|
||
USt wird bei der Anmeldung **aufgeschlagen** → Teilnehmer zahlt mehr.
|
||
|
||
Umsetzung in `App\Resources\EventResource::calculateAmount()`: nach allen Multiplikatoren (Early-Bird, `pay_per_day`,
|
||
Geschwister) gilt
|
||
`if ($event->tax_liable && $event->vat_pricing_mode === VatPricingMode::AddOn->value) $fee->multiply(1 + $event->vat_rate/100);`
|
||
danach `round(…, 2)`. Bei `inclusive`/nicht steuerpflichtig bleibt der Beitrag unverändert.
|
||
|
||
### Event-Snapshot (unveränderlich)
|
||
|
||
Bei Event-Anlage (`CreateEventCommand::execute()`) werden `tax_liable`, `vat_rate`, `vat_pricing_mode`,
|
||
`tax_exemption_reason`, `tax_exemption_note` aus dem Tenant **auf das Event kopiert und dort eingefroren** (Spalten auf
|
||
`events`). Preisermittlung und spätere Rechnungen lesen vom Event, nicht vom Tenant → spätere Tenant-Änderungen berühren
|
||
bestehende Events/Rechnungen nicht.
|
||
|
||
### Befreiungsgründe (DB-gestützt)
|
||
|
||
Tabelle `tax_exemption_reasons`, Model `App\Enumerations\TaxExemptionReason` (Eloquent, `slug` PK; `name`,
|
||
`invoice_text`, `requires_note`, `sort_order`). `options()` liefert `{value,label,text}` sortiert nach `sort_order`. FK
|
||
von `tenants` **und** `events`. Seed in Migration `170010`, verfeinert in `170020`. Gründe (in Reihenfolge):
|
||
`ustg_19` (§ 19 Kleinunternehmer), `ustg_4_24` (§ 4 Nr. 24 Jugendherbergen),
|
||
`ustg_4_25a` (§ 4 Nr. 25 Buchst. a — Jugendhilfe-Veranstaltungen, Default), `ustg_4_22a` (§ 4 Nr. 22 Buchst. a —
|
||
Vorträge/Kurse), `custom` (Freitext). Jeder Grund kapselt den Rechnungs-Pflichthinweis nach **§ 14 Abs. 4 Nr. 8 UStG**
|
||
(`invoice_text`; bei `custom` der Tenant-Freitext via `invoiceText(?note)`). Gemeinnützigkeit allein befreit **nicht** —
|
||
es braucht immer einen konkreten Rechtsgrund.
|
||
|
||
### Noch offen (nächster Schritt)
|
||
|
||
Die eigentliche **Rechnung**: tagesbasierte Positionen, USt aus dem gespeicherten Brutto herausrechnen (Satz vom
|
||
Event-Snapshot); bei Befreiung kein USt-Ausweis, stattdessen der Pflichthinweis des Grundes.
|