L1 Stammdaten: Backoffice-Seiten Kunden, Objekte, Teams und Dokumente

Listen mit Suche/Filter/Paginierung, Popups für Anlage und Bearbeitung,
Kundendetail mit Tabs, Dublettenhinweis und Zusammenführen, Objektdetail mit
Kartenlink, Dokumenten-Tab und Historie, Teamverwaltung mit Mitgliedern,
Dokumentenübersicht. Texte in messages de/en, Audit-Label Ansprechpartner.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 12:26:27 +02:00
co-authored by Claude Opus 5
parent 49c5ad0e33
commit d18f4fe431
28 changed files with 3660 additions and 12 deletions
+180
View File
@@ -0,0 +1,180 @@
{
"title": "Kunden",
"crumb": "Stammdaten",
"sub": "Kunden, Ansprechpartner und Objekte an einem Ort.",
"new": "Neuer Kunde",
"searchLabel": "Suche",
"searchPlaceholder": "Name, Kundennummer, Ort oder E-Mail",
"filter": {
"status": "Status",
"all": "Alle (ohne zusammengeführte)",
"apply": "Filtern",
"reset": "Zurücksetzen"
},
"status": {
"active": "Aktiv",
"inactive": "Inaktiv",
"provisional": "Vorläufig",
"merged": "Zusammengeführt"
},
"provisionalHint": "Vorläufig – Prüfung durch Backoffice erforderlich",
"columns": {
"number": "Kundennr.",
"name": "Name",
"city": "Ort",
"contact": "Kontakt",
"sites": "Objekte",
"status": "Status"
},
"empty": "Keine Kunden gefunden.",
"pagination": {
"prev": "Zurück",
"next": "Weiter",
"summary": "{from}–{to} von {total}"
},
"fields": {
"customerNumber": "Kundennummer",
"customerNumberHint": "Leer lassen: nächste freie Nummer wird vergeben.",
"companyName": "Firmenname",
"salutation": "Anrede",
"firstName": "Vorname",
"lastName": "Nachname",
"street": "Straße",
"houseNumber": "Hausnr.",
"postalCode": "PLZ",
"city": "Ort",
"country": "Land",
"phone": "Telefon",
"mobile": "Mobil",
"email": "E-Mail",
"notes": "Allgemeine Hinweise",
"billingNotes": "Abrechnungshinweise",
"status": "Status",
"createdAt": "Angelegt",
"updatedAt": "Geändert"
},
"sections": {
"customer": "Kunde",
"address": "Adresse",
"contact": "Erreichbarkeit",
"notes": "Hinweise"
},
"form": {
"createTitle": "Kunde anlegen",
"createSub": "Firmen- oder Privatkunde. Firmenname oder Nachname ist Pflicht.",
"editTitle": "Kunde bearbeiten",
"create": "Kunde anlegen",
"save": "Speichern",
"saving": "Speichert…",
"cancel": "Abbrechen",
"close": "Schließen",
"saved": "Gespeichert.",
"required": "Pflichtfeld"
},
"duplicates": {
"title": "Mögliche Dublette",
"hint": "Diese Kunden sind ähnlich. Bestehenden Kunden verwenden oder trotzdem neu anlegen.",
"open": "Bestehenden Kunden öffnen",
"createAnyway": "Trotzdem neu anlegen",
"score": "Übereinstimmung {percent} %",
"reasons": {
"customer_number": "Kundennummer",
"company_name": "Name",
"address": "Adresse",
"email": "E-Mail",
"phone": "Telefon"
}
},
"tabs": {
"master": "Stammdaten",
"contacts": "Ansprechpartner",
"sites": "Objekte",
"orders": "Aufträge",
"documents": "Dokumente"
},
"detail": {
"edit": "Bearbeiten",
"confirm": "Kunden bestätigen",
"confirmHint": "Vorläufigen Kunden nach Prüfung als aktiv übernehmen.",
"merge": "Zusammenführen",
"delete": "Löschen",
"deleteTitle": "Kunden löschen",
"deleteHint": "Der Kunde wird ausgeblendet. Aufträge, Berichte und Nachweise bleiben erhalten. Nur ohne offene Aufträge möglich.",
"deleteConfirm": "Kunden löschen",
"mergedInto": "Dieser Kunde wurde zusammengeführt in:",
"mergedOk": "Kunden zusammengeführt. Kontakte, Objekte, Aufträge und Dokumente liegen jetzt hier.",
"back": "Zur Kundenliste",
"readOnly": "Nur Lesezugriff."
},
"contacts": {
"new": "Ansprechpartner hinzufügen",
"createTitle": "Ansprechpartner hinzufügen",
"editTitle": "Ansprechpartner bearbeiten",
"empty": "Noch keine Ansprechpartner.",
"delete": "Entfernen",
"deleteConfirm": "Ansprechpartner entfernen?",
"preferred": "bevorzugt",
"fields": {
"name": "Name",
"role": "Funktion",
"phone": "Telefon",
"mobile": "Mobil",
"email": "E-Mail",
"preferredChannel": "Bevorzugter Kontaktweg",
"notes": "Bemerkungen"
},
"channel": {
"phone": "Telefon",
"mobile": "Mobil",
"email": "E-Mail",
"none": "Keine Angabe"
}
},
"sites": {
"empty": "Noch keine Objekte.",
"new": "Objekt anlegen"
},
"orders": {
"empty": "Keine Aufträge sichtbar.",
"hint": "Lesesicht. Aufträge werden im Bereich Aufträge bearbeitet.",
"columns": {
"number": "Auftrag",
"title": "Bezeichnung",
"site": "Objekt",
"team": "Team",
"date": "Termin",
"status": "Status"
}
},
"merge": {
"title": "Kunden zusammenführen",
"sub": "Kontakte, Objekte, Aufträge und Dokumente werden auf den Zielkunden umgehängt. Dieser Kunde wird als zusammengeführt markiert.",
"source": "Wird aufgelöst",
"target": "Zielkunde",
"candidates": "Mögliche Dubletten",
"noCandidates": "Keine ähnlichen Kunden gefunden. Zielkunde über die Kundennummer wählen.",
"targetNumber": "Oder Kundennummer des Zielkunden",
"confirm": "Datensätze geprüft. Zusammenführen bestätigen – das wird nicht automatisch rückgängig gemacht.",
"submit": "Zusammenführen"
},
"errors": {
"invalid": "Bitte die markierten Felder prüfen.",
"not_found": "Datensatz nicht gefunden.",
"forbidden": "Dafür fehlt die Berechtigung.",
"conflict": "Das geht so nicht: Der Datensatz wurde geändert oder ist bereits vergeben.",
"blocked": "Aktion aktuell nicht möglich.",
"generic": "Das hat nicht geklappt. Bitte erneut versuchen.",
"required": "Pflichtfeld",
"invalidField": "Eingabe prüfen",
"name_required": "Firmenname oder Nachname angeben.",
"number_taken": "Kundennummer ist bereits vergeben.",
"number_allocation": "Keine freie Kundennummer gefunden.",
"open_work_orders": "Es gibt noch offene Aufträge.",
"not_provisional": "Der Kunde ist nicht vorläufig.",
"already_merged": "Einer der Kunden ist bereits zusammengeführt.",
"same_customer": "Quelle und Ziel sind derselbe Kunde.",
"target_required": "Zielkunden auswählen.",
"target_not_found": "Kundennummer nicht gefunden.",
"confirm_required": "Bitte die Zusammenführung bestätigen."
}
}
+120
View File
@@ -0,0 +1,120 @@
{
"title": "Dokumente",
"crumb": "Ablage",
"sub": "Alle Unterlagen zu Kunden, Objekten und Aufträgen – mit Version, Prüfsumme und Sichtbarkeit.",
"empty": "Keine Dokumente gefunden.",
"columns": {
"document": "Dokument",
"category": "Kategorie",
"link": "Zuordnung",
"visibility": "Sichtbarkeit",
"version": "Version",
"size": "Größe",
"uploaded": "Hochgeladen"
},
"filter": {
"q": "Dateiname oder Titel",
"category": "Kategorie",
"allCategories": "Alle Kategorien",
"customer": "Kunde",
"allCustomers": "Alle Kunden",
"site": "Objekt",
"allSites": "Alle Objekte",
"workOrder": "Auftragsnummer",
"latestOnly": "Nur aktuelle Versionen",
"apply": "Filtern",
"reset": "Zurücksetzen"
},
"pagination": {
"prev": "Zurück",
"next": "Weiter",
"summary": "{from}–{to} von {total}"
},
"category": {
"order_confirmation": "Auftragsbestätigung",
"technical_drawing": "Technische Zeichnung",
"floor_plan": "Grundriss",
"wiring_diagram": "Schaltplan",
"assembly_instructions": "Montageanleitung",
"safety_document": "Sicherheitsunterlage",
"product_document": "Produktunterlage",
"customer_note": "Kundenhinweis",
"work_record": "Arbeitsnachweis",
"daily_report": "Tagesbericht",
"completion_report": "Abschlussbericht",
"customer_approval": "Kundenfreigabe",
"photo": "Foto",
"voice_note": "Sprachnotiz",
"signature": "Unterschrift",
"other": "Sonstiges Dokument"
},
"visibility": {
"backoffice_only": "Nur Backoffice",
"team_lead": "Für Teamleiter",
"team": "Für Montageteam",
"customer_report": "Für Kundenbericht freigegeben"
},
"link": {
"customer": "Kunde",
"site": "Objekt",
"workOrder": "Auftrag",
"none": "Ohne Zuordnung"
},
"upload": {
"title": "Dokument hochladen",
"file": "Datei",
"fileHint": "PDF bis 25 MB, Bilder (JPEG, PNG, WebP, HEIC) bis 15 MB, Audio bis 20 MB.",
"titleField": "Titel (optional)",
"category": "Kategorie",
"visibility": "Sichtbarkeit",
"submit": "Hochladen",
"newVersion": "Neue Version",
"newVersionTitle": "Neue Version hochladen",
"newVersionOf": "Neue Version von „{name}“",
"ok": "Dokument gespeichert."
},
"versions": {
"label": "v{version}",
"older": "{count, plural, one {# ältere Version} other {# ältere Versionen}}",
"latest": "aktuell"
},
"actions": {
"download": "Herunterladen",
"edit": "Bearbeiten",
"delete": "Entfernen",
"deleteConfirm": "Diese Version entfernen?"
},
"edit": {
"title": "Dokument bearbeiten",
"titleField": "Titel",
"save": "Speichern",
"saving": "Speichert…",
"cancel": "Abbrechen"
},
"uploadErrors": {
"empty_file": "Bitte eine Datei auswählen.",
"too_large": "Die Datei ist zu groß.",
"unsupported_type": "Dateityp nicht erlaubt. Erlaubt sind PDF, JPEG, PNG, WebP, HEIC und Audio.",
"type_mismatch": "Dateiinhalt passt nicht zum Dateityp.",
"malware": "Die Datei wurde vom Virenscan abgelehnt.",
"scanner_unavailable": "Virenscan nicht erreichbar. Bitte später erneut versuchen.",
"visibility_not_allowed": "Diese Sichtbarkeit ist nicht erlaubt.",
"lineage_not_found": "Ursprungsdokument nicht gefunden.",
"invalid_category": "Bitte eine Kategorie wählen.",
"site_not_found": "Objekt nicht gefunden.",
"customer_not_found": "Kunde nicht gefunden.",
"forbidden": "Dafür fehlt die Berechtigung.",
"not_found": "Auftrag nicht gefunden.",
"invalid": "Upload ungültig.",
"generic": "Upload fehlgeschlagen. Bitte erneut versuchen."
},
"errors": {
"invalid": "Bitte die Eingaben prüfen.",
"not_found": "Dokument nicht gefunden.",
"forbidden": "Dafür fehlt die Berechtigung.",
"conflict": "Das geht so nicht.",
"blocked": "Aktion aktuell nicht möglich.",
"generic": "Das hat nicht geklappt. Bitte erneut versuchen.",
"visibility_not_allowed": "Diese Sichtbarkeit ist nicht erlaubt."
}
}
+137
View File
@@ -0,0 +1,137 @@
{
"title": "Objekte",
"crumb": "Stammdaten",
"sub": "Baustellen, Filialen und Anlagen mit Hinweisen, Dokumenten und Einsatzhistorie.",
"new": "Neues Objekt",
"searchLabel": "Suche",
"searchPlaceholder": "Objekt, Adresse oder Kunde",
"filter": {
"status": "Status",
"all": "Alle",
"apply": "Filtern",
"reset": "Zurücksetzen"
},
"status": {
"active": "Aktiv",
"inactive": "Inaktiv",
"provisional": "Vorläufig"
},
"columns": {
"name": "Objekt",
"customer": "Kunde",
"address": "Adresse",
"orders": "Aufträge",
"status": "Status"
},
"empty": "Keine Objekte gefunden.",
"pagination": {
"prev": "Zurück",
"next": "Weiter",
"summary": "{from}–{to} von {total}"
},
"fields": {
"customerId": "Kunde",
"selectCustomer": "Kunden auswählen",
"name": "Objektbezeichnung",
"street": "Straße",
"houseNumber": "Hausnr.",
"postalCode": "PLZ",
"city": "Ort",
"country": "Land",
"contactId": "Ansprechpartner vor Ort",
"noContact": "Kein hinterlegter Kontakt",
"onSiteContact": "Ansprechpartner vor Ort (Freitext)",
"phone": "Telefon vor Ort",
"accessNotes": "Zugangshinweise",
"parkingNotes": "Parkhinweise",
"safetyNotes": "Sicherheitsinformationen",
"technicalNotes": "Technische Hinweise",
"status": "Status",
"latitude": "Breitengrad",
"longitude": "Längengrad"
},
"sections": {
"base": "Objekt",
"address": "Adresse",
"onSite": "Vor Ort",
"notes": "Hinweise für den Einsatz",
"geo": "Koordinaten (optional)"
},
"form": {
"createTitle": "Objekt anlegen",
"createSub": "Jedes Objekt gehört zu einem Kunden.",
"editTitle": "Objekt bearbeiten",
"create": "Objekt anlegen",
"save": "Speichern",
"saving": "Speichert…",
"cancel": "Abbrechen",
"saved": "Gespeichert.",
"contactHint": "Kontakte des Kunden stehen nach dem Anlegen zur Auswahl."
},
"tabs": {
"master": "Stammdaten",
"documents": "Dokumente",
"history": "Historie"
},
"detail": {
"edit": "Bearbeiten",
"delete": "Löschen",
"deleteTitle": "Objekt löschen",
"deleteHint": "Das Objekt wird ausgeblendet. Historie und Nachweise bleiben erhalten. Nur ohne offene Aufträge möglich.",
"deleteConfirm": "Objekt löschen",
"map": "Karte öffnen (OpenStreetMap)",
"noMap": "Keine Adresse für die Karte",
"customer": "Kunde",
"back": "Zur Objektliste",
"noNotes": "Keine Hinweise hinterlegt."
},
"history": {
"title": "Einsatzhistorie",
"onlyApproved": "Nur freigegebene",
"showAll": "Alle Einsätze",
"approvedOnlyHint": "Angezeigt werden freigegebene Einsätze.",
"empty": "Noch keine Einsätze an diesem Objekt.",
"workDone": "Durchgeführte Arbeiten",
"noWorkDone": "Keine Tätigkeiten erfasst.",
"materials": "Material",
"noMaterials": "Kein Material erfasst.",
"photos": "{count, plural, =0 {Keine Fotos} one {# Foto} other {# Fotos}}",
"reports": "Berichte",
"noReports": "Kein freigegebener Bericht.",
"reportType": {
"daily": "Tagesbericht",
"completion": "Abschlussbericht"
},
"reportLink": "{type} v{version} vom {date}",
"signed": "Kundenunterschrift liegt vor",
"notSigned": "Keine Kundenunterschrift",
"followUp": "Offene Folgearbeiten",
"emergency": "Notdienst",
"noTeam": "Kein Team",
"openOrder": "Auftrag öffnen"
},
"statusGroup": {
"new": "Neu",
"planned": "Geplant",
"en_route": "Unterwegs",
"in_progress": "In Arbeit",
"documentation_incomplete": "Dokumentation unvollständig",
"in_review": "Zur Prüfung",
"ready_for_billing": "Bereit zur Abrechnung",
"billed": "Abgerechnet",
"cancelled": "Storniert"
},
"errors": {
"invalid": "Bitte die markierten Felder prüfen.",
"not_found": "Datensatz nicht gefunden.",
"forbidden": "Dafür fehlt die Berechtigung.",
"conflict": "Das geht so nicht: Der Datensatz wurde geändert.",
"blocked": "Aktion aktuell nicht möglich.",
"generic": "Das hat nicht geklappt. Bitte erneut versuchen.",
"required": "Pflichtfeld",
"invalidField": "Eingabe prüfen",
"customer_not_found": "Kunde nicht gefunden.",
"contact_mismatch": "Der Kontakt gehört nicht zu diesem Kunden.",
"open_work_orders": "Es gibt noch offene Aufträge."
}
}
+75
View File
@@ -0,0 +1,75 @@
{
"title": "Teams",
"crumb": "Stammdaten",
"sub": "Montageteams mit Teamleitung, Mitgliedern und Einsatzgebiet.",
"new": "Neues Team",
"showInactive": "Inaktive anzeigen",
"hideInactive": "Inaktive ausblenden",
"empty": "Noch keine Teams.",
"columns": {
"name": "Team",
"leader": "Teamleiter",
"members": "Mitglieder",
"phone": "Telefon",
"vehicle": "Fahrzeug",
"area": "Einsatzgebiet",
"status": "Status"
},
"status": {
"active": "Aktiv",
"inactive": "Inaktiv"
},
"fields": {
"name": "Teamname",
"leaderUserId": "Teamleiter",
"noLeader": "Kein Teamleiter",
"status": "Status",
"phone": "Telefon",
"vehicle": "Fahrzeug",
"area": "Einsatzgebiet",
"notes": "Interne Hinweise"
},
"members": {
"title": "Mitglieder",
"add": "Mitglied hinzufügen",
"remove": "Entfernen",
"user": "Person",
"selectUser": "Person auswählen",
"validFrom": "Gültig ab",
"validTo": "Gültig bis",
"validToHint": "Leer = unbefristet",
"empty": "Noch keine Mitglieder.",
"current": "aktuell",
"ended": "beendet",
"upcoming": "ab {date}",
"count": "{count, plural, =0 {Keine Mitglieder} one {# Mitglied} other {# Mitglieder}}"
},
"form": {
"createTitle": "Team anlegen",
"editTitle": "Team bearbeiten",
"sub": "Mitglieder kommen aus den aktiven Nutzern des Mandanten.",
"save": "Speichern",
"create": "Team anlegen",
"saving": "Speichert…",
"cancel": "Abbrechen",
"delete": "Team löschen",
"deleteHint": "Das Team wird ausgeblendet. Nur ohne offene Aufträge möglich.",
"deleteConfirm": "Team wirklich löschen?"
},
"readOnly": "Nur Lesezugriff.",
"errors": {
"invalid": "Bitte die markierten Felder prüfen.",
"not_found": "Team nicht gefunden.",
"forbidden": "Dafür fehlt die Berechtigung.",
"conflict": "Das geht so nicht: Der Name ist bereits vergeben.",
"blocked": "Aktion aktuell nicht möglich.",
"generic": "Das hat nicht geklappt. Bitte erneut versuchen.",
"required": "Pflichtfeld",
"invalidField": "Eingabe prüfen",
"duplicate_member": "Eine Person ist mehrfach eingetragen.",
"inactive_user": "Nur aktive Nutzer des Mandanten sind möglich.",
"name_taken": "Teamname ist bereits vergeben.",
"valid_to_before_from": "„Gültig bis“ liegt vor „Gültig ab“.",
"open_work_orders": "Dem Team sind noch offene Aufträge zugewiesen."
}
}