Add lane reservation support: implement reservation timer, expiration logic, and new self-serve lane commands (RESERVE and RELEASE); enhance permission checks across routes for global and department-level operations.
This commit is contained in:
@@ -12,6 +12,7 @@ require_once WD . '/modules/selfserve/traits/selfserve_lane_timer_t.php';
|
||||
require_once WD . '/modules/selfserve/traits/selfserve_lane_license_plate_t.php';
|
||||
require_once WD . '/modules/selfserve/traits/selfserve_lane_customer_number_t.php';
|
||||
require_once WD . '/modules/selfserve/traits/selfserve_lane_invoice_t.php';
|
||||
require_once WD . '/modules/selfserve/traits/selfserve_lane_reservation_timer_t.php';
|
||||
require_once WD . '/modules/selfserve/traits/selfserve_lane_log_t.php';
|
||||
|
||||
use modules\selfserve\interfaces\selfserve_lane_i;
|
||||
@@ -23,6 +24,7 @@ use modules\selfserve\traits\selfserve_lane_license_plate_t;
|
||||
use modules\selfserve\traits\selfserve_lane_log_t;
|
||||
use modules\selfserve\traits\selfserve_lane_mode_t;
|
||||
use modules\selfserve\traits\selfserve_lane_port_controller_t;
|
||||
use modules\selfserve\traits\selfserve_lane_reservation_timer_t;
|
||||
use modules\selfserve\traits\selfserve_lane_state_t;
|
||||
use modules\selfserve\traits\selfserve_lane_status_t;
|
||||
use modules\selfserve\traits\selfserve_lane_timer_t;
|
||||
@@ -39,6 +41,7 @@ class selfserve_lane implements selfserve_lane_i
|
||||
selfserve_lane_license_plate_t,
|
||||
selfserve_lane_customer_number_t,
|
||||
selfserve_lane_invoice_t,
|
||||
selfserve_lane_reservation_timer_t,
|
||||
selfserve_lane_log_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,8 @@ enum selfserve_lane_command
|
||||
case START; // command to start the lane
|
||||
case STOP; // command to stop the lane
|
||||
case RESET; // command to reset the lane
|
||||
case RESERVE; // command to reserve the lane
|
||||
case RELEASE; // command to release the lane (from reservation)
|
||||
|
||||
public static function tryFrom(string $commandParam): ?selfserve_lane_command
|
||||
{
|
||||
@@ -14,6 +16,8 @@ enum selfserve_lane_command
|
||||
'START' => selfserve_lane_command::START,
|
||||
'STOP' => selfserve_lane_command::STOP,
|
||||
'RESET' => selfserve_lane_command::RESET,
|
||||
'RESERVE' => selfserve_lane_command::RESERVE,
|
||||
'RELEASE' => selfserve_lane_command::RELEASE,
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ trait selfserve_lane_cache_t
|
||||
const CACHE_SELFSERVE_LANE_KEY_STATE = self::CACHE_SELFSERVE_PREFIX . 'state';
|
||||
const CACHE_SELFSERVE_LANE_KEY_MODE = self::CACHE_SELFSERVE_PREFIX . 'mode';
|
||||
const CACHE_SELFSERVE_LANE_KEY_WASH_START_TIME = self::CACHE_SELFSERVE_PREFIX . 'wash_start_time';
|
||||
|
||||
const CACHE_SELFSERVE_LANE_KEY_RESERVATION_START_TIME = self::CACHE_SELFSERVE_PREFIX . 'lane_reservation_start_time';
|
||||
const CACHE_SELFSERVE_LANE_KEY_CUSTOMER_NUMBER = self::CACHE_SELFSERVE_PREFIX . 'customer_number';
|
||||
const CACHE_SELFSERVE_LANE_KEY_LICENSE_PLATE = self::CACHE_SELFSERVE_PREFIX . 'license_plate';
|
||||
|
||||
|
||||
@@ -33,6 +33,35 @@ trait selfserve_lane_command_t
|
||||
{
|
||||
// Handle the command
|
||||
switch ($command) {
|
||||
case selfserve_lane_command::RESERVE:
|
||||
// Require lane to be available before reserving
|
||||
if (!$this->getLaneStatus()->equals(selfserve_lane_status::AVAILABLE)) throw new \RuntimeException("Cannot reserve lane: Lane is not available.");
|
||||
// Require the customer number
|
||||
if (empty($customer_number = $arguments->customer_number)) throw new \InvalidArgumentException("Customer number is required to reserve the lane.");
|
||||
// Validate customer number
|
||||
if (!is_numeric($customer_number) || (int)$customer_number <= 0) throw new \InvalidArgumentException("Invalid customer number: " . $customer_number);
|
||||
if (!(new users_o())->getUserByCustomerNumber((int)$customer_number)->exists()) throw new \InvalidArgumentException("Customer number does not exist: " . $customer_number);
|
||||
// Set the customer number
|
||||
$this->setCustomerNumber($customer_number);
|
||||
// Set the lane status to RESERVED when reserved
|
||||
$this->setLaneStatus(selfserve_lane_status::RESERVED);
|
||||
// Set the reservation time
|
||||
$this->setReservationStartTime(time());
|
||||
// Log the lane reserve event
|
||||
$this->logLaneAction(selfserve_lane_log_action::RESERVE_LANE);
|
||||
break;
|
||||
case selfserve_lane_command::RELEASE:
|
||||
// Require lane to be reserved before releasing
|
||||
if (!$this->getLaneStatus()->equals(selfserve_lane_status::RESERVED)) throw new \RuntimeException("Cannot release lane: Lane is not reserved.");
|
||||
// Check if the customer number equals the argument customer number
|
||||
if (($this->getCustomerNumber() !== $arguments->customer_number) && !$this->isBypassCustomerNumberValidation()) {
|
||||
throw new \InvalidArgumentException("Customer number mismatch: Lane customer number " . $this->getCustomerNumber() . " does not match argument customer number " . $arguments->customer_number);
|
||||
}
|
||||
// Reset the lane
|
||||
self::execute(selfserve_lane_command::RESET, new selfserve_lane_command_arguments());
|
||||
// Log the lane release event
|
||||
$this->logLaneAction(selfserve_lane_log_action::RELEASE_LANE);
|
||||
break;
|
||||
case selfserve_lane_command::START:
|
||||
// Require lane to be available before starting
|
||||
if (!$this->getLaneStatus()->equals(selfserve_lane_status::AVAILABLE)) throw new \RuntimeException("Cannot start lane: Lane is not available.");
|
||||
@@ -81,6 +110,7 @@ trait selfserve_lane_command_t
|
||||
$this->setWashStartTime(self::DEFAULT_WASH_START_TIME);
|
||||
$this->setCustomerNumber(self::DEFAULT_CUSTOMER_NUMBER);
|
||||
$this->setLicensePlate(self::DEFAULT_LICENSE_PLATE);
|
||||
$this->setReservationStartTime(null);
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException("Unknown command: " . $command->name);
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace modules\selfserve\traits;
|
||||
require_once WD . '/modules/selfserve/helpers/selfserve_lane_status.php';
|
||||
require_once WD . '/modules/selfserve/classes/selfserve_lane.php';
|
||||
use modules\selfserve\classes\selfserve_lane;
|
||||
use modules\selfserve\classes\selfserve_lane_command_arguments;
|
||||
use modules\selfserve\helpers\selfserve_lane_command;
|
||||
use modules\selfserve\helpers\selfserve_lane_status;
|
||||
|
||||
trait selfserve_lane_reservation_timer_t
|
||||
{
|
||||
const DEFAULT_LANE_RESERVATION_TIME = 300 * 1000; // Default reservation time in milliseconds (5 minutes)
|
||||
/**
|
||||
* The timestamp of the reservation time of the lane
|
||||
* @var int|null $reservation_start_time
|
||||
*/
|
||||
public ?int $reservation_start_time = null;
|
||||
|
||||
/**
|
||||
* Get the lane reservation time
|
||||
* @return int|null The timestamp of the reservation time of the lane, or null if not set
|
||||
*/
|
||||
public function getReservationStartTime(): ?int
|
||||
{
|
||||
$reservation_start_time = $this->getLaneCache($this->id, self::CACHE_SELFSERVE_LANE_KEY_RESERVATION_START_TIME);
|
||||
if (!empty($reservation_start_time)) {
|
||||
$this->reservation_start_time = $reservation_start_time;
|
||||
}
|
||||
return $this->reservation_start_time;
|
||||
}
|
||||
/**
|
||||
* Set the lane reservation time
|
||||
* @param int|null $timestamp The timestamp of the reservation time of the lane, or null to clear
|
||||
* @return selfserve_lane_reservation_timer_t|selfserve_lane
|
||||
*/
|
||||
public function setReservationStartTime(?int $timestamp): self
|
||||
{
|
||||
$this->reservation_start_time = $timestamp;
|
||||
$this->setLaneCache($this->id, self::CACHE_SELFSERVE_LANE_KEY_RESERVATION_START_TIME, $this->reservation_start_time);
|
||||
return $this;
|
||||
}
|
||||
/**
|
||||
* Get the elapsed time since the reservation started
|
||||
* @return int|null The elapsed time in seconds since the reservation started, or null if reservation has not started
|
||||
*/
|
||||
public function getElapsedReservationTime(): ?int
|
||||
{
|
||||
$reservation_start_time = $this->getReservationStartTime();
|
||||
if ($reservation_start_time === null) {
|
||||
return null; // Reservation has not started
|
||||
}
|
||||
return time() - $reservation_start_time;
|
||||
}
|
||||
/**
|
||||
* Get remaining reservation time
|
||||
* @return int|null The remaining reservation time in seconds, or null if the reservation has not started
|
||||
*/
|
||||
public function getRemainingReservationTime(): ?int
|
||||
{
|
||||
$elapsed_time = $this->getElapsedReservationTime();
|
||||
if ($elapsed_time === null) {
|
||||
return null; // Reservation has not started
|
||||
}
|
||||
$remaining_time = (self::DEFAULT_LANE_RESERVATION_TIME / 1000) - $elapsed_time;
|
||||
return max($remaining_time, 0);
|
||||
}
|
||||
/**
|
||||
* Check if the reservation has expired
|
||||
* @return bool True if the reservation has expired, false otherwise
|
||||
*/
|
||||
public function isReservationExpired(): bool
|
||||
{
|
||||
$remaining_time = $this->getRemainingReservationTime();
|
||||
if ($remaining_time === null) {
|
||||
return false; // Reservation has not started
|
||||
}
|
||||
return $remaining_time <= 0;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,11 @@
|
||||
namespace modules\selfserve\traits;
|
||||
require_once WD . '/modules/selfserve/helpers/selfserve_lane_status.php';
|
||||
require_once WD . '/modules/selfserve/classes/selfserve_lane.php';
|
||||
|
||||
use Exception;
|
||||
use modules\selfserve\classes\selfserve_lane;
|
||||
use modules\selfserve\classes\selfserve_lane_command_arguments;
|
||||
use modules\selfserve\helpers\selfserve_lane_command;
|
||||
use modules\selfserve\helpers\selfserve_lane_log_action;
|
||||
use modules\selfserve\helpers\selfserve_lane_status;
|
||||
|
||||
@@ -20,6 +24,7 @@ trait selfserve_lane_status_t
|
||||
/**
|
||||
* Get the current status of the self-serve lane
|
||||
* @return selfserve_lane_status The current status of the self-serve lane
|
||||
* @throws Exception If the execution of the release command fails
|
||||
*/
|
||||
public function getLaneStatus(): selfserve_lane_status
|
||||
{
|
||||
@@ -32,6 +37,11 @@ trait selfserve_lane_status_t
|
||||
$this->status = selfserve_lane_status::AVAILABLE;
|
||||
$this->setLaneCache($this->id, self::CACHE_SELFSERVE_LANE_KEY_STATUS, $this->status);
|
||||
}
|
||||
// If the status is RESERVED, check if the reservation has expired
|
||||
if ($this->status->equals(selfserve_lane_status::RESERVED) && $this->isReservationExpired()) {
|
||||
// Release the lane if the reservation has expired
|
||||
$this->execute(selfserve_lane_command::RELEASE, new selfserve_lane_command_arguments());
|
||||
}
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace modules\selfserve\traits;
|
||||
require_once WD . '/modules/selfserve/helpers/selfserve_lane_status.php';
|
||||
require_once WD . '/modules/selfserve/classes/selfserve_lane.php';
|
||||
use modules\selfserve\classes\selfserve_lane;
|
||||
use modules\selfserve\helpers\selfserve_lane_status;
|
||||
|
||||
trait selfserve_lane_timer_t
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user