feat(accounting): incoming-invoices inbox with camera capture + triage/re-bill
Adds the Accounting → Incoming invoices frontend on top of the existing /api/admin/expenses backend: - accounting.service.ts: typed client (inbound upload/list/get/update/ categorize, expense list, re-bill, supplier-payment, categories). - AccountingInboxPage: capture a supplier invoice via the device CAMERA (<input accept="image/*" capture="environment">) or a PDF/image upload; inbox list with status badges + parsed summary; a triage modal to confirm fields and pick a disposition (re-bill / pass-through / company expense / duplicate / declined). Re-bill uses the customer picker and mints an editable scheduled invoice (chains categorize -> rebill). - AccountingLayout: "Incoming invoices" sub-nav item + AccountingIndex that redirects /admin/accounting to the first enabled sub-feature. - App.tsx: /admin/accounting/inbox route (gated by incomingInvoices). - i18n: accounting.inbox/disposition/markup + subnav.incomingInvoices + common.saving (EN + DE, DE authored natively). Camera capture needs no native app — the mobile web input drives the device camera straight into the upload endpoint. OCR/QR auto-extraction is still a backend follow-up (extractionService is a no-op), so fields are confirmed manually in the triage modal for now. Verified: npm run build green; en/de JSON valid.
This commit is contained in:
@@ -98,6 +98,7 @@
|
||||
"error": "Fehler",
|
||||
"configureInSettings": "Standards in den Einstellungen anpassen ↗",
|
||||
"save": "Speichern",
|
||||
"saving": "Speichern…",
|
||||
"cancel": "Abbrechen",
|
||||
"delete": "Löschen",
|
||||
"edit": "Bearbeiten",
|
||||
@@ -3398,7 +3399,54 @@
|
||||
"body": "Aktiviere die Steuerliste (oder eine andere Buchhaltungs-Unterfunktion) unter Einstellungen → Funktionen, um loszulegen."
|
||||
},
|
||||
"subnav": {
|
||||
"incomingInvoices": "Eingangsrechnungen",
|
||||
"taxReport": "Steuer"
|
||||
},
|
||||
"disposition": {
|
||||
"rebill": "An Kunde weiterverrechnen",
|
||||
"durchlaufend": "Durchlaufender Posten",
|
||||
"eigener_aufwand": "Eigener Aufwand",
|
||||
"duplikat": "Duplikat",
|
||||
"abgelehnt": "Abgelehnt"
|
||||
},
|
||||
"markup": {
|
||||
"none": "Keiner / aus Vertrag",
|
||||
"percent": "Prozent",
|
||||
"flat": "Pauschal"
|
||||
},
|
||||
"inbox": {
|
||||
"captureTitle": "Lieferantenrechnung erfassen",
|
||||
"captureBody": "Fotografiere eine Papierrechnung mit der Gerätekamera oder lade ein PDF / Bild hoch.",
|
||||
"scanCamera": "Mit Kamera scannen",
|
||||
"uploadFile": "Datei hochladen",
|
||||
"capturedToast": "Dokument erfasst.",
|
||||
"categorizedToast": "Dokument kategorisiert.",
|
||||
"triageTitle": "Dokument kategorisieren",
|
||||
"saveCategorize": "Speichern",
|
||||
"categorize": "Kategorisieren",
|
||||
"empty": "Noch keine Dokumente — oben eines erfassen.",
|
||||
"untitled": "Unbenanntes Dokument",
|
||||
"noAmount": "Betrag nicht erfasst",
|
||||
"rebillHint": "Erstellt eine bearbeitbare geplante Rechnung beim Kunden. MwSt-/Steuerbehandlung ist v1 — mit Treuhänder prüfen.",
|
||||
"status": {
|
||||
"unsorted": "Neu",
|
||||
"categorized": "Kategorisiert",
|
||||
"declined": "Abgelehnt",
|
||||
"duplicate": "Duplikat"
|
||||
},
|
||||
"field": {
|
||||
"supplier": "Lieferant",
|
||||
"total": "Total",
|
||||
"currency": "Währung",
|
||||
"invoiceDate": "Rechnungsdatum",
|
||||
"disposition": "Zuordnung",
|
||||
"category": "Kategorie",
|
||||
"categoryNone": "— keine —",
|
||||
"declineReason": "Grund",
|
||||
"customer": "Kunde",
|
||||
"eventId": "Event-ID (optional)",
|
||||
"markup": "Zuschlag"
|
||||
}
|
||||
}
|
||||
},
|
||||
"calendar": {
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
"error": "Error",
|
||||
"configureInSettings": "Configure defaults in Settings ↗",
|
||||
"save": "Save",
|
||||
"saving": "Saving…",
|
||||
"cancel": "Cancel",
|
||||
"delete": "Delete",
|
||||
"edit": "Edit",
|
||||
@@ -3398,7 +3399,54 @@
|
||||
"body": "Enable the Tax report (or another accounting sub-feature) under Settings → Features to get started."
|
||||
},
|
||||
"subnav": {
|
||||
"incomingInvoices": "Incoming invoices",
|
||||
"taxReport": "Tax"
|
||||
},
|
||||
"disposition": {
|
||||
"rebill": "Re-bill to client",
|
||||
"durchlaufend": "Pass-through",
|
||||
"eigener_aufwand": "Company expense",
|
||||
"duplikat": "Duplicate",
|
||||
"abgelehnt": "Declined"
|
||||
},
|
||||
"markup": {
|
||||
"none": "None / from contract",
|
||||
"percent": "Percent",
|
||||
"flat": "Flat"
|
||||
},
|
||||
"inbox": {
|
||||
"captureTitle": "Capture a supplier invoice",
|
||||
"captureBody": "Photograph a paper invoice with your device camera, or upload a PDF / image.",
|
||||
"scanCamera": "Scan with camera",
|
||||
"uploadFile": "Upload file",
|
||||
"capturedToast": "Document captured.",
|
||||
"categorizedToast": "Document categorized.",
|
||||
"triageTitle": "Categorize document",
|
||||
"saveCategorize": "Save",
|
||||
"categorize": "Categorize",
|
||||
"empty": "No documents yet — capture one above.",
|
||||
"untitled": "Untitled document",
|
||||
"noAmount": "amount not entered",
|
||||
"rebillHint": "Creates an editable scheduled invoice on the client. VAT/tax handling is v1 — verify with your Treuhänder.",
|
||||
"status": {
|
||||
"unsorted": "New",
|
||||
"categorized": "Categorized",
|
||||
"declined": "Declined",
|
||||
"duplicate": "Duplicate"
|
||||
},
|
||||
"field": {
|
||||
"supplier": "Supplier",
|
||||
"total": "Total",
|
||||
"currency": "Currency",
|
||||
"invoiceDate": "Invoice date",
|
||||
"disposition": "Disposition",
|
||||
"category": "Category",
|
||||
"categoryNone": "— none —",
|
||||
"declineReason": "Reason",
|
||||
"customer": "Client",
|
||||
"eventId": "Event ID (optional)",
|
||||
"markup": "Markup"
|
||||
}
|
||||
}
|
||||
},
|
||||
"calendar": {
|
||||
|
||||
Reference in New Issue
Block a user