mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 16:28:12 +00:00
feat(train-scheduling): mid-route consist changes, audit history, safer workspace
- planned couples: loose wagons join the train at a route stop, added from the schedule yards tab; capacity credits them per corridor edge and coupling validates locomotive weight/length caps per leg - real-cut toggle: a cut wagon permanently leaves the train build at its cut yard (soft cut still sits out one trip only) - fix heaviest-leg display counting a shared slot's full cargo on every spanned edge (phantom pull-weight overload on S-2026-00045) - confirmation dialogs for workspace add/load/unload/remove actions - train-builder History and Detached-wagons tabs, backed by paginated endpoints; builder detaches now always write adjustment-log rows Migrations 3660 (planned_wagon_couples, planned_wagon_real_cuts) and 3670 (adjustment log train_schedule_id nullable) — both applied to the dev DB by hand; watch mode does not run migrations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,13 @@ export type WagonStock = {
|
||||
* math.
|
||||
*/
|
||||
byYardId?: Map<string, Map<string, number>>;
|
||||
/**
|
||||
* Wagons the schedule CUTS mid-route (staff plan): each is stock only up to
|
||||
* its cut stop. Consumers debit it from its pool on every edge at/after the
|
||||
* cut, so a leg riding past the cut never counts it. Absent = no cuts.
|
||||
* `poolYardId` is the wagon's boarding pool ('' on a single-yard consist).
|
||||
*/
|
||||
cutWagons?: Array<{ wagonTypeId: string; poolYardId: string; cutYardId: string }>;
|
||||
};
|
||||
|
||||
export type FlexPlanResult = {
|
||||
@@ -324,6 +331,16 @@ export function planWagonsWithStock(params: {
|
||||
}
|
||||
return row;
|
||||
};
|
||||
// Cut wagons are pre-consumed on every edge at/after their cut stop: they
|
||||
// are steel for gmp→lebu but not for gmp→dct. Unknown cut yard (no stops
|
||||
// given / off-corridor) is skipped — conservative, same as before cuts.
|
||||
for (const cut of stock.cutWagons ?? []) {
|
||||
const fromEdge = stops.indexOf(cut.cutYardId);
|
||||
if (fromEdge < 0) continue;
|
||||
const pool = stock.byYardId ? cut.poolYardId : '';
|
||||
const row = usedRow(rowKeyFor(cut.wagonTypeId, pool));
|
||||
for (let e = fromEdge; e < edgeCount; e += 1) row[e] += 1;
|
||||
}
|
||||
const availableFor = (wagonTypeId: string, leg: BookingLeg): number => {
|
||||
const pool = poolOf(leg);
|
||||
const total = totalFor(wagonTypeId, pool);
|
||||
|
||||
Reference in New Issue
Block a user