mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-28 23:00:57 +00:00
[200~feat: add CustomsPaymentsCard and PaymentsTab components for handling customs payments and payment summaries
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import {
|
||||
defaultPlannedWagonYards,
|
||||
misalignedWagons,
|
||||
scheduleYardOf,
|
||||
} from './planned-wagon-yards.util';
|
||||
|
||||
const w = (id: string, currentYardId: string | null) => ({ id, currentYardId });
|
||||
|
||||
describe('planned-wagon-yards.util', () => {
|
||||
it('scheduleYardOf prefers the plan and falls back to the physical yard', () => {
|
||||
expect(scheduleYardOf({ w1: 'B' }, w('w1', 'C'))).toBe('B');
|
||||
expect(scheduleYardOf({ w1: 'B' }, w('w2', 'C'))).toBe('C');
|
||||
expect(scheduleYardOf(null, w('w2', null))).toBeNull();
|
||||
});
|
||||
|
||||
it('defaultPlannedWagonYards snapshots on-route yards and rehomes the rest to origin', () => {
|
||||
const { plan, rehomed } = defaultPlannedWagonYards(
|
||||
[w('a', 'A'), w('b', 'B'), w('x', 'X'), w('n', null)],
|
||||
new Set(['A', 'B', 'C']),
|
||||
'A',
|
||||
);
|
||||
expect(plan).toEqual({ a: 'A', b: 'B', x: 'A', n: 'A' });
|
||||
expect(rehomed.map((r) => r.id)).toEqual(['x', 'n']);
|
||||
});
|
||||
|
||||
it('misalignedWagons lists only planned wagons standing elsewhere', () => {
|
||||
const out = misalignedWagons({ a: 'A', b: 'B' }, [w('a', 'A'), w('b', 'C'), w('z', 'Z')]);
|
||||
expect(out.map((r) => r.id)).toEqual(['b']);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Per-schedule wagon yard plan: `{ wagonId: yardId }` — where THIS departure
|
||||
* boards each consist wagon, independent of where the steel physically stands
|
||||
* (`wagons.current_yard_id`, one fact shared by every schedule of the train).
|
||||
*/
|
||||
export type PlannedWagonYards = Record<string, string>;
|
||||
|
||||
type YardedWagon = { id: string; currentYardId: string | null };
|
||||
|
||||
/** Yard a schedule boards a wagon from: its own plan first, the physical yard otherwise. */
|
||||
export function scheduleYardOf(
|
||||
plan: PlannedWagonYards | null | undefined,
|
||||
wagon: YardedWagon,
|
||||
): string | null {
|
||||
return plan?.[wagon.id] ?? wagon.currentYardId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default plan when a schedule is created from a built train: snapshot every
|
||||
* wagon's physical yard (so later physical moves never shift this departure's
|
||||
* capacity); a wagon standing off the route's pickup stops — or nowhere — is
|
||||
* planned at the origin instead, and reported back so staff can redistribute.
|
||||
*/
|
||||
export function defaultPlannedWagonYards(
|
||||
wagons: readonly YardedWagon[],
|
||||
pickupYardIds: ReadonlySet<string>,
|
||||
originYardId: string,
|
||||
): { plan: PlannedWagonYards; rehomed: YardedWagon[] } {
|
||||
const plan: PlannedWagonYards = {};
|
||||
const rehomed: YardedWagon[] = [];
|
||||
for (const wagon of wagons) {
|
||||
if (wagon.currentYardId && pickupYardIds.has(wagon.currentYardId)) {
|
||||
plan[wagon.id] = wagon.currentYardId;
|
||||
} else {
|
||||
plan[wagon.id] = originYardId;
|
||||
rehomed.push(wagon);
|
||||
}
|
||||
}
|
||||
return { plan, rehomed };
|
||||
}
|
||||
|
||||
/** Wagons whose planned yard disagrees with where they physically stand. */
|
||||
export function misalignedWagons<T extends YardedWagon>(
|
||||
plan: PlannedWagonYards | null | undefined,
|
||||
wagons: readonly T[],
|
||||
): T[] {
|
||||
return wagons.filter((w) => {
|
||||
const planned = plan?.[w.id];
|
||||
return planned != null && planned !== w.currentYardId;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user