> */ private array $rows; /** * @param array> $rows */ public function __construct(array $rows) { $this->rows = array_values($rows); $this->num_rows = count($this->rows); } /** * @return array|null */ public function fetch_assoc(): ?array { if ($this->rows === []) { return null; } return array_shift($this->rows); } } final class OrdersRegistrationDateRangeDbStub { public string $lastQuery = ''; public int $queryCalls = 0; public function escape_string(string $value): string { return addslashes($value); } public function query(string $sql): OrdersRegistrationDateRangeDbResultStub { $this->queryCalls++; $this->lastQuery = $sql; return new OrdersRegistrationDateRangeDbResultStub([]); } } it('applies created_at bounds directly in SQL when filtering orders by registration number', function (): void { $dbStub = new OrdersRegistrationDateRangeDbStub(); $hadDb = array_key_exists('db', $GLOBALS); $previousDb = $hadDb ? $GLOBALS['db'] : null; $GLOBALS['db'] = $dbStub; try { $orders = (new orders_o())->getOrdersWithRegistrationNumberInDateRange( ' ec21235 ', '2025-03-01 00:00:00', '2025-04-30 23:59:59' ); expect($orders)->toBe([]); expect($dbStub->queryCalls)->toBeGreaterThan(0); expect($dbStub->lastQuery)->toContain("UPPER(TRIM(reg_1)) = 'EC21235'"); expect($dbStub->lastQuery)->toContain("UPPER(TRIM(reg_2)) = 'EC21235'"); expect($dbStub->lastQuery)->toContain("UPPER(TRIM(reg_3)) = 'EC21235'"); expect($dbStub->lastQuery)->toContain("created_at BETWEEN '2025-03-01 00:00:00' AND '2025-04-30 23:59:59'"); expect($dbStub->lastQuery)->toContain('AND deleted_at IS NULL'); expect($dbStub->lastQuery)->not->toContain('SELECT id, created_at'); } finally { if ($hadDb) { $GLOBALS['db'] = $previousDb; } else { unset($GLOBALS['db']); } } }); it('rejects an inverted date range for registration lookups', function (): void { $dbStub = new OrdersRegistrationDateRangeDbStub(); $hadDb = array_key_exists('db', $GLOBALS); $previousDb = $hadDb ? $GLOBALS['db'] : null; $GLOBALS['db'] = $dbStub; try { (new orders_o())->getOrdersWithRegistrationNumberInDateRange( 'EC21235', '2025-04-30 23:59:59', '2025-03-01 00:00:00' ); } finally { if ($hadDb) { $GLOBALS['db'] = $previousDb; } else { unset($GLOBALS['db']); } } })->throws(\Exception::class, 'The start date cannot be after the end date'); it('returns early when registration number is blank', function (): void { $dbStub = new OrdersRegistrationDateRangeDbStub(); $hadDb = array_key_exists('db', $GLOBALS); $previousDb = $hadDb ? $GLOBALS['db'] : null; $GLOBALS['db'] = $dbStub; try { $orders = (new orders_o())->getOrdersWithRegistrationNumberInDateRange( ' ', '2025-03-01 00:00:00', '2025-04-30 23:59:59' ); expect($orders)->toBe([]); expect($dbStub->queryCalls)->toBeGreaterThanOrEqual(0); } finally { if ($hadDb) { $GLOBALS['db'] = $previousDb; } else { unset($GLOBALS['db']); } } }); it('orders registration-matched orders by id ASC so invoice-collection reassignment is deterministic', function (): void { $dbStub = new OrdersRegistrationDateRangeDbStub(); $hadDb = array_key_exists('db', $GLOBALS); $previousDb = $hadDb ? $GLOBALS['db'] : null; $GLOBALS['db'] = $dbStub; try { (new orders_o())->getOrdersWithRegistrationNumberInDateRange( 'EC21235', '2025-03-01 00:00:00', '2025-04-30 23:59:59' ); expect($dbStub->lastQuery)->toContain('ORDER BY id ASC'); } finally { if ($hadDb) { $GLOBALS['db'] = $previousDb; } else { unset($GLOBALS['db']); } } });