63 lines
3.6 KiB
PHP
63 lines
3.6 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../app/Domain/Reporting/ReportFilters.php';
|
|
require_once __DIR__ . '/../app/Domain/Reporting/ReportAudience.php';
|
|
require_once __DIR__ . '/../app/Domain/Reporting/ReportDataMapper.php';
|
|
require_once __DIR__ . '/../app/Domain/Reporting/ReportQuery.php';
|
|
require_once __DIR__ . '/../app/Domain/Reporting/HoursPerClientReport.php';
|
|
require_once __DIR__ . '/../app/Domain/Reporting/TechnicianWorkloadReport.php';
|
|
require_once __DIR__ . '/../app/Domain/Reporting/SlaReport.php';
|
|
require_once __DIR__ . '/../app/Domain/Reporting/PrintReportRenderer.php';
|
|
|
|
function report_services_assert_same(mixed $expected, mixed $actual, string $message): void
|
|
{
|
|
if ($expected !== $actual) {
|
|
throw new RuntimeException($message . "\nExpected: " . var_export($expected, true) . "\nActual: " . var_export($actual, true));
|
|
}
|
|
}
|
|
|
|
$filters = ReportFilters::fromArray([
|
|
'date_from' => '2026-09-01', 'date_to' => '2026-09-30', 'client_id' => 7,
|
|
'technician_id' => 4, 'status' => 'open', 'priority' => 'high', 'sla' => 'warning',
|
|
]);
|
|
$entries = [
|
|
['client_id' => 7, 'client_name' => 'Acme', 'technician_id' => 4, 'technician_name' => 'Tess', 'work_date' => '2026-09-10', 'status' => 'open', 'priority' => 'high', 'sla_status' => 'warning', 'hours' => 1.25],
|
|
['client_id' => 7, 'client_name' => 'Acme', 'technician_id' => 4, 'technician_name' => 'Tess', 'work_date' => '2026-09-11', 'status' => 'open', 'priority' => 'high', 'sla_status' => 'warning', 'hours' => 1.75],
|
|
['client_id' => 8, 'client_name' => 'Beta', 'technician_id' => 4, 'work_date' => '2026-09-12', 'status' => 'open', 'priority' => 'high', 'sla_status' => 'warning', 'hours' => 9],
|
|
];
|
|
report_services_assert_same(
|
|
[['client_id' => 7, 'client_name' => 'Acme', 'hours' => 3.0]],
|
|
(new HoursPerClientReport($filters))->build($entries, ReportAudience::CLIENT),
|
|
'Hours-per-client should apply the common filters before aggregation and return a client-safe projection.'
|
|
);
|
|
|
|
$workload = (new TechnicianWorkloadReport($filters))->build($entries, ReportAudience::INTERNAL);
|
|
report_services_assert_same(
|
|
[['technician_id' => 4, 'technician_name' => 'Tess', 'hours' => 3.0, 'sla_hours' => 0.0]],
|
|
$workload,
|
|
'Technician workload should aggregate filtered hours with deterministic internal fields.'
|
|
);
|
|
$clientWorkload = (new TechnicianWorkloadReport())->build($entries, ReportAudience::CLIENT);
|
|
report_services_assert_same(
|
|
[['client_id' => 7, 'client_name' => 'Acme', 'hours' => 3.0, 'sla_hours' => 0.0], ['client_id' => 8, 'client_name' => 'Beta', 'hours' => 9.0, 'sla_hours' => 0.0]],
|
|
$clientWorkload,
|
|
'Client workload rows should preserve client attribution without technician identity.'
|
|
);
|
|
|
|
$filtered = (new SlaReport(ReportFilters::fromArray(['sla' => 'critical'])))->build([
|
|
['client_id' => 1, 'client_name' => 'Acme', 'allocated_hours' => 10, 'hours' => [9]],
|
|
['client_id' => 2, 'client_name' => 'Beta', 'allocated_hours' => 10, 'hours' => [2]],
|
|
], ReportAudience::CLIENT);
|
|
report_services_assert_same(1, count($filtered), 'SLA status filtering should use the computed usage status.');
|
|
report_services_assert_same(1, $filtered[0]['client_id'], 'SLA status filtering should retain the critical agreement.');
|
|
|
|
$html = (new PrintReportRenderer())->renderRecords('Rows', [
|
|
['name' => '<b>Acme</b>', 'hours' => 3.0],
|
|
]);
|
|
if (!str_contains($html, 'application/pdf') || !str_contains($html, '<b>Acme</b>') || !str_contains($html, '@page')) {
|
|
throw new RuntimeException('Print renderer should emit PDF-ready metadata, print CSS, and escaped record cells.');
|
|
}
|
|
|
|
printf("Focused report service tests: 5 passed\n");
|