Generalize per-vehicle-option booking rules to Front Seat too

Front Seat previously had a hardcoded max-per-booking check with no enable
toggle; now every Vehicle Option (front_seat/back_seat/whole_vehicle) gets
the same config-driven pair — an on/off toggle and a max passenger_count —
surfaced via new BOOKING_*_ENABLED/BOOKING_*_MAX_PER_BOOKING env vars,
editable from ManageAppSettings, and exposed on route pricing as
max_per_booking.
This commit is contained in:
Nyan Lin Paing
2026-08-30 15:45:27 +07:00
parent 914b7f97f3
commit bebcab88fa
11 changed files with 175 additions and 97 deletions
+4 -5
View File
@@ -27,11 +27,10 @@ Unlike a bus-booking system, **there is no seat map and no capacity tracking in
- A Booking can select **more than one Vehicle Option** in the same booking (e.g. `front_seat` + `back_seat` for a customer traveling with a companion) — stored as one row per selected option in `booking_vehicle_options` (`booking_id`, `vehicle_option`, `passenger_count`, `unit_price`, `line_total`), not a single column on `bookings`. `bookings.price` is the sum of every line's `line_total`.
- Each Vehicle Option can appear **at most once per booking** (no two separate `front_seat` lines — bump `passenger_count` instead). `whole_vehicle` cannot be combined with any other option in the same booking, since it already covers the entire vehicle.
- Any number of *different bookings* can book the same Route + Date + Time Slot. The system does not check whether a "Whole Vehicle" or "Back Seat" is already taken by someone else.
- The **only inventory rule enforced in code** is: **max Front Seats per booking**, checked against `passenger_count` on the `front_seat` line (`BOOKING_FRONT_SEAT_MAX_PER_BOOKING`, currently `1`a per-booking constraint, not a per-trip inventory check).
- Back Seat and Whole Vehicle availability are controlled by **blunt config toggles**, not database rows:
- `BOOKING_BACK_SEAT_ENABLED` — whether Back Seat can be selected at all right now.
- `BOOKING_WHOLE_VEHICLE_ENABLED` — whether Whole Vehicle can be selected at all right now.
- `BOOKING_FRONT_SEAT_MAX_PER_BOOKING` — currently `1`, expressed as config in case it ever needs to change.
- Every Vehicle Option is governed by the same two **blunt config-driven rules**, not database rows: an on/off toggle for whether it can be selected at all right now, and a max `passenger_count` a single booking may request for it (a per-booking constraint, not a per-trip inventory check):
- `BOOKING_FRONT_SEAT_ENABLED` / `BOOKING_FRONT_SEAT_MAX_PER_BOOKING` (currently `1`)
- `BOOKING_BACK_SEAT_ENABLED` / `BOOKING_BACK_SEAT_MAX_PER_BOOKING` (currently `3`)
- `BOOKING_WHOLE_VEHICLE_ENABLED` / `BOOKING_WHOLE_VEHICLE_MAX_PER_BOOKING` (currently `4`)
- This is a **deliberate v1 simplification**, not an oversight. Real per-route/date/time-slot capacity holding (e.g. "only 1 Whole Vehicle booking allowed per trip") is an explicitly deferred future phase — see §7. `booking_vehicle_options` is deliberately shaped so that phase can be built as a new query against it (`sum(passenger_count) group by vehicle_option` for a route/date/time-slot) rather than a schema rework.
- Consequence: double-booking of "Whole Vehicle" is possible by design until that future phase ships. Admins reconcile manually via the Filament Booking list (filterable by route + date + time).