feat: enhance booking operations to support freight forwarder variants and improve consolidation handling

This commit is contained in:
Marshal
2026-06-23 23:48:45 +00:00
parent 9d81a2e1ee
commit 07cd7dc111
8 changed files with 338 additions and 64 deletions

View File

@@ -201,8 +201,15 @@ export class RuleEngineService {
// Surcharges are now self-describing rates: any LIVE rate whose `trigger`
// is not ALWAYS. Each fires independently and stacks on top of base freight
// — hazard + reefer + overweight all add together, each with its own unit.
//
// A given surcharge identity (same trigger + rateType + unit + value +
// scope) must contribute exactly ONE line. Duplicate LIVE rate rows — e.g.
// from a non-idempotent seeder — would otherwise repeat the same surcharge
// many times and inflate the total, so we collapse them to one row each.
const liveRates = await this.ratesRepo.findLiveRates();
const surchargeRates = liveRates.filter((r) => r.trigger && r.trigger !== 'ALWAYS');
const surchargeRates = this.dedupeRatesBySignature(
liveRates.filter((r) => r.trigger && r.trigger !== 'ALWAYS'),
);
for (const rate of surchargeRates) {
const triggered = this.matchesTrigger(rate.trigger, {
@@ -404,4 +411,34 @@ export class RuleEngineService {
private surchargeCode(rate: Rate): string {
return rate.rateType ?? rate.trigger;
}
/**
* Collapse rates that describe the same charge to a single representative.
*
* Two rates are "the same" when they would produce an identical price line:
* same trigger, rateType, unit, value, currency, and scoping (container /
* cargo type). Duplicate rows (e.g. a seeder run more than once) therefore
* stack into one line instead of repeating — keeping the breakdown clean and
* the total correct. The first row of each signature is kept so an existing
* rateId is preserved for snapshotting.
*/
private dedupeRatesBySignature(rates: Rate[]): Rate[] {
const seen = new Set<string>();
const result: Rate[] = [];
for (const rate of rates) {
const signature = [
rate.trigger,
rate.rateType,
rate.rateUnit,
Number(rate.rateValue),
rate.currency,
rate.containerTypeId ?? '',
rate.cargoTypeId ?? '',
].join('|');
if (seen.has(signature)) continue;
seen.add(signature);
result.push(rate);
}
return result;
}
}