Merge branch 'master' into feat/TRU-149-route-scopes
This commit is contained in:
@@ -906,6 +906,68 @@ class orders_o extends db
|
|||||||
return (bool)$count;
|
return (bool)$count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the timestamp of the most recent completed wash for a license plate.
|
||||||
|
* Used by the front page to show the "last washed" hint when a plate is
|
||||||
|
* scanned (DHL trailer pick-up use case, TRU-78 / DRIFT 17).
|
||||||
|
*
|
||||||
|
* Only orders that have at least one non-deleted order item are
|
||||||
|
* considered (mirrors the contract used by customer_vehicles_o::
|
||||||
|
* getLastOrderByPlate() so the timestamp is always backed by a real wash).
|
||||||
|
*
|
||||||
|
* @param string $reg_1 The license plate to look up
|
||||||
|
* @return string|null MySQL datetime string of the most recent qualifying
|
||||||
|
* order's `created_at`, or null when the plate has
|
||||||
|
* never been washed.
|
||||||
|
*/
|
||||||
|
public function getLastWashTimestampForPlate(string $reg_1): ?string
|
||||||
|
{
|
||||||
|
$normalized_reg_1 = trim($reg_1);
|
||||||
|
if ($normalized_reg_1 === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$orders = self::getFieldsWhere([
|
||||||
|
'reg_1' => $normalized_reg_1,
|
||||||
|
'deleted_at' => null,
|
||||||
|
], [
|
||||||
|
'id',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Walk the orders newest-first and return the first one that actually
|
||||||
|
// has at least one non-deleted order item.
|
||||||
|
$candidate_ids = array_reverse(array_map(static function ($row) {
|
||||||
|
return (int)($row['id'] ?? 0);
|
||||||
|
}, $orders));
|
||||||
|
|
||||||
|
foreach ($candidate_ids as $order_id) {
|
||||||
|
if ($order_id <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$has_items = (new order_items_o())->getFieldsWhere([
|
||||||
|
'order_id' => $order_id,
|
||||||
|
'deleted_at' => null,
|
||||||
|
], ['id']);
|
||||||
|
|
||||||
|
if (count($has_items) === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$details = self::getFieldsWhere([
|
||||||
|
'id' => $order_id,
|
||||||
|
'deleted_at' => null,
|
||||||
|
], ['created_at']);
|
||||||
|
|
||||||
|
$created_at = $details[0]['created_at'] ?? null;
|
||||||
|
if (is_string($created_at) && $created_at !== '') {
|
||||||
|
return $created_at;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public function getFixedPricingTransactions(int $customer_number, false $asArray, string|null $dateFrom = null, string|null $dateTo = null): array
|
public function getFixedPricingTransactions(int $customer_number, false $asArray, string|null $dateFrom = null, string|null $dateTo = null): array
|
||||||
{
|
{
|
||||||
// Get the fixed pricing transactions for a customer
|
// Get the fixed pricing transactions for a customer
|
||||||
|
|||||||
@@ -126,11 +126,21 @@ class plateScansRoute
|
|||||||
'type' => (int)$tmp_scan_vehicle['type'],
|
'type' => (int)$tmp_scan_vehicle['type'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
// TRU-78 / DRIFT 17: enrich each scan with the
|
||||||
|
// timestamp of the most recent completed wash for
|
||||||
|
// that plate so the POS landing page can show
|
||||||
|
// "last washed" at a glance when DHL trailers are
|
||||||
|
// being picked up.
|
||||||
|
$plate_value = (string)$scan['plate'];
|
||||||
|
$tmp_scan_last_wash = [
|
||||||
|
'last_wash' => (new orders_o())->getLastWashTimestampForPlate($plate_value),
|
||||||
|
];
|
||||||
// Return the object as an array
|
// Return the object as an array
|
||||||
return [
|
return [
|
||||||
...$scan,
|
...$scan,
|
||||||
...$tmp_scan_customer,
|
...$tmp_scan_customer,
|
||||||
...$tmp_scan_seen_before,
|
...$tmp_scan_seen_before,
|
||||||
|
...$tmp_scan_last_wash,
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
$number_plate_scans->forceRestrictFilters(
|
$number_plate_scans->forceRestrictFilters(
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
it('orders_o exposes getLastWashTimestampForPlate that filters out orders without order items', function (): void {
|
||||||
|
$ordersFile = app_path('objects/orders_o.php');
|
||||||
|
expect(is_file($ordersFile))->toBeTrue();
|
||||||
|
|
||||||
|
$ordersCode = preg_replace('/\s+/', ' ', (string)file_get_contents($ordersFile));
|
||||||
|
|
||||||
|
expect($ordersCode)->toContain('public function getLastWashTimestampForPlate(string $reg_1): ?string');
|
||||||
|
|
||||||
|
// The helper must look at non-deleted orders with non-deleted order items,
|
||||||
|
// matching the contract used by customer_vehicles_o::getLastOrderByPlate().
|
||||||
|
expect($ordersCode)->toContain("'reg_1' => $normalized_reg_1");
|
||||||
|
expect($ordersCode)->toContain("'deleted_at' => null");
|
||||||
|
expect($ordersCode)->toContain("'order_id' => $order_id");
|
||||||
|
expect($ordersCode)->toContain('return $created_at;');
|
||||||
|
expect($ordersCode)->toContain('return null;');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('plateScansRoute enriches GET /numberplatescans with last_wash per scan (TRU-78)', function (): void {
|
||||||
|
$routeFile = app_path('routes/plateScansRoute.php');
|
||||||
|
$ordersFile = app_path('objects/orders_o.php');
|
||||||
|
|
||||||
|
expect(is_file($routeFile))->toBeTrue();
|
||||||
|
expect(is_file($ordersFile))->toBeTrue();
|
||||||
|
|
||||||
|
$routeCode = preg_replace('/\s+/', ' ', (string)file_get_contents($routeFile));
|
||||||
|
$ordersCode = preg_replace('/\s+/', ' ', (string)file_get_contents($ordersFile));
|
||||||
|
|
||||||
|
// The route already loads orders_o and customer_vehicles_o; verify the
|
||||||
|
// new enrichment is wired in the GET /numberplatescans handler.
|
||||||
|
expect($routeCode)->toContain("\$this->get('/numberplatescans', function () {");
|
||||||
|
expect($routeCode)->toContain("'last_wash'");
|
||||||
|
expect($routeCode)->toContain('getLastWashTimestampForPlate');
|
||||||
|
expect($routeCode)->toContain("'last_wash' => (new orders_o())->getLastWashTimestampForPlate");
|
||||||
|
expect($routeCode)->toContain('$tmp_scan_last_wash');
|
||||||
|
|
||||||
|
// The helper definition must live in orders_o so the enrichment is real,
|
||||||
|
// not a stub.
|
||||||
|
expect($ordersCode)->toContain('public function getLastWashTimestampForPlate(string $reg_1): ?string');
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user