Files
api/services/nginx/app/tests/Unit/DailyReports/DepartmentOutsideHoursStatisticsServiceTest.php
T

183 lines
5.5 KiB
PHP

<?php
app_require('classes/department_outside_hours_statistics_service.php');
use classes\department_outside_hours_statistics_service;
function outside_hours_weekday_hours(int $department_id, array $overrides = []): array
{
return array_merge([
'department' => $department_id,
'monday_start' => '08:00:00',
'monday_end' => '17:00:00',
'tuesday_start' => '08:00:00',
'tuesday_end' => '17:00:00',
'wednesday_start' => '08:00:00',
'wednesday_end' => '17:00:00',
'thursday_start' => '08:00:00',
'thursday_end' => '17:00:00',
'friday_start' => '08:00:00',
'friday_end' => '17:00:00',
'saturday_start' => '08:00:00',
'saturday_end' => '17:00:00',
'sunday_start' => '08:00:00',
'sunday_end' => '17:00:00',
], $overrides);
}
it('counts only outside-hours washes and flags missing opening hours without counting them as closed', function (): void {
$service = new department_outside_hours_statistics_service();
$summary = $service->summarizeCandidates(
[
[
'source' => 'orders',
'dedupe_key' => 'order:100',
'department_id' => 1,
'start_at' => '2026-03-23 06:45:00',
],
[
'source' => 'orders',
'dedupe_key' => 'order:101',
'department_id' => 1,
'start_at' => '2026-03-23 10:15:00',
],
[
'source' => 'orders',
'dedupe_key' => 'order:102',
'department_id' => 2,
'start_at' => '2026-03-23 05:30:00',
],
],
[
1 => outside_hours_weekday_hours(1),
2 => outside_hours_weekday_hours(2, [
'monday_start' => null,
'monday_end' => null,
]),
],
[1, 2],
'2026-03-23',
'2026-03-23'
);
expect($summary['total'])->toBe(1);
expect($summary['by_source'])->toBe([
'orders' => 1,
'xlvask' => 0,
'selfserve' => 0,
]);
expect($summary['has_missing_opening_hours'])->toBeTrue();
expect($summary['missing_department_ids'])->toBe([2]);
});
it('deduplicates linked washes with self-serve first, then xlvask, then orders', function (): void {
$service = new department_outside_hours_statistics_service();
$deduplicated = $service->deduplicateCandidates([
[
'source' => 'orders',
'dedupe_key' => 'order:200',
'department_id' => 1,
'start_at' => '2026-03-23 06:00:00',
],
[
'source' => 'xlvask',
'dedupe_key' => 'order:200',
'department_id' => 1,
'start_at' => '2026-03-23 06:05:00',
],
[
'source' => 'selfserve',
'dedupe_key' => 'order:200',
'department_id' => 1,
'start_at' => '2026-03-23 06:10:00',
],
[
'source' => 'xlvask',
'dedupe_key' => 'xlvask:wash-standalone',
'department_id' => 1,
'start_at' => '2026-03-23 23:00:00',
],
[
'source' => 'selfserve',
'dedupe_key' => 'selfserve:501',
'department_id' => 1,
'start_at' => '2026-03-23 23:30:00',
],
]);
expect($deduplicated)->toHaveCount(3);
expect($deduplicated[0]['source'])->toBe('selfserve');
expect($deduplicated[0]['dedupe_key'])->toBe('order:200');
expect(array_column($deduplicated, 'source'))->toBe([
'selfserve',
'xlvask',
'selfserve',
]);
});
it('builds daily trend points with per-day missing-hours diagnostics', function (): void {
$service = new department_outside_hours_statistics_service();
$trend = $service->buildTrendFromCandidates(
[
[
'source' => 'orders',
'dedupe_key' => 'order:301',
'department_id' => 1,
'start_at' => '2026-03-23 06:00:00',
],
[
'source' => 'orders',
'dedupe_key' => 'order:302',
'department_id' => 2,
'start_at' => '2026-03-23 05:00:00',
],
[
'source' => 'selfserve',
'dedupe_key' => 'selfserve:701',
'department_id' => 2,
'start_at' => '2026-03-24 05:15:00',
],
],
[
1 => outside_hours_weekday_hours(1),
2 => outside_hours_weekday_hours(2, [
'monday_start' => null,
'monday_end' => null,
]),
],
[1, 2],
'2026-03-23',
'2026-03-24'
);
expect($trend['has_missing_opening_hours'])->toBeTrue();
expect($trend['missing_department_ids'])->toBe([2]);
expect($trend['points'])->toBe([
[
'date' => '2026-03-23',
'total' => 1,
'by_source' => [
'orders' => 1,
'xlvask' => 0,
'selfserve' => 0,
],
'has_missing_opening_hours' => true,
'missing_department_ids' => [2],
],
[
'date' => '2026-03-24',
'total' => 1,
'by_source' => [
'orders' => 0,
'xlvask' => 0,
'selfserve' => 1,
],
'has_missing_opening_hours' => false,
'missing_department_ids' => [],
],
]);
});