mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-06 10:03:38 +00:00
feat(reports): record loading and unloading time per stop
The OCC report publishes total loading and unloading time and the other activity left over from a station stay, but nothing recorded when handling started or ended — the July 2026 seed had to write the figure into a checkpoint note. Four nullable stamps now ride the stop's arrival row, which is the row the staying-time report builds a stay from (a turnaround's departure belongs to a different schedule). Handling is unloading start to loading end, so a container stop reads as one window and a bulk station that only loads or only unloads still reports its half; other activity is the rest of the stay. Both stay NULL where nothing was logged rather than collapsing to zero. - station-staying-time: + loading/unloading and other activity per stop - turnaround-cycle: + the same, summed over the cycle's stops - loading-unloading (new): per train per station per period, so a week or month view is that train's average over its stops - the stop/stay query moves to operations-classification, shared by both
This commit is contained in:
@@ -487,6 +487,12 @@ async function upsertTrain(ds: DataSource, code: string): Promise<string> {
|
||||
return row.id;
|
||||
}
|
||||
|
||||
/** The handling window a stop records — the loading/unloading report's input. */
|
||||
interface Handling {
|
||||
unloadingStartedAt: Date;
|
||||
loadingCompletedAt: Date;
|
||||
}
|
||||
|
||||
async function upsertCheckpoint(
|
||||
ds: DataSource,
|
||||
scheduleId: string,
|
||||
@@ -495,7 +501,18 @@ async function upsertCheckpoint(
|
||||
kind: 'ARRIVED' | 'DEPARTED',
|
||||
occurredAt: Date,
|
||||
note: string,
|
||||
handling?: Handling,
|
||||
): Promise<void> {
|
||||
const params = [
|
||||
scheduleId,
|
||||
yardId,
|
||||
sequenceNo,
|
||||
kind,
|
||||
occurredAt,
|
||||
note,
|
||||
handling?.unloadingStartedAt ?? null,
|
||||
handling?.loadingCompletedAt ?? null,
|
||||
];
|
||||
const existing = await ds.query<Array<{ id: string }>>(
|
||||
`SELECT id FROM freight.train_checkpoint_events
|
||||
WHERE train_schedule_id = $1 AND yard_id = $2 AND kind = $3 AND deleted_at IS NULL`,
|
||||
@@ -503,17 +520,20 @@ async function upsertCheckpoint(
|
||||
);
|
||||
if (existing.length) {
|
||||
await ds.query(
|
||||
`UPDATE freight.train_checkpoint_events SET occurred_at = $2, note = $3, updated_at = now()
|
||||
`UPDATE freight.train_checkpoint_events
|
||||
SET occurred_at = $2, note = $3,
|
||||
unloading_started_at = $4, loading_completed_at = $5, updated_at = now()
|
||||
WHERE id = $1`,
|
||||
[existing[0].id, occurredAt, note],
|
||||
[existing[0].id, occurredAt, note, params[6], params[7]],
|
||||
);
|
||||
return;
|
||||
}
|
||||
await ds.query(
|
||||
`INSERT INTO freight.train_checkpoint_events
|
||||
(train_schedule_id, yard_id, sequence_no, kind, occurred_at, note)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)`,
|
||||
[scheduleId, yardId, sequenceNo, kind, occurredAt, note],
|
||||
(train_schedule_id, yard_id, sequence_no, kind, occurred_at, note,
|
||||
unloading_started_at, loading_completed_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`,
|
||||
params,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -605,13 +625,17 @@ async function seedDmpTrains(ds: DataSource, ids: Ids): Promise<void> {
|
||||
arrivedAt: arrivedGelan,
|
||||
});
|
||||
|
||||
// The loading/unloading figure has nowhere of its own to live yet — no
|
||||
// table records when handling starts and ends — so it rides on the stop's
|
||||
// note, where the staying-time report surfaces it as the stop's reason.
|
||||
// The measured handling window, on the arrival row the staying-time report
|
||||
// builds the stop from: work starts when the train lands and ends when
|
||||
// loading finishes, which is what the OCC figure measures. The rest of the
|
||||
// stay reports as other activity.
|
||||
const note =
|
||||
`OCC July 2026 — loading/unloading ${handlingHours.toFixed(2)}h of ` +
|
||||
`${stayingHours.toFixed(2)}h total staying`;
|
||||
await upsertCheckpoint(ds, schedule, dmp, 0, 'ARRIVED', arrivedAtDmp, note);
|
||||
await upsertCheckpoint(ds, schedule, dmp, 0, 'ARRIVED', arrivedAtDmp, note, {
|
||||
unloadingStartedAt: arrivedAtDmp,
|
||||
loadingCompletedAt: addHours(arrivedAtDmp, handlingHours),
|
||||
});
|
||||
await upsertCheckpoint(ds, schedule, dmp, 0, 'DEPARTED', departedDmp, note);
|
||||
}
|
||||
console.log(`DMP trains : ${DMP_TRAINS.length} trains with measured staying times`);
|
||||
|
||||
Reference in New Issue
Block a user