Merge pull request #63 from copenhagentruckwash/limble-module
limble-module
This commit is contained in:
@@ -5,6 +5,7 @@ require_once WD . '/modules/limble/interfaces/limble_endpoints_i.php';
|
||||
require_once WD . '/modules/limble/classes/limble_request.php';
|
||||
|
||||
use Exception;
|
||||
use limble\helpers\limble_tasks_pagination;
|
||||
use limble_endpoints_i;
|
||||
|
||||
abstract class limble_endpoints extends limble_request implements limble_endpoints_i
|
||||
@@ -14,14 +15,11 @@ abstract class limble_endpoints extends limble_request implements limble_endpoin
|
||||
* @inheritDoc
|
||||
* @throws Exception If the module is not enabled
|
||||
*/
|
||||
public function listTasks(): array
|
||||
public function listTasks(limble_tasks_pagination $pagination): array
|
||||
{
|
||||
$this->requireModuleEnabled();
|
||||
$url = $this->config->api_url . '/tasks';
|
||||
$params = [
|
||||
// 'status' => 'open',
|
||||
// 'limit' => 100,
|
||||
];
|
||||
$params = [...$pagination->getParams()];
|
||||
return $this->sendRequest(
|
||||
$url,
|
||||
'GET',
|
||||
@@ -51,6 +49,22 @@ abstract class limble_endpoints extends limble_request implements limble_endpoin
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception If the module is not enabled
|
||||
*/
|
||||
public function getTaskInstructions(int $taskId): array
|
||||
{
|
||||
$this->requireModuleEnabled();
|
||||
$url = $this->config->api_url . '/tasks/' . $taskId . '/instructions';
|
||||
return $this->sendRequest(
|
||||
$url,
|
||||
'GET',
|
||||
[],
|
||||
[self::getAuthHeader(), 'Content-Type: application/json']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception If the module is not enabled
|
||||
@@ -59,12 +73,14 @@ abstract class limble_endpoints extends limble_request implements limble_endpoin
|
||||
{
|
||||
$this->requireModuleEnabled();
|
||||
$url = $this->config->api_url . '/tasks';
|
||||
// Set the taskId as a pagination parameter
|
||||
$pagination = new limble_tasks_pagination();
|
||||
$pagination->tasks = $taskId;
|
||||
$pagination->limit = 1; // Limit to 1 task
|
||||
return $this->sendRequest(
|
||||
$url,
|
||||
'GET',
|
||||
[
|
||||
'cursor' => $taskId,
|
||||
],
|
||||
[...$pagination->getParams()],
|
||||
[self::getAuthHeader(), 'Content-Type: application/json']
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace limble\helpers;
|
||||
|
||||
class limble_object_helper
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace limble\helpers;
|
||||
|
||||
abstract class limble_pagination_helper
|
||||
{
|
||||
/**
|
||||
* Limit of items per page.
|
||||
* @var int $limit
|
||||
*/
|
||||
public int $limit = 100;
|
||||
/**
|
||||
* Page number to display.
|
||||
* @var int $page
|
||||
*/
|
||||
public int $page = 1;
|
||||
|
||||
public function getParams(): array
|
||||
{
|
||||
return array_filter((array)$this, function ($value) {
|
||||
return is_int($value) || is_string($value);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace limble\helpers;
|
||||
|
||||
class limble_task_comment extends limble_object_helper
|
||||
{
|
||||
/**
|
||||
* The unique identifier for the comment.
|
||||
* @var int $commentID
|
||||
*/
|
||||
public int $commentID;
|
||||
/**
|
||||
* The content of the comment.
|
||||
* @var string $comment
|
||||
*/
|
||||
public string $comment;
|
||||
/**
|
||||
* An array of files associated with the comment.
|
||||
* @var array $commentFiles
|
||||
*/
|
||||
public array $commentFiles;
|
||||
/**
|
||||
* The timestamp when the comment was created.
|
||||
* @var int $timestamp
|
||||
*/
|
||||
public int $timestamp;
|
||||
/**
|
||||
* The unique identifier for the user who created the comment.
|
||||
* @var int $userID
|
||||
*/
|
||||
public int $userID;
|
||||
/**
|
||||
* The email address associated with the comment, if any.
|
||||
* @var string|null $commentEmailAddress
|
||||
*/
|
||||
public ?string $commentEmailAddress;
|
||||
/**
|
||||
* Indicates whether the comment should be shown to external users.
|
||||
* @var bool $showExternalUsers
|
||||
*/
|
||||
public bool $showExternalUsers;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace limble\helpers;
|
||||
|
||||
class limble_task_instruction extends limble_object_helper
|
||||
{
|
||||
/**
|
||||
* The unique identifier for the instruction.
|
||||
* @var int $instructionID
|
||||
*/
|
||||
public int $instructionID;
|
||||
/**
|
||||
* The unique identifier for the task associated with this instruction.
|
||||
* @var int $taskID
|
||||
*/
|
||||
public int $taskID;
|
||||
/**
|
||||
* The unique identifier for the parent instruction, if any.
|
||||
* @var int $parentInstructionID
|
||||
*/
|
||||
public int $parentInstructionID;
|
||||
/**
|
||||
* The instruction text that describes what needs to be done.
|
||||
* @var string $instruction
|
||||
*/
|
||||
public string $instruction;
|
||||
/**
|
||||
* The type of instruction, represented as an integer.
|
||||
* @var int $type
|
||||
*/
|
||||
public int $type;
|
||||
/**
|
||||
* An array of options related to the instruction.
|
||||
* @var array $options
|
||||
*/
|
||||
public array $options;
|
||||
/**
|
||||
* Indicates whether a response is required for this instruction.
|
||||
* @var bool $response
|
||||
*/
|
||||
public bool $response;
|
||||
/**
|
||||
* An array of files associated with the instruction.
|
||||
* @var array $instructionFiles
|
||||
*/
|
||||
public array $instructionFiles;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace limble\helpers;
|
||||
|
||||
class limble_tasks_pagination extends limble_pagination_helper
|
||||
{
|
||||
/**
|
||||
* The unique identifier for the task.
|
||||
* @note This is used to specify a specific task when retrieving pagination data.
|
||||
* @see limble_task::taskID
|
||||
* @var int $tasks
|
||||
*/
|
||||
public int $tasks;
|
||||
}
|
||||
@@ -53,26 +53,26 @@ class limble_webhook_payload_task extends limble_webhook_payload
|
||||
public function __construct(array $payload)
|
||||
{
|
||||
parent::__construct($payload);
|
||||
$this->slack->send_message('Initializing Limble Webhook Payload Task', 'Limble Webhook Task Initialization');
|
||||
$this->taskID = (int)($payload['taskID'] ?? 0);
|
||||
$this->status = (string)($payload['status'] ?? '');
|
||||
$this->category = (string)($payload['category'] ?? '');
|
||||
$this->user = (string)($payload['user'] ?? '');
|
||||
$this->taskObject = new limble_task(((new limble())->getTask($payload['taskID'])) ?: []);
|
||||
$this->slack->send_message('Task has been initialized with ID: ' . $this->taskID, 'Limble Webhook Task Initialized');
|
||||
$this->taskObject = new limble_task(((new limble())->getTask($payload['taskID']))[0] ?? []);
|
||||
$this->notifyWebhook();
|
||||
}
|
||||
|
||||
protected function notifyWebhook(): void
|
||||
{
|
||||
// Generate the message to notify the webhook
|
||||
$message = "";
|
||||
$message .= "Task ID: " . $this->taskID . "\n";
|
||||
$message .= "Name: " . $this->taskObject->name . "\n";
|
||||
$message .= "Description: " . $this->taskObject->description . "\n";
|
||||
$message .= "User: " . $this->user . "\n";
|
||||
$message .= "Status: " . $this->status . "\n";
|
||||
$message .= "Category: " . $this->category . "\n";
|
||||
// Notify the webhook with the task object
|
||||
$this->slack->send_message('
|
||||
Task ID: ' . $this->taskID . '
|
||||
Status: ' . $this->status . '
|
||||
Category: ' . $this->category . '
|
||||
User: ' . $this->user,
|
||||
'Limble Webhook Notification'
|
||||
);
|
||||
$this->slack->send_message($message, 'Limble Webhook Task Notification');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
<?php
|
||||
|
||||
|
||||
use limble\helpers\limble_task_instruction;
|
||||
use limble\helpers\limble_tasks_pagination;
|
||||
|
||||
interface limble_endpoints_i
|
||||
{
|
||||
|
||||
/**
|
||||
* Get the tasks from the limble API
|
||||
* @param limble_tasks_pagination $pagination
|
||||
* @return array
|
||||
*/
|
||||
public function listTasks(): array;
|
||||
public function listTasks(limble_tasks_pagination $pagination): array;
|
||||
|
||||
/**
|
||||
* Get a specific task from the limble API
|
||||
@@ -17,6 +21,14 @@ interface limble_endpoints_i
|
||||
*/
|
||||
public function getTask(int $taskId): array;
|
||||
|
||||
/**
|
||||
* Get the list of task instructions from the limble API
|
||||
* @param int $taskId
|
||||
* @return limble_task_instruction[]
|
||||
* @see limble_task_instruction
|
||||
*/
|
||||
public function getTaskInstructions(int $taskId): array;
|
||||
|
||||
|
||||
/**
|
||||
* Get the auth header for the API
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace limble;
|
||||
|
||||
require_once WD . '/modules/limble/helpers/limble_object_helper.php';
|
||||
require_once WD . '/modules/limble/helpers/limble_pagination_helper.php';
|
||||
require_once WD . '/modules/limble/helpers/limble_tasks_pagination.php';
|
||||
require_once WD . '/modules/limble/helpers/limble_task_instruction.php';
|
||||
require_once WD . '/modules/limble/helpers/limble_task.php';
|
||||
require_once WD . '/modules/limble/helpers/limble_tasks.php';
|
||||
require_once WD . '/modules/limble/helpers/limble_webhook_payload.php';
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace helpers;
|
||||
|
||||
use Exception;
|
||||
use objects\products_o;
|
||||
|
||||
class xlvask_parser_h_nger extends xlvask_product_parser
|
||||
{
|
||||
use xlvask_product_parser_t;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('Hænger');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o
|
||||
{
|
||||
// For some reason, in XLVask the primary product is stored as vask_h_nger in some cases,
|
||||
// This is a workaround to handle that case. (Since the functionality is exactly the same as // xlvask_parser_stor_bil)
|
||||
return (new xlvask_parser_stor_bil())->parseProduct(...func_get_args());
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ class xlvask_parser_vask_udf_rt extends xlvask_product_parser
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->setup('vask_udf_rt');
|
||||
$this->setup('Vask udført');
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ 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.
|
||||
|
||||
@@ -8,6 +8,20 @@ use objects\products_o;
|
||||
trait xlvask_product_parser_t
|
||||
{
|
||||
protected string $OriginalProductName;
|
||||
/**
|
||||
* This property indicates whether the parser is dynamic.
|
||||
* When set to true, the parser will handle dynamic pricing.
|
||||
* This should be set to true if the pricing of the product can change based on certain conditions,
|
||||
* such as the amount of usage, time of day, or other factors.
|
||||
* When this is set to true, the parser should implement logic to handle dynamic pricing.
|
||||
* @example
|
||||
* The "flowmeter" product parser uses this to calculate the price based on the amount of water used.
|
||||
* * @note This is used to determine whether the parser should calculate a dynamic price or a static price.
|
||||
* @see xlvask_product_parser_t::calculateDynamicPrice()
|
||||
* When this is set to false, the parser should return a static price. (amount x price per unit)
|
||||
* @var bool $useDynamicPricing
|
||||
*/
|
||||
protected bool $useDynamicPricing = false;
|
||||
|
||||
|
||||
/**
|
||||
@@ -40,5 +54,4 @@ trait xlvask_product_parser_t
|
||||
*/
|
||||
abstract protected function parse(xlvask_wash_item $wash_item, xlvask_usage_log $xlvask_usage_log): products_o;
|
||||
|
||||
|
||||
}
|
||||
@@ -312,6 +312,7 @@ class xlvask_usage_log extends xlvask_helper
|
||||
'Stor bil',
|
||||
'Lille bil',
|
||||
'Vask udført',
|
||||
'Hænger',
|
||||
];
|
||||
usort($generatedItems, function ($a, $b) use ($primaryItems) {
|
||||
// Check if the item is a primary item
|
||||
@@ -362,7 +363,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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the formatted date of the wash start time.
|
||||
|
||||
@@ -73,7 +73,7 @@ class xlvask_vehicles extends xlvask_helper
|
||||
$xlvask = new xlvask();
|
||||
$xlvask_cache = $xlvask->getCache();
|
||||
if ($xlvask_cache->isVehicleCached($registrationNumber)) {
|
||||
//return $xlvask_cache->getVehicleCache($registrationNumber);
|
||||
return $xlvask_cache->getVehicleCache($registrationNumber);
|
||||
} else if ($onlyCache) {
|
||||
return null; // Return null if onlyCache is true and vehicle is not cached
|
||||
}
|
||||
|
||||
@@ -229,7 +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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the product associated with this wash item.
|
||||
@@ -352,4 +352,10 @@ class xlvask_wash_item extends xlvask_helper
|
||||
// If either PriceIncVat or Count is not numeric, return 0
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
public function getUnitPriceExVat(): float
|
||||
{
|
||||
// Calculate the unit price excluding VAT
|
||||
return $this->getPriceExVat() / (float)$this->Count;
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,7 @@ require_once WD . '/modules/xlvask/helpers/xlvask_parser_specials_be_sider.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_ikke_ht_dysebom_p_tag.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_ht_osc_sider.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_kun_b_rster_ved_hytten.php';
|
||||
require_once WD . '/modules/xlvask/helpers/xlvask_parser_h_nger.php';
|
||||
|
||||
use helpers\xlvask_cache;
|
||||
use helpers\xlvask_create_customer;
|
||||
|
||||
@@ -90,10 +90,19 @@ class collected_order_invoices_o extends db
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the invoice collection as an array
|
||||
* @throws ApiErrorException If the payment method is Stripe and the request fails
|
||||
* @throws Exception If the request was not successful
|
||||
*/
|
||||
public function asArray(): array
|
||||
{
|
||||
// Require the invoice collection to be selected
|
||||
self::requireSelected();
|
||||
// Check if the object is cached
|
||||
$cached = self::getCached('asArray', $this->id);
|
||||
if ($cached !== null) {
|
||||
return (array)$cached;
|
||||
}
|
||||
$tmp = [
|
||||
'id' => (int)$this->id,
|
||||
'customer_number' => (int)$this->customer_number->value(),
|
||||
@@ -130,6 +139,9 @@ class collected_order_invoices_o extends db
|
||||
]);
|
||||
$tmp['stripe'] = $stripe_details;
|
||||
}
|
||||
// Cache the result
|
||||
self::cache('asArray', $tmp, $this->id);
|
||||
self::setCachedExpiration('asArray', self::$asArrayCacheExpiration, $this->id);
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
@@ -141,6 +153,8 @@ class collected_order_invoices_o extends db
|
||||
*/
|
||||
public function getOrders(bool $count = false): array|int
|
||||
{
|
||||
// Require the invoice collection to be selected
|
||||
self::requireSelected();
|
||||
$orders = new orders_o();
|
||||
$order_ids = $orders->getFieldsWhere(
|
||||
[
|
||||
@@ -542,7 +556,8 @@ class collected_order_invoices_o extends db
|
||||
|
||||
public function objectChanged(): void
|
||||
{
|
||||
//TODO: Add cache invalidation
|
||||
// Invalidate the cache, so the next time the object is requested, it will be fetched from the database
|
||||
self::deleteCached('asArray', $this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -609,6 +624,8 @@ class collected_order_invoices_o extends db
|
||||
foreach ( $orders as $order ) {
|
||||
self::addInvoiceToDraft($order['id'], true, $draft_id, $currency);
|
||||
}
|
||||
// Object changed
|
||||
self::objectChanged();
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -837,6 +854,8 @@ class collected_order_invoices_o extends db
|
||||
// Set the order to the new invoice collection
|
||||
$order_object->invoice_collection_id->set($tmp->id);
|
||||
}
|
||||
// Invalidate the cache for the invoice collection
|
||||
$this->objectChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -912,6 +931,7 @@ class collected_order_invoices_o extends db
|
||||
$transaction->invoice_collection_id->set($this->id);
|
||||
$transaction->created_at->set(self::getFirstDayOfMonth($this->created_at->value()));
|
||||
$transaction->objectChanged();
|
||||
$this->objectChanged();
|
||||
// Add the vehicle subscriptions to the transaction
|
||||
$order_items_o = new order_items_o();
|
||||
foreach ( $vehicle_array as $vehicle ) {
|
||||
@@ -974,6 +994,7 @@ class collected_order_invoices_o extends db
|
||||
$order_item_object->requireSelected();
|
||||
$order_item_object->include_in_invoice->set(0);
|
||||
$order_item_object->price->set((int)self::getWashSubscriptionPrice((new products_o())->select((int)$order_item['product_id'])->price->value()) / 2);
|
||||
$order_item_object->objectChanged();
|
||||
}
|
||||
// Check if the order item product id is equal any of the vehicle subscription addons product id
|
||||
if (isset($vehicle_regs[$order['reg_1']]['addons'][$order_item['product_id']])) {
|
||||
@@ -999,10 +1020,13 @@ class collected_order_invoices_o extends db
|
||||
$order_item_object->requireSelected();
|
||||
$order_item_object->include_in_invoice->set(0);
|
||||
$order_item_object->price->set($tmp_subscription_price);
|
||||
$order_item_object->objectChanged();
|
||||
}
|
||||
}
|
||||
$order_object->objectChanged();
|
||||
}
|
||||
}
|
||||
$this->objectChanged();
|
||||
//print_r($vehicle_array);
|
||||
}
|
||||
|
||||
@@ -1034,6 +1058,8 @@ class collected_order_invoices_o extends db
|
||||
$order->requireSelected();
|
||||
$order->delete();
|
||||
}
|
||||
// Clear the cache for the invoice collection
|
||||
$this->objectChanged();
|
||||
}
|
||||
|
||||
private static function getFirstDayOfMonth(string $timestamp): string
|
||||
@@ -1137,7 +1163,10 @@ class collected_order_invoices_o extends db
|
||||
$order_item_object->requireSelected();
|
||||
$order_item_object->include_in_invoice->set(0);
|
||||
$order_item_object->price->set(0);
|
||||
$order_item_object->objectChanged();
|
||||
}
|
||||
}
|
||||
// Invalidate the cache for the invoice collection
|
||||
$this->objectChanged();
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,11 @@ class customer_vehicles_o extends db
|
||||
public function asArray(): array
|
||||
{
|
||||
self::requireSelected();
|
||||
// Check if the vehicle is cached
|
||||
$cached = $this->getCached('asArray', $this->id);
|
||||
if ($cached) {
|
||||
return (array)$cached;
|
||||
}
|
||||
$wash_subscription = (bool)$this->wash_subscription->value();
|
||||
$addons = self::transformObjectsToArray(
|
||||
self::getAddons()
|
||||
@@ -53,7 +58,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 [
|
||||
$tmp = [
|
||||
'id' => (int)$this->id,
|
||||
'user_id' => (int)(new users_o())->getUserIdFromEconomic((int)$customer_number),
|
||||
'customer_id' => (int)$this->customer_id->value(),
|
||||
@@ -74,6 +79,10 @@ class customer_vehicles_o extends db
|
||||
return $vehicle_type->toArray();
|
||||
}, $this->getVehicleTypes()),
|
||||
];
|
||||
// Cache the result
|
||||
$this->cache('asArray', $tmp, $this->id);
|
||||
$this->setCachedExpiration('asArray', self::$asArrayCacheExpiration, $this->id);
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,7 +246,8 @@ class customer_vehicles_o extends db
|
||||
|
||||
public function objectChanged(): void
|
||||
{
|
||||
// Since the customer_vehicles object is not cached, there is no need to invalidate the cache
|
||||
// Clear the cache for the object
|
||||
$this->deleteCached('asArray', $this->id);
|
||||
}
|
||||
|
||||
public function structure(): void
|
||||
@@ -245,6 +255,11 @@ class customer_vehicles_o extends db
|
||||
$this->setTable('customer_vehicles');
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function getObjectProperties(): void
|
||||
{
|
||||
$this->customer_id = new object_property($this->table, $this->id, 'customer_id', 'int', true);
|
||||
@@ -345,6 +360,7 @@ class customer_vehicles_o extends db
|
||||
$xlvask->updateVehicle($xlvask_vehicle);
|
||||
// Cache the updated vehicle
|
||||
$xlvask->getCache()->setVehicleCache($xlvask_vehicle->registrationNumber, $xlvask_vehicle);
|
||||
$this->objectChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -393,6 +409,7 @@ class customer_vehicles_o extends db
|
||||
/** @var xlvask_vehicles $vehicles */
|
||||
$xlvask_vehicle = $vehicles::getVehicleByRegistrationNumber((string)$this->reg->value());
|
||||
$xlvask->getCache()->setVehicleCache($xlvask_vehicle->registrationNumber, $xlvask_vehicle);
|
||||
$this->objectChanged();
|
||||
return $xlvask_vehicle;
|
||||
}
|
||||
|
||||
@@ -429,5 +446,6 @@ class customer_vehicles_o extends db
|
||||
$xlvask->updateVehicle($xlvask_vehicle);
|
||||
// Cache the updated vehicle
|
||||
$xlvask->getCache()->setVehicleCache($xlvask_vehicle->registrationNumber, $xlvask_vehicle);
|
||||
$this->objectChanged();
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace objects;
|
||||
|
||||
use classes\db;
|
||||
use classes\object_property;
|
||||
use Exception;
|
||||
use traits\db_object_t;
|
||||
|
||||
class order_items_o extends db
|
||||
@@ -62,11 +63,6 @@ class order_items_o extends db
|
||||
$this->setTable('order_items');
|
||||
}
|
||||
|
||||
public function objectChanged(): void
|
||||
{
|
||||
// No need to invalidate the cache, since the order_items object is not cached
|
||||
}
|
||||
|
||||
public function getOrderItemById(int $id): order_items_o
|
||||
{
|
||||
global $db;
|
||||
@@ -113,11 +109,37 @@ class order_items_o extends db
|
||||
if ($related_item_id) {
|
||||
$this->related_item_id->set($related_item_id);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Inform the order object that a new item has been added
|
||||
$this->getOrder()->objectChanged();
|
||||
} catch (Exception $e) {
|
||||
$response->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function objectChanged(): void
|
||||
{
|
||||
// This method is called when the object is changed, to inform the order object
|
||||
// that an item has been added, edited or removed.
|
||||
// This is used to update the order total and other related properties.
|
||||
$order = $this->getOrder();
|
||||
$order->objectChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the order object associated with this order item
|
||||
* @return orders_o The order object associated with this order item
|
||||
* @throws Exception If the order item is not selected
|
||||
* @throws Exception If no order is selected
|
||||
*/
|
||||
public function getOrder(): orders_o
|
||||
{
|
||||
self::requireSelected();
|
||||
return (new orders_o())->select($this->id);
|
||||
}
|
||||
|
||||
public function edit(int $id, int $order_id, int $product_id, string $reference, string $notes, int $cashier_id, int $price, int $quantity): void
|
||||
{
|
||||
global $db, $response;
|
||||
@@ -132,7 +154,9 @@ class order_items_o extends db
|
||||
|
||||
// Set the values of the object properties
|
||||
$this->getObjectProperties();
|
||||
} catch (\Exception $e) {
|
||||
// Inform the order object that an item has been edited
|
||||
$this->objectChanged();
|
||||
} catch (Exception $e) {
|
||||
$response->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
@@ -173,13 +197,17 @@ class order_items_o extends db
|
||||
if ($notes) {
|
||||
$this->notes->set($notes);
|
||||
}
|
||||
$this->objectChanged();
|
||||
|
||||
} catch (\Exception $e) {
|
||||
} catch (Exception $e) {
|
||||
$response->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function removeOrderItem(int $id): void
|
||||
{
|
||||
// TODO: Implement delete() method instead
|
||||
@@ -187,6 +215,8 @@ class order_items_o extends db
|
||||
$this->id = $id;
|
||||
$sql = "DELETE FROM $this->table WHERE id = $this->id or related_item_id = $this->id";
|
||||
$db->query($sql);
|
||||
// Inform the order object that an item has been removed
|
||||
$this->getOrder()->objectChanged();
|
||||
}
|
||||
|
||||
public function getItemAsArray(): array
|
||||
@@ -236,7 +266,8 @@ class order_items_o extends db
|
||||
$db->query($sql);
|
||||
// Set the values of the object properties
|
||||
$this->getObjectProperties();
|
||||
} catch (\Exception $e) {
|
||||
$this->objectChanged();
|
||||
} catch (Exception $e) {
|
||||
$response->error($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ class orders_o extends db
|
||||
public object_property $wash_id; // The XL Vask Wash ID, if any
|
||||
public object_property $lane; // The lane used for the order, if any
|
||||
|
||||
|
||||
public function structure(): void
|
||||
{
|
||||
$this->setTable('orders');
|
||||
@@ -116,9 +117,49 @@ class orders_o extends db
|
||||
{
|
||||
// Set the deleted_at property to the current timestamp
|
||||
$this->deleted_at->set(date('Y-m-d H:i:s'));
|
||||
$this->objectChanged();
|
||||
// Save the object
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception If the order is not selected
|
||||
* This function is called when the order object is changed.
|
||||
*/
|
||||
public function objectChanged(): void
|
||||
{
|
||||
self::requireSelected();
|
||||
// Reset the cached object
|
||||
self::deleteCached('asArray', $this->id);
|
||||
// Inform the order collection that the order has changed
|
||||
$this->getOrderCollection()->objectChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the order collection for the order
|
||||
* @return collected_order_invoices_o The order collection
|
||||
* @throws Exception If the order is not selected
|
||||
*/
|
||||
public function getOrderCollection(): collected_order_invoices_o
|
||||
{
|
||||
self::requireSelected();
|
||||
$order_collection = new collected_order_invoices_o();
|
||||
$order_collection->select($this->invoice_collection_id->value());
|
||||
if (!$order_collection->exists()) {
|
||||
throw new Exception('Order collection not found');
|
||||
}
|
||||
return $order_collection;
|
||||
}
|
||||
|
||||
public function exists(): bool
|
||||
{
|
||||
// Check if the id is greater than 0, and that the deleted_at property is null
|
||||
if ($this->id > 0) {
|
||||
$this->getObjectProperties();
|
||||
return $this->deleted_at->value() === null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function restore(): void
|
||||
{
|
||||
// Set the deleted_at property to null
|
||||
@@ -192,16 +233,6 @@ class orders_o extends db
|
||||
$this->{$data['field']}->set($data['value']);
|
||||
}
|
||||
|
||||
public function exists(): bool
|
||||
{
|
||||
// Check if the id is greater than 0, and that the deleted_at property is null
|
||||
if ($this->id > 0) {
|
||||
$this->getObjectProperties();
|
||||
return $this->deleted_at->value() === null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the order as completed
|
||||
* @throws Exception If the order is not selected
|
||||
@@ -223,11 +254,6 @@ class orders_o extends db
|
||||
$this->objectChanged();
|
||||
}
|
||||
|
||||
public function objectChanged(): void
|
||||
{
|
||||
// Since the orders object is not cached, there is no need to invalidate the cache
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the order by invoice id
|
||||
* @param int $invoiceId
|
||||
@@ -427,22 +453,6 @@ class orders_o extends db
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the order collection for the order
|
||||
* @return collected_order_invoices_o The order collection
|
||||
* @throws Exception If the order is not selected
|
||||
*/
|
||||
public function getOrderCollection(): collected_order_invoices_o
|
||||
{
|
||||
self::requireSelected();
|
||||
$order_collection = new collected_order_invoices_o();
|
||||
$order_collection->select($this->invoice_collection_id->value());
|
||||
if (!$order_collection->exists()) {
|
||||
throw new Exception('Order collection not found');
|
||||
}
|
||||
return $order_collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the wash subscription transactions for a customer
|
||||
* @throws Exception If something goes wrong
|
||||
@@ -473,9 +483,22 @@ class orders_o extends db
|
||||
);
|
||||
}
|
||||
|
||||
public function asArray(): array
|
||||
/**
|
||||
* @return array The order as an array
|
||||
* @throws Exception
|
||||
* Convert the order object to an array
|
||||
*/
|
||||
public function asArray(bool $skipCache = false): array
|
||||
{
|
||||
return [
|
||||
self::requireSelected();
|
||||
if (!$skipCache) {
|
||||
// Check if the object is cached
|
||||
$cached = self::getCached('asArray', $this->id);
|
||||
if ($cached) {
|
||||
return (array)$cached;
|
||||
}
|
||||
}
|
||||
$tmp = [
|
||||
'id' => $this->id,
|
||||
'customer_id' => (int)$this->customer_id->value(),
|
||||
'cashier_id' => (int)$this->cashier_id->value(),
|
||||
@@ -495,6 +518,10 @@ class orders_o extends db
|
||||
'lane' => $this->lane->value(),
|
||||
'closed_at' => (int)$this->invoice_collection_id->value() ? (new collected_order_invoices_o())->select((int)$this->invoice_collection_id->value())->closed_at->value() : null,
|
||||
];
|
||||
// Cache the object
|
||||
self::cache('asArray', $tmp, $this->id);
|
||||
self::setCachedExpiration('asArray', self::$asArrayCacheExpiration, $this->id);
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
public function getNetAmount(): float
|
||||
@@ -754,8 +781,8 @@ class orders_o extends db
|
||||
'',
|
||||
'', //$washItem->OriginalProductName,
|
||||
2285,
|
||||
$washItem->getPriceExVat(),
|
||||
$washItem->Count,
|
||||
(int)$washItem->getUnitPriceExVat(),
|
||||
(int)$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)
|
||||
|
||||
@@ -6,6 +6,7 @@ use classes\limble;
|
||||
use classes\response;
|
||||
use classes\router;
|
||||
use classes\slack;
|
||||
use limble\helpers\limble_tasks_pagination;
|
||||
use limble\helpers\limble_webhook_payload_task;
|
||||
use traits\route_t;
|
||||
|
||||
@@ -21,7 +22,6 @@ class moduleLimbleRoute
|
||||
$this->post('/modules/limble/webhook/task', function () {
|
||||
global $response;
|
||||
$slack = new slack();
|
||||
$slack->send_message('Limble Webhook Task Triggered', 'Limble Webhook');
|
||||
//TODO: Add authentication of some sort here
|
||||
//self::requirePermission('modules_limble_webhooks_task');
|
||||
// Check if the module is enabled
|
||||
@@ -32,14 +32,7 @@ class moduleLimbleRoute
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
$response->error('Invalid JSON payload', 400);
|
||||
}
|
||||
$slack->send_message('TaskId: ' . ($payload['taskID'] ?? 'Not provided'), 'Limble Webhook Task ID');
|
||||
$slack->send_message('Payload: ' . json_encode($payload), 'Limble Webhook Task Payload');
|
||||
$task = new limble_webhook_payload_task($payload);
|
||||
//$task = new $limble->helpers->limble_webhook_payload_task($payload);
|
||||
$slack->send_message('Limble Webhook Task Received: ' . $task->taskID, 'Limble Webhook Task');
|
||||
$slack->send_message('Task Name: ' . $task->taskObject->name, 'Limble Webhook Task Name');
|
||||
// $slack->send_message('Task ID: ' . $payload['task_id'], 'Limble Webhook Task ID');
|
||||
|
||||
// Response
|
||||
$response->success('Debug', 200);
|
||||
},
|
||||
@@ -56,8 +49,10 @@ class moduleLimbleRoute
|
||||
// Check if the module is enabled
|
||||
$limble = new limble();
|
||||
$limble->requireModuleEnabled();
|
||||
$pagination = new limble_tasks_pagination();
|
||||
//$pagination->tasks = 2;
|
||||
// Get the tasks
|
||||
$tasks = $limble->getTasks()->formatTasks($limble->listTasks());
|
||||
$tasks = $limble->getTasks()->formatTasks($limble->listTasks($pagination));
|
||||
// Response
|
||||
$response->success($tasks, 200);
|
||||
},
|
||||
|
||||
@@ -41,7 +41,7 @@ class ordersRoute
|
||||
// Log the incident
|
||||
(new logs_o())->add('orders', 'global', 1, $user->id, 'LIST_ORDERS', 'Successfully listed orders');
|
||||
// Create economic_module_orders object
|
||||
$economic_module_orders = new economic_module_orders();
|
||||
//$economic_module_orders = new economic_module_orders();
|
||||
$orders = new orders_o();
|
||||
if (!$restrict_only_own) {
|
||||
$department_ids = $user->getGroup()->getDepartments();
|
||||
@@ -216,7 +216,8 @@ class ordersRoute
|
||||
if (isset($data['created_at'])) {
|
||||
$order->created_at->set($data['created_at']);
|
||||
}
|
||||
// If the department ID is set, validate it
|
||||
// Void any cached key for the order
|
||||
$order->objectChanged();
|
||||
// Log the incident
|
||||
(new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'EDIT_ORDER', 'Successfully updated an order (ID: ' . $data['id'] . ')');
|
||||
// Return a success message
|
||||
|
||||
@@ -44,10 +44,11 @@ use objects\users_o;
|
||||
|
||||
trait db_object_t
|
||||
{
|
||||
public int $id; // The id of the object in the database
|
||||
private string $table; // The table of the objects in the database (e.g. users)
|
||||
private array $searchableFields = []; // The fields to search in the database (e.g. ['name', 'email']). If empty, all fields will be searched
|
||||
private array $whereClauses = []; // The where clauses to add to the pagination query
|
||||
public static int $asArrayCacheExpiration = 600; // The id of the object in the database
|
||||
public int $id; // The table of the objects in the database (e.g. users)
|
||||
private string $table; // The fields to search in the database (e.g. ['name', 'email']). If empty, all fields will be searched
|
||||
private array $searchableFields = []; // The where clauses to add to the pagination query
|
||||
private array $whereClauses = []; // The cache expiration time for the asArray function, in seconds. This is used to cache the result of the asArray function to improve performance. Default is 10 minutes (600 seconds).
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -744,6 +745,40 @@ trait db_object_t
|
||||
redis->set($this->table . '_' . $objectId . '_' . $key, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cached object expiration time
|
||||
* @param string $key The key to set the cached object expiration time
|
||||
* @param int $seconds The number of seconds to set the cached object expiration time
|
||||
* @param null $objectId
|
||||
* @return void
|
||||
*/
|
||||
public function setCachedExpiration(string $key, int $seconds, $objectId = null): void
|
||||
{
|
||||
// If the object id is not set, use the object id
|
||||
if (!$objectId) {
|
||||
$objectId = $this->id;
|
||||
}
|
||||
// Set the expiration time for the cached data
|
||||
redis->expire($this->table . '_' . $objectId . '_' . $key, $seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cached object key (redis key)
|
||||
* @param string $key The key to get the cached object
|
||||
* @return string The cached object key
|
||||
* @throws Exception If the object is not selected, it throws an exception
|
||||
*/
|
||||
public function getCachedKey(string $key, $objectId = null): string
|
||||
{
|
||||
self::requireSelected();
|
||||
// If the object id is not set, use the object id
|
||||
if (!$objectId) {
|
||||
$objectId = $this->id;
|
||||
}
|
||||
// Return the cached data key
|
||||
return $this->table . '_' . $objectId . '_' . $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached object
|
||||
* @param string $key The key to get the cached object
|
||||
|
||||
Reference in New Issue
Block a user