mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
176 lines
7.2 KiB
SQL
176 lines
7.2 KiB
SQL
-- 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)
|
||
);
|