mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 07:10:57 +00:00
fix issue
This commit is contained in:
@@ -1522,22 +1522,48 @@ export class TrainSchedulingService {
|
||||
manager,
|
||||
);
|
||||
|
||||
const remainingBookings = (schedule.scheduleBookings ?? []).filter(
|
||||
(sb) => sb.bookingId !== bookingId,
|
||||
);
|
||||
if (remainingBookings.length === 0) {
|
||||
await this.wagonBookingAllocationsRepository.deleteByTrainSetId(
|
||||
schedule.trainSetId,
|
||||
manager,
|
||||
// Recompute the train-set composition from whatever survives this removal.
|
||||
// The removed booking's allocations were already deleted above, so any slot
|
||||
// left with zero allocations was ridden only by this booking — release it
|
||||
// (frees its reserved wagon slot). Shared slots keep their surviving
|
||||
// allocations and are re-weighed. This fixes stale tonnage/length/wagonCount
|
||||
// and orphaned RESERVED slots on a PARTIAL unassign (previously only the
|
||||
// fully-empty train was reset).
|
||||
const survivingSlots = await manager.getRepository(TrainSetWagon).find({
|
||||
where: { trainSetId: schedule.trainSetId },
|
||||
relations: { allocations: true },
|
||||
});
|
||||
let recomputedWeightTons = 0;
|
||||
let recomputedLengthMeters = 0;
|
||||
let recomputedWagonCount = 0;
|
||||
for (const slot of survivingSlots) {
|
||||
const slotAllocations = slot.allocations ?? [];
|
||||
if (slotAllocations.length === 0) {
|
||||
await manager.getRepository(TrainSetWagon).delete(slot.id);
|
||||
continue;
|
||||
}
|
||||
const slotWeight = slotAllocations.reduce(
|
||||
(sum, a) => sum + Number(a.allocatedWeightTons ?? 0),
|
||||
0,
|
||||
);
|
||||
await manager.getRepository(TrainSetWagon).delete({ trainSetId: schedule.trainSetId });
|
||||
await manager.getRepository(TrainSet).update(schedule.trainSetId, {
|
||||
totalWeightTons: 0,
|
||||
totalLengthMeters: 0,
|
||||
wagonCount: 0,
|
||||
status: 'DRAFT',
|
||||
});
|
||||
if (Number(slot.assignedWeightTons) !== slotWeight) {
|
||||
await manager
|
||||
.getRepository(TrainSetWagon)
|
||||
.update(slot.id, { assignedWeightTons: roundTons(slotWeight) });
|
||||
}
|
||||
recomputedWeightTons += slotWeight;
|
||||
recomputedLengthMeters += Number(slot.lengthMeters ?? 0);
|
||||
recomputedWagonCount += 1;
|
||||
}
|
||||
await manager.getRepository(TrainSet).update(schedule.trainSetId, {
|
||||
totalWeightTons: roundTons(recomputedWeightTons),
|
||||
totalLengthMeters: roundTons(recomputedLengthMeters),
|
||||
wagonCount: recomputedWagonCount,
|
||||
// Only downgrade to DRAFT once the train is fully empty; otherwise keep
|
||||
// the current status (an object literal lets TypeORM's contextual typing
|
||||
// accept the partial without pulling in relation fields).
|
||||
...(recomputedWagonCount === 0 ? { status: 'DRAFT' } : {}),
|
||||
});
|
||||
});
|
||||
|
||||
await this.trainCompositionRemovalLogRepository.create({
|
||||
@@ -3228,6 +3254,14 @@ export class TrainSchedulingService {
|
||||
if (!schedule) {
|
||||
throw new NotFoundException(`Train schedule ${id} not found`);
|
||||
}
|
||||
if (
|
||||
schedule.status !== TrainScheduleStatusEnum.Draft &&
|
||||
schedule.status !== TrainScheduleStatusEnum.Scheduled
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
`Cannot cancel a ${schedule.status} train; only DRAFT or SCHEDULED schedules may be cancelled`,
|
||||
);
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
|
||||
@@ -3397,6 +3431,27 @@ export class TrainSchedulingService {
|
||||
violations.push('Selected bookings must lie on the schedule route (origin before destination)');
|
||||
}
|
||||
|
||||
// Day-match: a booking scheduled for a specific EAT day must board a train
|
||||
// departing that same day. forceAssign downgrades a mismatch to a warning
|
||||
// so staff can knowingly move a booking onto an adjacent-day train.
|
||||
const scheduleDay = eatDay(new Date(dto.scheduleDate));
|
||||
const dayMismatched = bookings.filter(
|
||||
(b) =>
|
||||
!(targetScheduleId && b.trainScheduleId === targetScheduleId) &&
|
||||
b.scheduledDate != null &&
|
||||
eatDay(new Date(b.scheduledDate)) !== scheduleDay,
|
||||
);
|
||||
if (dayMismatched.length) {
|
||||
const message = `Bookings scheduled for a different day than this train's departure (${scheduleDay}): ${dayMismatched
|
||||
.map((b) => b.reference ?? b.id)
|
||||
.join(', ')}`;
|
||||
if (forceAssign) {
|
||||
warnings.push(message);
|
||||
} else {
|
||||
violations.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
if (!forceAssign) {
|
||||
for (const booking of bookings) {
|
||||
if (this.isHoldActive(booking)) {
|
||||
|
||||
Reference in New Issue
Block a user