Add multiple XLVask parsers, extend department and order selection logic, and add usage synchronization endpoint
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_2_b_rstevask extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('2_b_rstevask');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_3_b_rstevask extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('3_b_rstevask');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
return (new products_o())->select(64); // Irrelevant product ID
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_eu_spejl extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('EU spejl');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
return (new products_o())->select(64); // Other irrelevant product ID
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_halleje extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('Halleje');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
return (new products_o())->select(62); // Halleje product ID
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_ht_chassis extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('HT chassis');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
return (new products_o())->select(64); // Irrelevant product ID
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_ht_osc_sider_verst extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('ht_osc_sider_verst');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
return (new products_o())->select(64); // Irrelevant product ID
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_ht_sider extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('HT sider');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
return (new products_o())->select(64); // Other irrelevant product ID
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_ikke_ht_dysebom_bag extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('Ikke HT dysebom bag');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
return (new products_o())->select(64); // Other irrelevant product ID
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_ikke_ht_dysebom_p_front extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('Ikke HT dysebom p\u00e5 front');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
return (new products_o())->select(64); // Other irrelevant product ID
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_lift extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('lift');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
return (new products_o())->select(64); // Irrelevant product ID for lift
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_s_be_dysebom extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('s_be_dysebom');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
return (new products_o())->select(64); // Other irrelevant product ID
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\product_options_o;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_skylning_med_ro extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('Skylning med RO'); // This is the name of Spot free product(s)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
// This parser is used for the "Skylning med RO" product, which is a spot-free rinse.
|
||||
// There are two different products that can be used for this, depending on the vehicle type.
|
||||
// Spot Free- Varevogn (23)
|
||||
// Spot Free- Lastbil (24)
|
||||
// This means that we need to check the vehicle type and return the appropriate product.
|
||||
$primary_product = $xlvask_usage_log->getPrimaryItem()->getProduct($xlvask_usage_log);
|
||||
$primary_product_id = $primary_product->id;
|
||||
// Get the available addons for the primary product
|
||||
$product_options = new product_options_o();
|
||||
if ($product_options->isOptionAllowedOnType(23, $primary_product_id)) {
|
||||
// If the primary product is a varevogn (van), return the Spot Free- Varevogn product
|
||||
return (new products_o())->select(23); // Spot Free- Varevogn product ID
|
||||
} elseif ($product_options->isOptionAllowedOnType(24, $primary_product_id)) {
|
||||
// If the primary product is a lastbil (truck), return the Spot Free- Lastbil product
|
||||
return (new products_o())->select(24); // Spot Free- Lastbil product ID
|
||||
}
|
||||
// Throw an exception if the vehicle type is not supported
|
||||
throw new Exception('Unsupported vehicle type for Skylning med RO product.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_stor_bil extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('Stor bil');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
//echo 'Attempting to parse Stor Bil product: ' . $this->OriginalProductName . PHP_EOL;
|
||||
//echo ' Step 1: Validating wash item and usage log.' . PHP_EOL;
|
||||
$registrationNumber = $xlvask_usage_log->RegistrationNumber;
|
||||
$vehicleType = $xlvask_usage_log->VehicleType; // E.g. "Bus/autocamper, M"
|
||||
/**
|
||||
* All the vehicle types that this parser supports.
|
||||
* Copied from XL Vask's vehicle types @ 10:32 10/06/2025
|
||||
* **
|
||||
* Anlægsmaskine
|
||||
* Bus/autocamper, L
|
||||
* Bus/autocamper, M
|
||||
* Bus/autocamper, S
|
||||
* Containerbil
|
||||
* Containerbil med hænger
|
||||
* Containertræk
|
||||
* Entreprenør forvogn/trækker
|
||||
* Entreprenør sættevogn
|
||||
* Forvogn med hænger
|
||||
* Forvogn med hænger, autotransport
|
||||
* Forvogn med krogehejs
|
||||
* Forvogn, L
|
||||
* Forvogn, lave sider
|
||||
* Forvogn, M
|
||||
* Forvogn, S
|
||||
* Forvogn, skraldebil
|
||||
* Kassevogn/Varevogn, L
|
||||
* Kassevogn/Varevogn, S
|
||||
* Kun trailer
|
||||
* Landbrugstraktor
|
||||
* Minibus
|
||||
* Personbil
|
||||
* Pickup
|
||||
* Sættevognstræk
|
||||
* Sættevognstræk, maskintrailer
|
||||
* Tankvogn
|
||||
* Tankvogn, Slamsuger
|
||||
* Tankvognstræk
|
||||
* Tankvognstræk, silobil
|
||||
* Trækker
|
||||
* Tømmerbil
|
||||
*/
|
||||
|
||||
$vehicleTypes = [
|
||||
// Formats for vehicle types
|
||||
// 'exact match' => ['Vehicle Type 1', 'Vehicle Type 2'], - Matches when the vehicle type is exactly one of these.
|
||||
// 'contains' => ['Vehicle Type 3', 'Vehicle Type 4'], - Matches when the vehicle type contains any of these substrings.
|
||||
// 'matchFunction' => function($vehicleType) { return true; } - Matches when the vehicle type passes this function.
|
||||
// product_id => ['exact match' => ['Vehicle Type 1', 'Vehicle Type 2'], 'contains' => ['Vehicle Type 3', 'Vehicle Type 4'], 'matchFunction' => function]
|
||||
// Trækker (1)
|
||||
1 => [
|
||||
'exact match' => ['Trækker'],
|
||||
'contains' => ['Trækker'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Trækker$/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Trailer (2)
|
||||
2 => [
|
||||
'exact match' => ['Kun trailer'],
|
||||
'contains' => ['Trailer'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Kun trailer$/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Sættevognstræk (3)
|
||||
3 => [
|
||||
'exact match' => ['Sættevognstræk'],
|
||||
'contains' => ['Sættevognstræk'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Sættevognstræk$/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Dolly (4)
|
||||
4 => [
|
||||
'exact match' => ['Dolly'],
|
||||
'contains' => ['Dolly'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Dolly$/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Forvogn (5)
|
||||
5 => [
|
||||
'exact match' => ['Forvogn, L', 'Forvogn, M', 'Forvogn, S', 'Forvogn, lave sider', 'Forvogn med krogehejs', 'Forvogn, skraldebil'],
|
||||
'contains' => ['Forvogn'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Forvogn/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Forvogn med hænger (6)
|
||||
6 => [
|
||||
'exact match' => ['Forvogn med hænger', 'Forvogn med hænger, autotransport'],
|
||||
'contains' => ['Forvogn med hænger'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Forvogn med hænger/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Tankvogn (7)
|
||||
7 => [
|
||||
'exact match' => ['Tankvogn', 'Tankvogn, Slamsuger'],
|
||||
'contains' => ['Tankvogn'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Tankvogn/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Tankvogn med hænger (8)
|
||||
8 => [
|
||||
'exact match' => ['Tankvognstræk', 'Tankvognstræk, silobil'],
|
||||
'contains' => ['Tankvognstræk'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Tankvognstræk/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Tankvognstræk (9)
|
||||
9 => [
|
||||
'exact match' => ['Tankvognstræk', 'Tankvognstræk, silobil'],
|
||||
'contains' => ['Tankvognstræk'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Tankvognstræk/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Kassevogn/Varevogn (15)
|
||||
15 => [
|
||||
'exact match' => ['Kassevogn/Varevogn, L', 'Kassevogn/Varevogn, S'],
|
||||
'contains' => ['Kassevogn', 'Varevogn'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Kassevogn\/Varevogn/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Campingvogn/Autocamper (16)
|
||||
16 => [
|
||||
'exact match' => ['Bus/autocamper, L', 'Bus/autocamper, M', 'Bus/autocamper, S'],
|
||||
'contains' => ['Bus', 'Autocamper'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Bus\/autocamper/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Bus (17)
|
||||
17 => [
|
||||
'exact match' => ['Bus/autocamper, L', 'Bus/autocamper, M', 'Bus/autocamper, S'],
|
||||
'contains' => ['Bus'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Bus\/autocamper/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Entreprenør forvogn (18)
|
||||
18 => [
|
||||
'exact match' => ['Entreprenør forvogn/trækker'],
|
||||
'contains' => ['Entreprenør forvogn', 'Trækker'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Entreprenør forvogn/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Entreprenør forvogn med kærre (19)
|
||||
19 => [
|
||||
'exact match' => ['Entreprenør sættevogn'],
|
||||
'contains' => ['Entreprenør sættevogn'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Entreprenør sættevogn$/', $vehicleType);
|
||||
}
|
||||
],
|
||||
// Entreprenør sættevogn (20)
|
||||
20 => [
|
||||
'exact match' => ['Entreprenør sættevogn'],
|
||||
'contains' => ['Entreprenør sættevogn'],
|
||||
'matchFunction' => function ($vehicleType) {
|
||||
return preg_match('/^Entreprenør sættevogn$/', $vehicleType);
|
||||
}
|
||||
],
|
||||
];
|
||||
|
||||
// Check if the vehicle type matches any of the defined vehicle types
|
||||
$isValidVehicleType = false;
|
||||
$productId = null; // Initialize product_id to null
|
||||
foreach ( $vehicleTypes as $product_id => $conditions ) {
|
||||
if (in_array($vehicleType, $conditions['exact match'], true)) {
|
||||
$isValidVehicleType = true;
|
||||
$productId = $product_id; // Set the product_id if an exact match is found
|
||||
break;
|
||||
}
|
||||
foreach ( $conditions['contains'] as $substring ) {
|
||||
if (strpos($vehicleType, $substring) !== false) {
|
||||
$isValidVehicleType = true;
|
||||
$productId = $product_id; // Set the product_id if a substring match is found
|
||||
break 2; // Break out of both loops
|
||||
}
|
||||
}
|
||||
if (isset($conditions['matchFunction']) && is_callable($conditions['matchFunction']) && $conditions['matchFunction']($vehicleType)) {
|
||||
$isValidVehicleType = true;
|
||||
$productId = $product_id; // Set the product_id if the match function returns true
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$isValidVehicleType) {
|
||||
//echo 'Step 2: Vehicle type does not match any of the defined vehicle types.' . PHP_EOL;
|
||||
throw new \Exception('Vehicle type does not match any of the defined vehicle types.');
|
||||
}
|
||||
//echo ' Found matching vehicle type: ' . $vehicleType . PHP_EOL;
|
||||
//echo ' Step 3: Vehicle type is valid, proceeding with product creation.' . PHP_EOL;
|
||||
|
||||
|
||||
// Check if the vehicle
|
||||
//print_r($xlvask_usage_log);
|
||||
|
||||
// Create a new product object
|
||||
return (new products_o())->select((int)$productId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\product_options_o;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_undervognskylning extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('Undervognskylning'); // This is the name of Spot free product(s)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
// This means that we need to check the vehicle type and return the appropriate product.
|
||||
$primary_product = $xlvask_usage_log->getPrimaryItem()->getProduct($xlvask_usage_log);
|
||||
$primary_product_id = $primary_product->id;
|
||||
// Get the available addons for the primary product
|
||||
$product_options = new product_options_o();
|
||||
if ($product_options->isOptionAllowedOnType(21, $primary_product_id)) {
|
||||
return (new products_o())->select(21); // Undervognskylning product ID
|
||||
}
|
||||
// Throw an exception if the vehicle type is not supported
|
||||
throw new Exception('Unsupported vehicle type for Undervognskylning');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
|
||||
abstract class xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
/**
|
||||
* The setup method initializes the Original Product Name.
|
||||
* This is required for the parser to function correctly.
|
||||
* @throws Exception If the Original Product Name is empty or null.
|
||||
*/
|
||||
public function setup(string $OriginalProductName): void
|
||||
{
|
||||
if (empty($OriginalProductName)) {
|
||||
throw new Exception('The Original Product Name cannot be empty or null. Please provide a valid product name.');
|
||||
}
|
||||
$this->OriginalProductName = $OriginalProductName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
trait xlvask_product_parser_t
|
||||
{
|
||||
protected string $OriginalProductName;
|
||||
|
||||
|
||||
/**
|
||||
* Parse the Original Product Name to a product object.
|
||||
* @param xlvask_wash_item $wash_item
|
||||
* @param xlvask_usage_log $xlvask_usage_log
|
||||
* @return products_o
|
||||
* @throws Exception If the product cannot be parsed.
|
||||
*/
|
||||
public function parseProduct(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
// Make sure the Original Product Name is set
|
||||
if (empty($this->OriginalProductName)) {
|
||||
throw new Exception('The Original Product Name is not set. Please provide a valid product name.');
|
||||
}
|
||||
// Make sure this is the correct parser
|
||||
//if ($this->OriginalProductName !== $wash_item->OriginalProductName) {
|
||||
// throw new Exception('The Original Product Name does not match the parser\'s Original Product Name. Expected: ' . $this->OriginalProductName . ', got: ' . $wash_item->OriginalProductName);
|
||||
//}
|
||||
// All checks passed, parse the product
|
||||
return $this->parse(...func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual parsing logic.
|
||||
* This method should be implemented in the class that uses this trait.
|
||||
* @param xlvask_wash_item $wash_item
|
||||
* @param xlvask_usage_log $xlvask_usage_log
|
||||
* @return products_o
|
||||
*/
|
||||
abstract protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o;
|
||||
|
||||
|
||||
}
|
||||
@@ -163,4 +163,107 @@ class xlvask_tasks
|
||||
}
|
||||
return $with_external_id; // Return the synchronized customers
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the sync usage task
|
||||
* This task is used to synchronize the usage of the XL Vask module.
|
||||
* It fetches the usage data from XL Vask and adds it to the applicable users.
|
||||
* The time format XL vask uses is "2025-05-01T00:00:00.000" - this is the ISO 8601 format.
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function runSyncUsage(): array|null
|
||||
{
|
||||
// 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()) {
|
||||
throw new Exception('XL Vask synchronization is not enabled.');
|
||||
}
|
||||
// Set the date from which to fetch the usage data
|
||||
// Since this is a cron task, we will fetch the usage data from the last 24 hours
|
||||
$minutes = 24 * 60; // 24 hours in minutes
|
||||
$dateFrom = date('Y-m-d\TH:i:s.000', strtotime('-' . $minutes . ' minutes'));
|
||||
echo $dateFrom;
|
||||
|
||||
|
||||
// If there are no customers, get them. TODO: Remove this in production, this is just for testing
|
||||
$xlvask->getTasks()->runSyncUsers(true);
|
||||
|
||||
// Get the cached customers
|
||||
$customers = $xlvask->getCache()->getAllCachedCustomers();
|
||||
|
||||
// Loop through the customers and check if there's any new usage data
|
||||
foreach ( $customers as $customer ) {
|
||||
/** @var xlvask_customer $customer */
|
||||
// Check if the customer has an externId
|
||||
if (empty($customer->externId)) {
|
||||
continue; // Skip customers without an externId
|
||||
}
|
||||
echo 'Checking customer: ' . $customer->name . ' (' . $customer->externId . ')' . PHP_EOL;
|
||||
$tmp_usage_logs = self::formatUsageLogs($xlvask->getUsageLog(
|
||||
$dateFrom,
|
||||
null, // regNr
|
||||
null, // vehicleId
|
||||
$customer->customerId // customerId
|
||||
));
|
||||
foreach ( $tmp_usage_logs as $log ) {
|
||||
/** @var xlvask_usage_log $log */
|
||||
// Check if the wash was completed
|
||||
if (!$log->isCompleted()) {
|
||||
echo 'A log is not completed: ' . $log->getFormattedDate() . ' - ' . $log->CustomerId . ' - ' . $log->VehicleId . PHP_EOL;
|
||||
continue; // Skip logs that are not completed
|
||||
}
|
||||
echo PHP_EOL;
|
||||
echo '### ' . $log->getFormattedDate() . ' - ' . $customer->name . ' (' . $customer->externId . ') - ' . $log->getTotalPrice() . PHP_EOL;
|
||||
echo '# License Plate: ' . $log->RegistrationNumber . PHP_EOL;
|
||||
echo '# Vehicle ID: ' . $log->VehicleId . PHP_EOL;
|
||||
echo '# Wash ID: ' . $log->WashId . PHP_EOL;
|
||||
echo '# Hall: ' . $log->Hall . PHP_EOL;
|
||||
echo '# Hall ID: ' . $log->HallId . PHP_EOL;
|
||||
echo '# Department: ' . $log->getDepartment()->id . PHP_EOL;
|
||||
echo '# Track / Lane: ' . $log->getLane() . PHP_EOL;
|
||||
echo '# Linked to order: ' . ($log->isLinkedToOrder() ? 'Yes' : 'No') . PHP_EOL;
|
||||
echo '# Items: ' . PHP_EOL;
|
||||
$tmp_skipped_items = [];
|
||||
foreach ( $log->WashItems as $item ) {
|
||||
/** @var xlvask_wash_item $item */
|
||||
// Skip items that have the id 64, since these are not relevant to anyone.
|
||||
$tmp_item_id = $item->getProduct($log)->id;
|
||||
if ($tmp_item_id === 64) {
|
||||
$tmp_skipped_items[] = $item;
|
||||
continue; // Skip items with id 64
|
||||
}
|
||||
echo '## ' . $item->Count . ' x ' . $item->OriginalProductName . ' @ ' . $item->getPriceExVat() . ' as ' . $tmp_item_id . PHP_EOL;
|
||||
}
|
||||
echo '### Total: ' . $log->getTotalPrice() . PHP_EOL;
|
||||
echo '### Skipped items: ' . count($tmp_skipped_items) . PHP_EOL;
|
||||
}
|
||||
//print_r($tmp_usage_logs);
|
||||
// Check if the customer has any usage data in the last 24 hours
|
||||
// This is a placeholder, you might want to implement a method to check this
|
||||
// if (!$xlvask->hasRecentUsageData($customer->externId, $dateFrom)) {
|
||||
// continue; // Skip customers without recent usage data
|
||||
// }
|
||||
}
|
||||
|
||||
// Process the usage data and update the users accordingly
|
||||
//$xlvask->processUsageData($usage_data);
|
||||
return [];
|
||||
}
|
||||
|
||||
private static function formatUsageLogs(array $getUsageLog): array
|
||||
{
|
||||
//print_r($getUsageLog);
|
||||
// Format the usage logs to a more readable format
|
||||
// This is a placeholder, you might want to implement a method to format the logs
|
||||
return array_map(/**
|
||||
* @throws Exception
|
||||
*/ function ($log) {
|
||||
$xlvask = new \classes\xlvask();
|
||||
return (new $xlvask->helpers->xlvask_usage_log())->setProperties($log);
|
||||
}, $getUsageLog);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,512 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\departments_o;
|
||||
use objects\orders_o;
|
||||
|
||||
class xlvask_usage_log
|
||||
{
|
||||
/**
|
||||
* Example of a usage log object:
|
||||
* [WashId] => 8cb0b5a7-ab4b-4dd5-b805-869733c23e54
|
||||
* [CustomerId] => 59440200
|
||||
* [Customer] => DITOBUS EXCURSIONS A/S
|
||||
* [VatNumber] => 31171520
|
||||
* [Location] => Hvidovre
|
||||
* [Hall] => Hvidovre_1
|
||||
* [HallId] => 845d29a1-a7d2-4e3b-bbc3-2b13242d744a
|
||||
* [StartTime] => 2025-06-02T15:20:14.950
|
||||
* [FinishTime] => 2025-06-02T15:25:55.377
|
||||
* [RegistrationNumber] => CZ92915
|
||||
* [VehicleType] => Bus/autocamper, M
|
||||
* [IdentificationType] => LPR
|
||||
* [IdentificationId] => CZ92915
|
||||
* [Info] => CZ92915
|
||||
* [Updated] =>
|
||||
* [Prepaid] =>
|
||||
* [FinishStatus] => 1
|
||||
* [CustomerGuid] => 21ba156a-b2d2-44be-8398-4b67d66003d6
|
||||
* [VehicleId] => e6679209-e52f-4376-9660-d56cb46f523b
|
||||
* [WashItems] => Array[washItem] => Array
|
||||
*/
|
||||
|
||||
/**
|
||||
* The wash ID of the usage log entry
|
||||
* @var int|string|null $WashId
|
||||
*/
|
||||
public int|string|null $WashId;
|
||||
/**
|
||||
* The ID of the customer (XLVask ID)
|
||||
* @var int|string|null $CustomerId
|
||||
*/
|
||||
public int|string|null $CustomerId;
|
||||
/**
|
||||
* The name of the customer
|
||||
* @var int|string|null $Customer
|
||||
*/
|
||||
public int|string|null $Customer;
|
||||
/**
|
||||
* The VAT number of the customer
|
||||
* @var int|string|null $VatNumber
|
||||
*/
|
||||
public int|string|null $VatNumber;
|
||||
/**
|
||||
* The location of the wash
|
||||
* @var int|string|null $Location
|
||||
*/
|
||||
public int|string|null $Location;
|
||||
/**
|
||||
* The hall where the wash took place
|
||||
* @var int|string|null $Hall
|
||||
*/
|
||||
public int|string|null $Hall;
|
||||
/**
|
||||
* The ID of the hall where the wash took place
|
||||
* @var int|string|null $HallId
|
||||
*/
|
||||
public int|string|null $HallId;
|
||||
/**
|
||||
* The start time of the wash
|
||||
* @var string|int|null $StartTime
|
||||
*/
|
||||
public string|int|null $StartTime;
|
||||
/**
|
||||
* The finish time of the wash
|
||||
* @var string|int|null $FinishTime
|
||||
*/
|
||||
public string|int|null $FinishTime;
|
||||
/**
|
||||
* The registration number of the vehicle
|
||||
* @var int|string|null $RegistrationNumber
|
||||
*/
|
||||
public int|string|null $RegistrationNumber;
|
||||
/**
|
||||
* The type of the vehicle
|
||||
* @var string|int|null $VehicleType
|
||||
*/
|
||||
public string|int|null $VehicleType;
|
||||
/**
|
||||
* The type of identification used for the wash
|
||||
* @var string|int|null $IdentificationType
|
||||
*/
|
||||
public string|int|null $IdentificationType;
|
||||
/**
|
||||
* The ID of the identification used for the wash
|
||||
* @var string|int|null $IdentificationId
|
||||
*/
|
||||
public string|int|null $IdentificationId;
|
||||
/**
|
||||
* Additional information about the wash
|
||||
* @var string|int|null $Info
|
||||
*/
|
||||
public string|int|null $Info;
|
||||
/**
|
||||
* The last updated time of the wash entry
|
||||
* @var string|int|null $Updated
|
||||
*/
|
||||
public string|int|null $Updated;
|
||||
/**
|
||||
* Indicates if the wash was prepaid
|
||||
* @var int|string|null $Prepaid
|
||||
*/
|
||||
public int|string|null $Prepaid;
|
||||
/**
|
||||
* The finish status of the wash
|
||||
* @var int|string|null $FinishStatus
|
||||
*/
|
||||
public int|string|null $FinishStatus;
|
||||
/**
|
||||
* The GUID of the customer in XL Vask
|
||||
* @var string|int|null $CustomerGuid
|
||||
*/
|
||||
public string|int|null $CustomerGuid;
|
||||
/**
|
||||
* The ID of the vehicle associated with the wash
|
||||
* @var string|int|null $vehicleId
|
||||
*/
|
||||
public string|int|null $VehicleId;
|
||||
/**
|
||||
* The wash items associated with the wash
|
||||
* @var array[washItem] $washItems
|
||||
* @see xlvask_wash_item
|
||||
*/
|
||||
public array $WashItems;
|
||||
|
||||
protected string $default_string = 'DEFAULT_STRING_1';
|
||||
protected string $default_int = 'DEFAULT_INT_1';
|
||||
protected string $default_bool = 'DEFAULT_BOOL_1';
|
||||
protected string $default_int_nullable = 'DEFAULT_INT_NULLABLE_1';
|
||||
protected string $default_string_nullable = 'DEFAULT_STRING_NULLABLE_1';
|
||||
protected string $default_bool_nullable = 'DEFAULT_BOOL_NULLABLE_1';
|
||||
|
||||
/**
|
||||
* Constructor to initialize the customer object with default values
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
$this->default_string = 'DEFAULT_STRING_1';
|
||||
$this->default_int = 'DEFAULT_INT_1';
|
||||
$this->default_bool = 'DEFAULT_BOOL_1';
|
||||
$this->default_int_nullable = 'DEFAULT_INT_NULLABLE_1';
|
||||
$this->default_string_nullable = 'DEFAULT_STRING_NULLABLE_1';
|
||||
$this->default_bool_nullable = 'DEFAULT_BOOL_NULLABLE_1';
|
||||
// Initialize the customer object with default values
|
||||
$this::reset();
|
||||
$this::setProperties($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset this object to its default values.
|
||||
* This method clears all properties of the usage log object,
|
||||
* effectively resetting it to a clean state.
|
||||
* @return void
|
||||
*/
|
||||
private function reset(): void
|
||||
{
|
||||
$this->WashId = $this->default_string;
|
||||
$this->CustomerId = $this->default_string;
|
||||
$this->Customer = $this->default_string;
|
||||
$this->VatNumber = $this->default_string;
|
||||
$this->Location = $this->default_string;
|
||||
$this->Hall = $this->default_string;
|
||||
$this->HallId = $this->default_string;
|
||||
$this->StartTime = $this->default_string;
|
||||
$this->FinishTime = $this->default_string;
|
||||
$this->RegistrationNumber = $this->default_string;
|
||||
$this->VehicleType = $this->default_string;
|
||||
$this->IdentificationType = $this->default_string;
|
||||
$this->IdentificationId = $this->default_string;
|
||||
$this->Info = $this->default_string;
|
||||
$this->Updated = $this->default_string_nullable;
|
||||
$this->Prepaid = $this->default_bool;
|
||||
$this->FinishStatus = $this->default_int;
|
||||
$this->CustomerGuid = $this->default_string;
|
||||
$this->VehicleId = $this->default_string;
|
||||
$this->WashItems = []; // Initialize as an empty array
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the properties of the object based on the provided data.
|
||||
* @note This method DOES NOT reset the object before setting the properties.
|
||||
* @param array $data
|
||||
* @return self
|
||||
* @throws Exception
|
||||
* @see reset()
|
||||
*/
|
||||
public function setProperties(array $data): self
|
||||
{
|
||||
$default_property_values = [
|
||||
'WashId' => $this->default_string,
|
||||
'CustomerId' => $this->default_string,
|
||||
'Customer' => $this->default_string,
|
||||
'VatNumber' => $this->default_string,
|
||||
'Location' => $this->default_string,
|
||||
'Hall' => $this->default_string,
|
||||
'HallId' => $this->default_string,
|
||||
'StartTime' => $this->default_string,
|
||||
'FinishTime' => $this->default_string,
|
||||
'RegistrationNumber' => $this->default_string,
|
||||
'VehicleType' => $this->default_string,
|
||||
'IdentificationType' => $this->default_string,
|
||||
'IdentificationId' => $this->default_string,
|
||||
'Info' => $this->default_string,
|
||||
'Updated' => $this->default_string_nullable,
|
||||
'Prepaid' => $this->default_bool,
|
||||
'FinishStatus' => $this->default_int,
|
||||
'CustomerGuid' => $this->default_string,
|
||||
'VehicleId' => $this->default_string,
|
||||
];
|
||||
foreach ( $data as $key => $value ) {
|
||||
if (property_exists(self::class, $key)) {
|
||||
switch ($default_property_values[$key] ?? null) {
|
||||
case $this->default_string:
|
||||
case $this->default_string_nullable:
|
||||
$nullable = $default_property_values[$key] === $this->default_string_nullable;
|
||||
// Check if the value is a string or can be converted to a string
|
||||
if (is_string($value) || is_numeric($value)) {
|
||||
$value = (string)$value; // Ensure the value is a string
|
||||
} elseif ($nullable) {
|
||||
$value = null; // If nullable, set to null
|
||||
} else {
|
||||
$value = ''; // If not nullable, set to empty string
|
||||
}
|
||||
break;
|
||||
case $this->default_int:
|
||||
case $this->default_int_nullable:
|
||||
$nullable = $default_property_values[$key] === $this->default_int_nullable;
|
||||
// Check if the value is numeric and convert it to an integer or null
|
||||
$value = is_numeric($value) ? (int)$value : ($nullable ? null : 0); // Ensure the value is an integer or null
|
||||
break;
|
||||
case $this->default_bool:
|
||||
case $this->default_bool_nullable:
|
||||
$nullable = $default_property_values[$key] === $this->default_bool_nullable;
|
||||
// Check if the value is a boolean or can be converted to a boolean
|
||||
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
||||
if ($value === null && !$nullable) {
|
||||
$value = false; // If the value is not a boolean and not nullable, set it to false
|
||||
}
|
||||
break;
|
||||
case null:
|
||||
break;
|
||||
default:
|
||||
// If the value is not a default string, keep it as is
|
||||
echo "No conversion needed for property '$key' with value '$value'." . PHP_EOL;
|
||||
break;
|
||||
}
|
||||
// Set the property value
|
||||
$this->{$key} = $value;
|
||||
} else {
|
||||
// If the property does not exist, throw an exception
|
||||
// Debug print all properties of the class
|
||||
//$properties = get_class_vars(self::class);
|
||||
//echo "Available properties in " . self::class . ": " . implode(', ', array_keys($properties)) . PHP_EOL;
|
||||
throw new Exception("Property '$key' does not exist in " . self::class);
|
||||
}
|
||||
}
|
||||
// If the washItems property is set, ensure it is an array
|
||||
if (isset($data['WashItems']) && is_array($data['WashItems'])) {
|
||||
//echo 'Setting WashItems with ' . count($this->WashItems) . ' items.' . PHP_EOL;
|
||||
$this->WashItems = self::generateWashItems($data['WashItems']);
|
||||
//print_r($this->WashItems);
|
||||
} else {
|
||||
//echo 'No washItems provided or not an array. Initializing as empty array.' . PHP_EOL;
|
||||
//print_r($data);
|
||||
}
|
||||
// After setting all properties, nullify nullable properties
|
||||
$this->unsetNullifiableProperties();
|
||||
// Return the populated object
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate wash items from the provided array.
|
||||
* This method takes an array of wash items and converts them into instances of xlvask_wash_item.
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function generateWashItems(array $washItems): array
|
||||
{
|
||||
// Generate wash items from the provided array
|
||||
$generatedItems = [];
|
||||
foreach ( $washItems as $item ) {
|
||||
if (is_array($item)) {
|
||||
$generatedItems[] = new xlvask_wash_item($item);
|
||||
} elseif ($item instanceof xlvask_wash_item) {
|
||||
$generatedItems[] = $item; // If it's already an instance, add it
|
||||
} else {
|
||||
throw new Exception("Invalid wash item type: " . gettype($item));
|
||||
}
|
||||
}
|
||||
// Sort the generated items with the sortWashItems method
|
||||
return self::sortWashItems($generatedItems);
|
||||
}
|
||||
|
||||
private static function sortWashItems(array $generatedItems): array
|
||||
{
|
||||
// Make sure the primary wash item is always first
|
||||
$primaryItems = [
|
||||
'Stor bil',
|
||||
'Lille bil',
|
||||
];
|
||||
usort($generatedItems, function ($a, $b) use ($primaryItems) {
|
||||
// Check if the item is a primary item
|
||||
$aIsPrimary = in_array($a->OriginalProductName, $primaryItems, true);
|
||||
$bIsPrimary = in_array($b->OriginalProductName, $primaryItems, true);
|
||||
// If both are primary items, keep their order
|
||||
if ($aIsPrimary && $bIsPrimary) {
|
||||
return 0;
|
||||
}
|
||||
// If only one is a primary item, it should come first
|
||||
return $aIsPrimary ? -1 : 1;
|
||||
});
|
||||
// Return the sorted array of wash items
|
||||
return $generatedItems;
|
||||
}
|
||||
|
||||
private function unsetNullifiableProperties(): void
|
||||
{
|
||||
// Unset properties that are null or empty strings
|
||||
$properties = [
|
||||
'WashId', 'CustomerId', 'Customer', 'VatNumber', 'Location',
|
||||
'Hall', 'HallId', 'StartTime', 'FinishTime', 'RegistrationNumber',
|
||||
'VehicleType', 'IdentificationType', 'IdentificationId', 'Info',
|
||||
'Updated', 'Prepaid', 'FinishStatus', 'CustomerGuid', 'VehicleId'
|
||||
];
|
||||
foreach ( $properties as $property ) {
|
||||
if ($this->isEmptyOrDefault($this->{$property})) {
|
||||
$tmp_value = $this->{$property};
|
||||
if ($tmp_value === $this->default_string || $tmp_value === $this->default_string_nullable) {
|
||||
$this->{$property} = ''; // Set to null if it matches the default string
|
||||
} elseif ($tmp_value === $this->default_int || $tmp_value === $this->default_int_nullable) {
|
||||
if ($tmp_value === $this->default_int_nullable) {
|
||||
$this->{$property} = null; // Set to null if it matches the default int nullable
|
||||
} else {
|
||||
$this->{$property} = 0; // Set to 0 if it matches the default int
|
||||
}
|
||||
} elseif ($tmp_value === $this->default_bool || $tmp_value === $this->default_bool_nullable) {
|
||||
$this->{$property} = false; // Set to null if it matches the default bool
|
||||
} else {
|
||||
$this->{$property} = null; // Otherwise, set to null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function isEmptyOrDefault($param): bool
|
||||
{
|
||||
// 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.
|
||||
* @return string The formatted date of the wash start time. YYYY-MM-DD HH:MM:SS format.
|
||||
* @note Returns an empty string if StartTime is not set.
|
||||
*/
|
||||
public function getFormattedDate(): string
|
||||
{
|
||||
// Format the date in a human-readable format
|
||||
if ($this->StartTime) {
|
||||
return date('Y-m-d H:i:s', strtotime($this->StartTime));
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the formatted finish date of the wash.
|
||||
* @return string The formatted finish date of the wash. YYYY-MM-DD HH:MM:SS format.
|
||||
* @note Returns an empty string if FinishTime is not set.
|
||||
*/
|
||||
public function getFormattedFinishDate(): string
|
||||
{
|
||||
// Format the finish date in a human-readable format
|
||||
if ($this->FinishTime) {
|
||||
return date('Y-m-d H:i:s', strtotime($this->FinishTime));
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total price of the wash.
|
||||
* This method calculates the total price of the wash by summing up the prices of all wash items.
|
||||
* @return float The total price of the wash.
|
||||
* @throws Exception If any of the wash items do not have a valid price.
|
||||
*/
|
||||
public function getTotalPrice(): float
|
||||
{
|
||||
// Calculate the total price of the wash by summing up the prices of all wash items
|
||||
$totalPrice = 0.0;
|
||||
foreach ( $this->WashItems as $item ) {
|
||||
/** @var xlvask_wash_item $item */
|
||||
if (isset($item->PriceIncVat) && is_numeric($item->PriceIncVat)) {
|
||||
// The reason why we use the PriceIncVat is that it is the final price, and the price without VAT is not always available / correct.
|
||||
$totalPrice += ((float)$item->PriceIncVat - (float)$item->Vat);
|
||||
} else {
|
||||
//print_r($item);
|
||||
throw new Exception("Invalid price for wash item: " . json_encode($item));
|
||||
}
|
||||
}
|
||||
return $totalPrice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the wash is completed.
|
||||
* @note This method checks the FinishStatus property to determine if the wash is completed.
|
||||
* * A wash is considered completed if the FinishStatus is set to 1.
|
||||
* @return bool
|
||||
*/
|
||||
public function isCompleted(): bool
|
||||
{
|
||||
// Check if the wash is completed based on the FinishStatus
|
||||
return $this->FinishStatus === 1; // Assuming 1 indicates a completed wash
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the primary wash item from the usage log.
|
||||
* This method returns the first wash item in the WashItems array as the primary item.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getPrimaryItem(): xlvask_wash_item
|
||||
{
|
||||
// Return the first wash item as the primary item
|
||||
if (isset($this->WashItems[0]) && $this->WashItems[0] instanceof xlvask_wash_item) {
|
||||
return $this->WashItems[0];
|
||||
}
|
||||
throw new Exception("No primary wash item found in the usage log.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the wash linked to an order?
|
||||
* @return bool
|
||||
* @note This method checks if an order exists with the "wash_id" field matching the WashId of this usage log.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function isLinkedToOrder(): bool
|
||||
{
|
||||
// Check if the wash is linked to an order by checking the "wash_id" field in the orders table
|
||||
$order = (new orders_o())->selectByWashId($this->WashId);
|
||||
return !empty($order);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the order associated with this wash.
|
||||
* @return orders_o|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getOrder(): ?orders_o
|
||||
{
|
||||
// Get the order associated with this wash by checking the "wash_id" field in the orders table
|
||||
$order = (new orders_o())->selectByWashId($this->WashId);
|
||||
if ($order) {
|
||||
return $order;
|
||||
}
|
||||
return null; // Return null if no order is found
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the department associated with this wash.
|
||||
* @throws Exception If the department cannot be determined.
|
||||
*/
|
||||
public function getDepartment(): ?departments_o
|
||||
{
|
||||
// Since the department / hall XLVASK API endpoints are not available,
|
||||
// We will try to get the department from the hall name.
|
||||
// These are formatted as "DepartmentName_HallNumber" (E.g. "Hvidovre_1").
|
||||
if (!empty($this->Hall)) {
|
||||
$parts = explode('_', $this->Hall);
|
||||
if (count($parts) > 1) {
|
||||
$departmentName = $parts[0];
|
||||
return (new departments_o())->selectByName($departmentName);
|
||||
}
|
||||
}
|
||||
// If the hall is not set or does not contain a department name, return null
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getLane(): ?int
|
||||
{
|
||||
// Since the department / hall XLVASK API endpoints are not available,
|
||||
// We will try to get the lane from the hall name.
|
||||
// These are formatted as "DepartmentName_HallNumber" (E.g. "Hvidovre_1").
|
||||
if (!empty($this->Hall)) {
|
||||
$parts = explode('_', $this->Hall);
|
||||
if (count($parts) > 1 && is_numeric($parts[1])) {
|
||||
return (int)$parts[1]; // Return the lane number as an integer
|
||||
}
|
||||
}
|
||||
// If the hall is not set or does not contain a lane number, return null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_wash_item
|
||||
{
|
||||
/**
|
||||
* Example of a wash item object:
|
||||
* [WashItemId] => 0774be08-6777-490f-add2-0ccff70771ee
|
||||
* [ExternalProductId] =>
|
||||
* [ExternalProductName] =>
|
||||
* [OriginalProductName] => Stor bil
|
||||
* [Unit] => stk
|
||||
* [UnitPrice] => 559
|
||||
* [Count] => 1
|
||||
* [Discount] => 65
|
||||
* [PriceExVat] => 559
|
||||
* [Vat] => 48.91
|
||||
* [PriceIncVat] => 244.56
|
||||
*/
|
||||
|
||||
/**
|
||||
* The ID of the wash item
|
||||
* @var string|int|float|null $WashItemId
|
||||
*/
|
||||
public string|int|float|null $WashItemId;
|
||||
/**
|
||||
* The external product ID of the wash item
|
||||
* @var string|int|float|null $ExternalProductId
|
||||
*/
|
||||
public string|int|float|null $ExternalProductId;
|
||||
/**
|
||||
* The external product name of the wash item
|
||||
* @var string|int|float|null $ExternalProductName
|
||||
*/
|
||||
public string|int|float|null $ExternalProductName;
|
||||
/**
|
||||
* The original product name of the wash item
|
||||
* @var string|int|float|null $OriginalProductName
|
||||
*/
|
||||
public string|int|float|null $OriginalProductName;
|
||||
/**
|
||||
* The Unit of the wash item
|
||||
* @var string|int|float|null $Unit
|
||||
*/
|
||||
public string|int|float|null $Unit;
|
||||
/**
|
||||
* The Unit price of the wash item
|
||||
* @var string|int|float|null $UnitPrice
|
||||
*/
|
||||
public string|int|float|null $UnitPrice;
|
||||
/**
|
||||
* The count of the wash item
|
||||
* @var string|int|float|null $Count
|
||||
*/
|
||||
public string|int|float|null $Count;
|
||||
/**
|
||||
* The discount applied to the wash item
|
||||
* @var string|int|float|null $Discount
|
||||
*/
|
||||
public string|int|float|null $Discount;
|
||||
/**
|
||||
* The price excluding VAT of the wash item
|
||||
* @var string|int|float|null $PriceExVat
|
||||
*/
|
||||
public string|int|float|null $PriceExVat;
|
||||
/**
|
||||
* The VAT amount of the wash item
|
||||
* @var string|int|float|null $Vat
|
||||
*/
|
||||
public string|int|float|null $Vat;
|
||||
/**
|
||||
* The price including VAT of the wash item
|
||||
* @var string|int|float|null $PriceIncVat
|
||||
*/
|
||||
public string|int|float|null $PriceIncVat;
|
||||
|
||||
protected string $default_string = 'DEFAULT_STRING_1';
|
||||
protected string $default_int = 'DEFAULT_INT_1';
|
||||
protected string $default_bool = 'DEFAULT_BOOL_1';
|
||||
protected string $default_int_nullable = 'DEFAULT_INT_NULLABLE_1';
|
||||
protected string $default_string_nullable = 'DEFAULT_STRING_NULLABLE_1';
|
||||
protected string $default_bool_nullable = 'DEFAULT_BOOL_NULLABLE_1';
|
||||
|
||||
/**
|
||||
* Constructor to initialize the customer object with default values
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
$this->default_string = 'DEFAULT_STRING_1';
|
||||
$this->default_int = 'DEFAULT_INT_1';
|
||||
$this->default_bool = 'DEFAULT_BOOL_1';
|
||||
$this->default_int_nullable = 'DEFAULT_INT_NULLABLE_1';
|
||||
$this->default_string_nullable = 'DEFAULT_STRING_NULLABLE_1';
|
||||
$this->default_bool_nullable = 'DEFAULT_BOOL_NULLABLE_1';
|
||||
// Initialize the customer object with default values
|
||||
$this::reset();
|
||||
$this::setProperties($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset this object to its default values.
|
||||
* This method clears all properties of the usage log object,
|
||||
* effectively resetting it to a clean state.
|
||||
* @return void
|
||||
*/
|
||||
private function reset(): void
|
||||
{
|
||||
$this->WashItemId = $this->default_string;
|
||||
$this->ExternalProductId = $this->default_string;
|
||||
$this->ExternalProductName = $this->default_string;
|
||||
$this->OriginalProductName = $this->default_string;
|
||||
$this->Unit = $this->default_string;
|
||||
$this->UnitPrice = $this->default_int; // Assuming Unit price is a float, but using default_int for initialization
|
||||
$this->Count = $this->default_int; // Assuming count is an integer
|
||||
$this->Discount = $this->default_int; // Assuming discount is a float, but using default_int for initialization
|
||||
$this->PriceExVat = $this->default_int; // Assuming priceExVat is a float, but using default_int for initialization
|
||||
$this->Vat = $this->default_int; // Assuming vat is a float, but using default_int for initialization
|
||||
$this->PriceIncVat = $this->default_int; // Assuming priceIncVat is a float, but using default_int for initialization
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the properties of the object based on the provided data.
|
||||
* @note This method DOES NOT reset the object before setting the properties.
|
||||
* @param array $data
|
||||
* @return self
|
||||
* @throws Exception
|
||||
* @see reset()
|
||||
*/
|
||||
public function setProperties(array $data): self
|
||||
{
|
||||
$default_property_values = [
|
||||
'WashItemId' => $this->default_string,
|
||||
'ExternalProductId' => $this->default_string,
|
||||
'ExternalProductName' => $this->default_string,
|
||||
'OriginalProductName' => $this->default_string,
|
||||
'Unit' => $this->default_string,
|
||||
'UnitPrice' => $this->default_int, // Assuming Unit price is a float, but using default_int for initialization
|
||||
'Count' => $this->default_int, // Assuming count is an integer
|
||||
'Discount' => $this->default_int, // Assuming discount is a float, but using default_int for initialization
|
||||
'PriceExVat' => $this->default_int, // Assuming priceExVat is a float, but using default_int for initialization
|
||||
'Vat' => $this->default_int, // Assuming vat is a float, but using default_int for initialization
|
||||
'PriceIncVat' => $this->default_int, // Assuming priceIncVat is a float, but using default_int for initialization
|
||||
];
|
||||
foreach ( $data as $key => $value ) {
|
||||
if (property_exists(self::class, $key)) {
|
||||
switch ($default_property_values[$key] ?? null) {
|
||||
case $this->default_string:
|
||||
case $this->default_string_nullable:
|
||||
$nullable = $default_property_values[$key] === $this->default_string_nullable;
|
||||
// Check if the value is a string or can be converted to a string
|
||||
if (is_string($value) || is_numeric($value)) {
|
||||
$value = (string)$value; // Ensure the value is a string
|
||||
} elseif ($nullable) {
|
||||
$value = null; // If nullable, set to null
|
||||
} else {
|
||||
$value = ''; // If not nullable, set to empty string
|
||||
}
|
||||
break;
|
||||
case $this->default_int:
|
||||
case $this->default_int_nullable:
|
||||
$nullable = $default_property_values[$key] === $this->default_int_nullable;
|
||||
// Check if the value is numeric and convert it to an integer or null
|
||||
$value = is_numeric($value) ? (int)$value : ($nullable ? null : 0); // Ensure the value is an integer or null
|
||||
break;
|
||||
case $this->default_bool:
|
||||
case $this->default_bool_nullable:
|
||||
$nullable = $default_property_values[$key] === $this->default_bool_nullable;
|
||||
// Check if the value is a boolean or can be converted to a boolean
|
||||
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
||||
if ($value === null && !$nullable) {
|
||||
$value = false; // If the value is not a boolean and not nullable, set it to false
|
||||
}
|
||||
break;
|
||||
case null:
|
||||
break;
|
||||
default:
|
||||
// If the value is not a default string, keep it as is
|
||||
echo "No conversion needed for property '$key' with value '$value'." . PHP_EOL;
|
||||
break;
|
||||
}
|
||||
// Set the property value
|
||||
$this->{$key} = $value;
|
||||
} else {
|
||||
// If the property does not exist, throw an exception
|
||||
throw new Exception("Property '$key' does not exist in " . self::class);
|
||||
}
|
||||
}
|
||||
// After setting all properties, nullify nullable properties
|
||||
$this->unsetNullifiableProperties();
|
||||
// Return the populated object
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function unsetNullifiableProperties(): void
|
||||
{
|
||||
// Unset properties that are null or empty strings
|
||||
$properties = [
|
||||
'WashItemId', 'ExternalProductId', 'ExternalProductName', 'OriginalProductName',
|
||||
'Unit', 'UnitPrice', 'Count', 'Discount', 'PriceExVat', 'Vat', 'PriceIncVat'
|
||||
];
|
||||
foreach ( $properties as $property ) {
|
||||
if ($this->isEmptyOrDefault($this->{$property})) {
|
||||
$tmp_value = $this->{$property};
|
||||
if ($tmp_value === $this->default_string || $tmp_value === $this->default_string_nullable) {
|
||||
$this->{$property} = ''; // Set to null if it matches the default string
|
||||
} elseif ($tmp_value === $this->default_int || $tmp_value === $this->default_int_nullable) {
|
||||
if ($tmp_value === $this->default_int_nullable) {
|
||||
$this->{$property} = null; // Set to null if it matches the default int nullable
|
||||
} else {
|
||||
$this->{$property} = 0; // Set to 0 if it matches the default int
|
||||
}
|
||||
} elseif ($tmp_value === $this->default_bool || $tmp_value === $this->default_bool_nullable) {
|
||||
$this->{$property} = false; // Set to null if it matches the default bool
|
||||
} else {
|
||||
$this->{$property} = null; // Otherwise, set to null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function isEmptyOrDefault($param): bool
|
||||
{
|
||||
// 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.
|
||||
* @throws Exception If the OriginalProductName is not set or if the product cannot be found.
|
||||
*/
|
||||
public function getProduct(xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
// Since the ExternalProductId is rarely set, we must use the OriginalProductName to find the product.
|
||||
// The OriginalProductName is the name of the service in the xlvask module, this is ususally very ambiguous.
|
||||
// Example: "Stor bil" represents a large car/vehicle (And doesn't specify the type of vehicle, this could be a truck, bus, etc.)
|
||||
if (empty($this->OriginalProductName)) {
|
||||
throw new Exception('The OriginalProductName is not set. Please provide a valid product name.');
|
||||
}
|
||||
|
||||
// Check if a parser exists for the OriginalProductName
|
||||
$parser_class = 'helpers\xlvask_parser_' . $this->getParserName();
|
||||
|
||||
if (!class_exists($parser_class)) {
|
||||
throw new Exception("No parser found for the OriginalProductName: {$this->OriginalProductName} (Parsed as: {$this->getParserName()}). Please ensure the parser class exists.");
|
||||
}
|
||||
|
||||
$parser = new $parser_class();
|
||||
if (!$parser instanceof xlvask_product_parser) {
|
||||
throw new Exception('The xlvask product parser class is not an instance of xlvask_product_parser. Please ensure it implements the correct interface.');
|
||||
}
|
||||
return $parser->parseProduct($this, $xlvask_usage_log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parser name based on the OriginalProductName.
|
||||
* This method converts the OriginalProductName to a valid parser name.
|
||||
* @return string
|
||||
*/
|
||||
private function getParserName(): string
|
||||
{
|
||||
// Convert the OriginalProductName to a valid parser name
|
||||
// Example: "Stor bil" becomes "stor_bil", "2-b\u00f8rstevask" becomes "2_br_stevask"
|
||||
// Remove all non-alphanumeric characters and replace spaces with underscores
|
||||
if (empty($this->OriginalProductName)) {
|
||||
throw new Exception('The OriginalProductName is not set. Please provide a valid product name.');
|
||||
}
|
||||
// Use preg_replace to replace non-alphanumeric characters with underscores
|
||||
$result = preg_replace('/[^a-z0-9]+/i', '_', $this->OriginalProductName);
|
||||
// Remove leading and trailing underscores
|
||||
$result = trim($result, '_');
|
||||
// Convert to lowercase
|
||||
if ($result === '') {
|
||||
throw new Exception('The OriginalProductName is empty after processing. Please provide a valid product name.');
|
||||
}
|
||||
// Remove any special characters that might still be present
|
||||
$result = preg_replace('/[^a-z0-9_]/i', '', $result);
|
||||
return strtolower($result);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,31 @@ namespace xlvask;
|
||||
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';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_usage_log.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_wash_item.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_product_parser_t.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_product_parser.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_stor_bil.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_halleje.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_2_b_rstevask.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_3_b_rstevask.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_ikke_ht_dysebom_bag.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_ht_sider.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_skylning_med_ro.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_eu_spejl.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_ikke_ht_dysebom_p_front.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_lift.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_ht_chassis.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_undervognskylning.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_ht_osc_sider_verst.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_s_be_dysebom.php';
|
||||
|
||||
|
||||
use helpers\xlvask_cache;
|
||||
use helpers\xlvask_customer;
|
||||
use helpers\xlvask_tasks;
|
||||
use helpers\xlvask_usage_log;
|
||||
use helpers\xlvask_wash_item;
|
||||
|
||||
class xlvask_helpers
|
||||
{
|
||||
@@ -28,4 +48,14 @@ class xlvask_helpers
|
||||
* @var string $xlvask_customer
|
||||
*/
|
||||
public string $xlvask_customer = xlvask_customer::class;
|
||||
/**
|
||||
* The xlvask usage log helper
|
||||
* @var string $xlvask_usage_log
|
||||
*/
|
||||
public string $xlvask_usage_log = xlvask_usage_log::class;
|
||||
/**
|
||||
* The xlvask wash item helper
|
||||
* @var string $xlvask_wash_item
|
||||
*/
|
||||
public string $xlvask_wash_item = xlvask_wash_item::class;
|
||||
}
|
||||
@@ -198,13 +198,6 @@ class departments_o extends db
|
||||
return $db->fetch_all($result);
|
||||
}
|
||||
|
||||
public function selectId(int $department_id): self
|
||||
{
|
||||
$this->id = $department_id;
|
||||
$this->getObjectProperties();
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDepartmentName(int $department): string
|
||||
{
|
||||
global $db;
|
||||
@@ -355,4 +348,30 @@ class departments_o extends db
|
||||
self::requireSelected();
|
||||
return (bool)$this->variables->getVariable('bookingsystem_time_based_enabled');
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a department by its name (case-sensitive, exact match)
|
||||
* @throws Exception If the department selection fails or the department is not found
|
||||
* @example "Hvidovre"
|
||||
*/
|
||||
public function selectByName(string $departmentName): self
|
||||
{
|
||||
$result = self::getFieldsWhere([
|
||||
'name' => $departmentName,
|
||||
], [
|
||||
'id',
|
||||
]);
|
||||
if (empty($result)) {
|
||||
throw new Exception('Department not found: ' . $departmentName);
|
||||
}
|
||||
$this->selectId($result[0]['id']);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function selectId(int $department_id): self
|
||||
{
|
||||
$this->id = $department_id;
|
||||
$this->getObjectProperties();
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -653,4 +653,25 @@ class orders_o extends db
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select an order by its wash ID
|
||||
* @param int|string|null $WashId The wash ID to select the order by
|
||||
* @return orders_o|null The selected order object or null if no order is found
|
||||
* @throws Exception
|
||||
*/
|
||||
public function selectByWashId(int|string|null $WashId): orders_o|null
|
||||
{
|
||||
$result = self::getFieldsWhere([
|
||||
'wash_id' => $WashId,
|
||||
'deleted_at' => null,
|
||||
], [
|
||||
'id'
|
||||
]);
|
||||
if (empty($result)) {
|
||||
return null; // No order found with the given wash ID
|
||||
}
|
||||
$this->select((int)$result[0]['id']);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -169,5 +169,23 @@ class moduleXLVaskRoute
|
||||
'modules_xlvask_sync_users' => 'Synchronize users with the xlvask module'
|
||||
]
|
||||
);
|
||||
|
||||
$this->get('/modules/xlvask/tasks/sync-usage', function () {
|
||||
global $response;
|
||||
//self::requirePermission('modules_xlvask_sync_usage');
|
||||
// Create the xlvask tasks object
|
||||
$xlvask = new xlvask();
|
||||
// Run the sync usage task
|
||||
$result = $xlvask->getTasks()->runSyncUsage();
|
||||
// Response
|
||||
$response->success(
|
||||
$result,
|
||||
200
|
||||
);
|
||||
},
|
||||
[
|
||||
'modules_xlvask_sync_usage' => 'Synchronize usage with the xlvask module'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user