# Vehicle-return workflow ## Preview `POST /api/v1/bookings/{public_ref}/return-preview` takes the same request body as the commit endpoint below and runs the identical evaluation (`evaluate_return()`) with no writes, no audit event and no outbox event — it exists so the UI's review step shows the server's actual answer instead of guessing the outcome client-side. It returns the canonical and submitted odometer readings, whether the submission is a regression, the resulting vehicle status with a human-readable reason, whether a quality issue would be created, and next-booking risk. `register_vehicle_return` (below) calls the same `evaluate_return()` function, so preview and commit cannot drift apart. ## Input - booking public reference; - submitted end odometer; - fuel level 0–100; - cleanliness flag; - damage flag; - technical warning flag; - notes; - idempotency key. ## Transaction 1. Authorize Rental Employee or Operations Manager. 2. Lock booking and vehicle rows. 3. Reject cancelled/already-returned booking unless idempotency replay matches. 4. Validate required fields; compare the submitted reading only with the vehicle's canonical odometer so a lower reading is recorded as evidence instead of rejected. 5. Create a return inspection. 6. Set booking to returned and store submitted end reading. 7. If submitted reading >= canonical odometer, update canonical odometer. 8. Otherwise create `odometer_regression`; keep canonical odometer unchanged. 9. Derive vehicle state: - damage or technical warning -> `blocked`; - service threshold reached -> `maintenance`; - otherwise -> `cleaning`. 10. Create quality issues for contradictions. 11. Create audit events. 12. Insert `vehicle.returned.v1` outbox event. 13. Commit once. ## Post-commit n8n behaviour The event contains enough identifiers to retrieve current state, not an uncontrolled full database snapshot. n8n may create a cleaning/maintenance follow-up through a narrow callback API and return its run ID. ## Failure behaviour - n8n unavailable: return succeeds; event stays pending. - duplicate event delivery: n8n and callback are idempotent by event ID. - callback fails: workflow appears failed and is retryable. - concurrent return submissions: only one succeeds; same idempotency key replays the original response.