-- 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 Mojo–Dire Dawa–Djibouti 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 $$;