Add machine wash configuration and controls to self-serve module
This commit is contained in:
@@ -360,9 +360,13 @@ class selfserve_wash_flow implements selfserve_wash_flow_i
|
||||
$allowedServices = $this->normalizeServiceNames(
|
||||
is_array($metadata['allowed_services'] ?? null) ? (array)$metadata['allowed_services'] : []
|
||||
);
|
||||
$machineAvailable = array_key_exists('machine_available', $metadata)
|
||||
$machineWashEnabled = $this->isMachineWashEnabled();
|
||||
if (!$machineWashEnabled) {
|
||||
$allowedServices = $this->withoutMachineService($allowedServices);
|
||||
}
|
||||
$machineAvailable = $machineWashEnabled && (array_key_exists('machine_available', $metadata)
|
||||
? (bool)$metadata['machine_available']
|
||||
: ($lane->exists() && !empty($lane->relay_machine_id->value()));
|
||||
: ($lane->exists() && !empty($lane->relay_machine_id->value())));
|
||||
$allVisibleQuestionsAnswered = array_key_exists('all_visible_questions_answered', $metadata)
|
||||
? (bool)$metadata['all_visible_questions_answered']
|
||||
: true;
|
||||
@@ -408,6 +412,7 @@ class selfserve_wash_flow implements selfserve_wash_flow_i
|
||||
'events' => $events,
|
||||
'allowed_services' => $allowedServices,
|
||||
'machine_available' => $machineAvailable,
|
||||
'machine_wash_enabled' => $machineWashEnabled,
|
||||
'all_visible_questions_answered' => $allVisibleQuestionsAnswered,
|
||||
'allowed' => (bool)$session->allowed->value(),
|
||||
'config_version_id' => $metadata['config_version_id'] ?? null,
|
||||
@@ -687,7 +692,12 @@ class selfserve_wash_flow implements selfserve_wash_flow_i
|
||||
}
|
||||
}
|
||||
|
||||
$machineAvailable = !empty($lane->relay_machine_id->value());
|
||||
$machineWashEnabled = $this->isMachineWashEnabled();
|
||||
if (!$machineWashEnabled) {
|
||||
$allowedServices = $this->withoutMachineService($allowedServices);
|
||||
}
|
||||
|
||||
$machineAvailable = $machineWashEnabled && !empty($lane->relay_machine_id->value());
|
||||
$allVisibleQuestionsAnswered = true;
|
||||
foreach ($visibleQuestions as $question) {
|
||||
if ($question['answer'] === null) {
|
||||
@@ -726,8 +736,10 @@ class selfserve_wash_flow implements selfserve_wash_flow_i
|
||||
'tasks' => $visibleTasks,
|
||||
'allowed_services' => $allowedServices,
|
||||
'machine_available' => $machineAvailable,
|
||||
'machine_wash_enabled' => $machineWashEnabled,
|
||||
'all_visible_questions_answered' => $allVisibleQuestionsAnswered,
|
||||
'allowed' => $machineAllowed,
|
||||
'blocked_reason' => !$machineWashEnabled ? 'Machine wash is disabled globally.' : null,
|
||||
'config_version_id' => $publishedConfigVersionId === null ? null : (int)$publishedConfigVersionId,
|
||||
'config_source' => $configSource,
|
||||
'evaluation_trace' => [
|
||||
@@ -826,6 +838,7 @@ class selfserve_wash_flow implements selfserve_wash_flow_i
|
||||
'tasks' => $snapshot['tasks'],
|
||||
'allowed_services' => $snapshot['allowed_services'],
|
||||
'machine_available' => $snapshot['machine_available'],
|
||||
'machine_wash_enabled' => $snapshot['machine_wash_enabled'] ?? true,
|
||||
'all_visible_questions_answered' => $snapshot['all_visible_questions_answered'],
|
||||
'allowed' => $snapshot['allowed'],
|
||||
'blocked_reason' => $snapshot['blocked_reason'] ?? null,
|
||||
@@ -3310,6 +3323,7 @@ class selfserve_wash_flow implements selfserve_wash_flow_i
|
||||
return [
|
||||
'allowed_services' => $snapshot['allowed_services'],
|
||||
'machine_available' => (bool)$snapshot['machine_available'],
|
||||
'machine_wash_enabled' => (bool)($snapshot['machine_wash_enabled'] ?? true),
|
||||
'all_visible_questions_answered' => (bool)$snapshot['all_visible_questions_answered'],
|
||||
'config_version_id' => $snapshot['config_version_id'] ?? null,
|
||||
'evaluation_trace' => $snapshot['evaluation_trace'] ?? null,
|
||||
@@ -3608,6 +3622,27 @@ class selfserve_wash_flow implements selfserve_wash_flow_i
|
||||
));
|
||||
}
|
||||
|
||||
protected function isMachineWashEnabled(): bool
|
||||
{
|
||||
try {
|
||||
return (new selfserve())->config->machine_wash_enabled->isTrue();
|
||||
} catch (\Throwable) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int,string> $services
|
||||
* @return array<int,string>
|
||||
*/
|
||||
protected function withoutMachineService(array $services): array
|
||||
{
|
||||
return array_values(array_filter(
|
||||
$this->normalizeServiceNames($services),
|
||||
static fn(string $service): bool => $service !== selfserve_lane_services::MACHINE->name
|
||||
));
|
||||
}
|
||||
|
||||
protected function taskUsesMachineControls(array $task): bool
|
||||
{
|
||||
if (in_array(selfserve_lane_services::MACHINE->name, $this->normalizeServiceNames($this->normalizeJsonArray($task['services'] ?? null)), true)) {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace modules\selfserve\config;
|
||||
|
||||
use Exception;
|
||||
use traits\module_config_variable;
|
||||
|
||||
class selfserve_machine_wash_enabled_c
|
||||
{
|
||||
use module_config_variable;
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::setupConfigVariable(
|
||||
'selfserve',
|
||||
'machine_wash_enabled',
|
||||
'bool',
|
||||
true,
|
||||
null,
|
||||
'Whether machine wash is available in customer-facing self-serve flows',
|
||||
'1',
|
||||
false,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
namespace modules\selfserve;
|
||||
require_once WD . '/modules/selfserve/config/selfserve_enabled_c.php';
|
||||
require_once WD . '/modules/selfserve/config/selfserve_machine_wash_enabled_c.php';
|
||||
require_once WD . '/modules/selfserve/config/selfserve_minute_product_c.php';
|
||||
require_once WD . '/modules/selfserve/config/selfserve_machine_wash_minutes_included_c.php';
|
||||
require_once WD . '/modules/selfserve/config/selfserve_dynamic_image_size_c.php';
|
||||
|
||||
use modules\selfserve\config\selfserve_dynamic_image_size_c;
|
||||
use modules\selfserve\config\selfserve_enabled_c;
|
||||
use modules\selfserve\config\selfserve_machine_wash_enabled_c;
|
||||
use modules\selfserve\config\selfserve_machine_wash_minutes_included_c;
|
||||
use modules\selfserve\config\selfserve_minute_product_c;
|
||||
use traits\module_config_t;
|
||||
@@ -21,6 +23,11 @@ class selfserve_c
|
||||
* @var selfserve_enabled_c $enabled
|
||||
*/
|
||||
public selfserve_enabled_c $enabled;
|
||||
/**
|
||||
* Whether machine wash is available in customer-facing self-serve flows
|
||||
* @var selfserve_machine_wash_enabled_c $machine_wash_enabled
|
||||
*/
|
||||
public selfserve_machine_wash_enabled_c $machine_wash_enabled;
|
||||
/**
|
||||
* The product ID used for minute-based self-serve billing
|
||||
* @var selfserve_minute_product_c $minute_product
|
||||
@@ -42,11 +49,13 @@ class selfserve_c
|
||||
$this->setupConfig('selfserve');
|
||||
$this->allowUpdate([
|
||||
selfserve_enabled_c::class,
|
||||
selfserve_machine_wash_enabled_c::class,
|
||||
selfserve_minute_product_c::class,
|
||||
selfserve_machine_wash_minutes_included_c::class,
|
||||
selfserve_dynamic_image_size_c::class
|
||||
]);
|
||||
$this->enabled = new selfserve_enabled_c();
|
||||
$this->machine_wash_enabled = new selfserve_machine_wash_enabled_c();
|
||||
$this->minute_product = new selfserve_minute_product_c();
|
||||
$this->machine_wash_minutes_included = new selfserve_machine_wash_minutes_included_c();
|
||||
$this->dynamic_image_size = new selfserve_dynamic_image_size_c();
|
||||
|
||||
@@ -716,6 +716,12 @@ class moduleSelfServeRoute
|
||||
// Merge services (if any)
|
||||
$merge_services((array)$t->services->value());
|
||||
}
|
||||
if (!$this->isMachineWashEnabled()) {
|
||||
$allowed_services = array_values(array_filter(
|
||||
$allowed_services,
|
||||
static fn(string $service): bool => $service !== selfserve_lane_services::MACHINE->name
|
||||
));
|
||||
}
|
||||
// Persist on lane cache (overwrites previous allowed services)
|
||||
try {
|
||||
$relay_sync = $lane->setAllowedServicesFromVisibleTasks($allowed_services);
|
||||
@@ -1807,12 +1813,21 @@ class moduleSelfServeRoute
|
||||
protected function isSelfServeModuleEnabled(): bool
|
||||
{
|
||||
try {
|
||||
return (bool)(new selfserve())->config->enabled->getVariableValue();
|
||||
return (new selfserve())->config->enabled->isTrue();
|
||||
} catch (\Throwable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected function isMachineWashEnabled(): bool
|
||||
{
|
||||
try {
|
||||
return (new selfserve())->config->machine_wash_enabled->isTrue();
|
||||
} catch (\Throwable) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected function canCustomerUseSelfServeLane(selfserve_lane $lane, int $customer_number): bool
|
||||
{
|
||||
return $customer_number > 0
|
||||
|
||||
@@ -167,12 +167,19 @@ it('wires the all-in-one self-serve studio replacement endpoints', function ():
|
||||
expect($studioGraph)->toContain('resolved');
|
||||
});
|
||||
|
||||
it('wires machine wash included minutes into self-serve module config', function (): void {
|
||||
it('wires machine wash controls into self-serve module config', function (): void {
|
||||
$selfserveConfig = file_get_contents(app_path('modules/selfserve/selfserve_c.php'));
|
||||
$machineWashEnabledConfig = file_get_contents(app_path('modules/selfserve/config/selfserve_machine_wash_enabled_c.php'));
|
||||
|
||||
expect($selfserveConfig)->not->toBeFalse();
|
||||
expect($selfserveConfig)->toContain('selfserve_machine_wash_minutes_included_c');
|
||||
expect($selfserveConfig)->toContain('machine_wash_minutes_included');
|
||||
expect($selfserveConfig)->toContain('selfserve_machine_wash_enabled_c');
|
||||
expect($selfserveConfig)->toContain('machine_wash_enabled');
|
||||
expect($machineWashEnabledConfig)->not->toBeFalse()
|
||||
->and($machineWashEnabledConfig)->toContain("'machine_wash_enabled'")
|
||||
->and($machineWashEnabledConfig)->toContain("'bool'")
|
||||
->and($machineWashEnabledConfig)->toContain('true');
|
||||
});
|
||||
|
||||
it('keeps legacy self-serve CRUD routes syncing canonical drafts', function (): void {
|
||||
@@ -409,6 +416,24 @@ it('filters machine button tasks out of self-serve snapshots when MACHINE is not
|
||||
->and($washFlow)->toContain("\$task['dynamic_images_vehicle_type'] ?? null");
|
||||
});
|
||||
|
||||
it('applies the global machine wash toggle before exposing machine tasks or services', function (): void {
|
||||
$washFlow = file_get_contents(app_path('modules/selfserve/classes/selfserve_wash_flow.php'));
|
||||
$moduleSelfServeRoute = file_get_contents(app_path('routes/moduleSelfServeRoute.php'));
|
||||
|
||||
expect($washFlow)->not->toBeFalse()
|
||||
->and($washFlow)->toContain('$machineWashEnabled = $this->isMachineWashEnabled();')
|
||||
->and($washFlow)->toContain('$allowedServices = $this->withoutMachineService($allowedServices);')
|
||||
->and($washFlow)->toContain('$machineAvailable = $machineWashEnabled && !empty($lane->relay_machine_id->value());')
|
||||
->and($washFlow)->toContain("'machine_wash_enabled' => \$machineWashEnabled")
|
||||
->and($washFlow)->toContain('Machine wash is disabled globally.')
|
||||
->and($washFlow)->toContain('->config->machine_wash_enabled->isTrue()');
|
||||
|
||||
expect($moduleSelfServeRoute)->not->toBeFalse()
|
||||
->and($moduleSelfServeRoute)->toContain('if (!$this->isMachineWashEnabled())')
|
||||
->and($moduleSelfServeRoute)->toContain('selfserve_lane_services::MACHINE->name')
|
||||
->and($moduleSelfServeRoute)->toContain('->config->machine_wash_enabled->isTrue()');
|
||||
});
|
||||
|
||||
it('keeps self-serve force stop distinct from normal STOP relay and gate behavior', function (): void {
|
||||
$washFlow = file_get_contents(app_path('modules/selfserve/classes/selfserve_wash_flow.php'));
|
||||
$sessionObject = file_get_contents(app_path('objects/selfserve_wash_sessions_o.php'));
|
||||
|
||||
Reference in New Issue
Block a user