import { AppDataSource } from '../data-source'; import { SeedEdrWagonFleetErNumbering2260000000000 } from '../migrations/2260000000000-SeedEdrWagonFleetErNumbering'; import { AddWagonTrainNumbers2270000000000 } from '../migrations/2270000000000-AddWagonTrainNumbers'; import { SeedWagonRunNumbers2280000000000 } from '../migrations/2280000000000-SeedWagonRunNumbers'; import { WagonNumberPartialUnique2280000000000 } from '../migrations/2280000000000-WagonNumberPartialUnique'; import { SeedWagonYardDoraleh2290000000000 } from '../migrations/2290000000000-SeedWagonYardDoraleh'; async function seedEdRWagons() { await AppDataSource.initialize(); const queryRunner = AppDataSource.createQueryRunner(); try { await queryRunner.connect(); await queryRunner.startTransaction(); // Fleet first (recreates every wagon with NULL yard + NULL runs), then the // columns are ensured to exist, then the run roster and the yard are applied // on top. Same order the migrations run in, so the script and a fresh // migrate agree. await new SeedEdrWagonFleetErNumbering2260000000000().up(queryRunner); await new AddWagonTrainNumbers2270000000000().up(queryRunner); // Not a wagon seed, but it owns wagon_number uniqueness — included so this // script leaves the same schema a real `migration:run` would, rather than a // database missing the partial unique index. await new WagonNumberPartialUnique2280000000000().up(queryRunner); await new SeedWagonRunNumbers2280000000000().up(queryRunner); await new SeedWagonYardDoraleh2290000000000().up(queryRunner); const summary = await queryRunner.query(` SELECT wt.code, wt.name, COUNT(*)::int AS wagons, MIN(w.wagon_number) AS first_wagon, MAX(w.wagon_number) AS last_wagon, COUNT(*) FILTER (WHERE w.status = 'AVAILABLE')::int AS available, COUNT(*) FILTER (WHERE w.current_yard_id IS NULL)::int AS no_yard, COUNT(*) FILTER (WHERE w.export_train_number IS NOT NULL)::int AS on_a_run FROM freight.wagons w JOIN freight.wagon_types wt ON wt.id = w.wagon_type_id WHERE w.wagon_number BETWEEN 'ER0001' AND 'ER1100' GROUP BY wt.code, wt.name ORDER BY MIN(w.wagon_number); `); const [totals] = await queryRunner.query(` SELECT COUNT(*)::int AS total, COUNT(*) FILTER (WHERE export_train_number IS NOT NULL)::int AS on_a_run FROM freight.wagons; `); const yards = await queryRunner.query(` SELECT COALESCE(y.label, '(no yard)') AS yard, COUNT(*)::int AS wagons FROM freight.wagons w LEFT JOIN freight.yards y ON y.id = w.current_yard_id GROUP BY y.label ORDER BY 2 DESC; `); const runs = await queryRunner.query(` SELECT export_train_number AS export_run, import_train_number AS import_run, COUNT(*)::int AS wagons FROM freight.wagons WHERE export_train_number IS NOT NULL GROUP BY export_train_number, import_train_number ORDER BY export_train_number; `); await queryRunner.commitTransaction(); console.log('\nFleet by wagon type:'); console.table(summary); console.log('Run roster (export/import pairs):'); console.table(runs); console.log('Fleet by yard:'); console.table(yards); console.log( `Seeded EDR wagon fleet — ${totals.total} wagons total (expected 1100), ` + `${totals.on_a_run} on a run (expected 533).`, ); } catch (error) { await queryRunner.rollbackTransaction(); throw error; } finally { await queryRunner.release(); await AppDataSource.destroy(); } } seedEdRWagons().catch((error) => { console.error('Failed to seed EDR wagon fleet:', error); process.exit(1); });