183 lines
5.5 KiB
PHP
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' => [],
|
|
],
|
|
]);
|
|
});
|