Files
edr-platform/e2e/freight/cypress/fixtures/seed-segment-weight.sql
2026-07-22 17:25:01 +00:00

176 lines
7.2 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 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 (MojoDire 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)
);