-- Arrange-data for flows/segment_weight.cy.ts. Idempotent. -- Run AFTER seed-intercity.sql + seed-export.sql (container types, E2E_WHEAT -- cargo, Mojo→Djibouti rates, yard distances come from those). -- -- Two dedicated trains on the Mojo → Dire Dawa → Djibouti Port corridor: -- -- TRN-SEG-W ("tolerance train") — locos 240T pull; LOCO-SEG-A carries a 90T -- overage tolerance, LOCO-SEG-B has NONE CONFIGURED (null). The S-2026-00024 -- regression pair: min-across-locos must keep the 90, not zero it. -- Consist: 2 CW4 (bulk) + 2 NW5 (containers). -- -- TRN-SEG-F ("border-full train") — locos 200T pull, no tolerance. -- Consist: 4 NW5. An 8×20ft export boarding at Dire Dawa commits every -- wagon on the border edge → the train goes FULL for its trade direction -- while the Mojo→Dire leg stays free: an intercity ride-along boards the -- SAME wagons there and alights before the export loads them. -- -- Wagons are dedicated inserts (WGN-SEG-*) so the fixture never competes with -- other specs for free fleet stock, and the corridor targets NAGAD (not -- DJIB_PORT) so no other spec's same-day schedule can steal FCFS bookings. -- 0. Reset any PREVIOUS segment-weight run (namespaced: TRN-SEG-* trains, -- CTR-SEG-* contracts, WGN-SEG-* wagons) so the spec re-runs on a warm DB. -- Everything is age-guarded (45 min): Cypress re-runs the spec's before() -- hook on cross-origin reloads, and an unguarded reset would soft-delete the -- CURRENT run's own schedules and contracts mid-flight. Consequence: rerun -- the spec no sooner than 45 minutes after a crashed run (or restack). UPDATE freight.train_schedules ts SET deleted_at = now(), booking_window_status = 'CLOSED' WHERE ts.deleted_at IS NULL AND ts.created_at < now() - interval '45 minutes' AND ts.train_set_id IN ( SELECT se.id FROM freight.train_sets se JOIN freight.trains t ON t.id = se.train_id WHERE t.code LIKE 'TRN-SEG-%' ); UPDATE freight.wagon_booking_allocations a SET deleted_at = now() WHERE a.deleted_at IS NULL AND a.booking_id IN ( SELECT b.id FROM freight.bookings b JOIN freight.contracts c ON c.id = b.contract_id WHERE c.reference LIKE 'CTR-SEG-%' AND c.created_at < now() - interval '45 minutes' ); UPDATE freight.bookings b SET deleted_at = now() WHERE b.deleted_at IS NULL AND b.contract_id IN ( SELECT id FROM freight.contracts WHERE reference LIKE 'CTR-SEG-%' AND created_at < now() - interval '45 minutes' ); UPDATE freight.contracts SET deleted_at = now() WHERE deleted_at IS NULL AND reference LIKE 'CTR-SEG-%' AND created_at < now() - interval '45 minutes'; -- Un-pin only wagons whose pin points at a dead schedule — live pins from the -- current run must survive a mid-run re-seed. UPDATE freight.wagons w SET current_train_schedule_id = NULL, train_set_wagon_id = NULL, current_yard_id = (SELECT id FROM freight.yards WHERE code = 'MOJO') WHERE w.wagon_number LIKE 'WGN-SEG-%' AND w.current_train_schedule_id IS NOT NULL AND w.current_train_schedule_id IN ( SELECT id FROM freight.train_schedules WHERE deleted_at IS NOT NULL ); -- 1. Locomotives at Mojo. INSERT INTO freight.locomotives (id, code, max_pull_weight_tons, max_train_length_meters, overage_tolerance_tons, current_yard_id) SELECT gen_random_uuid(), v.code, v.pull, 760, v.tol, y.id FROM (VALUES ('LOCO-SEG-A', 240, 90), ('LOCO-SEG-B', 240, NULL), ('LOCO-SEG-C', 200, NULL), ('LOCO-SEG-D', 200, NULL) ) AS v(code, pull, tol) JOIN freight.yards y ON y.code = 'MOJO' WHERE NOT EXISTS (SELECT 1 FROM freight.locomotives l WHERE l.code = v.code); -- 2. Built trains at Mojo. INSERT INTO freight.trains (id, code, train_name, capacity_tons, current_yard_id) SELECT gen_random_uuid(), v.code, v.name, 2000, y.id FROM (VALUES ('TRN-SEG-W', 'E2E Tolerance Carrier'), ('TRN-SEG-F', 'E2E Border-Full Carrier') ) AS v(code, name) JOIN freight.yards y ON y.code = 'MOJO' WHERE NOT EXISTS (SELECT 1 FROM freight.trains t WHERE t.code = v.code); -- 3. Couple the locomotive pairs (schedulable trains need >= 2 locos). INSERT INTO freight.train_locomotives (id, train_id, locomotive_id, sequence_no) SELECT gen_random_uuid(), t.id, l.id, v.seq FROM (VALUES ('TRN-SEG-W', 'LOCO-SEG-A', 0), ('TRN-SEG-W', 'LOCO-SEG-B', 1), ('TRN-SEG-F', 'LOCO-SEG-C', 0), ('TRN-SEG-F', 'LOCO-SEG-D', 1) ) AS v(train_code, loco_code, seq) JOIN freight.trains t ON t.code = v.train_code JOIN freight.locomotives l ON l.code = v.loco_code WHERE NOT EXISTS ( SELECT 1 FROM freight.train_locomotives tl WHERE tl.train_id = t.id AND tl.locomotive_id = l.id ); -- 4. Dedicated wagons, parked at Mojo. INSERT INTO freight.wagons (id, wagon_number, wagon_type_id, current_yard_id) SELECT gen_random_uuid(), v.num, wt.id, y.id FROM (VALUES ('WGN-SEG-C1', 'CW4'), ('WGN-SEG-C2', 'CW4'), ('WGN-SEG-N1', 'NW5'), ('WGN-SEG-N2', 'NW5'), ('WGN-SEG-N3', 'NW5'), ('WGN-SEG-N4', 'NW5'), ('WGN-SEG-N5', 'NW5'), ('WGN-SEG-N6', 'NW5') ) AS v(num, wt_code) JOIN freight.wagon_types wt ON wt.code = v.wt_code JOIN freight.yards y ON y.code = 'MOJO' WHERE NOT EXISTS (SELECT 1 FROM freight.wagons w WHERE w.wagon_number = v.num); -- 5. Couple them: W = 2 CW4 + 2 NW5, F = 4 NW5. UPDATE freight.wagons w SET train_id = t.id, sequence_number = v.seq FROM freight.trains t, (VALUES ('WGN-SEG-C1', 'TRN-SEG-W', 1), ('WGN-SEG-C2', 'TRN-SEG-W', 2), ('WGN-SEG-N1', 'TRN-SEG-W', 3), ('WGN-SEG-N2', 'TRN-SEG-W', 4), ('WGN-SEG-N3', 'TRN-SEG-F', 1), ('WGN-SEG-N4', 'TRN-SEG-F', 2), ('WGN-SEG-N5', 'TRN-SEG-F', 3), ('WGN-SEG-N6', 'TRN-SEG-F', 4) ) AS v(num, train_code, seq) WHERE w.wagon_number = v.num AND t.code = v.train_code AND w.train_id IS DISTINCT FROM t.id; -- 6. LIVE export rates for the NAGAD corridor: bulk from Mojo (tolerance -- train's wheat) and container from Dire Dawa (border-full scenario's -- mid-route export). INSERT INTO freight.rates (id, rate_type, applies_to, trigger, currency, rate_value, rate_unit, status, origin_yard_id, destination_yard_id, proposed_by_staff_id) SELECT gen_random_uuid(), v.rate_type, v.applies_to, 'ALWAYS', 'USD', v.value, v.unit, 'LIVE', a.id, b.id, u.id FROM (VALUES ('BULK_EXPORT', 'BULK', 'MOJO', 25, 'PER_TON'), ('CONTAINER_EXPORT', 'CONTAINER', 'DIRE_DAWA', 600, 'PER_CONTAINER') ) AS v(rate_type, applies_to, origin_code, value, unit) JOIN freight.yards a ON a.code = v.origin_code JOIN freight.yards b ON b.code = 'NAGAD' JOIN iam.users u ON u.email = 'operation@edr.local' WHERE NOT EXISTS ( SELECT 1 FROM freight.rates r WHERE r.rate_type = v.rate_type AND r.origin_yard_id = a.id AND r.destination_yard_id = b.id AND r.deleted_at IS NULL ); -- 7. Segment distance for the new corridor's border leg (Mojo–Dire comes -- from seed-intercity.sql). INSERT INTO freight.yard_distances (id, from_yard_id, to_yard_id, distance_km) SELECT gen_random_uuid(), a.id, b.id, 460 FROM freight.yards a JOIN freight.yards b ON b.code = 'NAGAD' WHERE a.code = 'DIRE_DAWA' AND NOT EXISTS ( SELECT 1 FROM freight.yard_distances d WHERE (d.from_yard_id = a.id AND d.to_yard_id = b.id) OR (d.from_yard_id = b.id AND d.to_yard_id = a.id) );