mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
Merge pull request #1299 from Tria-plc/freight_feature/usermanagement
fix: improve handling of container sizes in wagon cancellation logic
This commit is contained in:
@@ -54,6 +54,10 @@ import {
|
||||
* fee scales with the cancelled wagon count and differs by what was booked.
|
||||
*/
|
||||
export const WAGON_CANCELLATION_FEE_RATE_TYPE = 'CANCELLATION_FEE';
|
||||
|
||||
/** `booking_container.container_size` is stored as "20ft"/"40ft" — `Number()` on it is NaN. */
|
||||
const sizeFtOf = (size: string | number | null | undefined): number =>
|
||||
parseInt(String(size ?? ''), 10);
|
||||
/** invoices.type of the fee invoice — the settlement branch key in BookingInvoiceService. */
|
||||
export const WAGON_CANCEL_FEE_INVOICE_TYPE = 'WAGON_CANCEL_FEE';
|
||||
|
||||
@@ -603,11 +607,11 @@ export class BookingWagonCancellationService {
|
||||
const live = liveBySize.get(cut.containerSize) ?? 0;
|
||||
if (cut.quantity > live) {
|
||||
throw new BadRequestException(
|
||||
`Cannot cancel ${cut.quantity} × ${cut.containerSize}ft — the booking only has ${live}.`,
|
||||
`Cannot cancel ${cut.quantity} × ${sizeFtOf(cut.containerSize)}ft — the booking only has ${live}.`,
|
||||
);
|
||||
}
|
||||
bySize[cut.containerSize] = cut.quantity;
|
||||
wagons += cut.quantity * wagonsPerUnitForSize(Number(cut.containerSize));
|
||||
wagons += cut.quantity * wagonsPerUnitForSize(sizeFtOf(cut.containerSize));
|
||||
}
|
||||
wagons = round2(wagons);
|
||||
if (wagons > totalWagons) {
|
||||
@@ -849,7 +853,7 @@ export class BookingWagonCancellationService {
|
||||
// wagon-space each size's units occupy, so the total always equals
|
||||
// cut.wagons (whole wagons on an allocation cut, fractional on a quantity cut).
|
||||
const bySize = Object.entries(cut.quantities.bySize ?? {}).filter(([, qty]) => qty > 0);
|
||||
const spaceOf = ([size, qty]: [string, number]) => qty * wagonsPerUnitForSize(Number(size));
|
||||
const spaceOf = ([size, qty]: [string, number]) => qty * wagonsPerUnitForSize(sizeFtOf(size));
|
||||
const totalSpace = bySize.reduce((s, e) => s + spaceOf(e), 0);
|
||||
if (!bySize.length || totalSpace <= 0) throw missing('containers');
|
||||
const containerTypes = await this.dataSource.getRepository(ContainerType).find();
|
||||
@@ -858,7 +862,7 @@ export class BookingWagonCancellationService {
|
||||
let currency = '';
|
||||
for (const entry of bySize) {
|
||||
const [size] = entry;
|
||||
const sizeFt = Number(size);
|
||||
const sizeFt = sizeFtOf(size);
|
||||
const typeIds = new Set(
|
||||
containerTypes.filter((ct) => Number(ct.sizeFt) === sizeFt).map((ct) => ct.id),
|
||||
);
|
||||
@@ -892,7 +896,7 @@ export class BookingWagonCancellationService {
|
||||
const live = lines.reduce((s, l) => s + Number(l.quantity ?? 0), 0);
|
||||
if (live < toDrop) {
|
||||
throw new BadRequestException(
|
||||
`Booking changed since the request: only ${live} × ${size}ft left, cannot cancel ${toDrop}.`,
|
||||
`Booking changed since the request: only ${live} × ${sizeFtOf(size)}ft left, cannot cancel ${toDrop}.`,
|
||||
);
|
||||
}
|
||||
for (const line of lines) {
|
||||
@@ -936,7 +940,7 @@ export class BookingWagonCancellationService {
|
||||
});
|
||||
await manager.getRepository(BookingContainer).update(line.id, {
|
||||
quantity: qty - drop,
|
||||
wagonsRequired: round2((qty - drop) * wagonsPerUnitForSize(Number(size))),
|
||||
wagonsRequired: round2((qty - drop) * wagonsPerUnitForSize(sizeFtOf(size))),
|
||||
totalVgmTons: round3(Number(line.totalVgmTons) - droppedVgm),
|
||||
hazardousQuantity: keptUnits.filter((u) => u.isHazardous).length,
|
||||
reeferQuantity: keptUnits.filter((u) => u.isReefer).length,
|
||||
@@ -1024,7 +1028,7 @@ export class BookingWagonCancellationService {
|
||||
const doomedVgm = round3(doomed.reduce((s, u) => s + Number(u.vgmTons || 0), 0));
|
||||
await manager.getRepository(BookingContainer).update(line.id, {
|
||||
quantity: kept.length,
|
||||
wagonsRequired: round2(kept.length * wagonsPerUnitForSize(Number(size))),
|
||||
wagonsRequired: round2(kept.length * wagonsPerUnitForSize(sizeFtOf(size))),
|
||||
totalVgmTons: round3(Number(line.totalVgmTons) - doomedVgm),
|
||||
hazardousQuantity: kept.filter((u) => u.isHazardous).length,
|
||||
reeferQuantity: kept.filter((u) => u.isReefer).length,
|
||||
|
||||
Reference in New Issue
Block a user