Add support for self-serve task services and validation logic

- Introduce `services` property to `department_selfserve_tasks_o` for task-specific functionalities.
- Add service validation and normalization via `selfserve_lane_services` enum.
- Extend `departmentSelfserveTasksRoute` to handle `services` input for add/edit operations.
- Create `selfserve_lane_services` enum to define and validate service types.
This commit is contained in:
Jeppe Bundgaard
2026-02-18 12:47:00 +01:00
parent efaed8c6cc
commit 008e2af09a
3 changed files with 118 additions and 2 deletions
@@ -0,0 +1,9 @@
<?php
namespace modules\selfserve\helpers;
enum selfserve_lane_services
{
case MACHINE; // Relay that controls the machine power
}
@@ -5,6 +5,8 @@ namespace objects;
use classes\db;
use classes\object_property;
use Exception;
use modules\selfserve\helpers\selfserve_lane_command;
use modules\selfserve\helpers\selfserve_lane_services;
use traits\db_object_t;
class department_selfserve_tasks_o extends db
@@ -18,6 +20,7 @@ class department_selfserve_tasks_o extends db
public object_property $task; // The task
public object_property $description; // The task description
public object_property $order_priority; // The order priority of the task (lower numbers are shown first)
public object_property $services; // The services that the task enables (json), this is used to enable machine wash.
public object_property $created_at;
public object_property $updated_at;
public object_property $deleted_at;
@@ -53,10 +56,11 @@ class department_selfserve_tasks_o extends db
* @param string $task The task text
* @param string $description The task description
* @param int $order_priority The order priority of the task (lower numbers are shown first)
* @param selfserve_lane_services[]|null $services The services that the task enables (json), this is used to enable machine wash.
* @return department_selfserve_tasks_o
* @throws Exception If the object was not created successfully
*/
public function add(int $department, int $lane, int $product, int|null $condition_id, string $task, string $description, int $order_priority = 0): department_selfserve_tasks_o
public function add(int $department, int $lane, int $product, int|null $condition_id, string $task, string $description, int $order_priority = 0, ?array $services = null): self
{
global /** @var db $db */
$db;
@@ -70,6 +74,33 @@ class department_selfserve_tasks_o extends db
$task = $db->escape_string($task);
$description = $db->escape_string($description);
$order_priority = (int)$order_priority;
// If the services array is not null, validate and normalize to array of service names (strings)
$services_names = null;
if (!is_null($services)) {
$services_names = [];
foreach ($services as $service) {
if ($service instanceof selfserve_lane_services) {
$services_names[] = $service->name; // store by name
continue;
}
if (is_string($service)) {
$name = strtoupper(trim($service));
$valid = false;
foreach (selfserve_lane_services::cases() as $case) {
if ($case->name === $name) {
$valid = true;
break;
}
}
if (!$valid) {
throw new Exception("Invalid service: " . $service);
}
$services_names[] = $name;
continue;
}
throw new Exception("Invalid service type");
}
}
// Add the object
$tmp_id = self::add_object([
'department' => $department,
@@ -79,6 +110,7 @@ class department_selfserve_tasks_o extends db
'task' => $task,
'description' => $description,
'order_priority' => $order_priority,
'services' => $services_names,
]);
$this->id = $tmp_id;
self::getObjectProperties();
@@ -96,6 +128,7 @@ class department_selfserve_tasks_o extends db
$this->task = new object_property($this->table, $this->id, 'task', 'string', false);
$this->description = new object_property($this->table, $this->id, 'description', 'string', false);
$this->order_priority = new object_property($this->table, $this->id, 'order_priority', 'int', false);
$this->services = new object_property($this->table, $this->id, 'services', 'json', false);
$this->created_at = new object_property($this->table, $this->id, 'created_at', 'timestamp', false);
$this->updated_at = new object_property($this->table, $this->id, 'updated_at', 'timestamp', false);
$this->deleted_at = new object_property($this->table, $this->id, 'deleted_at', 'timestamp', false);
@@ -117,6 +150,7 @@ class department_selfserve_tasks_o extends db
'task' => (string)$this->task->value(),
'description' => (string)$this->description->value(),
'order_priority' => (int)$this->order_priority->value(),
'services' => (array)$this->services->value(),
// Timestamps
'created_at' => (string)$this->created_at->value(),
'updated_at' => (string)$this->updated_at->value(),
@@ -12,6 +12,7 @@ use objects\logs_o;
use attachments\helpers\attachment_content;
use classes\attachment_store;
use classes\attachments;
use modules\selfserve\helpers\selfserve_lane_services;
use traits\route_t;
class departmentSelfserveTasksRoute
@@ -109,6 +110,40 @@ class departmentSelfserveTasksRoute
$task = (string)$response->getRequestParameter('task');
$description = (string)$response->getRequestParameter('description');
$order_priority = (int)($response->getRequestParameter('order_priority') ?? 0);
// Optional services
$services_param = $response->isRequestParameterSet('services') ? $response->getRequestParameter('services') : null;
$services_enums = null;
if (!is_null($services_param)) {
// Accept array, JSON string, or comma-separated string
$raw = $services_param;
if (is_string($raw)) {
$decoded = json_decode($raw, true);
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
$raw = $decoded;
} else {
$raw = array_filter(array_map(function ($s) { return trim($s); }, explode(',', $services_param)), fn($s) => $s !== '');
}
}
if (!is_array($raw)) {
$response->error('Invalid format for services. Expected array, JSON array, or comma-separated string of service names.', 400);
}
// Map to enum cases by name (case-insensitive)
$services_enums = [];
foreach ($raw as $srv) {
$name = strtoupper(is_string($srv) ? trim($srv) : (string)$srv);
$matched = null;
foreach (selfserve_lane_services::cases() as $case) {
if ($case->name === $name) {
$matched = $case;
break;
}
}
if (!$matched) {
$response->error('Invalid service: ' . (string)$srv, 400);
}
$services_enums[] = $matched;
}
}
if (!$department || !$lane || !$product || !$task || !$description) {
$response->error('Missing required fields', 400);
@@ -127,7 +162,8 @@ class departmentSelfserveTasksRoute
$condition_id,
$task,
$description,
$order_priority
$order_priority,
$services_enums,
);
(new logs_o())->add('department_selfserve_tasks', 'global', 1, $user->id, 'ADD_TASK', 'User added a department self-serve task: ' . $task);
$response->success($task_o->asArray());
@@ -188,6 +224,43 @@ class departmentSelfserveTasksRoute
if (self::isParametersSet(['order_priority'])) {
$task_o->order_priority->set((int)self::getParameter('order_priority'));
}
if (self::isParametersSet(['services'])) {
$param = self::getParameter('services');
if ($param === null) {
// Explicitly clear services
$task_o->services->set(null);
} else {
$raw = $param;
if (is_string($raw)) {
$decoded = json_decode($raw, true);
if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
$raw = $decoded;
} else {
$raw = array_filter(array_map(function ($s) { return trim($s); }, explode(',', $param)), fn($s) => $s !== '');
}
}
if (!is_array($raw)) {
$response->error('Invalid format for services. Expected array, JSON array, or comma-separated string of service names.', 400);
}
// Validate and store names
$names = [];
foreach ($raw as $srv) {
$name = strtoupper(is_string($srv) ? trim($srv) : (string)$srv);
$valid = false;
foreach (selfserve_lane_services::cases() as $case) {
if ($case->name === $name) {
$valid = true;
break;
}
}
if (!$valid) {
$response->error('Invalid service: ' . (string)$srv, 400);
}
$names[] = $name;
}
$task_o->services->set($names);
}
}
(new logs_o())->add('department_selfserve_tasks', 'global', 1, $user->id, 'EDIT_TASK', 'User updated department self-serve task ID: ' . $id);
$response->success($task_o->asArray());