Files
edr-platform/apps/edr-freight-api/src/modules/bookings/clearance.util.ts

83 lines
2.8 KiB
TypeScript

import { Booking } from './entities/booking.entity';
/**
* Resolves which seeded clearance FileUploadSetting applies to a booking, from
* its trade direction, freight type and whether its service includes customs.
* Mirrors the codes seeded in file-upload-settings.seeder.ts.
*/
type Op = 'import' | 'export';
type Freight = 'container' | 'bulk';
/** Trade direction → clearance operation. DOMESTIC has no customs clearance. */
function operationFor(tradeDirection: string): Op | null {
if (tradeDirection === 'IMPORT') return 'import';
if (tradeDirection === 'EXPORT') return 'export';
return null; // DOMESTIC / intercity — no clearance gate
}
function freightFor(freightType: string): Freight {
return freightType === 'BULK' ? 'bulk' : 'container';
}
/** The customer-input clearance setting code, or null when no gate applies. */
export function clearanceSettingCode(
tradeDirection: string,
freightType: string,
includesCustoms: boolean,
): string | null {
const op = operationFor(tradeDirection);
if (!op) return null;
const freight = freightFor(freightType);
// Non-customs (Path A) bookings self-clear: the customer proves his own
// clearance with the SAME smaller document set a ONE_TIME self-clear
// contract uses (customs declaration, release permit, …) — not the
// GL-oriented booking sets.
if (!includesCustoms) {
return `contract_clearance_selfclear_${op}_${freight}`;
}
return `clearance_${op}_${freight}_with_customs`;
}
/** The GL-output (customs output) setting code, keyed on op + freight. */
export function clearanceOutputSettingCode(
tradeDirection: string,
freightType: string,
includesCustoms: boolean,
): string | null {
if (!includesCustoms) return null;
const op = operationFor(tradeDirection);
if (!op) return null;
const freight = freightFor(freightType);
return `clearance_output_${op}_${freight}`;
}
/** Convenience: resolve both codes for a loaded booking (with its serviceType). */
export function clearanceCodesForBooking(booking: Booking): {
inputCode: string | null;
outputCode: string | null;
includesCustoms: boolean;
} {
// Customs applies when EITHER the service type bundles it OR the booking was
// created with customsClearingEnabled (copied from the contract). Contract
// bookings carry customsClearingEnabled even when the serviceType relation
// isn't loaded / has includesCustoms=false — without this the per-booking
// clearance grid would resolve empty.
const includesCustoms =
Boolean(booking.serviceType?.includesCustoms) ||
Boolean(booking.customsClearingEnabled);
return {
inputCode: clearanceSettingCode(
booking.tradeDirection,
booking.freightType,
includesCustoms,
),
outputCode: clearanceOutputSettingCode(
booking.tradeDirection,
booking.freightType,
includesCustoms,
),
includesCustoms,
};
}