forked from fa/breadcrumb-the-shire
feat(helpdesk): add dashboards, communication feed, settings UI and fix routing
Add support/sales/controlling dashboards with KPIs, trend charts and risk indicators. Add debitor communication timeline, contact filters, system recommendations engine, and configurable controlling risk rules. Rename search→index to fix query-string preservation on back navigation. Remove fake escalation rate metric, add KPI info tooltips, and switch trend chart colors to red (created) / green (closed) for clarity. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -106,6 +106,7 @@ class TicketCommunicationServiceTest extends TestCase
|
||||
|
||||
$odataGateway = $this->createMock(BcODataGateway::class);
|
||||
$odataGateway->method('getTicketsForCustomer')->with('10001', 'Test GmbH')->willReturn($tickets);
|
||||
$odataGateway->method('getContactsForCustomer')->with('', 'Test GmbH')->willReturn([]);
|
||||
$odataGateway->method('getTicketLog')->willReturnCallback(static function (string $ticketNo): array {
|
||||
return [[
|
||||
'Entry_No' => 1,
|
||||
@@ -133,6 +134,53 @@ class TicketCommunicationServiceTest extends TestCase
|
||||
$this->assertContains('T12', $ticketNos);
|
||||
}
|
||||
|
||||
public function testLoadDebitorCommunicationFeedResolvesContactActorsOncePerDebitor(): void
|
||||
{
|
||||
$soapGateway = $this->createMock(BcSoapGateway::class);
|
||||
$soapGateway->method('getTicketCommunicationText')->willReturn([
|
||||
'ok' => false,
|
||||
'soap_used' => false,
|
||||
'return_value' => 400,
|
||||
'communication_text' => '',
|
||||
'message_entries' => '',
|
||||
'error' => 'SOAP unavailable',
|
||||
]);
|
||||
|
||||
$odataGateway = $this->createMock(BcODataGateway::class);
|
||||
$odataGateway->method('getTicketsForCustomer')->with('10001', 'Test GmbH')->willReturn([
|
||||
['No' => 'T1', 'Last_Activity_Date' => '2026-04-10T08:00:00Z', 'Created_On' => '2026-04-09T08:00:00Z'],
|
||||
['No' => 'T2', 'Last_Activity_Date' => '2026-04-09T08:00:00Z', 'Created_On' => '2026-04-08T08:00:00Z'],
|
||||
]);
|
||||
$odataGateway->expects($this->once())
|
||||
->method('getContactsForCustomer')
|
||||
->with('', 'Test GmbH')
|
||||
->willReturn([
|
||||
['No' => 'KT002967', 'Name' => 'Felix Schneider'],
|
||||
]);
|
||||
$odataGateway->expects($this->never())
|
||||
->method('getTicket');
|
||||
$odataGateway->method('getTicketLog')->willReturn([
|
||||
[
|
||||
'Entry_No' => 1,
|
||||
'Created_By' => 'KT002967',
|
||||
'Created_By_Type' => 'Contact',
|
||||
'Creation_Date' => '2026-04-03',
|
||||
'Creation_Time' => '07:59:00.000',
|
||||
'Type' => 'Nachricht',
|
||||
'State_Subtype' => '',
|
||||
'Record_ID' => 'Hallo',
|
||||
],
|
||||
]);
|
||||
|
||||
$service = new TicketCommunicationService($soapGateway, $odataGateway);
|
||||
$result = $service->loadDebitorCommunicationFeed('10001', 'Test GmbH', 2, 40, 250);
|
||||
|
||||
$this->assertTrue($result['ok']);
|
||||
$this->assertNotEmpty($result['entries']);
|
||||
$actors = array_unique(array_map(static fn (array $entry): string => (string) ($entry['actor'] ?? ''), $result['entries']));
|
||||
$this->assertSame(['Felix Schneider'], $actors);
|
||||
}
|
||||
|
||||
public function testLoadTicketCommunicationFeedRespectsEntryLimit(): void
|
||||
{
|
||||
$soapGateway = $this->createMock(BcSoapGateway::class);
|
||||
|
||||
Reference in New Issue
Block a user