mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 06:28:12 +00:00
auto allocation and batch managemnt, tracking the train
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
import type { ContainerPlacementInput } from './wagon-plan.util';
|
||||
|
||||
export type ContainerUnitForPlacement = {
|
||||
bookingId: string;
|
||||
bookingReference?: string | null;
|
||||
bookingContainerId: string;
|
||||
unitIndex: number;
|
||||
label: string;
|
||||
teuSlots?: number;
|
||||
sizeFt?: number;
|
||||
containerNumber?: string | null;
|
||||
};
|
||||
|
||||
export function placeholderContainerNumber(unit: ContainerUnitForPlacement): string {
|
||||
const ref = unit.bookingReference ?? unit.bookingId.slice(0, 8);
|
||||
return `TBD-${ref}-${unit.unitIndex + 1}`;
|
||||
}
|
||||
|
||||
export function isPlaceholderContainerNumber(value: string | null | undefined): boolean {
|
||||
return Boolean(value?.trim().startsWith('TBD-'));
|
||||
}
|
||||
|
||||
export function resolveContainerNumber(unit: ContainerUnitForPlacement): string {
|
||||
const trimmed = unit.containerNumber?.trim();
|
||||
return trimmed || placeholderContainerNumber(unit);
|
||||
}
|
||||
|
||||
export function autoFillPlacements(
|
||||
units: ContainerUnitForPlacement[],
|
||||
containerSlots: number[],
|
||||
): ContainerPlacementInput[] {
|
||||
if (!units.length || !containerSlots.length) return [];
|
||||
|
||||
const placements: ContainerPlacementInput[] = [];
|
||||
const MAX_TEU_PER_WAGON = 2;
|
||||
let currentSlotIndex = 0;
|
||||
let teuInCurrentSlot = 0;
|
||||
|
||||
for (const unit of units) {
|
||||
const teu = unit.teuSlots ?? (unit.sizeFt && unit.sizeFt >= 40 ? 2 : 1);
|
||||
|
||||
if (teuInCurrentSlot > 0 && teuInCurrentSlot + teu > MAX_TEU_PER_WAGON) {
|
||||
currentSlotIndex += 1;
|
||||
teuInCurrentSlot = 0;
|
||||
}
|
||||
|
||||
const sequenceNo =
|
||||
containerSlots[Math.min(currentSlotIndex, containerSlots.length - 1)] ??
|
||||
containerSlots[containerSlots.length - 1] ??
|
||||
containerSlots[0];
|
||||
|
||||
placements.push({
|
||||
bookingContainerId: unit.bookingContainerId,
|
||||
unitIndex: unit.unitIndex,
|
||||
sequenceNo,
|
||||
containerNumber: resolveContainerNumber(unit),
|
||||
});
|
||||
|
||||
teuInCurrentSlot += teu;
|
||||
}
|
||||
|
||||
return placements;
|
||||
}
|
||||
|
||||
export function findMissingContainerNumberIssues(
|
||||
units: ContainerUnitForPlacement[],
|
||||
placements: ContainerPlacementInput[],
|
||||
): Array<{ bookingId: string; issue: string }> {
|
||||
const issues: Array<{ bookingId: string; issue: string }> = [];
|
||||
const byUnit = new Map(
|
||||
placements.map((p) => [`${p.bookingContainerId}:${p.unitIndex}`, p]),
|
||||
);
|
||||
|
||||
for (const unit of units) {
|
||||
const placement = byUnit.get(`${unit.bookingContainerId}:${unit.unitIndex}`);
|
||||
if (!placement?.containerNumber?.trim()) {
|
||||
issues.push({
|
||||
bookingId: unit.bookingId,
|
||||
issue: `Missing container number for ${unit.label}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
export function placementsForBookings(
|
||||
placements: ContainerPlacementInput[],
|
||||
bookingIds: Set<string>,
|
||||
units: ContainerUnitForPlacement[],
|
||||
): ContainerPlacementInput[] {
|
||||
const unitBookingIds = new Map(
|
||||
units.map((u) => [`${u.bookingContainerId}:${u.unitIndex}`, u.bookingId]),
|
||||
);
|
||||
return placements.filter((p) => {
|
||||
const bookingId = unitBookingIds.get(`${p.bookingContainerId}:${p.unitIndex}`);
|
||||
return bookingId ? bookingIds.has(bookingId) : false;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user