From 2b6a8eedccdbe394d5cdfba630e854a7528ea18d Mon Sep 17 00:00:00 2001 From: Jeppe Bundgaard Date: Thu, 4 Jun 2026 08:07:40 +0200 Subject: [PATCH] Avoid session creation on MyWash summary refresh --- ...artmentSelfserveVehicleConditionsRoute.php | 23 +++++++-- .../Api/SelfserveCustomerStartApiTest.php | 48 +++++++++++++++++++ .../Selfserve/SelfserveRouteWiringTest.php | 3 +- 3 files changed, 70 insertions(+), 4 deletions(-) diff --git a/services/nginx/app/routes/departmentSelfserveVehicleConditionsRoute.php b/services/nginx/app/routes/departmentSelfserveVehicleConditionsRoute.php index 226d46ca..bf4fe90b 100644 --- a/services/nginx/app/routes/departmentSelfserveVehicleConditionsRoute.php +++ b/services/nginx/app/routes/departmentSelfserveVehicleConditionsRoute.php @@ -177,7 +177,7 @@ class departmentSelfserveVehicleConditionsRoute $this->assertSummaryAccess($user, $summary, $has_global, $has_own, 'list_department_selfserve_vehicle_conditions'); if ($this->shouldRefreshSummaryForVehicleType($summary, $vehicle_type_id)) { - $summary = $flow->synchronizeSession( + $refreshed_summary = $flow->synchronizeSession( (int)($summary['session']['lane_id'] ?? 0), (string)($summary['session']['reg'] ?? ''), isset($summary['session']['customer_number']) && $summary['session']['customer_number'] !== null @@ -185,8 +185,12 @@ class departmentSelfserveVehicleConditionsRoute : null, false, $vehicle_type_id, - false + false, + ['create_session' => false] ); + if (!empty($refreshed_summary['session']['id'])) { + $summary = $refreshed_summary; + } } $response->success($summary); @@ -203,7 +207,16 @@ class departmentSelfserveVehicleConditionsRoute } if ($vehicle_type_id !== null) { - $summary = $flow->synchronizeSession($lane_id, $reg, $customer_number, false, $vehicle_type_id, false); + $summary = $flow->synchronizeSession($lane_id, $reg, $customer_number, false, $vehicle_type_id, false, [ + 'create_session' => false, + ]); + if (empty($summary['session']['id'])) { + try { + $summary = $flow->getLatestSessionSummary($lane_id, $reg); + } catch (\RuntimeException) { + // Keep the read-only snapshot when no previous wash exists. + } + } } else { $summary = $flow->getLatestSessionSummary($lane_id, $reg); } @@ -493,6 +506,10 @@ class departmentSelfserveVehicleConditionsRoute } $session = is_array($summary['session'] ?? null) ? $summary['session'] : []; + if (($session['completed_at'] ?? null) !== null || selfserve_wash_sessions_o::isTerminalStatus($session['status'] ?? null)) { + return false; + } + $sessionVehicleTypeId = isset($session['vehicle_type_id']) && $session['vehicle_type_id'] !== null ? (int)$session['vehicle_type_id'] : null; diff --git a/services/nginx/app/tests/Api/SelfserveCustomerStartApiTest.php b/services/nginx/app/tests/Api/SelfserveCustomerStartApiTest.php index 5dd64cb0..37730a61 100644 --- a/services/nginx/app/tests/Api/SelfserveCustomerStartApiTest.php +++ b/services/nginx/app/tests/Api/SelfserveCustomerStartApiTest.php @@ -359,3 +359,51 @@ it('does not create an active wash preview session from read-only eligibility ch expect($openSession)->toBeNull(); }); + +it('does not create a replacement session when refreshing a completed summary with vehicle type', function (): void { + $group = api_fixtures()->createGroup([], [ + 'list_own_department_selfserve_vehicle_conditions', + ]); + $scenario = api_fixtures()->createSelfServeScenario([ + 'customer' => ['group_id' => $group['id']], + 'department_selfserve_enabled' => true, + 'lane_selfserve_enabled' => true, + 'session' => [ + 'status' => 'COMPLETED', + 'completed_at' => date('Y-m-d H:i:s'), + ], + ]); + $headers = api_fixtures()->bearerHeaders( + api_fixtures()->createAuthToken((int)$scenario['customer']['id']) + ); + $laneId = (int)$scenario['lane']['id']; + $reg = (string)$scenario['vehicle']['reg']; + $productId = (int)$scenario['product']['id']; + $sessionId = (int)$scenario['session']['id']; + + selfserve_customer_start_make_available($laneId); + + $summaryResponse = api_client() + ->get( + '/department/selfserve/washes/summary?lane_id=' . $laneId + . '®=' . urlencode($reg) + . '&vehicle_type=' . $productId, + $headers + ) + ->assertStatus(200) + ->assertSuccess(true); + + expect($summaryResponse->data()['session']['id'] ?? null)->toBe($sessionId) + ->and($summaryResponse->data()['session']['status'] ?? null)->toBe('COMPLETED'); + + $openSession = api_test_runtime()->queryOne( + 'SELECT id FROM selfserve_wash_sessions' + . ' WHERE lane_id = ' . $laneId + . ' AND reg = "' . api_test_runtime()->db()->real_escape_string($reg) . '"' + . ' AND completed_at IS NULL' + . ' AND deleted_at IS NULL' + . ' LIMIT 1' + ); + + expect($openSession)->toBeNull(); +}); diff --git a/services/nginx/app/tests/Unit/Selfserve/SelfserveRouteWiringTest.php b/services/nginx/app/tests/Unit/Selfserve/SelfserveRouteWiringTest.php index ba78d7ab..bbb2f6fc 100644 --- a/services/nginx/app/tests/Unit/Selfserve/SelfserveRouteWiringTest.php +++ b/services/nginx/app/tests/Unit/Selfserve/SelfserveRouteWiringTest.php @@ -485,7 +485,8 @@ it('keeps read-only self-serve preview and summary refreshes from touching relay expect($vehicleConditionsRoute)->toContain('$flow->synchronizeSession($lane_id, $reg, $customer_number, false, $vehicle_type_id, false, ['); expect($vehicleConditionsRoute)->toContain("'create_session' => false"); expect($vehicleConditionsRoute)->toContain('$summary = $flow->synchronizeSession('); - expect($vehicleConditionsRoute)->toContain('$summary = $flow->synchronizeSession($lane_id, $reg, $customer_number, false, $vehicle_type_id, false);'); + expect($vehicleConditionsRoute)->toContain('$summary = $flow->synchronizeSession($lane_id, $reg, $customer_number, false, $vehicle_type_id, false, ['); + expect($vehicleConditionsRoute)->toContain('$summary = $flow->getLatestSessionSummary($lane_id, $reg);'); expect($vehicleConditionsRoute)->toContain('$activate_machine = $this->requestBooleanFlag(\'activate_machine\', true);'); expect($vehicleConditionsRoute)->toContain('$sync_relay_state = $this->requestBooleanFlag(\'sync_relay_state\', true);'); expect($vehicleConditionsRoute)->toContain('$this->getWashFlow()->synchronizeSession($lane, $reg, $customer_id, $activate_machine, $vehicle_type_id, $sync_relay_state);');