From 174df0b7aa30fe737c7217830c45f4133bae5f7d Mon Sep 17 00:00:00 2001 From: ghost2023 Date: Wed, 1 Jul 2026 15:46:25 +0300 Subject: [PATCH] chore: fix script and add seed company --- .../edr-freight-api/src/scripts/cmds/index.ts | 2 + .../src/scripts/cmds/seed-test-company.cmd.ts | 85 ++++++ .../scripts/cmds/seed-test-contracts.cmd.ts | 104 +++---- .../scripts/cmds/seed-test-schedules.cmd.ts | 283 +++++++----------- .../edr-freight-api/src/scripts/cmds/types.ts | 1 - 5 files changed, 239 insertions(+), 236 deletions(-) create mode 100644 apps/edr-freight-api/src/scripts/cmds/seed-test-company.cmd.ts diff --git a/apps/edr-freight-api/src/scripts/cmds/index.ts b/apps/edr-freight-api/src/scripts/cmds/index.ts index 369aff010..810945bbb 100644 --- a/apps/edr-freight-api/src/scripts/cmds/index.ts +++ b/apps/edr-freight-api/src/scripts/cmds/index.ts @@ -3,8 +3,10 @@ import type { CommandContext } from "./types"; import { registerSeedTestContracts } from "./seed-test-contracts.cmd"; import { registerSeedTestSchedules } from "./seed-test-schedules.cmd"; +import { registerSeedTestCompany } from "./seed-test-company.cmd"; export function registerCommands(vorpal: Vorpal, ctx: CommandContext): void { registerSeedTestContracts(vorpal, ctx); registerSeedTestSchedules(vorpal, ctx); + registerSeedTestCompany(vorpal, ctx); } diff --git a/apps/edr-freight-api/src/scripts/cmds/seed-test-company.cmd.ts b/apps/edr-freight-api/src/scripts/cmds/seed-test-company.cmd.ts new file mode 100644 index 000000000..bef4ed031 --- /dev/null +++ b/apps/edr-freight-api/src/scripts/cmds/seed-test-company.cmd.ts @@ -0,0 +1,85 @@ +import type Vorpal from "vorpal"; +import { DataSource } from "typeorm"; +import type { CommandContext } from "./types"; +import { Company, CompanyType, CompanyKind, CompanyStatus, CompanyNationality } from "../../modules/companies/entities/company.entity"; +import { CompanyProfile, ProfileStatus, ProfileType } from "../../modules/companies/entities/company-profile.entity"; +import { ExternalProfile } from "../../modules/companies/entities/external-profile.entity"; + +export function registerSeedTestCompany( + vorpal: Vorpal, + ctx: CommandContext, +): void { + vorpal + .command("seed:test-company", "Generate a test company with approved importer/exporter profiles and an external user") + .option("--name ", "Company name (default: Test Company)") + .option("--email ", "Company email (default: company@test.com)") + .option("--tin ", "Tax ID (default: auto-generated TSTxxxxx)") + .action(async function (this: any, args: any) { + const { app } = ctx; + const ds = app.get(DataSource); + + const raw = await ds.query( + `SELECT "tin" FROM "freight"."companies" WHERE "tin" LIKE 'TST%' AND "deleted_at" IS NULL ORDER BY "tin" DESC LIMIT 1`, + ); + let nextTinNum = 1; + if (raw.length > 0) { + const num = parseInt((raw[0] as any).tin.replace("TST", ""), 10); + if (!isNaN(num)) nextTinNum = num + 1; + } + + const name = args.options?.name ?? "Test Company"; + const email = args.options?.email ?? "company@test.com"; + const tin = args.options?.tin ?? `TST${String(nextTinNum).padStart(6, "0")}`; + const userId = `ffffffff-0000-4000-8000-${String(nextTinNum).padStart(12, "0")}`; + + const existing = await ds.getRepository(Company).findOne({ where: { tin } }); + if (existing) { + this.log(`Company with TIN ${tin} already exists (${existing.name})`); + return; + } + + const company = await ds.getRepository(Company).save( + ds.getRepository(Company).create({ + name, + type: CompanyType.Customer, + kind: CompanyKind.Commercial, + status: CompanyStatus.Active, + tin, + country: "Ethiopia", + nationality: CompanyNationality.Ethiopian, + email, + phone: "+251911000000", + address: "Test Address", + }), + ); + this.log(` Created company: ${company.name} (TIN: ${tin})`); + + for (const type of [ProfileType.importer, ProfileType.exporter]) { + await ds.getRepository(CompanyProfile).save( + ds.getRepository(CompanyProfile).create({ + companyId: company.id, + type, + reference: `TST-${type.toUpperCase()}-${String(nextTinNum).padStart(3, "0")}`, + status: ProfileStatus.Active, + }), + ); + this.log(` Created ${type} profile (approved)`); + } + + await ds.getRepository(ExternalProfile).save( + ds.getRepository(ExternalProfile).create({ + userId, + companyId: company.id, + firstName: "Test", + lastName: "User", + isPrimaryContact: true, + activeProfileType: ProfileType.importer, + onboardingCompleted: true, + onboardingStep: "done", + }), + ); + this.log(` Created external profile: Test User (userId: ${userId})`); + + this.log(`\nDone — login with email "${email}" and password "password"`); + }); +} diff --git a/apps/edr-freight-api/src/scripts/cmds/seed-test-contracts.cmd.ts b/apps/edr-freight-api/src/scripts/cmds/seed-test-contracts.cmd.ts index 17ba79182..a46a9dee8 100644 --- a/apps/edr-freight-api/src/scripts/cmds/seed-test-contracts.cmd.ts +++ b/apps/edr-freight-api/src/scripts/cmds/seed-test-contracts.cmd.ts @@ -13,35 +13,6 @@ import { ContractRoute } from "../../modules/contracts/entities/contract-route.e import { ContractCargoScope } from "../../modules/contracts/entities/contract-cargo-scope.entity"; import { ContractRateSnapshot } from "../../modules/contracts/entities/contract-rate-snapshot.entity"; -const COMPANY_IDS = [ - "a0000001-0000-4000-8000-000000000001", - "a0000001-0000-4000-8000-000000000002", - "a0000001-0000-4000-8000-000000000003", - "a0000001-0000-4000-8000-000000000004", -]; - -const PROFILE_IDS = [ - "b0000001-0000-4000-8000-000000000001", - "b0000001-0000-4000-8000-000000000002", - "b0000001-0000-4000-8000-000000000003", - "b0000001-0000-4000-8000-000000000004", - "b0000001-0000-4000-8000-000000000005", - "b0000001-0000-4000-8000-000000000006", - "b0000001-0000-4000-8000-000000000007", - "b0000001-0000-4000-8000-000000000008", -]; - -const EXTERNAL_PROFILE_IDS = [ - "c0000001-0000-4000-8000-000000000001", - "c0000001-0000-4000-8000-000000000002", - "c0000001-0000-4000-8000-000000000003", - "c0000001-0000-4000-8000-000000000004", -]; - -function generateRef(index: number): string { - return `TST-CTR-${String(index).padStart(5, "0")}`; -} - export function registerSeedTestContracts( vorpal: Vorpal, ctx: CommandContext, @@ -124,7 +95,15 @@ export function registerSeedTestContracts( } const contractRepo = ds.getRepository(Contract); - let contractCount = 0; + + const maxRaw = await ds.query( + `SELECT "reference" FROM "freight"."contracts" WHERE "reference" LIKE 'TST-CTR-%' AND "deleted_at" IS NULL ORDER BY "reference" DESC LIMIT 1`, + ); + let nextRef = 1; + if (maxRaw.length > 0) { + const num = parseInt(maxRaw[0].reference.replace("TST-CTR-", ""), 10); + if (!isNaN(num)) nextRef = num + 1; + } for (let i = 0; i < count; i++) { const statusIdx = i % statusList.length; @@ -145,13 +124,7 @@ export function registerSeedTestContracts( }); if (!profile) continue; - const ref = generateRef(i + 1); - const exists = await contractRepo.findOne({ where: { reference: ref } }); - if (exists) { - this.log(` Contract ${ref} already exists — skipping`); - contractCount++; - continue; - } + const ref = `TST-CTR-${String(nextRef + i).padStart(5, "0")}`; const serviceTypeId = freightType === "BULK" && railBulk @@ -239,54 +212,52 @@ export function registerSeedTestContracts( ); } - contractCount++; this.log(` Created ${status} ${freightType} ${direction} contract: ${ref} (${company.name})`); } - this.log(`Done — ${contractCount} contracts ensured`); + this.log(`Done — ${count} new contracts created`); }); } interface CompanySeed { - id: string; name: string; tin: string; - profiles: Array<{ id: string; type: ProfileType; reference: string }>; - externalProfile: { id: string; userId: string; firstName: string; lastName: string }; + profiles: Array<{ type: ProfileType; reference: string }>; + externalProfile: { userId: string; firstName: string; lastName: string }; } const TEST_COMPANIES: CompanySeed[] = [ { - id: COMPANY_IDS[0], name: "Test Importer Co.", tin: "TST000001", + name: "Test Importer Co.", tin: "TST000001", profiles: [ - { id: PROFILE_IDS[0], type: ProfileType.importer, reference: "TST-IM-001" }, - { id: PROFILE_IDS[1], type: ProfileType.exporter, reference: "TST-EX-001" }, + { type: ProfileType.importer, reference: "TST-IM-001" }, + { type: ProfileType.exporter, reference: "TST-EX-001" }, ], - externalProfile: { id: EXTERNAL_PROFILE_IDS[0], userId: "00000000-0000-0000-0000-000000000001", firstName: "Abebe", lastName: "Kebede" }, + externalProfile: { userId: "00000000-0000-0000-0000-000000000001", firstName: "Abebe", lastName: "Kebede" }, }, { - id: COMPANY_IDS[1], name: "Test Exporter Ltd.", tin: "TST000002", + name: "Test Exporter Ltd.", tin: "TST000002", profiles: [ - { id: PROFILE_IDS[2], type: ProfileType.importer, reference: "TST-IM-002" }, - { id: PROFILE_IDS[3], type: ProfileType.exporter, reference: "TST-EX-002" }, + { type: ProfileType.importer, reference: "TST-IM-002" }, + { type: ProfileType.exporter, reference: "TST-EX-002" }, ], - externalProfile: { id: EXTERNAL_PROFILE_IDS[1], userId: "00000000-0000-0000-0000-000000000002", firstName: "Bekele", lastName: "Alemu" }, + externalProfile: { userId: "00000000-0000-0000-0000-000000000002", firstName: "Bekele", lastName: "Alemu" }, }, { - id: COMPANY_IDS[2], name: "Bulk Commodities PLC", tin: "TST000003", + name: "Bulk Commodities PLC", tin: "TST000003", profiles: [ - { id: PROFILE_IDS[4], type: ProfileType.importer, reference: "TST-IM-003" }, - { id: PROFILE_IDS[5], type: ProfileType.exporter, reference: "TST-EX-003" }, + { type: ProfileType.importer, reference: "TST-IM-003" }, + { type: ProfileType.exporter, reference: "TST-EX-003" }, ], - externalProfile: { id: EXTERNAL_PROFILE_IDS[2], userId: "00000000-0000-0000-0000-000000000003", firstName: "Chala", lastName: "Tesfaye" }, + externalProfile: { userId: "00000000-0000-0000-0000-000000000003", firstName: "Chala", lastName: "Tesfaye" }, }, { - id: COMPANY_IDS[3], name: "Hazardous Logistics Inc.", tin: "TST000004", + name: "Hazardous Logistics Inc.", tin: "TST000004", profiles: [ - { id: PROFILE_IDS[6], type: ProfileType.importer, reference: "TST-IM-004" }, - { id: PROFILE_IDS[7], type: ProfileType.exporter, reference: "TST-EX-004" }, + { type: ProfileType.importer, reference: "TST-IM-004" }, + { type: ProfileType.exporter, reference: "TST-EX-004" }, ], - externalProfile: { id: EXTERNAL_PROFILE_IDS[3], userId: "00000000-0000-0000-0000-000000000004", firstName: "Desta", lastName: "Hailu" }, + externalProfile: { userId: "00000000-0000-0000-0000-000000000004", firstName: "Desta", lastName: "Hailu" }, }, ]; @@ -297,11 +268,10 @@ async function seedTestCompanies(ds: DataSource, log: (msg: string) => void): Pr const result: Company[] = []; for (const seed of TEST_COMPANIES) { - let company = await companyRepo.findOne({ where: { id: seed.id } }); + let company = await companyRepo.findOne({ where: { tin: seed.tin } }); if (!company) { company = await companyRepo.save( companyRepo.create({ - id: seed.id, name: seed.name, type: CompanyType.Customer, kind: CompanyKind.Commercial, @@ -319,12 +289,13 @@ async function seedTestCompanies(ds: DataSource, log: (msg: string) => void): Pr } for (const p of seed.profiles) { - const existing = await profileRepo.findOne({ where: { id: p.id } }); + const existing = await profileRepo.findOne({ + where: { companyId: company.id, type: p.type }, + }); if (!existing) { await profileRepo.save( profileRepo.create({ - id: p.id, - companyId: seed.id, + companyId: company.id, type: p.type, reference: p.reference, status: ProfileStatus.Active, @@ -335,13 +306,14 @@ async function seedTestCompanies(ds: DataSource, log: (msg: string) => void): Pr } const ext = seed.externalProfile; - const existingExt = await extProfileRepo.findOne({ where: { id: ext.id } }); + const existingExt = await extProfileRepo.findOne({ + where: { companyId: company.id, userId: ext.userId }, + }); if (!existingExt) { await extProfileRepo.save( extProfileRepo.create({ - id: ext.id, userId: ext.userId, - companyId: seed.id, + companyId: company.id, firstName: ext.firstName, lastName: ext.lastName, isPrimaryContact: true, diff --git a/apps/edr-freight-api/src/scripts/cmds/seed-test-schedules.cmd.ts b/apps/edr-freight-api/src/scripts/cmds/seed-test-schedules.cmd.ts index 2d9002555..eeab0e2dd 100644 --- a/apps/edr-freight-api/src/scripts/cmds/seed-test-schedules.cmd.ts +++ b/apps/edr-freight-api/src/scripts/cmds/seed-test-schedules.cmd.ts @@ -12,8 +12,38 @@ import { TrainSet } from "../../modules/train-sets/entities/train-set.entity"; import { TrainSetLocomotive } from "../../modules/train-sets/entities/train-set-locomotive.entity"; import { TrainSetWagon } from "../../modules/train-sets/entities/train-set-wagon.entity"; import { TrainSchedule } from "../../modules/train-schedules/entities/train-schedule.entity"; -import { TrainScheduleBooking } from "../../modules/train-schedules/entities/train-schedule-booking.entity"; -import { Booking } from "../../modules/bookings/entities/booking.entity"; + +async function nextSequence(ds: DataSource, pattern: string): Promise { + const like = pattern.replace(/\*/g, "%"); + const raw = await ds.query( + `SELECT "train_number" FROM "freight"."train_schedules" WHERE "train_number" LIKE $1 AND "deleted_at" IS NULL ORDER BY "train_number" DESC LIMIT 1`, + [like.replace(/%/g, "") + "%"], + ); + if (raw.length === 0) return 1; + const ref: string = raw[0].train_number; + const num = parseInt(ref.replace(pattern.split("*")[0], ""), 10); + return isNaN(num) ? 1 : num + 1; +} + +async function nextRouteSeq(ds: DataSource, prefix: string): Promise { + const raw = await ds.query( + `SELECT "name" FROM "freight"."routes" WHERE "name" LIKE $1 AND "deleted_at" IS NULL ORDER BY "name" DESC LIMIT 1`, + [prefix + "%"], + ); + if (raw.length === 0) return 1; + const num = parseInt(raw[0].name.replace(prefix, ""), 10); + return isNaN(num) ? 1 : num + 1; +} + +async function nextWagonSeq(ds: DataSource, prefix: string): Promise { + const raw = await ds.query( + `SELECT "wagon_number" FROM "freight"."wagons" WHERE "wagon_number" LIKE $1 AND "deleted_at" IS NULL ORDER BY "wagon_number" DESC LIMIT 1`, + [prefix + "%"], + ); + if (raw.length === 0) return 1; + const num = parseInt(raw[0].wagon_number.replace(prefix, ""), 10); + return isNaN(num) ? 1 : num + 1; +} export function registerSeedTestSchedules( vorpal: Vorpal, @@ -43,8 +73,6 @@ export function registerSeedTestSchedules( return; } - this.log(`Seeding ${count} schedules (direction=${directionList.join(",")}, status=${statusList.join(",")}, days_ahead=${daysAhead})...`); - const yards = await ds.getRepository(Yard).find({ where: { isActive: true } }); const yardByCode = new Map(yards.map((y) => [y.code.toUpperCase(), y])); const djibouti = yardByCode.get("DJIBOUTI") ?? yards.find((y) => y.country === "Djibouti"); @@ -61,50 +89,90 @@ export function registerSeedTestSchedules( return; } - const route = await ensureTestRoute(ds, yards, djibouti, addis, (msg) => this.log(msg)); + const wagonType = wagonTypes[0]; + const wagonCapacity = Number(wagonType.capacityTons) || 70; + const wagonLength = Number(wagonType.lengthMeters) || 14; + const tareWeight = Number(wagonType.tareWeightTons) || 14; + const locomotiveRepo = ds.getRepository(Locomotive); const scheduleRepo = ds.getRepository(TrainSchedule); const trainSetRepo = ds.getRepository(TrainSet); - let seeded = 0; + const wagonRepo = ds.getRepository(Wagon); + const routeRepo = ds.getRepository(Route); + const milestoneRepo = ds.getRepository(RouteMilestone); + + let nextTrainNum = await nextSequence(ds, "TST-SCH-*"); + const routePrefix = "TST-RTE-"; + let nextRouteNum = await nextRouteSeq(ds, routePrefix); + + const now = new Date(); + const travelHours = 11; + const intermediateYards = yards.filter( + (y) => y.id !== djibouti.id && y.id !== addis.id, + ); + + let loco = await locomotiveRepo.findOne({ where: { code: "TST-LOCO-01" } }); + if (!loco) { + loco = await locomotiveRepo.save( + locomotiveRepo.create({ + code: "TST-LOCO-01", + name: "Test Locomotive", + locomotiveType: "DIESEL", + maxPullWeightTons: 4200, + maxTrainLengthMeters: 760, + status: "AVAILABLE", + currentYardId: djibouti.id, + }), + ); + } for (let i = 0; i < count; i++) { + const seq = nextTrainNum + i; + const trainNumber = `TST-SCH-${String(seq).padStart(5, "0")}`; const dir = directionList[i % directionList.length]; const status = statusList[i % statusList.length]; - const trainNumber = `TST-SCH-${String(i + 1).padStart(3, "0")}`; - - const existing = await scheduleRepo.findOne({ where: { trainNumber } }); - if (existing) { - this.log(` Schedule ${trainNumber} already exists — skipping`); - seeded++; - continue; - } - + const isDispatched = status === "DISPATCHED"; const originYard = dir === "IMPORT" ? djibouti : addis; const destYard = dir === "IMPORT" ? addis : djibouti; - const isDispatched = status === "DISPATCHED"; + const routeName = `${routePrefix}${String(nextRouteNum + i).padStart(3, "0")}`; - const now = new Date(); const departure = new Date(now); - departure.setDate(departure.getDate() + daysAhead); + departure.setDate(departure.getDate() + daysAhead + i); departure.setHours(7, 0, 0, 0); - - const travelHours = dir === "IMPORT" ? 12 : 10; const arrival = new Date(departure.getTime() + travelHours * 60 * 60 * 1000); - const locomotive = await ensureTestLocomotive(ds, originYard.id, (msg) => this.log(msg)); - const wagonCount = 4; - const wagonType = wagonTypes[0]; - const wagonCapacity = Number(wagonType.capacityTons) || 70; - const wagonLength = Number(wagonType.lengthMeters) || 14; - const tareWeight = Number(wagonType.tareWeightTons) || 14; - const totalWagonWeight = wagonCount * (tareWeight + 20); + const route = await routeRepo.save( + routeRepo.create({ + name: routeName, + originYardId: originYard.id, + destinationYardId: destYard.id, + isActive: true, + }), + ); + await milestoneRepo.save( + milestoneRepo.create({ routeId: route.id, yardId: originYard.id, sequenceNo: 1 }), + ); + for (const [mi, y] of intermediateYards.entries()) { + await milestoneRepo.save( + milestoneRepo.create({ routeId: route.id, yardId: y.id, sequenceNo: (mi + 1) * 2 }), + ); + } + await milestoneRepo.save( + milestoneRepo.create({ + routeId: route.id, + yardId: destYard.id, + sequenceNo: (intermediateYards.length + 1) * 2, + }), + ); + + const totalWagonWeight = 4 * (tareWeight + 20); const trainSet = await trainSetRepo.save( trainSetRepo.create({ - locomotiveId: locomotive.id, + locomotiveId: loco.id, totalWeightTons: totalWagonWeight, - totalLengthMeters: wagonLength * wagonCount, - wagonCount, + totalLengthMeters: wagonLength * 4, + wagonCount: 4, status: isDispatched ? "DISPATCHED" : status === "DRAFT" ? "DRAFT" : "ASSIGNED", }), ); @@ -112,7 +180,7 @@ export function registerSeedTestSchedules( await ds.getRepository(TrainSetLocomotive).save( ds.getRepository(TrainSetLocomotive).create({ trainSetId: trainSet.id, - locomotiveId: locomotive.id, + locomotiveId: loco.id, sequenceNo: 0, }), ); @@ -134,26 +202,31 @@ export function registerSeedTestSchedules( }), ); - for (let w = 0; w < wagonCount; w++) { - const seq = w + 1; - const wagonNumber = `${trainNumber}-W${String(seq).padStart(2, "0")}`; + const wagonPrefix = `${trainNumber}-W`; + let nextWagon = await nextWagonSeq(ds, wagonPrefix); + for (let w = 0; w < 4; w++) { + const ws = nextWagon + w; + const wagonNumber = `${wagonPrefix}${String(ws).padStart(2, "0")}`; - const physicalWagon = await ensureTestWagon(ds, { + const wagon = wagonRepo.create({ wagonNumber, wagonTypeId: wagonType.id, - yardId: originYard.id, - trainScheduleId: schedule.id, + currentYardId: originYard.id, + currentTrainScheduleId: schedule.id, tareWeight, - capacityTons: wagonCapacity, - dispatched: isDispatched, + maxPayloadWeight: wagonCapacity, + status: isDispatched ? WagonStatus.Assigned : WagonStatus.Available, + notes: "Test seed wagon", }); + const saved = await wagonRepo.save(wagon as any); + const physicalWagon = Array.isArray(saved) ? saved[0] : saved; await ds.getRepository(TrainSetWagon).save( ds.getRepository(TrainSetWagon).create({ trainSetId: trainSet.id, wagonTypeId: wagonType.id, physicalWagonId: physicalWagon.id, - sequenceNo: seq, + sequenceNo: w + 1, capacityTons: wagonCapacity, lengthMeters: wagonLength, assignedWeightTons: 20, @@ -162,137 +235,9 @@ export function registerSeedTestSchedules( ); } - const scheduleBookings = await ds.getRepository(TrainScheduleBooking).find({ - where: { trainScheduleId: schedule.id }, - }); - if (scheduleBookings.length === 0) { - const booking = await ds.getRepository(Booking).findOne({ where: {}, order: { createdAt: "DESC" } }); - if (booking) { - await ds.getRepository(TrainScheduleBooking).save( - ds.getRepository(TrainScheduleBooking).create({ - trainScheduleId: schedule.id, - bookingId: booking.id, - }), - ); - } - } - - seeded++; this.log(` Created ${status} ${dir} schedule: ${trainNumber} (${originYard.label} → ${destYard.label})`); } - this.log(`Done — ${seeded} train schedules ensured`); + this.log(`Done — ${count} new train schedules created`); }); } - -async function ensureTestRoute( - ds: DataSource, - yards: Yard[], - originYard: Yard, - destYard: Yard, - log: (msg: string) => void, -): Promise { - const repo = ds.getRepository(Route); - const name = `TST-RTE-${originYard.code}_${destYard.code}`; - let route = await repo.findOne({ where: { name } }); - if (route) return route; - - route = await repo.save( - repo.create({ - name, - originYardId: originYard.id, - destinationYardId: destYard.id, - isActive: true, - }), - ); - log(` Created route: ${name}`); - - const milestoneRepo = ds.getRepository(RouteMilestone); - const intermediateYards = yards.filter( - (y) => y.id !== originYard.id && y.id !== destYard.id, - ); - - await milestoneRepo.save( - milestoneRepo.create({ - routeId: route.id, - yardId: originYard.id, - sequenceNo: 0, - }), - ); - - for (const [idx, y] of intermediateYards.entries()) { - await milestoneRepo.save( - milestoneRepo.create({ - routeId: route.id, - yardId: y.id, - sequenceNo: (idx + 1) * 2, - }), - ); - } - - await milestoneRepo.save( - milestoneRepo.create({ - routeId: route.id, - yardId: destYard.id, - sequenceNo: (intermediateYards.length + 1) * 2, - }), - ); - - log(` Added ${intermediateYards.length + 2} milestones`); - return route; -} - -async function ensureTestLocomotive( - ds: DataSource, - yardId: string, - log: (msg: string) => void, -): Promise { - const repo = ds.getRepository(Locomotive); - const code = "TST-LOCO-01"; - let loco = await repo.findOne({ where: { code } }); - if (loco) return loco; - - loco = await repo.save( - repo.create({ - code, - name: "Test Locomotive", - locomotiveType: "DIESEL", - maxPullWeightTons: 4200, - maxTrainLengthMeters: 760, - status: "AVAILABLE", - currentYardId: yardId, - }), - ); - log(` Created locomotive: ${code}`); - return loco; -} - -async function ensureTestWagon( - ds: DataSource, - input: { - wagonNumber: string; - wagonTypeId: string; - yardId: string; - trainScheduleId: string; - tareWeight: number; - capacityTons: number; - dispatched: boolean; - }, -): Promise { - const repo = ds.getRepository(Wagon); - const existing = await repo.findOne({ where: { wagonNumber: input.wagonNumber } }); - if (existing) return existing; - - const wagon = repo.create({ - wagonNumber: input.wagonNumber, - wagonTypeId: input.wagonTypeId, - currentYardId: input.yardId, - currentTrainScheduleId: input.trainScheduleId, - tareWeight: input.tareWeight, - maxPayloadWeight: input.capacityTons, - status: input.dispatched ? WagonStatus.Assigned : WagonStatus.Available, - notes: "Test seed wagon", - }); - const saved = await repo.save(wagon as any); - return Array.isArray(saved) ? saved[0] : saved; -} diff --git a/apps/edr-freight-api/src/scripts/cmds/types.ts b/apps/edr-freight-api/src/scripts/cmds/types.ts index bd0fbb9c9..6c805e07d 100644 --- a/apps/edr-freight-api/src/scripts/cmds/types.ts +++ b/apps/edr-freight-api/src/scripts/cmds/types.ts @@ -1,4 +1,3 @@ -import type Vorpal from "vorpal"; import type { INestApplicationContext } from "@nestjs/common"; export type CommandContext = {