Files
edr-platform/e2e/freight/cypress/fixtures/seed-intercity.sql
2026-07-22 10:50:36 +00:00

132 lines
5.8 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/intercity_one_time.cy.ts. Idempotent.
--
-- The e2e DB boots with yards + a wagon fleet only: no container types, no
-- locomotives, no Train-Builder train, no yard distances, no routes. The spec
-- drives route + schedule creation through the UI; this fixture provides only
-- the infrastructure the UI journey cannot reasonably create in-flow:
--
-- 1. container types (booking form resolves 20ft/40ft by size_ft)
-- 2. container-type → wagon-type allow-list (wagon planner)
-- 3. two locomotives (a schedulable train needs >= 2)
-- 4. a built Train-Builder train at Mojo with four NW5 flat wagons
-- 5. yard distances for MojoDire DawaDjibouti Port (route creation
-- refuses unconfigured pairs)
-- 1. Container types.
INSERT INTO freight.container_types (id, code, label, size_ft, is_active)
SELECT gen_random_uuid(), v.code, v.label, v.size_ft, true
FROM (VALUES ('20FT', '20FT', 20), ('40FT', '40FT', 40)) AS v(code, label, size_ft)
WHERE NOT EXISTS (SELECT 1 FROM freight.container_types t WHERE t.code = v.code);
-- 2. 20ft/40ft containers ride NW5 flat wagons.
INSERT INTO freight.container_type_wagon_types (container_type_id, wagon_type_id)
SELECT ct.id, wt.id
FROM freight.container_types ct
JOIN freight.wagon_types wt ON wt.code = 'NW5'
WHERE ct.code IN ('20FT', '40FT')
AND NOT EXISTS (
SELECT 1 FROM freight.container_type_wagon_types x
WHERE x.container_type_id = ct.id AND x.wagon_type_id = wt.id
);
-- 3. Two locomotives at Mojo (status defaults to AVAILABLE).
INSERT INTO freight.locomotives
(id, code, max_pull_weight_tons, max_train_length_meters, current_yard_id)
SELECT gen_random_uuid(), v.code, 4000, 760, y.id
FROM (VALUES ('LOCO-E2E-1'), ('LOCO-E2E-2')) AS v(code)
JOIN freight.yards y ON y.code = 'MOJO'
WHERE NOT EXISTS (SELECT 1 FROM freight.locomotives l WHERE l.code = v.code);
-- 4a. Built train at Mojo (status defaults to AVAILABLE).
INSERT INTO freight.trains (id, code, train_name, capacity_tons, current_yard_id)
SELECT gen_random_uuid(), 'TRN-E2E-1', 'E2E Export Carrier', 2000, y.id
FROM freight.yards y
WHERE y.code = 'MOJO'
AND NOT EXISTS (SELECT 1 FROM freight.trains t WHERE t.code = 'TRN-E2E-1');
-- 4b. Couple both locomotives (available-trains filter requires >= 2).
INSERT INTO freight.train_locomotives (id, train_id, locomotive_id, sequence_no)
SELECT gen_random_uuid(), t.id, l.id,
row_number() OVER (ORDER BY l.code) - 1
FROM freight.trains t
JOIN freight.locomotives l ON l.code IN ('LOCO-E2E-1', 'LOCO-E2E-2')
WHERE t.code = 'TRN-E2E-1'
AND NOT EXISTS (
SELECT 1 FROM freight.train_locomotives tl
WHERE tl.train_id = t.id AND tl.locomotive_id = l.id
);
-- 4c. Couple four free NW5 flat wagons onto the train and park them at Mojo
-- with it (the seeded fleet sits at Doraleh; the planner reads the consist by
-- train_id, the yard only matters for warnings).
UPDATE freight.wagons w
SET train_id = t.id,
sequence_number = sub.rn,
current_yard_id = (SELECT id FROM freight.yards WHERE code = 'MOJO')
FROM freight.trains t,
LATERAL (
SELECT w2.id, row_number() OVER (ORDER BY w2.wagon_number) AS rn
FROM freight.wagons w2
JOIN freight.wagon_types wt ON wt.id = w2.wagon_type_id AND wt.code = 'NW5'
WHERE w2.train_id IS NULL AND w2.deleted_at IS NULL
ORDER BY w2.wagon_number
LIMIT 4
) sub
WHERE t.code = 'TRN-E2E-1'
AND w.id = sub.id
AND NOT EXISTS (SELECT 1 FROM freight.wagons wx WHERE wx.train_id = t.id);
-- 4d. One REQUIRED intercity clearance document, so the journey exercises the
-- real customer-upload → ops-review → finalize step (the seeder leaves the
-- intercity_documents setting empty).
INSERT INTO freight.file_upload_fields
(id, setting_id, file_key, file_label, is_required, is_multiple, max_files,
allowed_extensions, max_size_mb, display_order)
SELECT gen_random_uuid(), s.id, 'cargo_manifest', 'Cargo Manifest', true, false, 1,
'{pdf,jpg,jpeg,png}'::text[], 10, 1
FROM freight.file_upload_settings s
WHERE s.code = 'intercity_documents'
AND NOT EXISTS (
SELECT 1 FROM freight.file_upload_fields f
WHERE f.setting_id = s.id AND f.file_key = 'cargo_manifest' AND f.deleted_at IS NULL
);
-- 5. LIVE intercity container rate for Mojo → Dire Dawa (booking pricing
-- hard-blocks any container line without a rate on its exact leg; rates are
-- configured in USD and converted to the booking currency).
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(), 'INTERCITY_CONTAINER', 'INTERCITY', 'ALWAYS', 'USD', 500,
'PER_CONTAINER', 'LIVE', a.id, b.id, u.id
FROM freight.yards a
JOIN freight.yards b ON b.code = 'DIRE_DAWA'
JOIN iam.users u ON u.email = 'operation@edr.local'
WHERE a.code = 'MOJO'
AND NOT EXISTS (
SELECT 1 FROM freight.rates r
WHERE r.rate_type = 'INTERCITY_CONTAINER'
AND r.origin_yard_id = a.id AND r.destination_yard_id = b.id
AND r.deleted_at IS NULL
);
-- 6. Segment distances (symmetric — one row covers both directions). Guarded:
-- an e2e image built from a branch that predates the yard_distances feature
-- has no table, and its route form doesn't require distances either.
DO $$
BEGIN
IF to_regclass('freight.yard_distances') IS NOT NULL THEN
INSERT INTO freight.yard_distances (id, from_yard_id, to_yard_id, distance_km)
SELECT gen_random_uuid(), a.id, b.id, v.km
FROM (VALUES ('MOJO', 'DIRE_DAWA', 300), ('DIRE_DAWA', 'DJIB_PORT', 450))
AS v(from_code, to_code, km)
JOIN freight.yards a ON a.code = v.from_code
JOIN freight.yards b ON b.code = v.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)
OR (d.from_yard_id = b.id AND d.to_yard_id = a.id)
);
END IF;
END $$;