Add unit tests for Redis namespace safety, MotorAPI cache functionality, and configuration classes, alongside implementation of xlvask_automation_service

- Added tests to ensure Redis namespace safety for `db_object_t` and `users_o`.
- Implemented `MotorApiCachedResultTest` to validate metadata caching behavior.
- Introduced configuration classes for `xlvask_automatic_order_attachment_enabled` and `xlvask_automatic_order_creation_enabled`.
- Developed `xlvask_automation_service` with supporting features for usage log evaluation, suggestion building, and order automation.
This commit is contained in:
Jeppe Bundgaard
2026-05-12 00:22:27 +02:00
parent c1b66a81cc
commit 70080086da
21 changed files with 2326 additions and 57 deletions
@@ -2,11 +2,14 @@
namespace routes;
require_once WD . '/classes/xlvask_automation_service.php';
use classes\authentication;
use classes\redis;
use classes\response;
use classes\stripe;
use classes\xlvask;
use classes\xlvask_automation_service;
use objects\collected_order_invoices_o;
use objects\departments_o;
use objects\economic_module_orders;
@@ -14,7 +17,6 @@ use objects\logs_o;
use objects\orders_o;
use objects\stripe_module_orders_o;
use objects\stripe_payment_intents_o;
use objects\users_o;
use objects\xlvask_usage_logs_o;
use traits\route_t;
@@ -47,6 +49,8 @@ class xlvaskUsageLogsRoute
(new logs_o())->add('xlvask_usage_orders', 'global', 1, $user->id, 'LIST_XLVASK_USAGE_ORDERS', 'User accessed the list of xlvask usage orders');
$xlvask_usage_logs = new xlvask_usage_logs_o();
$xlvask = new xlvask();
$automation_service = new xlvask_automation_service();
$linked_order_ids_by_wash_id = [];
$xlvask->new($xlvask->helpers->xlvask_usage_log)->getDepartment();
$orders_o = new orders_o();
$xlvask_usage_log = $xlvask->new($xlvask->helpers->xlvask_usage_log);
@@ -62,7 +66,8 @@ class xlvaskUsageLogsRoute
// Make sure the Customer is not in the default customers list
->setAdditionalWhereClause("`Customer` NOT IN ('" . implode("', '", $xlvask_usage_log::$default_customers) . "')")
->listObjectsWithPaginationIfSet(
function ($log) use ($response_includes_items_link, $response_includes_items, $xlvask_usage_logs, $user, $xlvask) {
function ($log) use ($response_includes_items_link, $response_includes_items, $xlvask_usage_logs, $user, $xlvask, $automation_service, &$linked_order_ids_by_wash_id) {
$automation = $automation_service->evaluateUsageLogRow($log, (int)$user->id, true);
// Remove the 'id' field from the log
$id = (int)$log['id'];
unset($log['id']);
@@ -72,6 +77,12 @@ class xlvaskUsageLogsRoute
$tmp = $xlvask->new($xlvask->helpers->xlvask_usage_log);
// Set the properties of the temporary object
$tmp->setProperties($log);
$wash_id = (string)$tmp->WashId;
if ($wash_id !== '' && !array_key_exists($wash_id, $linked_order_ids_by_wash_id)) {
$linked_order = (new orders_o())->selectByWashId($wash_id);
$linked_order_ids_by_wash_id[$wash_id] = $linked_order !== null ? (int)$linked_order->id : null;
}
$linked_order_id = $wash_id !== '' ? $linked_order_ids_by_wash_id[$wash_id] : null;
// Define the result structure
$isEligibleForAutomaticContinuance = $tmp->isEligibleForAutomaticContinuance(true);
// Generate a fast link key for the order, used to retrieve the order with items later.
@@ -94,7 +105,10 @@ class xlvaskUsageLogsRoute
return [
'id' => $id, // Return the ID of the log
'fast_link_key' => $fast_link_key ?? null, // Return the fast link key if it was generated
'automation' => $automation,
...$tmp_res['order'], // Return the simulated order from XLVask (with or without items)
'usage_log_id' => $id,
'linked_order_id' => $linked_order_id,
];
},
$xlvask_usage_logs->forceRestrictFilters(
@@ -160,6 +174,115 @@ class xlvaskUsageLogsRoute
]
);
$this->post('/modules/xlvask/services/usage/orders/automation/run', function () {
global $response;
$this->requirePermission('manage_xlvask_usage_automation');
$user = (new authentication())->get_user();
if (!$user) {
$response->error('Invalid session', 400);
return;
}
$ids = $this->isParametersSet(['ids']) ? $this->getParameter('ids') : [];
if (!is_array($ids)) {
$ids = [];
}
$dateFrom = $this->isParametersSet(['dateFrom']) ? (string)$this->getParameter('dateFrom') : null;
$dateTo = $this->isParametersSet(['dateTo']) ? (string)$this->getParameter('dateTo') : null;
$limit = $this->isParametersSet(['limit']) ? (int)$this->getParameter('limit') : 100;
$response->success(
(new xlvask_automation_service())->runPending($dateFrom, $dateTo, $ids, $limit, (int)$user->id)
);
},
[
'manage_xlvask_usage_automation' => 'Evaluate and execute XL Vask usage-log automation',
]
);
$this->post('/modules/xlvask/services/usage/orders/{id}/automation/evaluate', function () {
global $response;
$this->requirePermission('manage_xlvask_usage_automation');
$user = (new authentication())->get_user();
if (!$user) {
$response->error('Invalid session', 400);
return;
}
$id = (int)($this->fromRoute('id') ?? 0);
if ($id < 1) {
$response->error('Invalid XL Vask usage log id', 400);
return;
}
$response->success(
(new xlvask_automation_service())->evaluateUsageLogById($id, (int)$user->id, true)
);
},
[
'manage_xlvask_usage_automation' => 'Evaluate XL Vask usage-log automation',
]
);
$this->post('/modules/xlvask/services/usage/orders/{id}/automation/accept', function () {
global $response;
$this->requirePermission('manage_xlvask_usage_automation');
$user = (new authentication())->get_user();
if (!$user) {
$response->error('Invalid session', 400);
return;
}
$id = (int)($this->fromRoute('id') ?? 0);
if ($id < 1) {
$response->error('Invalid XL Vask usage log id', 400);
return;
}
$suggestionId = $this->isParametersSet(['suggestion_id']) ? (int)$this->getParameter('suggestion_id') : null;
$reason = $this->isParametersSet(['reason']) ? trim((string)$this->getParameter('reason')) : null;
$response->success(
(new xlvask_automation_service())->acceptUsageLogById($id, (int)$user->id, $suggestionId, $reason)
);
},
[
'manage_xlvask_usage_automation' => 'Accept an XL Vask usage-log automation suggestion',
]
);
$this->post('/modules/xlvask/services/usage/orders/{id}/automation/deny', function () {
global $response;
$this->requirePermission('manage_xlvask_usage_automation');
$user = (new authentication())->get_user();
if (!$user) {
$response->error('Invalid session', 400);
return;
}
$id = (int)($this->fromRoute('id') ?? 0);
if ($id < 1) {
$response->error('Invalid XL Vask usage log id', 400);
return;
}
$suggestionId = $this->isParametersSet(['suggestion_id']) ? (int)$this->getParameter('suggestion_id') : null;
$reason = $this->isParametersSet(['reason']) ? trim((string)$this->getParameter('reason')) : null;
$response->success(
(new xlvask_automation_service())->denyUsageLogById($id, (int)$user->id, $suggestionId, $reason)
);
},
[
'manage_xlvask_usage_automation' => 'Deny an XL Vask usage-log automation suggestion',
]
);
$this->get('/modules/xlvask/services/usage/orders/fast-link', function () {
global $response;
self::requireParameters([