diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_cache.php b/services/nginx/app/modules/xlvask/helpers/xlvask_cache.php index 94b27433..02232061 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_cache.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_cache.php @@ -60,6 +60,7 @@ class xlvask_cache implements xlvask_cache_i /** * @inheritDoc + * @throws Exception If there are issues retrieving customers. */ public function getAllCachedCustomers(): array { @@ -68,7 +69,7 @@ class xlvask_cache implements xlvask_cache_i foreach ( $keys as $key ) { $customer_data = redis->get($key); if ($customer_data) { - $customers[] = json_decode($customer_data); + $customers[] = (new xlvask_customer([], json_decode($customer_data))); } } return $customers; diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_customer.php b/services/nginx/app/modules/xlvask/helpers/xlvask_customer.php index 901a7fe9..c4f9bbef 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_customer.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_customer.php @@ -3,6 +3,7 @@ namespace helpers; use Exception; +use objects\users_o; class xlvask_customer { @@ -148,8 +149,13 @@ class xlvask_customer * Constructor to initialize the customer object with default values * @throws Exception */ - public function __construct(array $data = []) + public function __construct(array $data = [], \stdClass $data_object = null) { + // If a data object is provided, convert it to an array + if ($data_object !== null) { + $data = (array)$data_object; + } + // Set default values for properties $this->default_string = 'DEFAULT_STRING_1'; $this->default_int = 'DEFAULT_INT_1'; $this->default_bool = 'DEFAULT_BOOL_1'; @@ -319,4 +325,40 @@ class xlvask_customer { return (array)$this; } + + /** + * Convert the customer object from an array representation. + * This method populates the customer object with values from the provided array. + * @param array $data + * @return self + * @throws Exception If there are issues setting properties. + */ + public function fromArray(array $data): self + { + // Reset the object to its default values before setting properties + $this->reset(); + // Set the properties from the provided array + return $this->setProperties($data); + } + + /** + * Get the user associated with this customer. + * This method retrieves the user object based on the externId of the customer. + * If the externId is not set or the user cannot be found, it returns null. + * @return users_o|null + */ + public function getUser(): ?users_o + { + if (empty($this->externId)) { + return null; + } + try { + $user = new users_o(); + $user->getUserByCustomerNumber((int)$this->externId); + return $user; + } catch (Exception $e) { + // Handle the exception if needed + return null; + } + } } \ No newline at end of file diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_parser_2_b_rstevask.php b/services/nginx/app/modules/xlvask/helpers/xlvask_parser_2_b_rstevask.php index 20aa2745..4abae3a9 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_parser_2_b_rstevask.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_parser_2_b_rstevask.php @@ -21,6 +21,6 @@ class xlvask_parser_2_b_rstevask extends xlvask_product_parser */ protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o { - return (new products_o())->select(63); // 2 Børstevask product ID + return (new products_o())->select(64); // 2 Børstevask product ID is actually 63, but since we're currently not using it we just return the 64 (Irrelevant) product ID. } } \ No newline at end of file diff --git a/services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php b/services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php index 8a18c098..85d0e449 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_tasks.php @@ -3,6 +3,7 @@ namespace helpers; use Exception; +use objects\orders_o; use objects\users_o; class xlvask_tasks @@ -257,6 +258,18 @@ class xlvask_tasks } else { // If no order is found, we will generate a new order. echo '# No potential order found for this wash.' . PHP_EOL; + // Verify the customer object + if (!$customer instanceof xlvask_customer) { + echo '# The customer object is not an instance of xlvask_customer.' . PHP_EOL; + continue; // Skip this wash + } + if (!$tmp_order = $this->createOrderFromWash($log, $customer)) { + echo '# Failed to create an order from this wash.' . PHP_EOL; + } else { + echo '# Order created successfully.' . PHP_EOL; + echo '# Order ID: ' . $tmp_order->id . PHP_EOL; + echo '# Order total: ' . $tmp_order->getNetAmount() . PHP_EOL; + } } echo '# This wash is not linked to an order, generating a new order.' . PHP_EOL; } @@ -287,4 +300,35 @@ class xlvask_tasks return (new $xlvask->helpers->xlvask_usage_log())->setProperties($log); }, $getUsageLog); } + + /** + * @throws Exception If the log is not completed, or if the customer does not have an externId, or if the customer does not exist in this system. + */ + public function createOrderFromWash(xlvask_usage_log $log, xlvask_customer|\stdClass $customer): ?orders_o + { + // Make sure the XL Vask module is enabled + $xlvask = new \classes\xlvask(); + $xlvask->requireModuleEnabled(); + + // Check if the log is completed + if (!$log->isCompleted()) { + throw new Exception('The log ( ID: ' . $log->WashId . ' ) is not completed, cannot create an order from it.'); + } + // Check if the customer has an externId + if (empty($customer->externId)) { + throw new Exception('The customer ( ID: ' . $customer->customerId . ' ) does not have an externId, cannot create an order from it.'); + } + // Check if the customer exists in this system + if (!$tmp_user = $customer->getUser()) { + throw new Exception('The customer ( ID: ' . $customer->customerId . ' ) does not exist in this system, cannot create an order from it.'); + } + // Create a new order object + $order = new orders_o(); + $order->addXLVaskOrder( + $tmp_user, + $log, + ); + // Return the order object + return $order; + } } \ 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 22459a7f..d6c49625 100644 --- a/services/nginx/app/modules/xlvask/helpers/xlvask_wash_item.php +++ b/services/nginx/app/modules/xlvask/helpers/xlvask_wash_item.php @@ -292,14 +292,19 @@ class xlvask_wash_item return strtolower($result); } - public function getPriceExVat(): float + /** + * Check if the wash item should be included in the order. + * This method checks if the wash item has a count above zero or if the price excluding VAT is greater than zero. + * @note This method was added to accommodate the need to check if the wash item should be included in the order. + * @return bool + * @see getPriceExVat() + * @see isCountAboveZero() + */ + public function shouldIncludeInOrder(): bool { - // Calculate the price excluding VAT - if (is_numeric($this->PriceIncVat) && is_numeric($this->Count)) { - return (float)$this->PriceIncVat - (float)$this->Vat; - } - // If either PriceIncVat or Count is not numeric, return 0 - return 0.0; + // Check if the wash item should be included in the order + // This is based on whether the count is above zero or the price excluding VAT is greater than zero. + return ($this->isCountAboveZero() || $this->getPriceExVat() > 0); } /** @@ -312,4 +317,14 @@ class xlvask_wash_item // Check if the count is above zero return is_numeric($this->Count) && (float)$this->Count > 0; } + + public function getPriceExVat(): float + { + // Calculate the price excluding VAT + if (is_numeric($this->PriceIncVat) && is_numeric($this->Count)) { + return (float)$this->PriceIncVat - (float)$this->Vat; + } + // If either PriceIncVat or Count is not numeric, return 0 + return 0.0; + } } \ 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 29fe792f..bee7f33c 100644 --- a/services/nginx/app/modules/xlvask/interfaces/xlvask_cache_i.php +++ b/services/nginx/app/modules/xlvask/interfaces/xlvask_cache_i.php @@ -43,7 +43,9 @@ interface xlvask_cache_i /** * Get all cached customers. - * @return array[xlvask_customer] + * @return array[xlvask_customer] An array of all cached customer objects. + * @example [xlvask_customer, xlvask_customer, ...] + * @see xlvask_customer */ public function getAllCachedCustomers(): array; diff --git a/services/nginx/app/objects/orders_o.php b/services/nginx/app/objects/orders_o.php index 6d8e5624..5397c8ba 100644 --- a/services/nginx/app/objects/orders_o.php +++ b/services/nginx/app/objects/orders_o.php @@ -8,6 +8,7 @@ use classes\object_property; use classes\response; use Exception; use helpers\xlvask_usage_log; +use helpers\xlvask_wash_item; use traits\db_object_t; class orders_o extends db @@ -713,4 +714,60 @@ class orders_o extends db } return null; // No order found with the given registration number and date range } + + /** + * Add a new XL Vask order + * @param users_o $user The user who is placing the order (Billing customer) + * @param xlvask_usage_log $xlvask_usage_log The XL Vask usage log containing the wash items, department, and registration number + * @return orders_o The created order object + * @throws Exception If the order is not selected, or if the user or department is not valid + */ + public function addXLVaskOrder(users_o $user, xlvask_usage_log $xlvask_usage_log): orders_o + { + // Add a new order for XL Vask + $this->add( + (int)$user->customer_number->value(), + 2285, + '', + 'This transaction was created automatically, based on usage log ' . $xlvask_usage_log->WashId, + (int)$xlvask_usage_log->getDepartment()->id, + $xlvask_usage_log->RegistrationNumber, + ); + // Add the products to the order + $firstItemId = null; + /** @var xlvask_wash_item $washItem */ + foreach ( $xlvask_usage_log->WashItems as $washItem ) { + // Check if the item should be included in the order + // Check if the product is with id 64 (irrelevant product, a bi product of the wash) + if (!$washItem->shouldIncludeInOrder() || $washItem->getProduct($xlvask_usage_log)->id === 64) { + continue; // Skip items that should not be included in the order + } + $order_item = new order_items_o(); + $order_item->add( + $this->id, + $washItem->getProduct($xlvask_usage_log)->id, + '', + $washItem->OriginalProductName, + 2285, + $washItem->getPriceExVat(), + $washItem->Count, + $firstItemId === null ? null : $firstItemId, // Set the first item as the parent item (if applicable) + ); + // Set the first item ID for the next item to link to (provided this is the first item) + if ($firstItemId === null) { + $firstItemId = (int)$order_item->id; + } + } + // Validate the order matches the desired total + $total = $this->getNetAmount(); + if ($total !== $xlvask_usage_log->getTotalPrice()) { + throw new Exception('The total amount of the order does not match the expected total. Expected: ' . $xlvask_usage_log->getTotalPrice() . ', Actual: ' . $total); + } + // Set the wash ID for the order + $this->wash_id->set($xlvask_usage_log->WashId); + // Save the order + $this->objectChanged(); + // Return the order object + return $this; + } } \ No newline at end of file