Enhance invoice and self-serve logic with subuser support
- Add subuser ID management to `selfserve_lane_command_arguments`. - Update `invoice` function to include optional command arguments. - Attach metadata to orders with self-serve and subuser details. - Introduce `OTHER_TYPE_SELF_SERVE_WASH` in `attachment_content`.
This commit is contained in:
@@ -5,6 +5,7 @@ namespace attachments\helpers;
|
||||
class attachment_content
|
||||
{
|
||||
const OTHER_TYPE_WASH_CERTIFICATE = 'WASH_CERTIFICATE';
|
||||
const OTHER_TYPE_SELF_SERVE_WASH = 'SELF_SERVE_WASH';
|
||||
public ?string $image; // Used to store the attachment object name, in the attachment store.
|
||||
public ?string $document; // Used to store the attachment object name, in the attachment store.
|
||||
public ?attachment_relation $relation; // Used to store the attachment relation object.
|
||||
@@ -49,4 +50,4 @@ class attachment_content
|
||||
$this->relation = $relation;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ class selfserve_lane_command_arguments
|
||||
{
|
||||
public ?string $license_plate = null;
|
||||
public ?int $customer_number = null;
|
||||
public ?int $subuser_id = null;
|
||||
public bool $defer_relay_side_effects = false;
|
||||
|
||||
/**
|
||||
@@ -25,6 +26,12 @@ class selfserve_lane_command_arguments
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setSubuserId(?int $subuser_id): self
|
||||
{
|
||||
$this->subuser_id = $subuser_id !== null && $subuser_id > 0 ? $subuser_id : null;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDeferRelaySideEffects(bool $defer_relay_side_effects): self
|
||||
{
|
||||
$this->defer_relay_side_effects = $defer_relay_side_effects;
|
||||
@@ -40,6 +47,9 @@ class selfserve_lane_command_arguments
|
||||
if (array_key_exists('customer_number', $params)) {
|
||||
$this->setCustomerNumber($params['customer_number']);
|
||||
}
|
||||
if (array_key_exists('subuser_id', $params)) {
|
||||
$this->setSubuserId($params['subuser_id'] === null ? null : (int)$params['subuser_id']);
|
||||
}
|
||||
if (array_key_exists('defer_relay_side_effects', $params)) {
|
||||
$this->setDeferRelaySideEffects(filter_var(
|
||||
$params['defer_relay_side_effects'],
|
||||
|
||||
@@ -6,13 +6,18 @@ require_once WD . '/modules/selfserve/helpers/selfserve_lane_mode.php';
|
||||
require_once WD . '/modules/selfserve/classes/selfserve_lane.php';
|
||||
|
||||
use classes\selfserve;
|
||||
use classes\economic;
|
||||
use Exception;
|
||||
use attachments\helpers\attachment_content;
|
||||
use modules\selfserve\classes\selfserve_lane_command_arguments;
|
||||
use modules\selfserve\classes\selfserve_lane;
|
||||
use modules\selfserve\helpers\selfserve_lane_mode;
|
||||
use modules\selfserve\helpers\selfserve_lane_status;
|
||||
use objects\customer_vehicles_o;
|
||||
use objects\order_items_o;
|
||||
use objects\orders_o;
|
||||
use objects\selfserve_wash_sessions_o;
|
||||
use objects\subusers_o;
|
||||
|
||||
trait selfserve_lane_invoice_t
|
||||
{
|
||||
@@ -102,7 +107,7 @@ trait selfserve_lane_invoice_t
|
||||
* @return bool True on success, false on failure
|
||||
* @throws Exception if lane ID is not set, lane is not occupied, customer number or license plate is not set, or product ID is not set
|
||||
*/
|
||||
public function invoice(): bool
|
||||
public function invoice(?selfserve_lane_command_arguments $arguments = null): bool
|
||||
{
|
||||
$this->last_invoice_order_id = null;
|
||||
|
||||
@@ -115,12 +120,10 @@ trait selfserve_lane_invoice_t
|
||||
$included_minutes = $this->resolveIncludedMinutesForBilling();
|
||||
$billable_minutes = $this->calculateBillableMinutes($elapsed_minutes, $included_minutes);
|
||||
|
||||
if ($billable_minutes <= 0) {
|
||||
return true;
|
||||
$order = $this->createInvoiceOrderContext($arguments);
|
||||
if ($billable_minutes > 0) {
|
||||
$this->billable_minutes_order_item = $this->addMinuteBillingLine((int)$order->id, (int)$product_id, $billable_minutes);
|
||||
}
|
||||
|
||||
$order = $this->createInvoiceOrderContext();
|
||||
$this->billable_minutes_order_item = $this->addMinuteBillingLine((int)$order->id, (int)$product_id, $billable_minutes);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -212,10 +215,13 @@ trait selfserve_lane_invoice_t
|
||||
return max(0, $elapsed_minutes - $included_minutes);
|
||||
}
|
||||
|
||||
protected function createInvoiceOrderContext(): orders_o
|
||||
protected function createInvoiceOrderContext(?selfserve_lane_command_arguments $arguments = null): orders_o
|
||||
{
|
||||
$billing_customer_number = $this->getCustomerNumber();
|
||||
$draft_customer_number = (new economic())->getTransactionDraftCustomerNumber();
|
||||
$order_customer_number = $draft_customer_number ?? $billing_customer_number;
|
||||
$order = (new orders_o())->add(
|
||||
$this->getCustomerNumber(),
|
||||
$order_customer_number,
|
||||
self::INVOICE_SYSTEM_USER_ID,
|
||||
'',
|
||||
'',
|
||||
@@ -224,10 +230,101 @@ trait selfserve_lane_invoice_t
|
||||
);
|
||||
$order->lane->set($this->id);
|
||||
$this->last_invoice_order_id = (int)$order->id;
|
||||
$this->attachSelfServeMetadataToOrder($order, $billing_customer_number, $draft_customer_number, $arguments);
|
||||
|
||||
return $order;
|
||||
}
|
||||
|
||||
protected function attachSelfServeMetadataToOrder(
|
||||
orders_o $order,
|
||||
int $billing_customer_number,
|
||||
?int $draft_customer_number,
|
||||
?selfserve_lane_command_arguments $arguments = null
|
||||
): void {
|
||||
try {
|
||||
$order->addAttachment(
|
||||
(new attachment_content())->setOther(
|
||||
$this->buildSelfServeOrderAttachmentPayload($billing_customer_number, $draft_customer_number, $arguments)
|
||||
)
|
||||
);
|
||||
} catch (\Throwable) {
|
||||
// Metadata attachments must not block billing; the order itself is the source of record.
|
||||
}
|
||||
}
|
||||
|
||||
protected function buildSelfServeOrderAttachmentPayload(
|
||||
int $billing_customer_number,
|
||||
?int $draft_customer_number,
|
||||
?selfserve_lane_command_arguments $arguments = null
|
||||
): array {
|
||||
$session = $this->findOpenSelfServeSessionForAttachment($billing_customer_number);
|
||||
$subuser_id = $arguments?->subuser_id;
|
||||
|
||||
return [
|
||||
'type' => attachment_content::OTHER_TYPE_SELF_SERVE_WASH,
|
||||
'source' => 'selfserve',
|
||||
'customer_number' => $billing_customer_number,
|
||||
'draft_customer_number' => $draft_customer_number,
|
||||
'subuser_id' => $subuser_id,
|
||||
'subuser' => $this->formatSelfServeAttachmentSubuser($subuser_id),
|
||||
'session_id' => $session?->id,
|
||||
'lane_id' => (int)$this->id,
|
||||
'department_id' => (int)$this->department_lane->department->value(),
|
||||
'license_plate' => (string)$this->getLicensePlate(),
|
||||
'lane_status' => $this->getLaneStatus()->name,
|
||||
'lane_mode' => $this->getLaneMode()->name,
|
||||
'wash_start_time' => (int)$this->getWashStartTime(),
|
||||
'elapsed_wash_time_seconds' => (int)$this->getElapsedWashTime(),
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function findOpenSelfServeSessionForAttachment(int $billing_customer_number): ?selfserve_wash_sessions_o
|
||||
{
|
||||
$license_plate = trim((string)$this->getLicensePlate());
|
||||
if ($license_plate === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
$session = (new selfserve_wash_sessions_o())->selectLatestOpenByLaneAndReg(
|
||||
(int)$this->id,
|
||||
selfserve::standardize_registration($license_plate),
|
||||
$billing_customer_number > 0 ? $billing_customer_number : null
|
||||
);
|
||||
return $session->exists() ? $session : null;
|
||||
} catch (\Throwable) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected function formatSelfServeAttachmentSubuser(?int $subuser_id): ?array
|
||||
{
|
||||
if ($subuser_id === null || $subuser_id <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
$subuser = (new subusers_o())->select($subuser_id);
|
||||
if (!$subuser->exists()) {
|
||||
return [
|
||||
'id' => $subuser_id,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => (int)$subuser->id,
|
||||
'name' => $subuser->name->value(),
|
||||
'username' => $subuser->username->value(),
|
||||
'email' => $subuser->email->value(),
|
||||
];
|
||||
} catch (\Throwable) {
|
||||
return [
|
||||
'id' => $subuser_id,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
protected function addMinuteBillingLine(int $order_id, int $product_id, int $quantity): order_items_o
|
||||
{
|
||||
return (new order_items_o())->addItemToOrder(
|
||||
|
||||
Reference in New Issue
Block a user