-- FLOW-TWO fixture — rates for the REVERSED (export-direction) corridor. -- -- Run AFTER seed-import-corridor.sql and seed-flow2-legs.sql. Idempotent. -- -- seed-flow2-legs.sql rates every FORWARD pair (i < j, DJIB_PORT-first order). -- The export scenarios (TC-01 … TC-20 of the second flow-two batch) run the -- corridor the other way — F→A — and book MID-corridor export legs like -- MOJO→DJIB_PORT and DIRE_DAWA→NAGAD. Pricing hard-blocks a booking on a pair -- with no LIVE rate, so every REVERSED ordered pair gets one here. -- -- Corridor stop order (CORRIDOR in import-utils.ts): -- A=DJIB_PORT B=NAGAD C=DIRE_DAWA D=E2E_AWASH E=MOJO F=KALITY -- Export runs F→A, so an export leg is (higher seq) → (lower seq). -- -- DIRECTION IS DERIVED FROM THE YARDS' COUNTRIES, never from our intent -- (resolveTradeDirectionForBooking). So: -- x → DJIB_PORT crosses the border → EXPORT → CONTAINER_EXPORT / BULK_EXPORT -- wholly-Ethiopian reversed pair → DOMESTIC → INTERCITY_CONTAINER / _BULK -- Getting the rate_type wrong does not fail loudly — the booking 404s at -- pricing, far from the cause. -- -- Flat, distance-free values: these specs assert capacity, never money. DROP TABLE IF EXISTS flow2_rev_pairs; CREATE TEMP TABLE flow2_rev_pairs AS WITH stops(code, seq) AS ( VALUES ('DJIB_PORT', 1), ('NAGAD', 2), ('DIRE_DAWA', 3), ('E2E_AWASH', 4), ('MOJO', 5), ('KALITY', 6) ) -- a.seq > b.seq — the reversed direction, i.e. running toward the port. SELECT a.code AS from_code, b.code AS to_code, (a.seq - b.seq) AS legs FROM stops a JOIN stops b ON a.seq > b.seq; -- 1. Freight rates on every reversed pair. 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 flow2_rev_pairs p CROSS JOIN LATERAL (VALUES (CASE WHEN p.to_code = 'DJIB_PORT' THEN 'CONTAINER_EXPORT' ELSE 'INTERCITY_CONTAINER' END, CASE WHEN p.to_code = 'DJIB_PORT' THEN 'CONTAINER' ELSE 'INTERCITY' END, 100 * p.legs, 'PER_CONTAINER'), (CASE WHEN p.to_code = 'DJIB_PORT' THEN 'BULK_EXPORT' ELSE 'INTERCITY_BULK' END, CASE WHEN p.to_code = 'DJIB_PORT' THEN 'BULK' ELSE 'INTERCITY' END, 5 * p.legs, 'PER_TON') ) AS v(rate_type, applies_to, value, unit) JOIN freight.yards a ON a.code = p.from_code JOIN freight.yards b ON b.code = p.to_code 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 ); -- 2. Yard distances on the reversed pairs. yard_distances is NOT symmetric — -- pricing and the available-days lookup both walk it directionally, and a -- missing row reads as "not on the network". INSERT INTO freight.yard_distances (id, from_yard_id, to_yard_id, distance_km) SELECT gen_random_uuid(), a.id, b.id, 100 * p.legs FROM flow2_rev_pairs p JOIN freight.yards a ON a.code = p.from_code JOIN freight.yards b ON b.code = p.to_code WHERE NOT EXISTS ( SELECT 1 FROM freight.yard_distances d WHERE d.from_yard_id = a.id AND d.to_yard_id = b.id AND d.deleted_at IS NULL ); DROP TABLE flow2_rev_pairs;