feat(helpdesk): add customer engagement analytics page [skip ci]
New "Customer analytics" page under Monitoring: surfaces who is actively in contact vs. who has gone quiet, so the team can reach out before a customer slips away. - KPI tiles: total / active / no-contact / never-in-contact - "Customers without recent contact" — longest silence first - "Top customers by communication" — most ticket activity in the period - Configurable no-contact threshold (helpdesk settings, default 60 days) CustomerEngagementService aggregates the global ticket snapshot per customer (same single-pull model as RiskRadarService — no N+1 to BC). Last contact is the most recent ticket activity; silence beyond the threshold flags the customer. Revenue ranking deferred (BC OData exposes no per-customer ledger). All within modules/helpdesk/. Tests + PHPStan green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -130,9 +130,9 @@
|
||||
"Close rate": "Close-Rate",
|
||||
"Avg. resolution": "Ø Lösungszeit",
|
||||
"Open backlog": "Offene Tickets",
|
||||
"kpi_tooltip_close_rate": "Geschlossene \u00f7 erstellte Tickets im Zeitraum. \u00dcber 1\u00d7 = R\u00fcckstau wird abgebaut.",
|
||||
"kpi_tooltip_close_rate": "Geschlossene ÷ erstellte Tickets im Zeitraum. Über 1× = Rückstau wird abgebaut.",
|
||||
"kpi_tooltip_resolution": "Median der Bearbeitungsdauer aller im Zeitraum geschlossenen Tickets.",
|
||||
"kpi_tooltip_backlog": "Aktueller Stand aller offenen Tickets \u2013 unabh\u00e4ngig vom gew\u00e4hlten Zeitraum. Zeigt den R\u00fcckstau.",
|
||||
"kpi_tooltip_backlog": "Aktueller Stand aller offenen Tickets – unabhängig vom gewählten Zeitraum. Zeigt den Rückstau.",
|
||||
"Backlog shrinking": "Rückstau wird abgebaut",
|
||||
"Backlog growing": "Rückstau wächst",
|
||||
"unassigned": "ohne Bearbeiter",
|
||||
@@ -372,7 +372,7 @@
|
||||
"Back to list": "Zurück zur Liste",
|
||||
"Save & close": "Speichern & schließen",
|
||||
"Software product updated": "Software-Produkt aktualisiert",
|
||||
"Software product not found": "Software-Produkt nicht gefunden",
|
||||
"Software product not found": "Softwareprodukt nicht gefunden",
|
||||
"Product details": "Produktdetails",
|
||||
"Enter product name...": "Produktname eingeben...",
|
||||
"Name must not exceed 255 characters": "Name darf maximal 255 Zeichen lang sein",
|
||||
@@ -436,8 +436,6 @@
|
||||
"Create handover": "Übergabe erstellen",
|
||||
"Continue": "Weiter",
|
||||
"Cancel": "Abbrechen",
|
||||
"Back": "Zurück",
|
||||
"Back to list": "Zurück zur Liste",
|
||||
"Please select a customer": "Bitte wählen Sie einen Kunden",
|
||||
"Please select a software product": "Bitte wählen Sie ein Softwareprodukt",
|
||||
"Software product has no handover protocol schema": "Softwareprodukt hat kein Übergabeprotokoll-Schema",
|
||||
@@ -445,27 +443,22 @@
|
||||
"Please complete step 1 first": "Bitte schließen Sie zuerst Schritt 1 ab",
|
||||
"Debitor number is required": "Debitornummer ist erforderlich",
|
||||
"Software product is required": "Softwareprodukt ist erforderlich",
|
||||
"Software product not found": "Softwareprodukt nicht gefunden",
|
||||
"Failed to create handover": "Übergabe konnte nicht erstellt werden",
|
||||
"You do not have permission to edit this handover": "Sie haben keine Berechtigung, diese Übergabe zu bearbeiten",
|
||||
"You do not have permission to set this status": "Sie haben keine Berechtigung, diesen Status zu setzen",
|
||||
"Invalid status": "Ungültiger Status",
|
||||
"Unknown field: %s": "Unbekanntes Feld: %s",
|
||||
"%s is required": "%s ist erforderlich",
|
||||
"Failed to save": "Speichern fehlgeschlagen",
|
||||
"Failed to update status": "Status konnte nicht aktualisiert werden",
|
||||
"No protocol fields defined.": "Keine Protokollfelder definiert.",
|
||||
"Please select...": "Bitte auswählen...",
|
||||
"Handover protocol": "Übergabeprotokoll",
|
||||
"Change status": "Status ändern",
|
||||
"Customer": "Kunde",
|
||||
"Debitor No.": "Debitornr.",
|
||||
"Progress": "Fortschritt",
|
||||
"Created by": "Erstellt von",
|
||||
"Search handovers...": "Übergaben suchen...",
|
||||
"ID": "ID",
|
||||
"History": "Verlauf",
|
||||
"Current": "Aktuell",
|
||||
"Viewing version %d": "Version %d wird angezeigt",
|
||||
"compared with version %d": "verglichen mit Version %d",
|
||||
"Back to current": "Zurück zur aktuellen Version",
|
||||
@@ -475,7 +468,6 @@
|
||||
"Failed to restore": "Wiederherstellen fehlgeschlagen",
|
||||
"Only managers can restore revisions": "Nur Manager können Versionen wiederherstellen",
|
||||
"Revision not found": "Version nicht gefunden",
|
||||
"Created": "Erstellt",
|
||||
"Fields changed": "Felder geändert",
|
||||
"Status changed": "Status geändert",
|
||||
"Fields and status changed": "Felder und Status geändert",
|
||||
@@ -521,11 +513,8 @@
|
||||
"Ticket status": "Ticketstatus",
|
||||
"Assignment": "Zuweisung",
|
||||
"Resolved": "Erledigt",
|
||||
"Closed": "Geschlossen",
|
||||
"Open": "Offen",
|
||||
"Assign update": "Update zuweisen",
|
||||
"Assign": "Zuweisen",
|
||||
"Unassigned": "Nicht zugewiesen",
|
||||
"Assigned": "Zugewiesen",
|
||||
"Update": "Update",
|
||||
"Hotfix": "Hotfix",
|
||||
@@ -537,8 +526,6 @@
|
||||
"Update assigned successfully": "Update erfolgreich zugewiesen",
|
||||
"Failed to assign update": "Update konnte nicht zugewiesen werden",
|
||||
"Select domain...": "Domain auswählen...",
|
||||
"Loading domains...": "Domains werden geladen...",
|
||||
"No domains found for this customer": "Keine Domains für diesen Kunden gefunden",
|
||||
"No updates for this domain yet": "Noch keine Updates für diese Domain",
|
||||
"Search updates...": "Updates suchen...",
|
||||
"Open in Gitea": "In Gitea öffnen",
|
||||
@@ -547,9 +534,7 @@
|
||||
"View software updates list": "Software-Updates-Liste anzeigen",
|
||||
"Assign and manage software updates": "Software-Updates zuweisen und verwalten",
|
||||
"Security level": "Sicherheitsstufe",
|
||||
"Low": "Niedrig",
|
||||
"Normal": "Normal",
|
||||
"High": "Hoch",
|
||||
"Critical": "Kritisch",
|
||||
"Save failed": "Speichern fehlgeschlagen",
|
||||
"Invalid CSRF token": "Ungültiges CSRF-Token",
|
||||
@@ -557,13 +542,10 @@
|
||||
"Missing domain number": "Domain-Nummer fehlt",
|
||||
"Invalid security level": "Ungültige Sicherheitsstufe",
|
||||
"Failed to save security level": "Sicherheitsstufe konnte nicht gespeichert werden",
|
||||
|
||||
"Under review": "In Prüfung",
|
||||
"Assignment": "Zuweisung",
|
||||
"Assigned to": "Zugewiesen an",
|
||||
"Assigned at": "Zugewiesen am",
|
||||
"Not assigned yet": "Noch nicht zugewiesen",
|
||||
"Assign": "Zuweisen",
|
||||
"Change assignment": "Zuweisung ändern",
|
||||
"Assign handover": "Übergabe zuweisen",
|
||||
"Assign to": "Zuweisen an",
|
||||
@@ -586,7 +568,6 @@
|
||||
"Failed to submit for review": "Einreichen zur Prüfung fehlgeschlagen",
|
||||
"You are not assigned to this handover": "Sie sind dieser Übergabe nicht zugewiesen",
|
||||
"Handover cannot be submitted for review in its current status": "Übergabe kann im aktuellen Status nicht zur Prüfung eingereicht werden",
|
||||
"In progress": "In Bearbeitung",
|
||||
"Done": "Abgeschlossen",
|
||||
"Assigned to (column)": "Zugewiesen an",
|
||||
"How do you want to proceed?": "Wie möchten Sie vorgehen?",
|
||||
@@ -602,5 +583,24 @@
|
||||
"Please select an employee to assign": "Bitte wählen Sie einen Mitarbeiter aus",
|
||||
"Delete handover": "Übergabe löschen",
|
||||
"Delete this handover?": "Diese Übergabe löschen?",
|
||||
"Handover deleted": "Übergabe gelöscht"
|
||||
"Handover deleted": "Übergabe gelöscht",
|
||||
"Customer analytics": "Kundenanalyse",
|
||||
"No-contact threshold": "Kein-Kontakt-Schwelle",
|
||||
"Could not load customer analytics.": "Kundenanalyse konnte nicht geladen werden.",
|
||||
"No customer data available.": "Keine Kundendaten verfügbar.",
|
||||
"No contact": "Kein Kontakt",
|
||||
"Never in contact": "Nie in Kontakt",
|
||||
"days ago": "Tage her",
|
||||
"never": "nie",
|
||||
"Tickets in period": "Tickets im Zeitraum",
|
||||
"Last contact": "Letzter Kontakt",
|
||||
"Customers without recent contact": "Kunden ohne jüngsten Kontakt",
|
||||
"Longest silence first — consider reaching out.": "Längste Funkstille zuerst — Kontaktaufnahme erwägen.",
|
||||
"Top customers by communication": "Top-Kunden nach Kommunikation",
|
||||
"Most ticket activity in the selected period.": "Meiste Ticket-Aktivität im gewählten Zeitraum.",
|
||||
"Every customer has been in contact recently.": "Alle Kunden waren kürzlich in Kontakt.",
|
||||
"No communication recorded in the selected period.": "Keine Kommunikation im gewählten Zeitraum erfasst.",
|
||||
"Customer engagement": "Kundenbindung",
|
||||
"No-contact threshold (days)": "Kein-Kontakt-Schwelle (Tage)",
|
||||
"Customers without any communication for longer than this are flagged in the customer analytics view.": "Kunden ohne jegliche Kommunikation über diesen Zeitraum hinaus werden in der Kundenanalyse markiert."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user