From 6ee8c0e2b1b226d6636b739cf9de872213c81e80 Mon Sep 17 00:00:00 2001 From: Jepp9350 <2jepp9350@gmail.com> Date: Wed, 18 Jun 2025 15:20:59 +0200 Subject: [PATCH 1/5] Add vehicle caching methods to XLVask: interface and implementation updates for handling vehicle cache. --- .../modules/xlvask/helpers/xlvask_cache.php | 86 +++++++++++++++++++ .../xlvask/interfaces/xlvask_cache_i.php | 43 ++++++++++ 2 files changed, 129 insertions(+) diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_cache.php b/services/nginx/app/modules/xlvask/helpers/xlvask_cache.php index 972813e0..18c4120d 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_cache.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_cache.php @@ -132,4 +132,90 @@ class xlvask_cache implements xlvask_cache_i } throw new Exception("Customer with number $customer_number is not cached."); } + + /** + * @inheritDoc + */ + public function getVehicleCache(string $registration): xlvask_vehicle + { + if (self::isVehicleCached($registration)) { + $vehicle_data = (object)json_decode(redis->get('xlvask_vehicle_' . $registration), true); + $tmp = new xlvask_vehicle(); + // Assign the properties shared by the xlvask_vehicle class. + foreach ( $vehicle_data as $key => $value ) { + if (property_exists($tmp, $key)) { + $tmp->{$key} = $value; + } + } + return $tmp; // Return the xlvask_vehicle object + } + throw new Exception("Vehicle with registration $registration is not cached."); + } + + /** + * @inheritDoc + */ + public function isVehicleCached(string $registration): bool + { + return (redis->exists('xlvask_vehicle_' . $registration)); + } + + /** + * @inheritDoc + * @throws Exception If there is an error encoding the vehicle data to JSON. + * @see xlvask_vehicle + */ + public function setVehicleCache(string $registration, xlvask_vehicle $vehicle): void + { + $vehicle_data = json_encode($vehicle, JSON_THROW_ON_ERROR); + redis->set('xlvask_vehicle_' . $registration, $vehicle_data); + redis->expire('xlvask_vehicle_' . $registration, 3600); // Set cache expiration to 1 hour + } + + /** + * @inheritDoc + */ + public function clearVehicleCache(string $registration): void + { + if (self::isVehicleCached($registration)) { + redis->delete('xlvask_vehicle_' . $registration); + } else { + throw new Exception("Vehicle with registration $registration is not cached."); + } + } + + /** + * @inheritDoc + */ + public function clearAllVehicleCache(): void + { + $keys = redis->get_keys('xlvask_vehicle_*'); + redis->clear_keys($keys); + } + + /** + * @inheritDoc + */ + public function getAllCachedVehicles(): array + { + $keys = redis->get_keys('xlvask_vehicle_*'); + $vehicles = []; + foreach ( $keys as $key ) { + $vehicle_data = redis->get($key); + if ($vehicle_data) { + $vehicle_data = json_decode($vehicle_data, true); + $tmp = new xlvask_vehicle(); + // Assign the properties shared by the xlvask_vehicle class. + foreach ( $vehicle_data as $property => $value ) { + if (property_exists($tmp, $property)) { + $tmp->{$property} = $value; + } + } + $vehicles[] = $tmp; // Add the xlvask_vehicle object to the array + } else { + throw new Exception("Failed to retrieve vehicle data for key: $key"); + } + } + return $vehicles; + } } \ No newline at end of file diff --git a/services/nginx/app/modules/xlvask/interfaces/xlvask_cache_i.php b/services/nginx/app/modules/xlvask/interfaces/xlvask_cache_i.php index bee7f33c..65a1bf31 100644 --- a/services/nginx/app/modules/xlvask/interfaces/xlvask_cache_i.php +++ b/services/nginx/app/modules/xlvask/interfaces/xlvask_cache_i.php @@ -4,6 +4,7 @@ namespace xlvask\interfaces; use Exception; use helpers\xlvask_customer; +use helpers\xlvask_vehicle; interface xlvask_cache_i { @@ -63,4 +64,46 @@ interface xlvask_cache_i * @example [xlvask_customer, xlvask_customer, ...] */ public function getCachedCustomersByCustomerNumbers(array $customer_numbers, bool $allow_missing = false): array; + + /** + * Check if a vehicle is cached by its registration number. + * @param string $registration The vehicle registration number to check. + * @return bool True if the vehicle is cached, false otherwise. + */ + public function isVehicleCached(string $registration): bool; + + /** + * Get the cached vehicle object by its registration number. + * @param string $registration The vehicle registration number to retrieve. + * @return xlvask_vehicle The cached vehicle object. + * @throws Exception If the vehicle is not cached. + */ + public function getVehicleCache(string $registration): xlvask_vehicle; + + /** + * Set the cache for a specific vehicle. + * @param string $registration The vehicle registration number to cache. + * @param xlvask_vehicle $vehicle The vehicle object to cache. + */ + public function setVehicleCache(string $registration, xlvask_vehicle $vehicle): void; + + /** + * Clear the cache for a specific vehicle. + * @param string $registration The vehicle registration number to clear the cache for. + */ + public function clearVehicleCache(string $registration): void; + + /** + * Clear all cached vehicles. + * This will remove all vehicle caches, so use with caution. + */ + public function clearAllVehicleCache(): void; + + /** + * Get all cached vehicles. + * @return array An array of all cached vehicle objects. + * @example [xlvask_vehicle, xlvask_vehicle, ...] + * @see xlvask_vehicle + */ + public function getAllCachedVehicles(): array; } \ No newline at end of file From 3bf1292775ea38da5e01cd9595ef5187128a2c60 Mon Sep 17 00:00:00 2001 From: Jepp9350 <2jepp9350@gmail.com> Date: Wed, 18 Jun 2025 15:34:07 +0200 Subject: [PATCH 2/5] Add `runSyncVehicles` method to XLVask helpers for vehicle synchronization and caching. --- .../modules/xlvask/helpers/xlvask_tasks.php | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php b/services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php index d82c987a..5fe6a88d 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php @@ -36,10 +36,12 @@ class xlvask_tasks // Synchronize users, this will keep the users (XL Vask customer objects) in cache up to date $this->runSyncUsers(true); $this->runSyncUsage(); + $this->runSyncVehicles(); $this->runCleanupTasks(); }; } + /** * Run the synchronize users task * This task fetches the users from XL Vask, and synchronizes them with this system. @@ -359,6 +361,44 @@ class xlvask_tasks return $order; } + /** + * Synchronize vehicles with XL Vask + * This method is used to synchronize the vehicles with XL Vask. + * It fetches the vehicles from XL Vask and adds them to the cache. + * This includes: + * - Fetching the vehicles from XL Vask + * - Caching the vehicles in this system + * @param bool $isSilent If true, will not throw an exception if synchronization is not enabled + * @return null|array + * @throws Exception If the task fails or if synchronization is not enabled + * @see xlvask_vehicle + * @see xlvask_cache::getVehicleCache() + * @see xlvask_cache::setVehicleCache() + * @see xlvask_cache::isVehicleCached() + */ + public function runSyncVehicles(bool $isSilent = false): ?array + { + // Define the XL Vask object + $xlvask = new \classes\xlvask(); + // Require the module to be enabled + $xlvask->requireModuleEnabled(); + // Check if synchronization is enabled + if (!$xlvask->config->synchronization_enabled->isTrue()) { + if (!$isSilent) { + throw new Exception('XL Vask synchronization is not enabled.'); + } + return null; // Synchronization is not enabled, do nothing + } + // Get the vehicles from XL Vask + $vehicles = $xlvask->getVehicles(); + // Cache the vehicles + foreach ( $vehicles as $vehicle ) { + /** @var xlvask_vehicle $vehicle */ + $xlvask->getCache()->setVehicleCache($vehicle->registrationNumber, $vehicle); + } + return $vehicles; // Return the vehicles + } + /** * Run the cleanup tasks * This task is used to clean up the XL Vask module. From 9d431d55d84b2a54a0d8bfda3bc6df7832a02f86 Mon Sep 17 00:00:00 2001 From: Jepp9350 <2jepp9350@gmail.com> Date: Wed, 18 Jun 2025 15:39:27 +0200 Subject: [PATCH 3/5] Refactor vehicle synchronization logic in XLVask helpers, update instantiation, and remove legacy customer creation code. --- .../modules/xlvask/helpers/xlvask_tasks.php | 4 +++- .../nginx/app/routes/moduleXLVaskRoute.php | 22 +------------------ 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php b/services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php index 5fe6a88d..32cac9ed 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php @@ -390,7 +390,9 @@ class xlvask_tasks return null; // Synchronization is not enabled, do nothing } // Get the vehicles from XL Vask - $vehicles = $xlvask->getVehicles(); + /** @var xlvask_vehicles $vehicles */ + $vehicles = new $xlvask->helpers->xlvask_vehicles(); + $vehicles = $vehicles->getVehicles(); // Cache the vehicles foreach ( $vehicles as $vehicle ) { /** @var xlvask_vehicle $vehicle */ diff --git a/services/nginx/app/routes/moduleXLVaskRoute.php b/services/nginx/app/routes/moduleXLVaskRoute.php index cb51f75e..645c1c3b 100644 --- a/services/nginx/app/routes/moduleXLVaskRoute.php +++ b/services/nginx/app/routes/moduleXLVaskRoute.php @@ -6,7 +6,6 @@ use classes\authentication; use classes\response; use classes\router; use classes\xlvask; -use helpers\xlvask_customer; use objects\orders_o; use objects\users_o; use traits\route_t; @@ -197,26 +196,7 @@ class moduleXLVaskRoute $xlvask = new xlvask(); $user = new users_o(); $user->getUserByCustomerNumber(12345679); - //$xlvask->getTasks()->runSyncUsers(false); - //echo 'Creating customer in XLVask for user: ' . $user->customer_number->value() . " (" . $user->getCustomerName((int)$user->customer_number->value()) . ")\n"; - if (!$xlvask->getCache()->isCustomerCached($user->customer_number->value())) { - throw new \Exception('Customer is not cached in XLVask'); - } - // Get the customer from the cache - $xlvask_customer = $xlvask->getCache()->getCustomerCache($user->customer_number->value()); - $new_customer = new $xlvask->helpers->xlvask_customer(); - /** @var xlvask_customer $new_customer */ - $new_customer->customerId = $xlvask->getGuid()->generate(); - $new_customer->excludeFromAutoInvoice = true; - //$new_customer->discount = 0; - $new_customer->active = true; - $new_customer->name = $user->getCustomerName((int)$user->customer_number->value()); - $new_customer->externId = (string)$user->customer_number->value() . '-' . $user->id; - if (!$new_customer->isValid()) { - throw new \Exception('Customer is not valid in XLVask, missing required properties: ' . implode(', ', $new_customer->getMissingRequiredProperties())); - } - // Create the customer in XLVask - $result = $xlvask->createCustomer($new_customer); + $result = $xlvask->getTasks()->runSyncVehicles(false); // Response $response->success( $result, From 75e3efcb896804b4a123253918ce8517d4dc5d7e Mon Sep 17 00:00:00 2001 From: Jepp9350 <2jepp9350@gmail.com> Date: Thu, 19 Jun 2025 11:06:53 +0200 Subject: [PATCH 4/5] Introduce `xlvask_helper` base class and refactor XLVask helper classes to extend it. Add methods for XLVask vehicle checks and retrievals, enhance vehicle caching functionality, and update helper class instantiation logic. --- services/nginx/app/classes/xlvask.php | 13 ++++++- .../xlvask/helpers/xlvask_create_customer.php | 2 +- .../modules/xlvask/helpers/xlvask_guid.php | 2 +- .../modules/xlvask/helpers/xlvask_helper.php | 8 +++++ .../xlvask/helpers/xlvask_usage_log.php | 2 +- .../modules/xlvask/helpers/xlvask_vehicle.php | 2 +- .../xlvask/helpers/xlvask_vehicle_type.php | 2 +- .../xlvask/helpers/xlvask_vehicle_types.php | 2 +- .../xlvask/helpers/xlvask_vehicles.php | 12 +++++-- .../xlvask/helpers/xlvask_wash_item.php | 2 +- .../app/modules/xlvask/xlvask_helpers.php | 27 ++++++++++++++ .../nginx/app/objects/customer_vehicles_o.php | 35 +++++++++++++++++++ 12 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 services/nginx/app/modules/xlvask/helpers/xlvask_helper.php diff --git a/services/nginx/app/classes/xlvask.php b/services/nginx/app/classes/xlvask.php index dac73d30..3d9bff46 100644 --- a/services/nginx/app/classes/xlvask.php +++ b/services/nginx/app/classes/xlvask.php @@ -12,6 +12,7 @@ require_once WD . '/modules/xlvask/xlvask_helpers.php'; */ +use Exception; use helpers\xlvask_cache; use helpers\xlvask_guid; use helpers\xlvask_tasks; @@ -46,7 +47,7 @@ class xlvask extends xlvask_endpoints implements xlvask_i public function requireModuleEnabled(): void { if (!(bool)$this->config->enabled->getVariableValue()) { - throw new \Exception('xlvask module is not enabled'); + throw new Exception('xlvask module is not enabled'); } } @@ -76,4 +77,14 @@ class xlvask extends xlvask_endpoints implements xlvask_i { return new $this->helpers->xlvask_guid(); } + + /** + * Create a new instance of a helper class + * @param string $helper_class The class name of the helper to create + * @throws Exception If the helper class does not exist or is not a valid helper. + */ + public function new(string $helper_class): \helpers\xlvask_vehicle_types|\helpers\xlvask_usage_log|\helpers\xlvask_customer|xlvask_cache|xlvask_tasks|\helpers\xlvask_wash_item|\helpers\xlvask_create_customer|\helpers\xlvask_helper|\helpers\xlvask_vehicle_type|\helpers\xlvask_vehicle|\helpers\xlvask_vehicles|xlvask_guid + { + return $this->helpers->new($helper_class); + } } \ No newline at end of file diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_create_customer.php b/services/nginx/app/modules/xlvask/helpers/xlvask_create_customer.php index 71589a38..d606eb1b 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_create_customer.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_create_customer.php @@ -6,7 +6,7 @@ use classes\xlvask; use Exception; use objects\users_o; -class xlvask_create_customer +class xlvask_create_customer extends xlvask_helper { /** diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_guid.php b/services/nginx/app/modules/xlvask/helpers/xlvask_guid.php index 9b5a76d5..591a2ea3 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_guid.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_guid.php @@ -2,7 +2,7 @@ namespace helpers; -class xlvask_guid +class xlvask_guid extends xlvask_helper { /** * Generates a unique GUID for the XLVask system. diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_helper.php b/services/nginx/app/modules/xlvask/helpers/xlvask_helper.php new file mode 100644 index 00000000..e633737c --- /dev/null +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_helper.php @@ -0,0 +1,8 @@ +getCache(); + if ($xlvask_cache->isVehicleCached($registrationNumber)) { + //return $xlvask_cache->getVehicleCache($registrationNumber); + } else if ($onlyCache) { + return null; // Return null if onlyCache is true and vehicle is not cached + } $vehicles = self::getVehicles(['registrationNumber' => $registrationNumber]); foreach ( $vehicles as $vehicle ) { if ($vehicle->registrationNumber === $registrationNumber) { diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_wash_item.php b/services/nginx/app/modules/xlvask/helpers/xlvask_wash_item.php index 38e9073f..f4f02252 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_wash_item.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_wash_item.php @@ -6,7 +6,7 @@ use classes\slack; use Exception; use objects\products_o; -class xlvask_wash_item +class xlvask_wash_item extends xlvask_helper { /** * Example of a wash item object: diff --git a/services/nginx/app/modules/xlvask/xlvask_helpers.php b/services/nginx/app/modules/xlvask/xlvask_helpers.php index 0e0a68b7..e876dfd3 100644 --- a/services/nginx/app/modules/xlvask/xlvask_helpers.php +++ b/services/nginx/app/modules/xlvask/xlvask_helpers.php @@ -3,6 +3,7 @@ namespace xlvask; // Helpers +require_once WD . '/modules/xlvask/helpers/xlvask_helper.php'; require_once WD . '/modules/xlvask/helpers/xlvask_tasks.php'; require_once WD . '/modules/xlvask/helpers/xlvask_cache.php'; require_once WD . '/modules/xlvask/helpers/xlvask_customer.php'; @@ -53,6 +54,7 @@ use helpers\xlvask_cache; use helpers\xlvask_create_customer; use helpers\xlvask_customer; use helpers\xlvask_guid; +use helpers\xlvask_helper; use helpers\xlvask_tasks; use helpers\xlvask_usage_log; use helpers\xlvask_vehicle; @@ -118,4 +120,29 @@ class xlvask_helpers * @var string $xlvask_vehicles */ public string $xlvask_vehicles = xlvask_vehicles::class; + + /** + * Construct a new xlvask_helper instance. + * This method is used to create a new instance of the xlvask_helper class. + * It is used to initialize the helper classes that are required to be extended by the xlvask_helper class. + * @param string $class The class name of the helper to be instantiated. + * @note This is used to initialize the helper classes. Those require to be extended by the xlvask_helper class. + * @return xlvask_vehicle_types|xlvask_vehicle_type|xlvask_vehicle|xlvask_create_customer|xlvask_wash_item|xlvask_usage_log|xlvask_customer|xlvask_cache|xlvask_tasks|xlvask_guid|xlvask_vehicles|xlvask_helper + * @throws \Exception + * @example + * $xlvaskHelper = new xlvask_helpers(); + * $xlvaskHelper->new(xlvask_tasks::class); + */ + public function new(string $class): xlvask_vehicle_types|xlvask_vehicle_type|xlvask_vehicle|xlvask_create_customer|xlvask_wash_item|xlvask_usage_log|xlvask_customer|xlvask_cache|xlvask_tasks|xlvask_guid|xlvask_vehicles|xlvask_helper + { + if (class_exists($class)) { + // Check if the class is a subclass of xlvask_helper + if (!is_subclass_of($class, xlvask_helper::class)) { + throw new \Exception("Class $class must extend xlvask_helper."); + } + return new $class(); + } else { + throw new \Exception("Class $class does not exist."); + } + } } \ No newline at end of file diff --git a/services/nginx/app/objects/customer_vehicles_o.php b/services/nginx/app/objects/customer_vehicles_o.php index 75c90ef1..93e934b1 100644 --- a/services/nginx/app/objects/customer_vehicles_o.php +++ b/services/nginx/app/objects/customer_vehicles_o.php @@ -4,7 +4,10 @@ namespace objects; use classes\db; use classes\object_property; +use classes\xlvask; use Exception; +use helpers\xlvask_vehicle; +use helpers\xlvask_vehicles; use traits\db_object_t; class customer_vehicles_o extends db @@ -47,6 +50,7 @@ class customer_vehicles_o extends db ); $last_order_id = self::getLastOrderId(); $customer_number = (int)$this->customer_id->value(); + $xlvask = $this->hasXLVask() ? $this->getXLVask() : null; return [ 'id' => (int)$this->id, 'user_id' => (int)(new users_o())->getUserIdFromEconomic((int)$customer_number), @@ -63,6 +67,7 @@ class customer_vehicles_o extends db 'list' => $addons, ], 'last_order_id' => ($last_order_id ? (int)$last_order_id : null), + 'xlvask' => ($xlvask?->toArray()), ]; } @@ -125,6 +130,36 @@ class customer_vehicles_o extends db return null; } + /** + * Check if the vehicle has an XLVask object + * @return bool + * @throws Exception If the object is not selected + * @note This method checks if the vehicle is registered in the XLVask system. + */ + public function hasXLVask(): bool + { + self::requireSelected(); + $xlvask = new xlvask(); + $vehicles = new $xlvask->helpers->xlvask_vehicles(); + /** @var xlvask_vehicles $vehicles */ + return $vehicles->getVehicleByRegistrationNumber((string)$this->reg->value(), true) !== null; + + } + + /** + * Get the XLVask object for the vehicle + * @return xlvask_vehicle + * @throws Exception If the object is not selected + */ + public function getXLVask(): xlvask_vehicle + { + self::requireSelected(); + $xlvask = new xlvask(); + $vehicles = new $xlvask->helpers->xlvask_vehicles(); + /** @var xlvask_vehicles $vehicles */ + return $vehicles->getVehicleByRegistrationNumber((string)$this->reg->value()); + } + /** * Add the default addons to the vehicle * @return void From 29aa63bb08b26cf38d90a1fba165bcb46a8ba275 Mon Sep 17 00:00:00 2001 From: Jepp9350 <2jepp9350@gmail.com> Date: Thu, 19 Jun 2025 15:01:22 +0200 Subject: [PATCH 5/5] Add vehicle type handling in `customer_vehicles_o`, including vehicle type retrieval, setting, and creation in XLVask. Extend route logic to support vehicle type updates and auto-start on LPR configurations, incorporating enhanced validation and permission checks. Refactor and streamline helper classes for consistency and functionality expansion. --- .../modules/xlvask/helpers/xlvask_helper.php | 10 +- .../xlvask/helpers/xlvask_usage_log.php | 11 +- .../modules/xlvask/helpers/xlvask_vehicle.php | 6 +- .../xlvask/helpers/xlvask_wash_item.php | 11 +- .../nginx/app/objects/customer_vehicles_o.php | 138 ++++++++++++++ .../nginx/app/routes/moduleXLVaskRoute.php | 6 +- services/nginx/app/routes/vehiclesRoute.php | 175 +++++++++++++++++- 7 files changed, 328 insertions(+), 29 deletions(-) diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_helper.php b/services/nginx/app/modules/xlvask/helpers/xlvask_helper.php index e633737c..d3c64e12 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_helper.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_helper.php @@ -4,5 +4,13 @@ namespace helpers; abstract class xlvask_helper { - + /** + * Convert the helper object to an array representation. + * This method returns an associative array containing all properties of the object. + * @return array + */ + public function toArray(): array + { + return (array)$this; + } } \ No newline at end of file diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_usage_log.php b/services/nginx/app/modules/xlvask/helpers/xlvask_usage_log.php index aeeda2b5..e3a6489a 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_usage_log.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_usage_log.php @@ -362,16 +362,7 @@ class xlvask_usage_log extends xlvask_helper // Check if the parameter is empty or matches the default values return $param === null || $param === '' || $param === $this->default_string || $param === $this->default_int || $param === $this->default_bool || $param === $this->default_int_nullable || $param === $this->default_string_nullable || $param === $this->default_bool_nullable; } - - /** - * Convert the customer object to an array representation. - * This method returns an associative array containing all properties of the object. - * @return array - */ - public function toArray(): array - { - return (array)$this; - } + /** * Get the formatted date of the wash start time. diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_vehicle.php b/services/nginx/app/modules/xlvask/helpers/xlvask_vehicle.php index 9dcebd75..ce289695 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_vehicle.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_vehicle.php @@ -59,9 +59,5 @@ class xlvask_vehicle extends xlvask_helper * @var array */ public array $multilineVehicleServices; - - public function toArray(): array - { - return (array)$this; - } + } \ No newline at end of file diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_wash_item.php b/services/nginx/app/modules/xlvask/helpers/xlvask_wash_item.php index f4f02252..3d53e6af 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_wash_item.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_wash_item.php @@ -229,16 +229,7 @@ class xlvask_wash_item extends xlvask_helper // Check if the parameter is empty or matches the default values return $param === null || $param === '' || $param === $this->default_string || $param === $this->default_int || $param === $this->default_bool || $param === $this->default_int_nullable || $param === $this->default_string_nullable || $param === $this->default_bool_nullable; } - - /** - * Convert the customer object to an array representation. - * This method returns an associative array containing all properties of the object. - * @return array - */ - public function toArray(): array - { - return (array)$this; - } + /** * Get the product associated with this wash item. diff --git a/services/nginx/app/objects/customer_vehicles_o.php b/services/nginx/app/objects/customer_vehicles_o.php index 93e934b1..43ad9905 100644 --- a/services/nginx/app/objects/customer_vehicles_o.php +++ b/services/nginx/app/objects/customer_vehicles_o.php @@ -6,7 +6,9 @@ use classes\db; use classes\object_property; use classes\xlvask; use Exception; +use helpers\xlvask_customer; use helpers\xlvask_vehicle; +use helpers\xlvask_vehicle_type; use helpers\xlvask_vehicles; use traits\db_object_t; @@ -68,6 +70,9 @@ class customer_vehicles_o extends db ], 'last_order_id' => ($last_order_id ? (int)$last_order_id : null), 'xlvask' => ($xlvask?->toArray()), + 'vehicle_types' => array_map(function ($vehicle_type) { + return $vehicle_type->toArray(); + }, $this->getVehicleTypes()), ]; } @@ -160,6 +165,22 @@ class customer_vehicles_o extends db return $vehicles->getVehicleByRegistrationNumber((string)$this->reg->value()); } + /** + * Get the vehicle types applicable to the vehicle (Wash types) + * @return array{xlvask_vehicle_type} + * @note This method retrieves the vehicle types from the XLVask system that are applicable to the vehicle. + * @return array of xlvask_vehicle_type objects + * @throws Exception If the object is not selected or if there is an error retrieving the vehicle types + * @see xlvask_vehicle_type + */ + public function getVehicleTypes(): array + { + self::requireSelected(); + return (new xlvask())->helpers->xlvask_vehicle_types::getVehicleTypesByProductId( + (int)$this->type->value() + ); + } + /** * Add the default addons to the vehicle * @return void @@ -292,4 +313,121 @@ class customer_vehicles_o extends db return (new customer_vehicles_o())->select((int)$result[0]['id']); } + /** + * Set the vehicle type id for the vehicle in the XLVask system + * @param string $vehicleTypeId The vehicle type id to set in the XLVask system + * @note This method updates the vehicle type in the XLVask system for the vehicle. + * @throws Exception If the associated customer is not registered in the XLVask system + * @throws Exception If the vehicle is not registered in the XLVask system + * @throws Exception If the vehicle type id is not valid or if there is an error updating the vehicle type in the XLVask system + * @throws Exception If the object is not selected + * @see xlvask_vehicle + * @example + * $vehicle = new customer_vehicles_o(); + * $vehicle->select(1); // Select the vehicle with id 1 + * $vehicleTypeId = 'some-vehicle-type-id'; // The vehicle type id to set + * $vehicle->setVehicleTypeId($vehicleTypeId); + * @see xlvask_vehicle_type + */ + public function setVehicleTypeId(string $vehicleTypeId): void + { + self::requireSelected(); + $xlvask = new xlvask(); + // Check if the vehicle is registered in the XLVask system + if (!$this->hasXLVask()) { + // Create a new XLVask vehicle + throw new Exception('Vehicle is not registered in the XLVask system. Please register the vehicle first.'); + } + // Set the vehicle type id + $xlvask_vehicle = $this->getXLVask(); + $xlvask_vehicle->vehicleTypeId = $vehicleTypeId; + // Update the XLVask vehicle + $xlvask->updateVehicle($xlvask_vehicle); + // Cache the updated vehicle + $xlvask->getCache()->setVehicleCache($xlvask_vehicle->registrationNumber, $xlvask_vehicle); + } + + /** + * Create a new vehicle in the XLVask system + * * @param string $registrationNumber The registration number of the vehicle + * @param int $customerId The customer id of the vehicle + * @param string|null $vehicleTypeId The vehicle type id of the vehicle, if not provided, the default vehicle type will be used + * @return xlvask_vehicle The created XLVask vehicle object + * @throws Exception If the customer is not registered in the XLVask system + * @throws Exception If the vehicle is already registered in the XLVask system + * @throws Exception If the vehicle type id is not valid or if there is an error creating the vehicle in the XLVask system + * @throws Exception If the object is not selected + * @note This method creates a new vehicle in the XLVask system for the vehicle. + * @see xlvask_vehicle + * @see xlvask_vehicle_type + * @example + * $vehicle = new customer_vehicles_o(); + * $vehicle->select(1); // Select the vehicle with id 1 + * $vehicleTypeId = 'some-vehicle-type-id'; // The vehicle type id to set, if not provided, the default vehicle type will be used + * $vehicle->createXLVaskVehicle($vehicleTypeId); + */ + public function createXLVaskVehicle(string $vehicleTypeId): xlvask_vehicle + { + self::requireSelected(); + $xlvask = new xlvask(); + // Check if the customer is registered in the XLVask system + $xlvask_customer = $this->getXLVaskCustomer(); + // Make sure the vehicle type id is valid for this vehicle type + $valid_vehicle_types = $xlvask->helpers->xlvask_vehicle_types::getVehicleTypesByProductId( + (int)$this->type->value() + ); + if (!in_array($vehicleTypeId, array_map(fn($type) => $type->vehicleTypeId, $valid_vehicle_types))) { + throw new Exception('Invalid vehicle type id provided. Please provide a valid vehicle type id for this vehicle type.'); + } + // Create a new XLVask vehicle + $xlvask_vehicle = new xlvask_vehicle(); + $xlvask_vehicle->registrationNumber = (string)$this->reg->value(); + $xlvask_vehicle->customerId = $xlvask_customer->customerId; + $xlvask_vehicle->vehicleTypeId = $vehicleTypeId; + $xlvask_vehicle->active = true; // Set the vehicle as active + $xlvask_vehicle->autoStartOnLpr = true; // Enable auto start on LPR + // Add the vehicle to the XLVask system + $xlvask->createVehicle($xlvask_vehicle); + // Cache the vehicle + $vehicles = $xlvask->helpers->new($xlvask->helpers->xlvask_vehicles); + /** @var xlvask_vehicles $vehicles */ + $xlvask_vehicle = $vehicles::getVehicleByRegistrationNumber((string)$this->reg->value()); + $xlvask->getCache()->setVehicleCache($xlvask_vehicle->registrationNumber, $xlvask_vehicle); + return $xlvask_vehicle; + } + + /** + * Get the XLVask customer object for the vehicle + * @return xlvask_customer The XLVask customer object for the vehicle + * @throws Exception If the object is not selected + * @note This method retrieves the XLVask customer object for the vehicle. + */ + public function getXLVaskCustomer(): xlvask_customer + { + self::requireSelected(); + $customer_number = (int)$this->customer_id->value(); + $xlvask = new xlvask(); + if ($xlvask->getCache()->isCustomerCached($customer_number)) { + return $xlvask->getCache()->getCustomerCache($customer_number); + } + // If the customer is not cached, throw an exception + throw new Exception('Customer is not registered in the XLVask system. Please register the customer first.'); + } + + /** + * Set the auto start on LPR for the vehicle in the XLVask system + * @param bool $autoStartOnLpr Whether to enable auto start on LPR for the vehicle + * @throws Exception If the object is not selected + * @note This method updates the auto start on LPR setting for the vehicle in the XLVask system. + */ + public function setAutoStartOnLpr(bool $autoStartOnLpr): void + { + self::requireSelected(); + $xlvask_vehicle = $this->getXLVask(); + $xlvask_vehicle->autoStartOnLpr = $autoStartOnLpr; + $xlvask = new xlvask(); + $xlvask->updateVehicle($xlvask_vehicle); + // Cache the updated vehicle + $xlvask->getCache()->setVehicleCache($xlvask_vehicle->registrationNumber, $xlvask_vehicle); + } } \ No newline at end of file diff --git a/services/nginx/app/routes/moduleXLVaskRoute.php b/services/nginx/app/routes/moduleXLVaskRoute.php index 645c1c3b..050a963c 100644 --- a/services/nginx/app/routes/moduleXLVaskRoute.php +++ b/services/nginx/app/routes/moduleXLVaskRoute.php @@ -196,10 +196,12 @@ class moduleXLVaskRoute $xlvask = new xlvask(); $user = new users_o(); $user->getUserByCustomerNumber(12345679); - $result = $xlvask->getTasks()->runSyncVehicles(false); + //$result = $xlvask->getTasks()->runSyncVehicles(false); + $vehicles = $xlvask->new($xlvask->helpers->xlvask_vehicles); + //print_r($vehicles::getVehicleByRegistrationNumber('BW93159')); // Response $response->success( - $result, + 'Debugging xlvask tasks', 200 ); }, diff --git a/services/nginx/app/routes/vehiclesRoute.php b/services/nginx/app/routes/vehiclesRoute.php index 79689d3b..432f300d 100644 --- a/services/nginx/app/routes/vehiclesRoute.php +++ b/services/nginx/app/routes/vehiclesRoute.php @@ -27,6 +27,37 @@ class vehiclesRoute if ($user) { // Log the incident (new logs_o())->add('vehicles', 'global', 1, $user->id, 'LIST_OWN_VEHICLES', 'Successfully listed own vehicles'); + // Check if the id parameter is set + if ($this->isParametersSet(['id'])) { + // Get the id parameter + $id = (int)$this->getParameter('id'); + $this->requireType($id, self::type_int()); + $this->requireMinValue($id, 1); + $this->requireMaxValue($id, 9999999999); + // Get the vehicle object + $vehicle = (new customer_vehicles_o())->select($id); + // Check if the vehicle exists + if (!$vehicle->exists()) { + // Log the incident + (new logs_o())->add('vehicles', 'global', 1, $user->id, 'LIST_OWN_VEHICLES', 'Vehicle not found'); + // Return an error + $response->error('Vehicle not found', 404); + } + // Check if the user is allowed to list the vehicle + if ((int)$vehicle->customer_id->value() !== (int)$user->customer_number->value()) { + // Check if the user has permission to list other users vehicles + if (!$user->hasPermission('list_vehicles_other')) { + // Log the incident + (new logs_o())->add('vehicles', 'global', 1, $user->id, 'LIST_OWN_VEHICLES', 'User tried to list a vehicle from another user'); + // Return an error + $response->error('You are not allowed to list vehicles from other users', 403); + } + } + // Return the vehicle as an array + $response->success( + [...$vehicle->asArray()] + ); + } // Return the list of the user's vehicles $vehicles_o = new customer_vehicles_o(); // Check if the user is allowed to list other user's vehicles @@ -212,7 +243,7 @@ class vehiclesRoute $response->error('Vehicle not found', 404); } // Check if the user is allowed to edit the vehicle - if ($vehicle->customer_id->value() !== (int)$user->customer_number->value()) { + if ((int)$vehicle->customer_id->value() !== (int)$user->customer_number->value()) { // Check if the user has permission to edit other users vehicles if (!$user->hasPermission('edit_vehicle_other')) { // Log the incident @@ -418,6 +449,148 @@ class vehiclesRoute ] ); + $this->post('/vehicles/set-auto-start-on-lpr', function () { + // Require the user to be logged in + global $response; + $this->requirePermission('set_auto_start_on_lpr'); + // Get the user object + $user = (new authentication())->get_user(); + // Check if the request was successful + if ($user) { + // Log the incident + (new logs_o())->add('vehicles', 'global', 1, $user->id, 'SET_AUTO_START_ON_LPR', 'User set auto start on LPR'); + // Get the request data + self::requireParameters([ + 'id', + 'active', + ]); + $id = (int)self::getParameter('id'); + self::requireType($id, self::type_int()); + self::requireMinValue($id, 1); + self::requireMaxValue($id, 9999999999); + // Validate the autoStartOnLpr (active) parameter + $autoStartOnLpr = (bool)self::getParameter('active'); + self::requireType($autoStartOnLpr, self::type_bool()); + // Get the vehicle object + $vehicle = (new customer_vehicles_o())->select($id); + // Check if the vehicle exists + if (!$vehicle->exists()) { + // Log the incident + (new logs_o())->add('vehicles', 'global', 1, $user->id, 'SET_AUTO_START_ON_LPR', 'Vehicle not found'); + // Return an error + $response->error('Vehicle not found', 404); + } + // Check if the user is allowed to edit the vehicle + if ((int)$vehicle->customer_id->value() !== (int)$user->customer_number->value()) { + // Check if the user has permission to edit other users vehicles + if (!$user->hasPermission('edit_vehicle_other')) { + // Log the incident + (new logs_o())->add('vehicles', 'global', 1, $user->id, 'SET_AUTO_START_ON_LPR', 'User tried to set auto start on LPR from another user'); + // Return an error + $response->error('You are not allowed to edit vehicles from other users', 403); + } + } + // Set the auto start on LPR + $vehicle->setAutoStartOnLpr( + $autoStartOnLpr + ); + // Return the vehicle as an array + $response->success( + [...$vehicle->asArray()] + ); + } else { + // Log the incident + (new logs_o())->add('vehicles', 'global', 1, 0, 'SET_AUTO_START_ON_LPR', 'No user found, or invalid session'); + // Return an error + $response->error('Invalid session', 401); + } + }, + [ + 'set_auto_start_on_lpr' => 'Set auto start on LPR', + 'set_auto_start_on_lpr_other' => 'Set auto start on LPR for another user\'s vehicle', + ] + ); + + $this->post('/vehicles/set-vehicle-type-id', function () { + // Require the user to be logged in + global $response; + $this->requirePermission('set_vehicle_type_id'); + // Get the user object + $user = (new authentication())->get_user(); + // Check if the request was successful + if ($user) { + // Log the incident + (new logs_o())->add('vehicles', 'global', 1, $user->id, 'SET_VEHICLE_TYPE_ID', 'User set vehicle type ID'); + // Get the request data + self::requireParameters([ + 'id', + 'vehicleTypeId', + ]); + $id = (int)self::getParameter('id'); + self::requireType($id, self::type_int()); + self::requireMinValue($id, 1); + self::requireMaxValue($id, 9999999999); + // Validate the vehicleTypeId + $vehicleTypeId = (string)self::getParameter('vehicleTypeId'); + self::requireType($vehicleTypeId, self::type_string()); + self::requireMinLength('vehicleTypeId', 1); + self::requireMaxLength('vehicleTypeId', 50); + // Get the vehicle object + $vehicle = (new customer_vehicles_o())->select($id); + // Check if the vehicle exists + if (!$vehicle->exists()) { + // Log the incident + (new logs_o())->add('vehicles', 'global', 1, $user->id, 'SET_VEHICLE_TYPE_ID', 'Vehicle not found'); + // Return an error + $response->error('Vehicle not found', 404); + } + // Check if the user is allowed to edit the vehicle + if ((int)$vehicle->customer_id->value() !== (int)$user->customer_number->value()) { + // Check if the user has permission to edit other users vehicles + if (!$user->hasPermission('edit_vehicle_other')) { + // Log the incident + (new logs_o())->add('vehicles', 'global', 1, $user->id, 'SET_VEHICLE_TYPE_ID', 'User tried to set vehicle type ID from another user'); + // Return an error + $response->error('You are not allowed to edit vehicles from other users', 403); + } + } + // Get the customer object + $customer = (new users_o())->getUserByCustomerNumber((int)$vehicle->customer_id->value()); + // Check if the vehicle is registered in the XL Vask system + if (!$vehicle->hasXLVask()) { + // Check if the customer has an XL Vask customer account + if (!$customer->hasXLVaskCustomerAccount()) { + // Log the incident + (new logs_o())->add('vehicles', 'global', 1, $user->id, 'SET_VEHICLE_TYPE_ID', 'User tried to set vehicle type ID on a vehicle that is not registered in the XL Vask system, without a customer account'); + // Return an error + $response->error('Vehicle is not registered in the XL Vask system', 400); + } else { + $vehicle->createXLVaskVehicle($vehicleTypeId); + } + } else { + // Set the vehicle type ID + $vehicle->setVehicleTypeId( + $vehicleTypeId + ); + } + // Return the vehicle as an array + $response->success( + [...$vehicle->asArray()] + ); + } else { + // Log the incident + (new logs_o())->add('vehicles', 'global', 1, 0, 'SET_VEHICLE_TYPE_ID', 'No user found, or invalid session'); + // Return an error + $response->error('Invalid session', 401); + } + }, + [ + 'set_vehicle_type_id' => 'Set vehicle type ID', + 'set_vehicle_type_id_other' => 'Set vehicle type ID for another user\'s vehicle', + ] + ); + + $this->get('/superuser/users-with-vehicle-subscriptions', function () { // Require the user to be logged in global $response;