mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 13:28:11 +00:00
feat(freight): changed the train schedule
This commit is contained in:
@@ -15,9 +15,9 @@ import {
|
||||
import { LocomotivesRepository } from "../locomotives/locomotives.repository";
|
||||
import { TrainSetWagon } from "../train-sets/entities/train-set-wagon.entity";
|
||||
import { TrainSet } from "../train-sets/entities/train-set.entity";
|
||||
import { Route } from "../routes/entities/route.entity";
|
||||
import { TrainScheduleBooking } from "../train-schedules/entities/train-schedule-booking.entity";
|
||||
import { TrainSchedule } from "../train-schedules/entities/train-schedule.entity";
|
||||
import { WagonBookingAllocation } from "../train-schedules/entities/wagon-booking-allocation.entity";
|
||||
import { WagonType } from "../wagon-types/entities/wagon-type.entity";
|
||||
import { WagonTypesRepository } from "../wagon-types/wagon-types.repository";
|
||||
import { CreateContainerTrainScheduleDto } from "./dto/create-container-train-schedule.dto";
|
||||
@@ -179,19 +179,12 @@ export class TrainSchedulingService {
|
||||
}
|
||||
|
||||
async createContainerTrainSchedule(dto: CreateContainerTrainScheduleDto) {
|
||||
const validation = await this.validateContainerBookingsForScheduling(dto);
|
||||
|
||||
if (!validation.valid) {
|
||||
throw new BadRequestException({
|
||||
message: "train_schedule_invalid",
|
||||
violations: validation.violations,
|
||||
});
|
||||
}
|
||||
const route = await this.getActiveRoute(dto.routeId);
|
||||
|
||||
const locomotive = await this.selectOrValidateLocomotive(
|
||||
dto.locomotiveId,
|
||||
validation.summary.totalWeightTons,
|
||||
validation.summary.totalLengthMeters,
|
||||
0,
|
||||
0,
|
||||
);
|
||||
|
||||
const createdSchedule = await this.dataSource.transaction(
|
||||
@@ -212,99 +205,24 @@ export class TrainSchedulingService {
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
Number(lockedLocomotive.maxPullWeightTons) <
|
||||
validation.summary.totalWeightTons
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
`Locomotive ${lockedLocomotive.code} cannot pull ${validation.summary.totalWeightTons}T`,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
Number(lockedLocomotive.maxTrainLengthMeters) <
|
||||
validation.summary.totalLengthMeters
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
`Locomotive ${lockedLocomotive.code} cannot support ${validation.summary.totalLengthMeters}m`,
|
||||
);
|
||||
}
|
||||
|
||||
const existingScheduleCount = await manager
|
||||
.getRepository(TrainScheduleBooking)
|
||||
.count({
|
||||
where: {
|
||||
bookingId: In(validation.bookings.map((booking) => booking.id)),
|
||||
},
|
||||
});
|
||||
|
||||
if (existingScheduleCount > 0) {
|
||||
throw new BadRequestException(
|
||||
"One or more bookings are already scheduled",
|
||||
);
|
||||
}
|
||||
|
||||
const trainSet = await this.buildTrainSet(
|
||||
const trainSet = await this.buildEmptyTrainSet(
|
||||
manager,
|
||||
lockedLocomotive,
|
||||
validation.wagonType,
|
||||
validation.summary.totalWeightTons,
|
||||
validation.summary.totalLengthMeters,
|
||||
validation.wagonPlan,
|
||||
);
|
||||
|
||||
const schedule = manager.getRepository(TrainSchedule).create({
|
||||
trainSetId: trainSet.id,
|
||||
originStationId: dto.originStationId,
|
||||
destinationStationId: dto.destinationStationId,
|
||||
routeId: route.id,
|
||||
originStationId: route.originYardId,
|
||||
destinationStationId: route.destinationYardId,
|
||||
scheduledDepartureDate: new Date(dto.scheduleDate),
|
||||
status: "SCHEDULED",
|
||||
status: "DRAFT",
|
||||
});
|
||||
|
||||
const savedSchedule = await manager
|
||||
.getRepository(TrainSchedule)
|
||||
.save(schedule);
|
||||
|
||||
const scheduleBookings = validation.bookings.map((booking) =>
|
||||
manager.getRepository(TrainScheduleBooking).create({
|
||||
trainScheduleId: savedSchedule.id,
|
||||
bookingId: booking.id,
|
||||
}),
|
||||
);
|
||||
await manager
|
||||
.getRepository(TrainScheduleBooking)
|
||||
.save(scheduleBookings);
|
||||
|
||||
const savedWagons = await manager.getRepository(TrainSetWagon).find({
|
||||
where: { trainSetId: trainSet.id },
|
||||
order: { sequenceNo: "ASC" },
|
||||
});
|
||||
|
||||
const wagonBySequence = new Map(
|
||||
savedWagons.map((wagon) => [wagon.sequenceNo, wagon]),
|
||||
);
|
||||
const allocationRows = validation.wagonPlan.flatMap((wagonPlan) => {
|
||||
const wagon = wagonBySequence.get(wagonPlan.sequenceNo);
|
||||
|
||||
if (!wagon) {
|
||||
throw new BadRequestException(
|
||||
`Missing wagon sequence ${wagonPlan.sequenceNo}`,
|
||||
);
|
||||
}
|
||||
|
||||
return wagonPlan.allocations.map((allocation) =>
|
||||
manager.getRepository(WagonBookingAllocation).create({
|
||||
trainSetWagonId: wagon.id,
|
||||
bookingId: allocation.bookingId,
|
||||
allocatedWeightTons: allocation.allocatedWeightTons,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
await manager
|
||||
.getRepository(WagonBookingAllocation)
|
||||
.save(allocationRows);
|
||||
|
||||
await locomotiveRepository.update(lockedLocomotive.id, {
|
||||
status: "ASSIGNED",
|
||||
});
|
||||
@@ -589,6 +507,21 @@ export class TrainSchedulingService {
|
||||
return savedTrainSet;
|
||||
}
|
||||
|
||||
async buildEmptyTrainSet(
|
||||
manager: EntityManager,
|
||||
locomotive: Locomotive,
|
||||
) {
|
||||
const trainSet = manager.getRepository(TrainSet).create({
|
||||
locomotiveId: locomotive.id,
|
||||
totalWeightTons: 0,
|
||||
totalLengthMeters: 0,
|
||||
wagonCount: 0,
|
||||
status: 'DRAFT',
|
||||
});
|
||||
|
||||
return manager.getRepository(TrainSet).save(trainSet);
|
||||
}
|
||||
|
||||
allocateBookingsToWagons(
|
||||
bookings: Booking[],
|
||||
baseWagonPlan: WagonPlanRecord[],
|
||||
@@ -648,6 +581,7 @@ export class TrainSchedulingService {
|
||||
const schedules = await this.dataSource.getRepository(TrainSchedule).find({
|
||||
relations: {
|
||||
trainSet: { locomotive: true },
|
||||
route: true,
|
||||
originStation: true,
|
||||
destinationStation: true,
|
||||
scheduleBookings: true,
|
||||
@@ -658,6 +592,7 @@ export class TrainSchedulingService {
|
||||
return schedules.map((schedule) => ({
|
||||
id: schedule.id,
|
||||
scheduleDate: schedule.scheduledDepartureDate,
|
||||
routeName: schedule.route?.name ?? null,
|
||||
origin:
|
||||
schedule.originStation?.label ?? schedule.originStation?.code ?? null,
|
||||
destination:
|
||||
@@ -689,6 +624,7 @@ export class TrainSchedulingService {
|
||||
.findOne({
|
||||
where: { id },
|
||||
relations: {
|
||||
route: true,
|
||||
trainSet: {
|
||||
locomotive: true,
|
||||
wagons: { wagonType: true, allocations: { booking: true } },
|
||||
@@ -708,6 +644,12 @@ export class TrainSchedulingService {
|
||||
return {
|
||||
id: schedule.id,
|
||||
status: schedule.status,
|
||||
route: schedule.route
|
||||
? {
|
||||
id: schedule.route.id,
|
||||
name: schedule.route.name,
|
||||
}
|
||||
: null,
|
||||
scheduledDepartureDate: schedule.scheduledDepartureDate,
|
||||
scheduledArrivalDate: schedule.scheduledArrivalDate,
|
||||
originStation: schedule.originStation,
|
||||
@@ -830,6 +772,22 @@ export class TrainSchedulingService {
|
||||
});
|
||||
}
|
||||
|
||||
private async getActiveRoute(routeId: string) {
|
||||
const route = await this.dataSource.getRepository(Route).findOne({
|
||||
where: { id: routeId },
|
||||
});
|
||||
|
||||
if (!route) {
|
||||
throw new NotFoundException(`Route ${routeId} not found`);
|
||||
}
|
||||
|
||||
if (!route.isActive) {
|
||||
throw new BadRequestException(`Route ${route.name} is inactive`);
|
||||
}
|
||||
|
||||
return route;
|
||||
}
|
||||
|
||||
private toUtcDateKey(value: Date | string) {
|
||||
const date = value instanceof Date ? value : new Date(value);
|
||||
return date.toISOString().slice(0, 10);
|
||||
|
||||
Reference in New Issue
Block a user