mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
issue fix
This commit is contained in:
@@ -577,11 +577,7 @@ export class TrainBuilderService {
|
||||
if (!wagon || wagon.trainId !== train.id) {
|
||||
throw new NotFoundException(`Wagon ${wagonId} is not part of this train`);
|
||||
}
|
||||
if (await this.isWagonPinnedToLiveSchedule(manager, wagon.id)) {
|
||||
throw new ConflictException(
|
||||
`Wagon ${wagon.wagonNumber} is pinned to an active schedule and cannot be removed`,
|
||||
);
|
||||
}
|
||||
await this.assertDetachableAndReleaseStaleSlots(manager, wagon);
|
||||
await manager.getRepository(Wagon).update(wagon.id, {
|
||||
trainId: null,
|
||||
sequenceNumber: null,
|
||||
@@ -618,11 +614,7 @@ export class TrainBuilderService {
|
||||
if (!wagon || wagon.trainId !== train.id) {
|
||||
throw new NotFoundException(`Wagon ${wagonId} is not part of this train`);
|
||||
}
|
||||
if (await this.isWagonPinnedToLiveSchedule(manager, wagon.id)) {
|
||||
throw new ConflictException(
|
||||
`Wagon ${wagon.wagonNumber} is pinned to an active schedule and cannot be removed`,
|
||||
);
|
||||
}
|
||||
await this.assertDetachableAndReleaseStaleSlots(manager, wagon);
|
||||
const previousStatus = wagon.status;
|
||||
const notes = buildMaintenanceNotes(formatTrainRunLabel(train), note);
|
||||
await manager.getRepository(Wagon).update(wagon.id, {
|
||||
@@ -705,6 +697,57 @@ export class TrainBuilderService {
|
||||
return rows.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach guard for removeWagon / sendWagonToMaintenance. A wagon is truly
|
||||
* pinned only while a live schedule still NEEDS it: a slot carrying booking
|
||||
* allocations, or any slot on a DISPATCHED run. An empty (allocation-free)
|
||||
* slot on a DRAFT/SCHEDULED schedule is a stale reservation — its load was
|
||||
* moved to another wagon (moveWagonLoad keeps the emptied slot) or its
|
||||
* booking left through a path that didn't clean up — and used to pin the
|
||||
* wagon forever. Release those slots here instead of blocking, with the
|
||||
* same recount removeTrainSetWagonSlot does (wagonCount / totalLengthMeters
|
||||
* feed the schedule capacity math).
|
||||
*/
|
||||
private async assertDetachableAndReleaseStaleSlots(
|
||||
manager: EntityManager,
|
||||
wagon: Wagon,
|
||||
): Promise<void> {
|
||||
const rows: { id: string; train_set_id: string; status: string; allocs: string }[] =
|
||||
await manager.query(
|
||||
`SELECT tsw.id, tsw.train_set_id, ts.status,
|
||||
(SELECT count(*)
|
||||
FROM freight.wagon_booking_allocations a
|
||||
WHERE a.train_set_wagon_id = tsw.id
|
||||
AND a.deleted_at IS NULL) AS allocs
|
||||
FROM freight.train_set_wagons tsw
|
||||
JOIN freight.train_schedules ts ON ts.train_set_id = tsw.train_set_id
|
||||
WHERE tsw.physical_wagon_id = $1
|
||||
AND ts.status IN ('DRAFT', 'SCHEDULED', 'DISPATCHED')
|
||||
AND ts.deleted_at IS NULL
|
||||
AND tsw.deleted_at IS NULL`,
|
||||
[wagon.id],
|
||||
);
|
||||
if (!rows.length) return;
|
||||
if (rows.some((r) => Number(r.allocs) > 0 || r.status === 'DISPATCHED')) {
|
||||
throw new ConflictException(
|
||||
`Wagon ${wagon.wagonNumber} is pinned to an active schedule and cannot be removed`,
|
||||
);
|
||||
}
|
||||
await manager.getRepository(TrainSetWagon).delete(rows.map((r) => r.id));
|
||||
for (const trainSetId of [...new Set(rows.map((r) => r.train_set_id))]) {
|
||||
const remaining = await manager.getRepository(TrainSetWagon).find({
|
||||
where: { trainSetId },
|
||||
select: { id: true, lengthMeters: true },
|
||||
});
|
||||
await manager.getRepository(TrainSet).update(trainSetId, {
|
||||
wagonCount: remaining.length,
|
||||
totalLengthMeters: round(
|
||||
remaining.reduce((sum, w) => sum + (Number(w.lengthMeters) || 0), 0),
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Persist a drag-reorder: `wagonIds` is the full consist in its new order. */
|
||||
async reorderWagons(id: string, dto: ReorderTrainWagonsDto) {
|
||||
await this.dataSource.transaction(async (manager) => {
|
||||
|
||||
Reference in New Issue
Block a user