feat(accounting): re-categorize incoming invoices, note field, pending re-bill pool
Address three incoming-invoice issues: 1. Re-categorization: a categorized invoice can now be changed again (e.g. passthrough → company expense). New "Re-categorize" button pre-fills the triage modal from the existing disposition/customer/markup/note. categorizeInbound is re-runnable — it unwinds any prior re-bill line (removes the invoice line + recomputes totals) before applying the new disposition, and refuses (INVOICE_LOCKED) when the re-bill is on an already-issued invoice. 2. Note field: new `note` column (migration 132 — 126 is already on beta) captured in triage and shown in the read-only view. 3. Re-bill like hours: rebill/passthrough now persist customer_account_id. Per-event customers accumulate as PENDING items, surfaced in a new "Pending re-bills" card and bundled into one invoice via "Bill these" (mirrors unbilled-hours billing). Monthly/manual customers keep auto-consolidating onto their running draft. Passthrough (durchlaufend) can now also attach to a customer with optional markup. Adds backend unit tests for buildInboundLineItem + isInvoiceMutable and en/de translations (other locales fall back to English defaults).
This commit is contained in:
@@ -3520,6 +3520,7 @@
|
||||
"saveCategorize": "Speichern",
|
||||
"saveCategorizePay": "Speichern & als bezahlt markieren",
|
||||
"categorize": "Kategorisieren",
|
||||
"recategorize": "Neu kategorisieren",
|
||||
"view": "Ansehen",
|
||||
"empty": "Noch keine Dokumente — oben eines erfassen.",
|
||||
"untitled": "Unbenanntes Dokument",
|
||||
@@ -3551,7 +3552,10 @@
|
||||
"eventId": "Event-ID (optional)",
|
||||
"markup": "Zuschlag",
|
||||
"reference": "Zahlungsreferenz",
|
||||
"referenceHint": "QR-/ESR-Referenz oder Mitteilung"
|
||||
"referenceHint": "QR-/ESR-Referenz oder Mitteilung",
|
||||
"note": "Notiz",
|
||||
"noteHint": "Interne Notiz zu dieser Rechnung (optional)",
|
||||
"passthroughCustomerHint": "Optional — einen Kunden zuordnen, um diese durchlaufende Position weiterzuverrechnen; leer lassen, um sie nur auf das Event zu buchen."
|
||||
}
|
||||
},
|
||||
"expenseStatus": {
|
||||
@@ -3584,7 +3588,15 @@
|
||||
"paid": "Bezahlt",
|
||||
"paidToast": "Als bezahlt markiert.",
|
||||
"categorizedToast": "Kategorisiert.",
|
||||
"categorizedPaidToast": "Kategorisiert und als bezahlt markiert."
|
||||
"categorizedPaidToast": "Kategorisiert und als bezahlt markiert.",
|
||||
"pendingRebill": "Weiterverrechnung offen",
|
||||
"pendingTitle": "Offene Weiterverrechnungen",
|
||||
"pendingBody": "Kategorisierte Rechnungen, die auf die Weiterverrechnung warten. Posten eines Kunden zu einer Rechnung bündeln.",
|
||||
"pendingCount": "{{count}} Posten",
|
||||
"pendingCount_other": "{{count}} Posten",
|
||||
"billPending": "Verrechnen",
|
||||
"bundledToast": "{{count}} Weiterverrechnung zu einer Rechnung gebündelt.",
|
||||
"bundledToast_other": "{{count}} Weiterverrechnungen zu einer Rechnung gebündelt."
|
||||
},
|
||||
"expense": {
|
||||
"kind": "Art",
|
||||
|
||||
@@ -3520,6 +3520,7 @@
|
||||
"saveCategorize": "Save",
|
||||
"saveCategorizePay": "Save & mark paid",
|
||||
"categorize": "Categorize",
|
||||
"recategorize": "Re-categorize",
|
||||
"view": "View",
|
||||
"empty": "No documents yet — capture one above.",
|
||||
"untitled": "Untitled document",
|
||||
@@ -3551,7 +3552,10 @@
|
||||
"eventId": "Event ID (optional)",
|
||||
"markup": "Markup",
|
||||
"reference": "Payment reference",
|
||||
"referenceHint": "QR / ESR reference or message"
|
||||
"referenceHint": "QR / ESR reference or message",
|
||||
"note": "Note",
|
||||
"noteHint": "Internal note for this invoice (optional)",
|
||||
"passthroughCustomerHint": "Optional — attach a client to re-bill this passthrough; leave empty to only book it to the event."
|
||||
}
|
||||
},
|
||||
"expenseStatus": {
|
||||
@@ -3584,7 +3588,15 @@
|
||||
"paid": "Paid",
|
||||
"paidToast": "Marked as paid.",
|
||||
"categorizedToast": "Categorized.",
|
||||
"categorizedPaidToast": "Categorized and marked paid."
|
||||
"categorizedPaidToast": "Categorized and marked paid.",
|
||||
"pendingRebill": "Pending re-bill",
|
||||
"pendingTitle": "Pending re-bills",
|
||||
"pendingBody": "Categorized invoices waiting to be re-billed. Bundle a client’s items into one invoice.",
|
||||
"pendingCount": "{{count}} item",
|
||||
"pendingCount_other": "{{count}} items",
|
||||
"billPending": "Bill these",
|
||||
"bundledToast": "Bundled {{count}} re-bill into one invoice.",
|
||||
"bundledToast_other": "Bundled {{count}} re-bills into one invoice."
|
||||
},
|
||||
"expense": {
|
||||
"kind": "Type",
|
||||
|
||||
Reference in New Issue
Block a user