add Group 9 delivery scenarios for self-haul and last-mile paths

- Implemented G9·S38 tests for customer self-haul truck assignments, ensuring compliance with container limits and truck assignments.
- Added G9·S39 tests for last-mile delivery, self-haul, and yard pickup, verifying independent paths for multiple bookings on the same train.
- Created seed data for Group 1 and Group 2 scenarios, ensuring proper setup for weight and capacity tests.
- Updated booking interface to deprecate  in favor of  for better clarity in allocations.
This commit is contained in:
Marshal
2026-08-01 12:14:37 +00:00
parent 3424dacd5f
commit 123f925cc1
32 changed files with 6928 additions and 80 deletions

View File

@@ -100,6 +100,67 @@ Full map in `cypress/fixtures/users.json`.
the DB at the start of each test: switching origin between tests reloads
the spec bundle, so module-level variables do NOT survive across tests.
### The 40-scenario suite (`flows/g1_*` … `flows/g10_*`)
S1S40 from the scenario document, one file per group after Group 1:
| File | Scenarios | Subject |
| --- | --- | --- |
| `g1_s1_expiry_promotes_waitlist.cy.ts` | S1 | expiry frees exactly the waitlist's space |
| `g1_s2_exact_fill.cy.ts` | S2 | four bookings fill the train to the slot |
| `g1_s3_underfill_day_stays_open.cy.ts` | S3 | under-filled day stays bookable |
| `g1_s4_split_closes_gap.cy.ts` | S4 | a split closes the last gap |
| `g1_s5_cascading_expiry.cy.ts` | S5 | one expiry cascades into a second promotion |
| `g1_s6_s8_offers_and_priority.cy.ts` | S6S8 | declined split, government preemption, priority tiers |
| `g2_weight.cy.ts` | S9S12 | weight vs slots, and the tolerance rules |
| `g3_export.cy.ts` | S13S18 | export FCFS, whole-or-nothing |
| `g4_multi_schedule.cy.ts` | S19S21 | two trains on one day |
| `g5_waitlist.cy.ts` | S22S24 | recovery: rebooking, split remainders, queue walking |
| `g6_corridor.cy.ts` | S25S29 | the run: alighting, tracking, checkpoints |
| `g7_disruptions.cy.ts` | S30S33 | cancel, wagon shortage, breakage, under-filled dispatch |
| `g8_import_customs.cy.ts` | S34S37 | the clearance chain |
| `g9_delivery.cy.ts` | S38S39 | self-haul trucks and last-mile |
| `g10_validation.cy.ts` | S40 | line validation and the parked re-priced booking |
**Read `SCENARIO_ENGINE_NOTES.md` before changing any of these.** Five
scenarios describe behaviour the engine does not implement (out-of-order
checkpoints, second-duty gating, hazardous/reefer clamping) or invert what it
does (mid-corridor intercity). Those are written as a passing test of CURRENT
behaviour plus an adjacent `it.skip` naming the desired behaviour — un-skipping
one is the definition of done for the corresponding fix, not a test repair.
Three specs are also flag- or policy-dependent and say so in their headers:
`g3_export` needs `FREIGHT_EXPORT_SPLIT` off, and `g4_multi_schedule` asserts
the whole-placement policy (S20) rather than the fill-first one (S21).
### Group 1 conventions (`flows/g1_*.cy.ts`)
The visual counterpart to the corridor suite — helpers in `flows/g1-utils.ts`,
arrange-data in `fixtures/seed-g1-train.sql` (run it AFTER
`seed-import-corridor.sql`).
Two things make these different from the older flow specs:
- **A 53-wagon BUILT train** (`TRN-G1-1`), not a loco pair. A loco-pair
schedule cannot hold 53: `syncScheduleMaxWagons` recomputes `max_wagons`
from locomotive length (`floor(760 / 13.966) = 54` on this corridor). A
built train's physical consist wins outright — see
`booking-batch.service.ts:4152`. The consist staff marshal IS the capacity.
- **The configuration phase and every capacity verdict run through the UI**:
the consist is seen in the Train Builder, the schedule is created through
the real "New schedule" form, the batch is run from the
`Doc review complete — run batch` button, and FULL/NOT FULL is read off the
batch board's Priority Tracking tab — which renders the literal
`Capacity line · 53/53 wagons · FULL` divider plus `In the batch` /
`Waiting list` / `Expired` lanes.
Bulk cargo still goes through the API (`bookContainers`): a 30-wagon booking
is 30-60 ISO-number inputs, which tests the form rather than the engine. Each
scenario books its ONE small booking visually via
`bookContainersVisually()`. **Payment is always API-driven** — the portal has
no mock payment path; "Pay now" redirects off-origin to a real gateway, which
Cypress cannot follow.
## Extending
Deep module flows (booking wizard → staff approval → scheduling → billing)