mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 19:00:55 +00:00
add hard capacity ceiling to weight limit rules
This commit is contained in:
@@ -133,6 +133,13 @@ export class ContractBookingService {
|
||||
});
|
||||
}
|
||||
|
||||
// Hard capacity gate: a container line whose total weight exceeds the
|
||||
// container type's max capacity can never be booked — no surcharge path,
|
||||
// no override. Checked before any row is written.
|
||||
if (freightType === 'CONTAINER') {
|
||||
await this.assertWithinMaxCapacity(contract, dto);
|
||||
}
|
||||
|
||||
// Denormalize route/direction/freight onto the booking for the scheduling engine.
|
||||
const booking = await this.bookingsRepository.create({
|
||||
reference,
|
||||
@@ -608,6 +615,7 @@ export class ContractBookingService {
|
||||
overweightSurchargeAmount: number;
|
||||
currency: string | null;
|
||||
pairingErrors: string[];
|
||||
capacityErrors: string[];
|
||||
lineItems: PriceLineItemDto[];
|
||||
totalAmount: number;
|
||||
}> {
|
||||
@@ -621,6 +629,7 @@ export class ContractBookingService {
|
||||
overweightSurchargeAmount: 0,
|
||||
currency: null,
|
||||
pairingErrors: [],
|
||||
capacityErrors: [],
|
||||
lineItems: [],
|
||||
totalAmount: 0,
|
||||
};
|
||||
@@ -695,16 +704,63 @@ export class ContractBookingService {
|
||||
(v) => v.message,
|
||||
);
|
||||
|
||||
// Hard capacity ceiling — a non-empty result means the create call will be
|
||||
// rejected, so the form can block submit up front.
|
||||
const capacityErrors = await this.ruleEngineService.capacityViolations(
|
||||
resolved.map(({ line, ct, totalVgmTons }) => ({
|
||||
containerTypeId: ct.id,
|
||||
quantity: line.quantity,
|
||||
totalVgmTons,
|
||||
})),
|
||||
contract.tradeDirection,
|
||||
);
|
||||
|
||||
return {
|
||||
overweightLines: computed.overweightLines,
|
||||
overweightSurchargeAmount,
|
||||
currency: computed.currency,
|
||||
pairingErrors,
|
||||
capacityErrors,
|
||||
lineItems: computed.lineItems,
|
||||
totalAmount: computed.totalAmount,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws when any container line's total weight exceeds the hard capacity
|
||||
* ceiling of its weight limit rule. Mirrors validateShipment's line
|
||||
* resolution so the gate matches what the form preview reported.
|
||||
*/
|
||||
private async assertWithinMaxCapacity(
|
||||
contract: Contract,
|
||||
dto: CreateBookingUnderContractDto,
|
||||
): Promise<void> {
|
||||
const lines = dto.containers ?? [];
|
||||
if (!lines.length) return;
|
||||
|
||||
const containers = await Promise.all(
|
||||
lines.map(async (line) => {
|
||||
const ct = await this.resolveContainerTypeForSize(
|
||||
line.containerSize,
|
||||
contract.isReefer || (line.reeferQuantity ?? 0) > 0,
|
||||
);
|
||||
const totalVgmTons = (line.units ?? []).reduce(
|
||||
(s, u) => s + Number(u.vgmTons ?? 0),
|
||||
0,
|
||||
);
|
||||
return { containerTypeId: ct.id, quantity: line.quantity, totalVgmTons };
|
||||
}),
|
||||
);
|
||||
|
||||
const violations = await this.ruleEngineService.capacityViolations(
|
||||
containers,
|
||||
contract.tradeDirection,
|
||||
);
|
||||
if (violations.length) {
|
||||
throw new BadRequestException(violations.join('; '));
|
||||
}
|
||||
}
|
||||
|
||||
private async max20ftPairDiffTons(): Promise<number> {
|
||||
const row = await this.dataSource
|
||||
.getRepository(TrainSchedulingGlobalRules)
|
||||
|
||||
Reference in New Issue
Block a user