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

139 lines
4.2 KiB
PHP

<?php
app_require('classes/department_wash_count_service.php');
use classes\department_wash_count_service;
final class DepartmentWashCountFakeResult
{
public int $num_rows;
private int $cursor = 0;
public function __construct(private readonly array $rows)
{
$this->num_rows = count($rows);
}
public function fetch_assoc(): ?array
{
if (!array_key_exists($this->cursor, $this->rows)) {
return null;
}
return $this->rows[$this->cursor++];
}
}
final class DepartmentWashCountFakeDb
{
public array $queries = [];
public function escape_string(string $value): string
{
return addslashes($value);
}
public function getDatabase(): string
{
return 'test_db';
}
public function query(string $sql): DepartmentWashCountFakeResult
{
$this->queries[] = $sql;
if (str_contains($sql, 'information_schema.COLUMNS') || str_contains($sql, 'information_schema.STATISTICS')) {
return new DepartmentWashCountFakeResult([['c' => 1, 'DATA_TYPE' => 'text']]);
}
if (str_contains($sql, 'COUNT(DISTINCT o.id) AS quantity')) {
return new DepartmentWashCountFakeResult([[
'quantity' => 3,
'products' => 5,
'earnings' => 250,
]]);
}
return new DepartmentWashCountFakeResult([[
'department_id' => 7,
'hour_bucket' => '2026-04-01 12:00:00',
'wash_count' => 2,
]]);
}
}
function department_wash_count_find_query(array $queries, string $needle): string
{
foreach ($queries as $query) {
if (str_contains($query, $needle)) {
return $query;
}
}
return '';
}
it('builds wash counts from order washes and completed self-serve sessions with linked-order dedupe', function (): void {
$hadDb = array_key_exists('db', $GLOBALS);
$previousDb = $GLOBALS['db'] ?? null;
$fakeDb = new DepartmentWashCountFakeDb();
$GLOBALS['db'] = $fakeDb;
try {
$service = new department_wash_count_service();
$rows = $service->countByHourForDepartments('2026-04-01 00:00:00', '2026-04-01 23:59:59', [7]);
expect($rows)->toBe([[
'department_id' => 7,
'hour_bucket' => '2026-04-01 12:00:00',
'wash_count' => 2,
]]);
$query = department_wash_count_find_query($fakeDb->queries, 'FROM selfserve_wash_sessions s');
expect($query)->toContain('FROM selfserve_wash_sessions s')
->and($query)->toContain("UPPER(TRIM(s.status)) = 'COMPLETED'")
->and($query)->toContain('s.completed_at IS NOT NULL')
->and($query)->toContain('COALESCE(linked_o.created_at, s.completed_at)')
->and($query)->toContain("CONCAT('order:', linked_o.id)")
->and($query)->toContain('GROUP BY dedupe_key, department_id');
} finally {
if ($hadDb) {
$GLOBALS['db'] = $previousDb;
} else {
unset($GLOBALS['db']);
}
}
});
it('keeps transaction totals order-based while using expanded wash counts', function (): void {
$hadDb = array_key_exists('db', $GLOBALS);
$previousDb = $GLOBALS['db'] ?? null;
$fakeDb = new DepartmentWashCountFakeDb();
$GLOBALS['db'] = $fakeDb;
try {
$service = new department_wash_count_service();
$summary = $service->transactionSummary('2026-04-01 00:00:00', '2026-04-01 23:59:59', [7]);
expect($summary)->toBe([
'quantity' => 3,
'products' => 5,
'earnings' => 250,
'washes' => 2,
]);
$summaryQuery = department_wash_count_find_query($fakeDb->queries, 'COUNT(DISTINCT o.id) AS quantity');
$countQuery = department_wash_count_find_query($fakeDb->queries, 'FROM selfserve_wash_sessions s');
expect($summaryQuery)->toContain('COUNT(DISTINCT o.id) AS quantity')
->and($summaryQuery)->not->toContain('selfserve_wash_sessions')
->and($countQuery)->toContain('selfserve_wash_sessions');
} finally {
if ($hadDb) {
$GLOBALS['db'] = $previousDb;
} else {
unset($GLOBALS['db']);
}
}
});