mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 18:20:57 +00:00
Merge branch 'dev' into freight/feat/invoice
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import 'reflect-metadata';
|
||||
import { config } from 'dotenv';
|
||||
import { resolve } from 'path';
|
||||
|
||||
config({ path: resolve(__dirname, '../../.env') });
|
||||
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from '../app.module';
|
||||
import { ApprovedFirstLastMileDemoBookingsSeeder } from '../seed/approved-first-lastmile-demo-bookings.seeder';
|
||||
|
||||
async function main() {
|
||||
const app = await NestFactory.createApplicationContext(AppModule, {
|
||||
logger: ['error', 'warn', 'log'],
|
||||
});
|
||||
|
||||
try {
|
||||
const seeder = app.get(ApprovedFirstLastMileDemoBookingsSeeder);
|
||||
await seeder.run();
|
||||
console.log('Approved first/last-mile demo bookings seeded.');
|
||||
} finally {
|
||||
await app.close();
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error('Approved first/last-mile demo booking seed failed:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -21,8 +21,18 @@ import { WarehouseYard } from '../modules/warehouses/entities/warehouse-yard.ent
|
||||
import { WarehouseZone } from '../modules/warehouses/entities/warehouse-zone.entity';
|
||||
import { Warehouse } from '../modules/warehouses/entities/warehouse.entity';
|
||||
|
||||
const TRAIN_NUMBER = 'ICD-DEMO-EXP-DJ-01';
|
||||
const BOOKING_REFS = ['ICD-DEMO-EXP-001', 'ICD-DEMO-EXP-002', 'ICD-DEMO-EXP-003'];
|
||||
const DEMO_TRAINS = [
|
||||
{
|
||||
trainNumber: 'ICD-DEMO-EXP-DJ-01',
|
||||
bookingRefs: ['ICD-DEMO-EXP-001', 'ICD-DEMO-EXP-002', 'ICD-DEMO-EXP-003'],
|
||||
arrivalOffsetHours: 1,
|
||||
},
|
||||
{
|
||||
trainNumber: 'ICD-DEMO-EXP-DJ-02',
|
||||
bookingRefs: ['ICD-DEMO-EXP-004', 'ICD-DEMO-EXP-005', 'ICD-DEMO-EXP-006'],
|
||||
arrivalOffsetHours: 2,
|
||||
},
|
||||
];
|
||||
|
||||
async function main() {
|
||||
const app = await NestFactory.createApplicationContext(AppModule, {
|
||||
@@ -44,13 +54,6 @@ async function main() {
|
||||
const scheduleRepo = dataSource.getRepository(TrainSchedule);
|
||||
const scheduleBookingRepo = dataSource.getRepository(TrainScheduleBooking);
|
||||
|
||||
const existingSchedule = await scheduleRepo.findOne({ where: { trainNumber: TRAIN_NUMBER } });
|
||||
if (existingSchedule) {
|
||||
console.log(`Export Djibouti interchange demo already seeded: ${TRAIN_NUMBER}`);
|
||||
console.log(`Schedule ID: ${existingSchedule.id}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const originYard =
|
||||
(await yardRepo.findOne({ where: { code: 'MOJO' } })) ??
|
||||
(await yardRepo.findOne({ where: { country: 'Ethiopia' } }));
|
||||
@@ -83,10 +86,6 @@ async function main() {
|
||||
throw new Error(`Cannot seed export Djibouti interchange demo, missing: ${missing.join(', ')}`);
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
const departure = new Date(now - 6 * 60 * 60 * 1000);
|
||||
const arrival = new Date(now - 60 * 60 * 1000);
|
||||
|
||||
const locomotive =
|
||||
(await locomotiveRepo.findOne({ where: { code: 'ICD-DEMO-LOCO' } })) ??
|
||||
(await locomotiveRepo.save(
|
||||
@@ -97,83 +96,106 @@ async function main() {
|
||||
}),
|
||||
));
|
||||
|
||||
const trainSet = await trainSetRepo.save(
|
||||
trainSetRepo.create({
|
||||
locomotiveId: locomotive.id,
|
||||
totalWeightTons: 700,
|
||||
totalLengthMeters: 360,
|
||||
wagonCount: 12,
|
||||
status: 'COMPLETED',
|
||||
}),
|
||||
);
|
||||
const now = Date.now();
|
||||
const seededSchedules: TrainSchedule[] = [];
|
||||
|
||||
const schedule = await scheduleRepo.save(
|
||||
scheduleRepo.create({
|
||||
trainSetId: trainSet.id,
|
||||
originStationId: originYard!.id,
|
||||
destinationStationId: destinationYard!.id,
|
||||
scheduledDepartureDate: departure,
|
||||
scheduledArrivalDate: arrival,
|
||||
actualArrivalAt: arrival,
|
||||
status: 'ARRIVED' as TrainSchedule['status'],
|
||||
trainNumber: TRAIN_NUMBER,
|
||||
}),
|
||||
);
|
||||
for (const [trainIndex, demo] of DEMO_TRAINS.entries()) {
|
||||
const existingSchedule = await scheduleRepo.findOne({ where: { trainNumber: demo.trainNumber } });
|
||||
if (existingSchedule) {
|
||||
console.log(`Export Djibouti interchange demo already seeded: ${demo.trainNumber}`);
|
||||
console.log(`Schedule ID: ${existingSchedule.id}`);
|
||||
seededSchedules.push(existingSchedule);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const [index, reference] of BOOKING_REFS.entries()) {
|
||||
const weight = 5200 + index * 800;
|
||||
const booking = await bookingRepo.save(
|
||||
bookingRepo.create({
|
||||
reference,
|
||||
originYardId: originYard!.id,
|
||||
destinationYardId: destinationYard!.id,
|
||||
serviceTypeId: serviceType!.id,
|
||||
status: 'IN_TRANSIT',
|
||||
paymentStatus: 'PAID',
|
||||
scheduledDate: new Date(),
|
||||
contractType: 'SPOT',
|
||||
equipmentReturn: 'TERMINAL',
|
||||
paymentCurrency: 'ETB',
|
||||
totalAmount: 0,
|
||||
isGovernment: false,
|
||||
tradeDirection: 'EXPORT',
|
||||
freightType: index % 2 === 0 ? 'CONTAINER' : 'BULK',
|
||||
cargoTypeId: cargoType?.id ?? null,
|
||||
cargoFreeText: cargoType ? null : `Export Djibouti interchange demo cargo ${index + 1}`,
|
||||
cargoTotalWeightVgm: weight,
|
||||
const arrival = new Date(now - demo.arrivalOffsetHours * 60 * 60 * 1000);
|
||||
const departure = new Date(arrival.getTime() - 5 * 60 * 60 * 1000);
|
||||
|
||||
const trainSet = await trainSetRepo.save(
|
||||
trainSetRepo.create({
|
||||
locomotiveId: locomotive.id,
|
||||
totalWeightTons: 700 + trainIndex * 80,
|
||||
totalLengthMeters: 360 + trainIndex * 20,
|
||||
wagonCount: 12 + trainIndex,
|
||||
status: 'COMPLETED',
|
||||
}),
|
||||
);
|
||||
|
||||
await inventoryRepo.save(
|
||||
inventoryRepo.create({
|
||||
warehouseId: warehouse!.id,
|
||||
yardId: warehouseYard!.id,
|
||||
zoneId: warehouseZone!.id,
|
||||
bookingId: booking.id,
|
||||
quantity: 1,
|
||||
weight,
|
||||
status: 'DISPATCHED',
|
||||
inspectionStatus: 'PASSED',
|
||||
arrivedAt: new Date(now - 4 * 60 * 60 * 1000),
|
||||
inspectedAt: new Date(now - 3 * 60 * 60 * 1000),
|
||||
readyForLoadingAt: new Date(now - 2 * 60 * 60 * 1000),
|
||||
loadedAt: new Date(now - 90 * 60 * 1000),
|
||||
dispatchedAt: new Date(now - 70 * 60 * 1000),
|
||||
notes: '[ICD-DEMO] Eligible for Djibouti export unload and interchange generation',
|
||||
const schedule = await scheduleRepo.save(
|
||||
scheduleRepo.create({
|
||||
trainSetId: trainSet.id,
|
||||
originStationId: originYard!.id,
|
||||
destinationStationId: destinationYard!.id,
|
||||
scheduledDepartureDate: departure,
|
||||
scheduledArrivalDate: arrival,
|
||||
actualArrivalAt: arrival,
|
||||
status: 'ARRIVED' as TrainSchedule['status'],
|
||||
trainNumber: demo.trainNumber,
|
||||
direction: 'EXPORT',
|
||||
}),
|
||||
);
|
||||
|
||||
await scheduleBookingRepo.save(
|
||||
scheduleBookingRepo.create({
|
||||
trainScheduleId: schedule.id,
|
||||
bookingId: booking.id,
|
||||
}),
|
||||
);
|
||||
for (const [bookingIndex, reference] of demo.bookingRefs.entries()) {
|
||||
const weight = 5200 + trainIndex * 600 + bookingIndex * 800;
|
||||
const booking = await bookingRepo.save(
|
||||
bookingRepo.create({
|
||||
reference,
|
||||
originYardId: originYard!.id,
|
||||
destinationYardId: destinationYard!.id,
|
||||
serviceTypeId: serviceType!.id,
|
||||
status: 'IN_TRANSIT',
|
||||
paymentStatus: 'PAID',
|
||||
scheduledDate: new Date(),
|
||||
contractType: 'SPOT',
|
||||
equipmentReturn: 'TERMINAL',
|
||||
paymentCurrency: 'ETB',
|
||||
totalAmount: 0,
|
||||
isGovernment: false,
|
||||
tradeDirection: 'EXPORT',
|
||||
freightType: bookingIndex % 2 === 0 ? 'CONTAINER' : 'BULK',
|
||||
cargoTypeId: cargoType?.id ?? null,
|
||||
cargoFreeText: cargoType
|
||||
? null
|
||||
: `Export Djibouti interchange demo cargo ${trainIndex + 1}-${bookingIndex + 1}`,
|
||||
cargoTotalWeightVgm: weight,
|
||||
}),
|
||||
);
|
||||
|
||||
await inventoryRepo.save(
|
||||
inventoryRepo.create({
|
||||
warehouseId: warehouse!.id,
|
||||
yardId: warehouseYard!.id,
|
||||
zoneId: warehouseZone!.id,
|
||||
bookingId: booking.id,
|
||||
quantity: 1,
|
||||
weight,
|
||||
status: 'DISPATCHED',
|
||||
inspectionStatus: 'PASSED',
|
||||
arrivedAt: new Date(departure.getTime() + 2 * 60 * 60 * 1000),
|
||||
inspectedAt: new Date(departure.getTime() + 3 * 60 * 60 * 1000),
|
||||
readyForLoadingAt: new Date(departure.getTime() + 4 * 60 * 60 * 1000),
|
||||
loadedAt: new Date(departure.getTime() + 4.5 * 60 * 60 * 1000),
|
||||
dispatchedAt: departure,
|
||||
notes: '[ICD-DEMO] Eligible for Djibouti export unload and interchange generation',
|
||||
}),
|
||||
);
|
||||
|
||||
await scheduleBookingRepo.save(
|
||||
scheduleBookingRepo.create({
|
||||
trainScheduleId: schedule.id,
|
||||
bookingId: booking.id,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
seededSchedules.push(schedule);
|
||||
}
|
||||
|
||||
console.log('Export Djibouti interchange demo seeded.');
|
||||
console.log(`Train number: ${TRAIN_NUMBER}`);
|
||||
console.log(`Schedule ID: ${schedule.id}`);
|
||||
for (const schedule of seededSchedules) {
|
||||
console.log(`Train number: ${schedule.trainNumber}`);
|
||||
console.log(`Schedule ID: ${schedule.id}`);
|
||||
}
|
||||
console.log('Open Djibouti Unloading, click "Auto Unload Export Items", then check Interchange Documents.');
|
||||
} finally {
|
||||
await app.close();
|
||||
|
||||
219
apps/edr-freight-api/src/scripts/seed-import-djibouti-demo.ts
Normal file
219
apps/edr-freight-api/src/scripts/seed-import-djibouti-demo.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
import 'reflect-metadata';
|
||||
import { config } from 'dotenv';
|
||||
import { resolve } from 'path';
|
||||
|
||||
config({ path: resolve(__dirname, '../../.env') });
|
||||
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { AppModule } from '../app.module';
|
||||
import { Booking } from '../modules/bookings/entities/booking.entity';
|
||||
import { Locomotive } from '../modules/locomotives/entities/locomotive.entity';
|
||||
import { ImportDjiboutiOperation } from '../modules/train-scheduling/entities/import-djibouti-operation.entity';
|
||||
import { CargoType } from '../modules/rule-engine/entities/cargo-type.entity';
|
||||
import { ServiceType } from '../modules/rule-engine/entities/service-type.entity';
|
||||
import { Yard } from '../modules/rule-engine/entities/yard.entity';
|
||||
import { TrainSchedule } from '../modules/train-schedules/entities/train-schedule.entity';
|
||||
import { TrainScheduleBooking } from '../modules/train-schedules/entities/train-schedule-booking.entity';
|
||||
import { TrainSet } from '../modules/train-sets/entities/train-set.entity';
|
||||
|
||||
const DEMO_TRAINS = [
|
||||
{
|
||||
trainNumber: 'IMP-DJB-NAGAD-01',
|
||||
bookingRefs: ['IMP-DJB-NGD-001', 'IMP-DJB-NGD-002', 'IMP-DJB-NGD-003'],
|
||||
departureOffsetHours: 4,
|
||||
},
|
||||
{
|
||||
trainNumber: 'IMP-DJB-NAGAD-02',
|
||||
bookingRefs: ['IMP-DJB-NGD-004', 'IMP-DJB-NGD-005', 'IMP-DJB-NGD-006'],
|
||||
departureOffsetHours: 8,
|
||||
},
|
||||
];
|
||||
|
||||
function addHours(date: Date, hours: number): Date {
|
||||
return new Date(date.getTime() + hours * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const app = await NestFactory.createApplicationContext(AppModule, {
|
||||
logger: ['error', 'warn', 'log'],
|
||||
});
|
||||
|
||||
try {
|
||||
const dataSource = app.get(DataSource);
|
||||
const yardRepo = dataSource.getRepository(Yard);
|
||||
const serviceTypeRepo = dataSource.getRepository(ServiceType);
|
||||
const cargoTypeRepo = dataSource.getRepository(CargoType);
|
||||
const locomotiveRepo = dataSource.getRepository(Locomotive);
|
||||
const trainSetRepo = dataSource.getRepository(TrainSet);
|
||||
const scheduleRepo = dataSource.getRepository(TrainSchedule);
|
||||
const bookingRepo = dataSource.getRepository(Booking);
|
||||
const scheduleBookingRepo = dataSource.getRepository(TrainScheduleBooking);
|
||||
const importOperationRepo = dataSource.getRepository(ImportDjiboutiOperation);
|
||||
|
||||
const originYard =
|
||||
(await yardRepo.findOne({ where: { code: 'NAGAD' } })) ??
|
||||
(await yardRepo.findOne({ where: { country: 'Djibouti' } }));
|
||||
const destinationYard =
|
||||
(await yardRepo.findOne({ where: { code: 'INDODE' } })) ??
|
||||
(await yardRepo.save(
|
||||
yardRepo.create({
|
||||
code: 'INDODE',
|
||||
label: 'Indode Dry Port',
|
||||
country: 'Ethiopia',
|
||||
isActive: true,
|
||||
displayOrder: 6,
|
||||
}),
|
||||
));
|
||||
const serviceType =
|
||||
(await serviceTypeRepo.findOne({ where: { code: 'RAIL_CONTAINER' } })) ??
|
||||
(await serviceTypeRepo.findOne({ where: { isActive: true } }));
|
||||
const cargoType = await cargoTypeRepo.findOne({ where: { isActive: true } });
|
||||
|
||||
const missing = [
|
||||
!originYard ? 'NAGAD/Djibouti origin yard' : '',
|
||||
!destinationYard ? 'INDODE destination yard' : '',
|
||||
!serviceType ? 'service type' : '',
|
||||
].filter(Boolean);
|
||||
|
||||
if (missing.length) {
|
||||
throw new Error(`Cannot seed Djibouti-side import demo, missing: ${missing.join(', ')}`);
|
||||
}
|
||||
|
||||
const locomotive =
|
||||
(await locomotiveRepo.findOne({ where: { code: 'ICD-DEMO-IMP-LOCO' } })) ??
|
||||
(await locomotiveRepo.save(
|
||||
locomotiveRepo.create({
|
||||
code: 'ICD-DEMO-IMP-LOCO',
|
||||
name: 'Djibouti Import Demo Locomotive',
|
||||
locomotiveType: 'DIESEL',
|
||||
maxPullWeightTons: 4200,
|
||||
maxTrainLengthMeters: 760,
|
||||
status: 'IMPORT_READY',
|
||||
currentYardId: originYard!.id,
|
||||
}),
|
||||
));
|
||||
|
||||
const now = new Date();
|
||||
const seededSchedules: TrainSchedule[] = [];
|
||||
|
||||
for (const [trainIndex, demo] of DEMO_TRAINS.entries()) {
|
||||
const existingSchedule = await scheduleRepo.findOne({
|
||||
where: { trainNumber: demo.trainNumber },
|
||||
});
|
||||
|
||||
if (existingSchedule) {
|
||||
console.log(`Djibouti-side import demo already seeded: ${demo.trainNumber}`);
|
||||
console.log(`Schedule ID: ${existingSchedule.id}`);
|
||||
seededSchedules.push(existingSchedule);
|
||||
continue;
|
||||
}
|
||||
|
||||
const departure = addHours(now, demo.departureOffsetHours);
|
||||
const arrival = addHours(departure, 12);
|
||||
|
||||
const trainSet = await trainSetRepo.save(
|
||||
trainSetRepo.create({
|
||||
locomotiveId: locomotive.id,
|
||||
totalWeightTons: 900 + trainIndex * 120,
|
||||
totalLengthMeters: 430 + trainIndex * 25,
|
||||
wagonCount: 18 + trainIndex * 2,
|
||||
status: 'ASSIGNED',
|
||||
}),
|
||||
);
|
||||
|
||||
const schedule = await scheduleRepo.save(
|
||||
scheduleRepo.create({
|
||||
trainSetId: trainSet.id,
|
||||
originStationId: originYard!.id,
|
||||
destinationStationId: destinationYard!.id,
|
||||
scheduledDepartureDate: departure,
|
||||
scheduledArrivalDate: arrival,
|
||||
status: 'SCHEDULED' as TrainSchedule['status'],
|
||||
trainNumber: demo.trainNumber,
|
||||
direction: 'IMPORT',
|
||||
maxWagons: 53,
|
||||
bookingWindowStatus: 'CLOSED',
|
||||
}),
|
||||
);
|
||||
|
||||
for (const [bookingIndex, reference] of demo.bookingRefs.entries()) {
|
||||
const weight = 6800 + trainIndex * 900 + bookingIndex * 750;
|
||||
const booking = await bookingRepo.save(
|
||||
bookingRepo.create({
|
||||
reference,
|
||||
originYardId: originYard!.id,
|
||||
destinationYardId: destinationYard!.id,
|
||||
serviceTypeId: serviceType!.id,
|
||||
status: 'PAID',
|
||||
paymentStatus: 'PAID',
|
||||
scheduledDate: departure,
|
||||
contractType: 'SPOT',
|
||||
equipmentReturn: 'TERMINAL',
|
||||
paymentCurrency: 'ETB',
|
||||
totalAmount: 0,
|
||||
isGovernment: false,
|
||||
tradeDirection: 'IMPORT',
|
||||
freightType: bookingIndex % 2 === 0 ? 'CONTAINER' : 'BULK',
|
||||
cargoTypeId: cargoType?.id ?? null,
|
||||
cargoFreeText: cargoType
|
||||
? null
|
||||
: `Djibouti import demo cargo ${trainIndex + 1}-${bookingIndex + 1}`,
|
||||
cargoTotalWeightVgm: weight,
|
||||
priorityScore: 80 - trainIndex * 5 - bookingIndex,
|
||||
trainScheduleId: schedule.id,
|
||||
schedulingStatus: 'SCHEDULED',
|
||||
scheduledAt: now,
|
||||
}),
|
||||
);
|
||||
|
||||
await scheduleBookingRepo.save(
|
||||
scheduleBookingRepo.create({
|
||||
trainScheduleId: schedule.id,
|
||||
bookingId: booking.id,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
await importOperationRepo.save(
|
||||
importOperationRepo.create({
|
||||
trainScheduleId: schedule.id,
|
||||
documents: {
|
||||
DELIVERY_ORDER: {
|
||||
reference: `DO-${demo.trainNumber}`,
|
||||
uploadedAt: now.toISOString(),
|
||||
uploadedBy: 'Demo Seeder',
|
||||
notes: 'Demo delivery order for Djibouti-side import flow',
|
||||
},
|
||||
RAILWAY_BILL: {
|
||||
reference: `RB-${demo.trainNumber}`,
|
||||
uploadedAt: now.toISOString(),
|
||||
uploadedBy: 'Demo Seeder',
|
||||
notes: 'Demo railway bill for Djibouti-side import flow',
|
||||
},
|
||||
},
|
||||
performedBy: 'Demo Seeder',
|
||||
notes: '[ICD-DEMO] Nagad to Indode import train for Djibouti-side flow',
|
||||
}),
|
||||
);
|
||||
|
||||
seededSchedules.push(schedule);
|
||||
}
|
||||
|
||||
console.log('Djibouti-side import demo seeded.');
|
||||
console.log(`Corridor: ${originYard!.code} -> ${destinationYard!.code}`);
|
||||
for (const schedule of seededSchedules) {
|
||||
console.log(`Train number: ${schedule.trainNumber}`);
|
||||
console.log(`Schedule ID: ${schedule.id}`);
|
||||
console.log(`Backoffice URL: /dashboard/operations/train-scheduling-v2/${schedule.id}`);
|
||||
}
|
||||
} finally {
|
||||
await app.close();
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('Djibouti-side import demo seed failed:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,126 @@
|
||||
import 'reflect-metadata';
|
||||
import { config } from 'dotenv';
|
||||
import { resolve } from 'path';
|
||||
|
||||
config({ path: resolve(__dirname, '../../.env') });
|
||||
|
||||
import { AppDataSource } from '../data-source';
|
||||
import { Locomotive } from '../modules/locomotives/entities/locomotive.entity';
|
||||
import { Yard } from '../modules/rule-engine/entities/yard.entity';
|
||||
import { TrainSchedule } from '../modules/train-schedules/entities/train-schedule.entity';
|
||||
import { TrainSet } from '../modules/train-sets/entities/train-set.entity';
|
||||
|
||||
const TRAIN_NUMBER = 'NEGAD-INDODE-ARR-01';
|
||||
|
||||
function addHours(date: Date, hours: number): Date {
|
||||
return new Date(date.getTime() + hours * 60 * 60 * 1000);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const dataSource = await AppDataSource.initialize();
|
||||
|
||||
try {
|
||||
await dataSource.transaction(async (manager) => {
|
||||
const yardRepo = manager.getRepository(Yard);
|
||||
const locomotiveRepo = manager.getRepository(Locomotive);
|
||||
const trainSetRepo = manager.getRepository(TrainSet);
|
||||
const scheduleRepo = manager.getRepository(TrainSchedule);
|
||||
|
||||
const negad =
|
||||
(await yardRepo.findOne({ where: { code: 'NEGAD' } })) ??
|
||||
(await yardRepo.save(
|
||||
yardRepo.create({
|
||||
code: 'NEGAD',
|
||||
label: 'Negad',
|
||||
country: 'Djibouti',
|
||||
isActive: true,
|
||||
displayOrder: 5,
|
||||
}),
|
||||
));
|
||||
|
||||
const indode =
|
||||
(await yardRepo.findOne({ where: { code: 'INDODE' } })) ??
|
||||
(await yardRepo.save(
|
||||
yardRepo.create({
|
||||
code: 'INDODE',
|
||||
label: 'Indode Dry Port',
|
||||
country: 'Ethiopia',
|
||||
isActive: true,
|
||||
displayOrder: 6,
|
||||
}),
|
||||
));
|
||||
|
||||
const locomotive =
|
||||
(await locomotiveRepo.findOne({ where: { code: 'NEGAD-INDODE-LOCO' } })) ??
|
||||
(await locomotiveRepo.save(
|
||||
locomotiveRepo.create({
|
||||
code: 'NEGAD-INDODE-LOCO',
|
||||
name: 'Negad to Indode Demo Locomotive',
|
||||
locomotiveType: 'DIESEL',
|
||||
maxPullWeightTons: 4200,
|
||||
maxTrainLengthMeters: 760,
|
||||
status: 'AVAILABLE',
|
||||
currentYardId: indode.id,
|
||||
}),
|
||||
));
|
||||
|
||||
const now = new Date();
|
||||
const departure = addHours(now, -12);
|
||||
const arrival = now;
|
||||
|
||||
let schedule = await scheduleRepo.findOne({ where: { trainNumber: TRAIN_NUMBER } });
|
||||
if (!schedule) {
|
||||
const trainSet = await trainSetRepo.save(
|
||||
trainSetRepo.create({
|
||||
locomotiveId: locomotive.id,
|
||||
totalWeightTons: 960,
|
||||
totalLengthMeters: 420,
|
||||
wagonCount: 18,
|
||||
status: 'COMPLETED',
|
||||
}),
|
||||
);
|
||||
|
||||
schedule = scheduleRepo.create({
|
||||
trainSetId: trainSet.id,
|
||||
originStationId: negad.id,
|
||||
destinationStationId: indode.id,
|
||||
scheduledDepartureDate: departure,
|
||||
scheduledArrivalDate: arrival,
|
||||
actualDepartureAt: departure,
|
||||
actualArrivalAt: arrival,
|
||||
status: 'ARRIVED' as TrainSchedule['status'],
|
||||
trainNumber: TRAIN_NUMBER,
|
||||
direction: 'IMPORT',
|
||||
maxWagons: 53,
|
||||
bookingWindowStatus: 'CLOSED',
|
||||
});
|
||||
} else {
|
||||
schedule.originStationId = negad.id;
|
||||
schedule.destinationStationId = indode.id;
|
||||
schedule.scheduledDepartureDate = departure;
|
||||
schedule.scheduledArrivalDate = arrival;
|
||||
schedule.actualDepartureAt = departure;
|
||||
schedule.actualArrivalAt = arrival;
|
||||
schedule.status = 'ARRIVED' as TrainSchedule['status'];
|
||||
schedule.direction = 'IMPORT';
|
||||
schedule.bookingWindowStatus = 'CLOSED';
|
||||
|
||||
if (schedule.trainSetId) {
|
||||
await trainSetRepo.update(schedule.trainSetId, { status: 'COMPLETED' });
|
||||
}
|
||||
}
|
||||
|
||||
const saved = await scheduleRepo.save(schedule);
|
||||
console.log(`Seeded ARRIVED train ${TRAIN_NUMBER}`);
|
||||
console.log(`Schedule ID: ${saved.id}`);
|
||||
console.log(`Route: ${negad.code} -> ${indode.code}`);
|
||||
});
|
||||
} finally {
|
||||
await dataSource.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error('Negad to Indode arrived train seed failed:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user