feat(sprint8): Phase 2 — Treasury frontend + PDF receipts

Backend:
- ReceiptPdfService: Generates Quittung PDF per payment (OpenPDF, A4)
- FinancialReportService: Annual financial report PDF (Jahresabschluss)
- FinanceController: Added receipt download, annual report, CSV export endpoints
- Portal receipt download with member ownership verification

Frontend:
- src/services/finance.ts: Complete React Query service (types, hooks, mutations)
- /finance: Dashboard with KPI cards, recent transactions, outstanding members
- /finance/payments: Payment list with filtering, void, receipt download
- /finance/kassenbuch: Kassenbuch ledger with date range, CSV export
- /finance/fee-schedules: Fee schedule CRUD with interval management
- /finance/reports: Annual report PDF download
- /portal/finance: Member self-service balance + payment history + receipts

Navigation & i18n:
- Added Finanzen (Wallet icon) to admin sidebar
- Portal finance page for member payments
- Comprehensive de.json + en.json finance keys (~100 translations)
This commit is contained in:
Patrick Plate
2026-06-15 08:24:43 +02:00
parent 721503b231
commit 3211ade5be
13 changed files with 2419 additions and 1 deletions
+110
View File
@@ -839,5 +839,115 @@
"topicLocked": "Dieses Thema ist gesperrt. Neue Antworten sind nicht möglich.",
"reportReason": "Grund der Meldung:",
"backToTopics": "Zurück zur Übersicht"
},
"finance": {
"title": "Vereinsfinanzen",
"subtitle": "Übersicht über Einnahmen, Ausgaben und Mitgliedsbeiträge",
"totalBalance": "Gesamtsaldo",
"incomeThisMonth": "Einnahmen (Monat)",
"expensesThisMonth": "Ausgaben (Monat)",
"outstandingMembers": "Offene Beiträge",
"outstandingTitle": "Säumige Mitglieder",
"monthsOverdue": "Monate überfällig",
"noOutstanding": "Keine offenen Beiträge",
"recentTransactions": "Letzte Buchungen",
"noTransactions": "Keine Buchungen vorhanden",
"recordPayment": "Zahlung erfassen",
"recordExpense": "Ausgabe erfassen",
"payments": "Zahlungen",
"kassenbuch": "Kassenbuch",
"feeSchedules": "Beitragsordnung",
"reports": "Berichte",
"exportCsv": "CSV exportieren",
"from": "Von",
"to": "Bis",
"date": "Datum",
"type": "Typ",
"description": "Beschreibung",
"income": "Einnahme",
"expense": "Ausgabe",
"balance": "Saldo",
"incomeLabel": "Einnahme",
"expenseLabel": "Ausgabe",
"loading": "Laden...",
"previous": "Zurück",
"next": "Weiter",
"member": "Mitglied",
"amount": "Betrag",
"period": "Zeitraum",
"paymentMethod": "Zahlungsart",
"actions": "Aktionen",
"filterByStatus": "Nach Status filtern",
"allStatuses": "Alle",
"noPayments": "Keine Zahlungen vorhanden",
"voidReason": "Grund für die Stornierung:",
"memberIdPlaceholder": "Mitglieds-ID eingeben",
"periodFrom": "Zeitraum von",
"periodTo": "Zeitraum bis",
"reference": "Referenz",
"referencePlaceholder": "z.B. Überweisungsreferenz",
"expenseReferencePlaceholder": "z.B. Rechnungsnummer",
"saving": "Wird gespeichert...",
"category": "Kategorie",
"descriptionPlaceholder": "z.B. Stromrechnung Juni",
"bankTransfer": "Überweisung",
"cash": "Bar",
"sepa": "SEPA-Lastschrift",
"card": "Kartenzahlung",
"createFeeSchedule": "Beitragssatz erstellen",
"scheduleName": "Bezeichnung",
"scheduleNamePlaceholder": "z.B. Monatsbeitrag Standard",
"intervalLabel": "Intervall",
"scheduleDescPlaceholder": "Optionale Beschreibung",
"default": "Standard",
"deactivate": "Deaktivieren",
"noFeeSchedules": "Keine Beitragssätze vorhanden",
"annualReport": "Jahresabschluss",
"annualReportDescription": "Vollständiger Finanzbericht mit Einnahmen, Ausgaben und Mitgliederbeiträgen.",
"auditorReport": "Kassenprüfbericht",
"auditorReportDescription": "Bericht für den Kassenprüfer mit allen Transaktionsdetails.",
"downloadPdf": "PDF herunterladen",
"comingSoon": "Demnächst verfügbar",
"status": {
"label": "Status",
"paid": "Bezahlt",
"pending": "Ausstehend",
"overdue": "Überfällig",
"voided": "Storniert"
},
"method": {
"BANK_TRANSFER": "Überweisung",
"CASH": "Bar",
"SEPA": "SEPA-Lastschrift",
"CARD": "Kartenzahlung"
},
"interval": {
"MONTHLY": "Monatlich",
"QUARTERLY": "Vierteljährlich",
"YEARLY": "Jährlich",
"ONE_TIME": "Einmalig"
},
"categories": {
"rent": "Miete",
"utilities": "Nebenkosten",
"equipment": "Ausstattung",
"seeds": "Saatgut",
"supplies": "Verbrauchsmaterial",
"insurance": "Versicherung",
"legal": "Rechtsberatung",
"other": "Sonstiges"
},
"portal": {
"title": "Meine Zahlungen",
"currentBalance": "Aktueller Saldo",
"allPaid": "Alle Beiträge bezahlt",
"paymentDue": "Zahlung fällig",
"noFeeAssigned": "Kein Beitragssatz zugewiesen",
"feeSchedule": "Beitragssatz",
"noFee": "Keiner",
"lastPayment": "Letzte Zahlung",
"paymentHistory": "Zahlungshistorie",
"noPayments": "Noch keine Zahlungen vorhanden"
}
}
}