Merge lane/abrechnung in feature/craftvia-mvp

Konflikte gelöst (additiv): Benachrichtigungstexte (Planung + Meilensteine), Event-Typen,
Navigation, Job-Queues/Prozessoren (geocode-site, planning-watch, billing-pdf), OpenAPI-Tags,
Smoke-Prüfungen (zweiter Mandant: Planung + Abrechnung).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 10:37:52 +02:00
co-authored by Claude Opus 5
79 changed files with 4481 additions and 40 deletions
+250
View File
@@ -0,0 +1,250 @@
{
"crumb": "Billing",
"title": "Billing overview",
"subtitle": "Completed orders, confirmed milestones and approved daily reports for your accounting. No prices, no invoices.",
"hm": "{value} h",
"tabs": { "open": "Open", "billed": "Billed", "voided": "Voided" },
"filter": {
"title": "Filter",
"q": "Search",
"qPlaceholder": "Order number or customer",
"from": "Period from",
"to": "Period to",
"customer": "Customer",
"team": "Team",
"kind": "Type",
"any": "All",
"apply": "Apply",
"reset": "Reset"
},
"list": {
"noPermission": "The billing overview is not enabled for your role.",
"empty": {
"open": "Nothing open – all entries are billed.",
"billed": "No entries billed yet.",
"voided": "No voided entries."
},
"selectHint": "Select entries to print them together.",
"print": "Print billing sheets",
"select": "Selection",
"selectRow": "Select {number}",
"order": "Order",
"customerSite": "Customer / site",
"section": "Type / section",
"period": "Period",
"work": "Working time",
"travel": "Travel time",
"trips": "Trips",
"material": "Material",
"readySince": "Ready since",
"billedAt": "Billed on",
"voidedAt": "Voided on",
"pending": "{value} h pending times",
"invoice": "Invoice {number}",
"pagination": "Pages",
"prev": "Previous",
"next": "Next",
"page": "Page {page} of {pages}"
},
"kind": { "order_completion": "Order completion", "milestone": "Milestone", "daily_report": "Daily report" },
"status": { "open": "Open", "billed": "Billed", "voided": "Voided" },
"milestoneStatus": { "open": "Open", "reached": "Reported as reached", "confirmed": "Confirmed", "billed": "Billed" },
"detail": {
"back": "Back to billing overview",
"title": "Billing sheet {number}",
"markBilled": "Mark as billed",
"pdf": "PDF",
"print": "Print view",
"changeInvoice": "Change invoice number",
"void": "Void",
"openOrder": "Open order",
"photos": "Photos",
"report": "Report {number} · v{version}",
"done": {
"billed": "Marked as billed. The statement is frozen, the PDF is being created.",
"voided": "Voided. The positions are free again – this is the new open entry.",
"invoice": "Invoice number saved."
},
"pdfPending": "The PDF billing sheet is being created.",
"pdfRequest": "Request PDF again",
"pdfRequested": "PDF creation requested.",
"voidedInfo": "Voided on {at} by {by}"
},
"bill": {
"title": "Mark as billed",
"sub": "Your accounting issues the invoice outside of Craftvia.",
"submit": "Billed",
"pending": "Saving …",
"invoiceNumber": "Invoice number (optional)",
"invoiceHint": "Number from your accounting, if already available.",
"pendingWarning": "{value} h pending times ({count}) are not approved yet and not included.",
"confirmPending": "Bill anyway – pending times stay excluded",
"freezeHint": "The statement is frozen; included times and materials cannot be billed a second time."
},
"invoice": { "title": "Change invoice number", "submit": "Save" },
"void": {
"title": "Void billing",
"sub": "Times and material become free again, a new open entry is created.",
"submit": "Void",
"pending": "Voiding …",
"reason": "Reason"
},
"print": {
"back": "Back to overview",
"count": "{count, plural, =1 {1 billing sheet} other {# billing sheets}}",
"print": "Print",
"empty": "No entries selected."
},
"tab": {
"milestones": "Milestones",
"milestonesHint": "Confirm reached milestones – they then appear in the billing overview.",
"noMilestonesHint": "Without milestones, every approved daily report of a multi-day order becomes a billable section.",
"noMilestones": "No milestones defined.",
"reachedBy": "Reported as reached by {name} on {at}",
"confirmedBy": "Confirmed by {name} on {at}",
"rejected": "Last rejected: {reason}",
"up": "Move up",
"down": "Move down",
"delete": "Delete",
"confirm": "Confirm",
"reject": "Reject",
"rejectReason": "Reason for rejection",
"add": "Add milestone",
"newTitle": "Title",
"newTitlePlaceholder": "e.g. rough installation completed",
"newDescription": "Description",
"records": "Billing entries",
"noRecords": "No billing entries yet.",
"open": "Open"
},
"mobile": {
"title": "Milestones",
"rejected": "Rejected by the office: {reason}",
"waiting": "Reported – waiting for confirmation by the office.",
"queued": "Saved – will be sent as soon as there is a connection.",
"sent": "Reported as reached.",
"note": "Note",
"notePlaceholder": "Note (optional)",
"reachAria": "Report {title} as reached",
"confirmReach": "Report now",
"reach": "Report as reached",
"cancel": "Cancel"
},
"sheet": {
"title": "Billing sheet",
"dailyReportOf": "Daily report of {date}",
"period": "Period",
"status": "Status",
"invoiceNumber": "Invoice number",
"noAccounting": "Statement for your accounting – not an invoice, no prices."
},
"section": {
"order": "Order data",
"time": "Times",
"trips": "Trips",
"material": "Material",
"texts": "Additional work, deviations, open items",
"reports": "Reports and signature"
},
"field": {
"customer": "Customer",
"customerNumber": "Customer number",
"billingAddress": "Billing address",
"site": "Site",
"orderNumber": "Order number",
"externalOrderNumber": "External order number",
"offerNumber": "Offer number",
"title": "Order",
"orderType": "Order type",
"billingType": "Billing type",
"team": "Team",
"section": "Section",
"workDates": "Work days",
"billedAt": "Billed",
"billingNotes": "Customer billing notes"
},
"billingType": { "fixed": "Fixed price", "time_material": "Time and material", "maintenance_contract": "Maintenance contract", "warranty": "Warranty" },
"time": {
"hm": "{value} h",
"empty": "No approved times in this section.",
"person": "Person",
"work": "Work",
"travel": "Travel time",
"materialProcurement": "Material procurement",
"total": "Total",
"breaks": "Breaks (info)",
"manual": "of which recorded manually (approved): {value} h",
"sum": "Total",
"breaksInfo": "Travel time = outbound + return travel. Breaks are listed for information only and are not part of the totals.",
"pendingHint": "{value} h pending ({count} entries), not approved yet – not included.",
"runningHint": "A time entry is still running and is not included."
},
"trips": {
"count": "{count, plural, =0 {No trip} =1 {1 trip} other {# trips}}",
"rule": "A crew travelling together counts as one trip."
},
"material": {
"name": "Description",
"articleNumber": "Item no.",
"quantity": "Quantity",
"planned": "Planned",
"status": "Status",
"reason": "Reason for deviation",
"undocumented": "Not recorded",
"empty": "No material in this section.",
"used": "Material used",
"additional": "Additional material",
"notUsed": "Planned items not used",
"notUsedInfo": "For information only."
},
"materialStatus": { "fully_used": "Fully used", "partially_used": "Partially used", "not_used": "Not used", "additional": "Additional" },
"texts": {
"fromReport": "({number})",
"empty": "No details in the reports.",
"additionalWork": "Additional work",
"deviations": "Deviations",
"openItems": "Open items"
},
"reports": {
"empty": "No approved report in this section.",
"number": "Report",
"type": "Type",
"date": "Date",
"approvedAt": "Approved",
"signature": "Signature",
"noSignature": "No signature"
},
"reportType": { "daily": "Daily report", "completion": "Completion report" },
"outcome": { "signed": "Signed", "customer_absent": "Customer absent", "refused": "Signature refused", "later": "Signature to follow", "not_required": "Not required" },
"pdf": {
"documentTitle": "Billing sheet {number} – {kind}",
"page": "Page {page} of {pages}",
"recordId": "Entry ID",
"created": "Created"
},
"errors": {
"not_found": "Not found or no permission.",
"forbidden": "You are not allowed to do this.",
"invalid": "Please check your input.",
"conflict": "The entry has changed in the meantime. Reload the page.",
"blocked": "Not possible yet.",
"internal": "Action not possible.",
"validation_failed": "Please check the required fields.",
"billing_record_not_found": "Billing entry not found.",
"billing_record_not_open": "The entry is no longer open.",
"billing_record_not_billed": "The entry is not billed.",
"pending_time_entries": "There are pending times. Please confirm that they are excluded.",
"positions_already_billed": "Some positions have been billed elsewhere in the meantime. Reload the page.",
"milestone_not_found": "Milestone not found.",
"milestone_not_open": "Only open milestones can be changed.",
"milestone_not_confirmable": "This milestone cannot be confirmed.",
"milestone_not_reached": "Only reported milestones can be rejected.",
"not_editable": "The order can no longer be changed in this status.",
"work_order_not_found": "Order not found.",
"work_order_status": "This is no longer possible for this order.",
"transition_blocked": "The order status cannot be reset – details are missing.",
"transition_forbidden": "You are not allowed to perform this status change.",
"reason_required": "Please enter a reason.",
"version_conflict": "The order has changed in the meantime. Reload the page."
}
}
+4 -2
View File
@@ -17,7 +17,8 @@
"emergency_new": "New emergencies",
"missing_signatures": "Missing signatures",
"sync_conflicts": "Sync conflicts",
"time_approvals": "Time approvals"
"time_approvals": "Time approvals",
"billing_ready": "Ready for billing"
},
"hints": {
"open": "Not yet billed or cancelled",
@@ -31,7 +32,8 @@
"emergency_new": "New or in review",
"missing_signatures": "Signature pending",
"sync_conflicts": "Review offline changes",
"time_approvals": "Review added time and corrections"
"time_approvals": "Review added time and corrections",
"billing_ready": "Open entries of the billing overview"
},
"open": "Show"
}
+2 -1
View File
@@ -14,5 +14,6 @@
"crumb": "Module",
"status": "Module under construction",
"hint": "This area is currently being built. Navigation, module activation and permissions are already in place."
}
},
"billing": "Billing overview"
}
+2 -1
View File
@@ -20,5 +20,6 @@
"admin": "Admin console",
"openMenu": "Open menu",
"closeMenu": "Close menu",
"timeApprovals": "Time approvals"
"timeApprovals": "Time approvals",
"billing": "Billing"
}
+16 -1
View File
@@ -51,7 +51,10 @@
"time_rejected": "Time rejected",
"planning_capacity_freed": "Finished early",
"planning_overrun": "Planned duration exceeded",
"planning_followup_at_risk": "Follow-up order at risk"
"planning_followup_at_risk": "Follow-up order at risk",
"milestone_reached": "Milestone reached",
"milestone_confirmed": "Milestone confirmed",
"milestone_rejected": "Milestone rejected"
},
"events": {
"work_order_assigned": {
@@ -145,6 +148,18 @@
"planning_followup_at_risk": {
"title": "Follow-up order at risk: {number}",
"message": "{title} – {customer} ({team}) is at risk due to the delay of {blocker}."
},
"milestone_reached": {
"title": "Milestone reached: {number}",
"message": "{actor} reports a milestone of {number} as reached. Please confirm."
},
"milestone_confirmed": {
"title": "Milestone confirmed: {number}",
"message": "{actor} confirmed your reported milestone of {number}."
},
"milestone_rejected": {
"title": "Milestone rejected: {number}",
"message": "{actor} rejected your reported milestone of {number}: {reason}"
}
},
"fallback": {
+2 -1
View File
@@ -156,7 +156,8 @@
"notes": "Notes",
"reports": "Reports",
"documents": "Documents",
"history": "History"
"history": "History",
"billing": "Milestones & billing"
}
},
"overview": {