feat(helpdesk): align module with core UI standards and fix KPI accuracy
- Add server-side ticket summary endpoint for exact KPI counts instead of client-side calculation from first 200 tickets - Extract summarizeTickets() as shared static method to avoid duplication - Replace custom .helpdesk-spinner CSS with core [aria-busy] pattern - Migrate settings connection-test feedback to showAsyncFlash() - Replace helpdesk-clickable-rows.js with delegated event handling - Remove unused helpdesk-search.js (dead code, never loaded) - Harmonize German wording: Debitoren → Kunden (8 i18n keys) - Add 6 PHPUnit tests for loadTicketSummary() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -260,6 +260,88 @@ class DebitorDetailServiceTest extends TestCase
|
||||
$this->assertSame('Timeout', $result['error']);
|
||||
}
|
||||
|
||||
// --- loadTicketSummary() ---
|
||||
|
||||
public function testLoadTicketSummaryReturnsFalseForEmptyCustomerNo(): void
|
||||
{
|
||||
$service = $this->createService();
|
||||
$result = $service->loadTicketSummary('', 'Test GmbH');
|
||||
$this->assertFalse($result['ok']);
|
||||
}
|
||||
|
||||
public function testLoadTicketSummaryReturnsFalseWhenNotConfigured(): void
|
||||
{
|
||||
$service = $this->createService(null, false);
|
||||
$result = $service->loadTicketSummary('10001', 'Test GmbH');
|
||||
$this->assertFalse($result['ok']);
|
||||
}
|
||||
|
||||
public function testLoadTicketSummaryReturnsExactCounts(): void
|
||||
{
|
||||
$tickets = [
|
||||
['No' => 'T001', 'Ticket_State' => 'Offen', 'Last_Activity_Date' => '2026-03-15T10:00:00Z'],
|
||||
['No' => 'T002', 'Ticket_State' => 'In Bearbeitung', 'Last_Activity_Date' => '2026-03-20T14:30:00Z'],
|
||||
['No' => 'T003', 'Ticket_State' => 'Erledigt', 'Last_Activity_Date' => '2026-03-10T08:00:00Z'],
|
||||
['No' => 'T004', 'Ticket_State' => 'Closed', 'Last_Activity_Date' => '2026-02-01T12:00:00Z'],
|
||||
['No' => 'T005', 'Ticket_State' => 'Open', 'Last_Activity_Date' => '2026-03-25T16:45:00Z'],
|
||||
];
|
||||
|
||||
$gateway = $this->createMock(BcODataGateway::class);
|
||||
$gateway->method('getTicketsForCustomer')->willReturn($tickets);
|
||||
|
||||
$service = $this->createService($gateway);
|
||||
$result = $service->loadTicketSummary('10001', 'Test GmbH');
|
||||
|
||||
$this->assertTrue($result['ok']);
|
||||
$this->assertSame(5, $result['total']);
|
||||
$this->assertSame(3, $result['open']); // Offen, In Bearbeitung, Open
|
||||
$this->assertSame('2026-03-25T16:45:00Z', $result['last_activity']);
|
||||
}
|
||||
|
||||
public function testLoadTicketSummaryHandlesEmptyTicketList(): void
|
||||
{
|
||||
$gateway = $this->createMock(BcODataGateway::class);
|
||||
$gateway->method('getTicketsForCustomer')->willReturn([]);
|
||||
|
||||
$service = $this->createService($gateway);
|
||||
$result = $service->loadTicketSummary('10001', 'Test GmbH');
|
||||
|
||||
$this->assertTrue($result['ok']);
|
||||
$this->assertSame(0, $result['total']);
|
||||
$this->assertSame(0, $result['open']);
|
||||
$this->assertSame('', $result['last_activity']);
|
||||
}
|
||||
|
||||
public function testLoadTicketSummaryIgnoresNullDateEntries(): void
|
||||
{
|
||||
$tickets = [
|
||||
['No' => 'T001', 'Ticket_State' => 'Offen', 'Last_Activity_Date' => '0001-01-01T00:00:00Z'],
|
||||
['No' => 'T002', 'Ticket_State' => 'Offen', 'Last_Activity_Date' => ''],
|
||||
];
|
||||
|
||||
$gateway = $this->createMock(BcODataGateway::class);
|
||||
$gateway->method('getTicketsForCustomer')->willReturn($tickets);
|
||||
|
||||
$service = $this->createService($gateway);
|
||||
$result = $service->loadTicketSummary('10001', 'Test GmbH');
|
||||
|
||||
$this->assertTrue($result['ok']);
|
||||
$this->assertSame(2, $result['open']);
|
||||
$this->assertSame('', $result['last_activity']);
|
||||
}
|
||||
|
||||
public function testLoadTicketSummaryReturnsErrorOnException(): void
|
||||
{
|
||||
$gateway = $this->createMock(BcODataGateway::class);
|
||||
$gateway->method('getTicketsForCustomer')->willThrowException(new \RuntimeException('Timeout'));
|
||||
|
||||
$service = $this->createService($gateway);
|
||||
$result = $service->loadTicketSummary('10001', 'Test GmbH');
|
||||
|
||||
$this->assertFalse($result['ok']);
|
||||
$this->assertSame('Timeout', $result['error']);
|
||||
}
|
||||
|
||||
// --- loadTicketLog() ---
|
||||
|
||||
public function testLoadTicketLogReturnsFalseForEmptyTicketNo(): void
|
||||
|
||||
Reference in New Issue
Block a user