enhance contract and train scheduling features

- Added pricing service integration to ContractsService for pre-persistence contract pricing.
- Updated LegCapacityPanel to display cargo weight instead of gross weight for better clarity on booked cargo.
- Enhanced train scheduling service to include cargo weight in booking details.
- Modified ClearanceDocumentsPage to include FULLY_EXECUTED status in booking status options.
- Refactored FileUploadSettingsPage to categorize file upload settings into tabs for better organization.
- Removed legacy onboarding fields and settings from file upload settings seeder.
- Improved type definitions for train scheduling to include cargo weight without wagon tare.
This commit is contained in:
Marshal
2026-08-01 05:37:46 +00:00
parent 6a4067ec42
commit a8788eb549
12 changed files with 511 additions and 463 deletions

View File

@@ -14,10 +14,10 @@ describe('BookingTransitionService — finalizeClearance gate', () => {
serviceType: { includesCustoms: false }, // no output set → only the input gate
};
// Input set has two required docs. Non-customs bookings resolve to the
// ONE_TIME self-clearance document set.
// Input set has two required docs. Non-customs bookings resolve to their
// own without-customs document set.
const inputSetting = {
code: 'contract_clearance_selfclear_import_container',
code: 'clearance_import_container_without_customs',
fields: [
{ fileKey: 'commercial_invoice', isRequired: true },
{ fileKey: 'packing_list', isRequired: true },
@@ -201,7 +201,7 @@ describe('BookingTransitionService — finalizeClearance customs output gate', (
*/
describe('BookingTransitionService — submitClearanceDocuments required-fields gate', () => {
const inputSetting = {
code: 'contract_clearance_selfclear_import_container',
code: 'clearance_import_container_without_customs',
fields: [
{ fileKey: 'commercial_invoice', fileLabel: 'Commercial invoice', isRequired: true },
{ fileKey: 'packing_list', fileLabel: 'Packing list', isRequired: true },

View File

@@ -11,10 +11,8 @@ describe('clearance.util — clearanceSettingCode', () => {
expect(clearanceSettingCode('IMPORT', 'CONTAINER', true)).toBe(
'clearance_import_container_with_customs',
);
// Non-customs bookings self-clear with the same document set a ONE_TIME
// self-clear contract uses.
expect(clearanceSettingCode('IMPORT', 'CONTAINER', false)).toBe(
'contract_clearance_selfclear_import_container',
'clearance_import_container_without_customs',
);
});
@@ -23,7 +21,7 @@ describe('clearance.util — clearanceSettingCode', () => {
'clearance_export_bulk_with_customs',
);
expect(clearanceSettingCode('EXPORT', 'BULK', false)).toBe(
'contract_clearance_selfclear_export_bulk',
'clearance_export_bulk_without_customs',
);
});

View File

@@ -39,12 +39,11 @@ export function clearanceSettingCode(
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.
// 4 import + 4 export cases (bulk/container × with/without customs) — each
// booking resolves to its own clearance_{op}_{freight}_{with|without}_customs
// set, independent of any contract-level clearance codes.
if (!includesCustoms) {
return `contract_clearance_selfclear_${op}_${freight}`;
return `clearance_${op}_${freight}_without_customs`;
}
return `clearance_${op}_${freight}_with_customs`;
}

View File

@@ -26,30 +26,22 @@ function freightFor(freightType: string): Freight {
/**
* The customer-input clearance setting code, or null when no gate applies.
*
* - Path B (customs bundled): the customer uploads the documents GL needs to do
* the clearance work → `contract_clearance_{op}_{freight}`.
* - Path A (no customs): the customer clears the cargo himself and uploads his
* own (smaller) clearance proof set → `contract_clearance_selfclear_{op}_{freight}`,
* reviewed by Operations rather than GL.
* Contract-level IMPORT/EXPORT clearance has been removed — clearance is
* collected per booking instead (see bookings/clearance.util.ts), so this
* always returns null for IMPORT/EXPORT now.
*
* DOMESTIC/intercity has no border, but a ONE_TIME intercity contract still
* collects the admin-configured intercity document set after both signatures
* (ops-reviewed, like Path A). GENERAL intercity contracts skip the contract
* gate and collect the same set per booking instead.
* (ops-reviewed). GENERAL intercity contracts skip the contract gate and
* collect the same set per booking instead.
*/
export function contractClearanceSettingCode(
tradeDirection: string,
freightType: string,
includesCustoms: boolean,
_freightType: string,
_includesCustoms: boolean,
): string | null {
if (tradeDirection === 'DOMESTIC') return INTERCITY_DOCUMENTS_SETTING_CODE;
const op = operationFor(tradeDirection);
if (!op) return null;
const freight = freightFor(freightType);
if (!includesCustoms) {
return `contract_clearance_selfclear_${op}_${freight}`;
}
return `contract_clearance_${op}_${freight}`;
return null;
}
/** The GL-output (customs output) setting code, keyed on op + freight. */

View File

@@ -42,6 +42,7 @@ describe('ContractsService duplicate guard', () => {
{} as never,
{} as never,
{} as never,
{ buildBreakdown: async () => ({ lineItems: [] }) } as never,
);
return (
service as unknown as {

View File

@@ -28,6 +28,7 @@ import { ContractCargoScope } from './entities/contract-cargo-scope.entity';
import { isEffectivelyExpired } from './utils/contract-expiry.util';
import { diffContractFields } from './contract-document-diff.util';
import { ContractDocumentHistoryService } from './contract-document-history.service';
import { ContractPricingService } from './contract-pricing.service';
import { FileRecord } from '../files/entities/file.entity';
/** Paginated contract list: flat `total` (backoffice) + `meta` block (portal). */
@@ -113,6 +114,7 @@ export class ContractsService {
private readonly filesService: FilesService,
private readonly minioService: MinioService,
private readonly documentHistory: ContractDocumentHistoryService,
private readonly pricingService: ContractPricingService,
) {}
/** Generate a unique contract reference number (CTR-YYYY-NNNNN). */
@@ -331,6 +333,33 @@ export class ContractsService {
);
}
// Price the contract BEFORE anything persists: a lane with no configured
// rate 422s here and the wizard shows its blocking modal — with no orphan
// DRAFT row left behind for the customer to trip over on retry. The probe
// carries exactly the fields buildBreakdown prices from; relation-only
// niceties (cargoType labels) are absent, which only affects display
// lines, never the missing-rate gates.
await this.pricingService.buildBreakdown({
tradeDirection: dto.tradeDirection,
freightType: dto.freightType,
paymentCurrency: 'USD',
customsClearingEnabled: includesCustoms,
isHazardous: dto.isHazardous ?? false,
isReefer: dto.isReefer ?? false,
equipmentReturn: dto.equipmentReturn ?? null,
firstMilePickupAddress: dto.firstMilePickupAddress ?? null,
lastMileDeliveryAddress: dto.lastMileDeliveryAddress ?? null,
routes: (dto.routes ?? []).map((r, i) => ({
originYardId: r.originYardId,
destinationYardId: r.destinationYardId,
sortOrder: r.sortOrder ?? i,
})),
cargoScope: (dto.cargoScope ?? []).map((c) => ({
containerSize: c.containerSize ?? null,
cargoTypeId: c.cargoTypeId ?? null,
})),
} as unknown as Contract);
// An explicit reference is caller-chosen — a collision there is a real
// conflict and should surface. Auto-generated references retry past a
// concurrent insert that grabbed the same sequence number.

View File

@@ -7746,6 +7746,9 @@ export class TrainSchedulingService {
weightTons: sb.booking
? this.grossBookingWeightTons(sb.booking, tareDims)
: 0,
// Cargo only (VGM / bulk tons) — what the customer actually booked,
// without the wagons' tare. The legs tab shows this per booking.
cargoWeightTons: sb.booking ? bookingCargoTons(sb.booking) : 0,
status: sb.booking?.status ?? null,
schedulingStatus: sb.booking?.schedulingStatus ?? null,
freightType: sb.booking?.freightType ?? null,

View File

@@ -115,43 +115,44 @@ const FOREIGN_ONBOARDING_FIELDS: OnboardingField[] = [
poaDelegationDefault(5),
];
/** Legacy combined set, kept for the older per-company-type codes. */
const LEGACY_ONBOARDING_FIELDS: OnboardingField[] = [
{
fileKey: "business_license",
fileLabel: "Business License / Trade License",
helpText:
"Verified against the government trade system during registration.",
isRequired: true,
isMultiple: false,
maxFiles: 1,
allowedExtensions: DOC_EXTENSIONS,
maxSizeMb: 10,
displayOrder: 1,
},
{
fileKey: "tin_certificate",
fileLabel: "TIN Certificate",
helpText: "Verified against the TIN registry during registration.",
isRequired: true,
isMultiple: false,
maxFiles: 1,
allowedExtensions: DOC_EXTENSIONS,
maxSizeMb: 10,
displayOrder: 2,
},
{
fileKey: "national_id_passport",
fileLabel: "National ID / Passport",
helpText: "Verified against the National ID API during registration.",
isRequired: true,
isMultiple: false,
maxFiles: 1,
allowedExtensions: DOC_EXTENSIONS,
maxSizeMb: 10,
displayOrder: 3,
},
];
// Legacy combined set for the removed per-company-type codes
// (company_onboarding_documents_customer/forwarder/transporter/forwarder_dj).
// const LEGACY_ONBOARDING_FIELDS: OnboardingField[] = [
// {
// fileKey: "business_license",
// fileLabel: "Business License / Trade License",
// helpText:
// "Verified against the government trade system during registration.",
// isRequired: true,
// isMultiple: false,
// maxFiles: 1,
// allowedExtensions: DOC_EXTENSIONS,
// maxSizeMb: 10,
// displayOrder: 1,
// },
// {
// fileKey: "tin_certificate",
// fileLabel: "TIN Certificate",
// helpText: "Verified against the TIN registry during registration.",
// isRequired: true,
// isMultiple: false,
// maxFiles: 1,
// allowedExtensions: DOC_EXTENSIONS,
// maxSizeMb: 10,
// displayOrder: 2,
// },
// {
// fileKey: "national_id_passport",
// fileLabel: "National ID / Passport",
// helpText: "Verified against the National ID API during registration.",
// isRequired: true,
// isMultiple: false,
// maxFiles: 1,
// allowedExtensions: DOC_EXTENSIONS,
// maxSizeMb: 10,
// displayOrder: 3,
// },
// ];
interface OnboardingDocumentSetting {
code: string;
@@ -175,31 +176,32 @@ const COMPANY_ONBOARDING_DOCUMENTS: OnboardingDocumentSetting[] = [
entity: "customer",
fields: FOREIGN_ONBOARDING_FIELDS,
},
// Legacy per-company-type codes (kept for back-compat; no longer used by the portal).
{
code: "company_onboarding_documents_customer",
label: "Customer onboarding documents",
entity: "customer",
fields: LEGACY_ONBOARDING_FIELDS,
},
{
code: "company_onboarding_documents_forwarder",
label: "Forwarder onboarding documents",
entity: "other",
fields: LEGACY_ONBOARDING_FIELDS,
},
{
code: "company_onboarding_documents_transporter",
label: "Transporter onboarding documents",
entity: "other",
fields: LEGACY_ONBOARDING_FIELDS,
},
{
code: "company_onboarding_documents_forwarder_dj",
label: "Djibouti forwarder onboarding documents",
entity: "other",
fields: LEGACY_ONBOARDING_FIELDS,
},
// Legacy per-company-type codes — removed, unused by any resolver or portal
// lookup (only `company_onboarding_documents_ethiopian`/`_foreign` are live).
// {
// code: "company_onboarding_documents_customer",
// label: "Customer onboarding documents",
// entity: "customer",
// fields: LEGACY_ONBOARDING_FIELDS,
// },
// {
// code: "company_onboarding_documents_forwarder",
// label: "Forwarder onboarding documents",
// entity: "other",
// fields: LEGACY_ONBOARDING_FIELDS,
// },
// {
// code: "company_onboarding_documents_transporter",
// label: "Transporter onboarding documents",
// entity: "other",
// fields: LEGACY_ONBOARDING_FIELDS,
// },
// {
// code: "company_onboarding_documents_forwarder_dj",
// label: "Djibouti forwarder onboarding documents",
// entity: "other",
// fields: LEGACY_ONBOARDING_FIELDS,
// },
];
const COMPANY_ONBOARDING_DESCRIPTION =
@@ -212,7 +214,7 @@ const COMPANY_ONBOARDING_DESCRIPTION =
// Two kinds of set per customs category: a CUSTOMER-INPUT set (the customer
// uploads) and a GL-OUTPUT set (Global Logistics uploads the customs outputs).
const JPG_EXTENSIONS = ["jpg", "jpeg", "png", "pdf"];
// const JPG_EXTENSIONS = ["jpg", "jpeg", "png", "pdf"]; // only used by the commented-out output field sets below
const CLEARANCE_ENTITY = "booking_clearance";
/** Build a clearance field with sensible defaults; `critical` marks isRequired. */
@@ -281,24 +283,23 @@ const EXPORT_BULK_FIELDS: OnboardingField[] = [
clearanceField("port_invoice", "Port Invoice", 3),
];
/** GL-uploaded customs output documents (import container). */
const IMPORT_CONTAINER_OUTPUT_FIELDS: OnboardingField[] = [
clearanceField("im4", "IM4 — Permanent Import Document", 1),
clearanceField("im5", "IM5Temporary Import Document", 2, {
required: false,
}),
clearanceField("transit_permitted", "Transit Permitted Screenshot", 3, {
extensions: JPG_EXTENSIONS,
}),
];
/** GL-uploaded customs output documents (export container). */
const EXPORT_CONTAINER_OUTPUT_FIELDS: OnboardingField[] = [
clearanceField("ex3", "EX3Permanent Export Document", 1),
clearanceField("ex8", "EX8 — Export Transit Document", 2),
clearanceField("export_release", "Export Release", 3),
clearanceField("t1", "T1 — Transport Document", 4),
];
// GL-uploaded customs output documents — unused now that all
// clearance_output_*/contract_clearance_output_* settings are commented out.
// const IMPORT_CONTAINER_OUTPUT_FIELDS: OnboardingField[] = [
// clearanceField("im4", "IM4Permanent Import Document", 1),
// clearanceField("im5", "IM5 — Temporary Import Document", 2, {
// required: false,
// }),
// clearanceField("transit_permitted", "Transit Permitted Screenshot", 3, {
// extensions: JPG_EXTENSIONS,
// }),
// ];
// const EXPORT_CONTAINER_OUTPUT_FIELDS: OnboardingField[] = [
// clearanceField("ex3", "EX3 — Permanent Export Document", 1),
// clearanceField("ex8", "EX8Export Transit Document", 2),
// clearanceField("export_release", "Export Release", 3),
// clearanceField("t1", "T1 — Transport Document", 4),
// ];
const CLEARANCE_DOCUMENT_SETTINGS: OnboardingDocumentSetting[] = [
// ── Customer-input sets ──
@@ -351,181 +352,194 @@ const CLEARANCE_DOCUMENT_SETTINGS: OnboardingDocumentSetting[] = [
fields: EXPORT_BULK_FIELDS,
},
// ── GL-output sets (customs only) ──
{
code: "clearance_output_import_container",
label: "Customs output documents (import container)",
entity: CLEARANCE_ENTITY,
fields: IMPORT_CONTAINER_OUTPUT_FIELDS,
},
{
code: "clearance_output_export_container",
label: "Customs output documents (export container)",
entity: CLEARANCE_ENTITY,
fields: EXPORT_CONTAINER_OUTPUT_FIELDS,
},
// Commented out per request. NOTE: these codes are still resolved and
// looked up at runtime by clearanceOutputSettingCode() in clearance.util.ts,
// called from booking-transition.service.ts (finalizeClearance,
// uploadClearanceOutputDocuments) and booking-clearance.service.ts —
// reachable from bookings.controller.ts's finalizeClearance/
// uploadClearanceOutputDocuments endpoints. finalizeClearance does not
// catch getByCode()'s NotFoundException, so finalizing a customs-enabled
// booking will 500 once these rows are gone from the DB too.
// {
// code: "clearance_output_import_container",
// label: "Customs output documents (import container)",
// entity: CLEARANCE_ENTITY,
// fields: IMPORT_CONTAINER_OUTPUT_FIELDS,
// },
// {
// code: "clearance_output_export_container",
// label: "Customs output documents (export container)",
// entity: CLEARANCE_ENTITY,
// fields: EXPORT_CONTAINER_OUTPUT_FIELDS,
// },
// Bulk output sets mirror the container output docs so customs+bulk bookings
// can finalize (previously bulk had no output set and got stuck at finalize).
{
code: "clearance_output_import_bulk",
label: "Customs output documents (import bulk)",
entity: CLEARANCE_ENTITY,
fields: IMPORT_CONTAINER_OUTPUT_FIELDS,
},
{
code: "clearance_output_export_bulk",
label: "Customs output documents (export bulk)",
entity: CLEARANCE_ENTITY,
fields: EXPORT_CONTAINER_OUTPUT_FIELDS,
},
// {
// code: "clearance_output_import_bulk",
// label: "Customs output documents (import bulk)",
// entity: CLEARANCE_ENTITY,
// fields: IMPORT_CONTAINER_OUTPUT_FIELDS,
// },
// {
// code: "clearance_output_export_bulk",
// label: "Customs output documents (export bulk)",
// entity: CLEARANCE_ENTITY,
// fields: EXPORT_CONTAINER_OUTPUT_FIELDS,
// },
];
// ── Contract pre-booking clearance settings (Path B) ────────────────────────
// For customs-clearance contracts the customer uploads clearance documents on
// the CONTRACT (before any booking exists). Same customer doc sets as the legacy
// booking clearance, plus the GL output sets, keyed on the contract. Resolved by
// contract-clearance.util.ts (codes: contract_clearance_{op}_{freight} and
// contract_clearance_output_{op}_container).
const CONTRACT_CLEARANCE_ENTITY = "contract_clearance";
// ── Contract pre-booking clearance settings ─────────────────────────────────
// Removed — clearance is now collected once, per booking, instead of also on
// the contract. See bookings/clearance.util.ts + CLEARANCE_DOCUMENT_SETTINGS.
// const CONTRACT_CLEARANCE_ENTITY = "contract_clearance";
const CONTRACT_CLEARANCE_SETTINGS: OnboardingDocumentSetting[] = [
{
code: "contract_clearance_import_container",
label: "Contract clearance documents (import container)",
entity: CONTRACT_CLEARANCE_ENTITY,
fields: IMPORT_CONTAINER_FIELDS,
},
{
code: "contract_clearance_export_container",
label: "Contract clearance documents (export container)",
entity: CONTRACT_CLEARANCE_ENTITY,
fields: EXPORT_CONTAINER_FIELDS,
},
{
code: "contract_clearance_import_bulk",
label: "Contract clearance documents (import bulk)",
entity: CONTRACT_CLEARANCE_ENTITY,
fields: IMPORT_BULK_FIELDS,
},
{
code: "contract_clearance_export_bulk",
label: "Contract clearance documents (export bulk)",
entity: CONTRACT_CLEARANCE_ENTITY,
fields: EXPORT_BULK_FIELDS,
},
// GL ET output sets uploaded during pre-booking clearance.
{
code: "contract_clearance_output_import_container",
label: "Contract customs output documents (import container)",
entity: CONTRACT_CLEARANCE_ENTITY,
fields: IMPORT_CONTAINER_OUTPUT_FIELDS,
},
{
code: "contract_clearance_output_export_container",
label: "Contract customs output documents (export container)",
entity: CONTRACT_CLEARANCE_ENTITY,
fields: EXPORT_CONTAINER_OUTPUT_FIELDS,
},
// Bulk output sets mirror the container output docs so customs+bulk contracts
// can finalize (previously bulk had no output set and got stuck at finalize).
{
code: "contract_clearance_output_import_bulk",
label: "Contract customs output documents (import bulk)",
entity: CONTRACT_CLEARANCE_ENTITY,
fields: IMPORT_CONTAINER_OUTPUT_FIELDS,
},
{
code: "contract_clearance_output_export_bulk",
label: "Contract customs output documents (export bulk)",
entity: CONTRACT_CLEARANCE_ENTITY,
fields: EXPORT_CONTAINER_OUTPUT_FIELDS,
},
];
// Contract-level IMPORT/EXPORT clearance input codes — removed. Clearance is
// now collected once, per booking, via bookings/clearance.util.ts's 4+4
// clearance_{op}_{freight}_{with|without}_customs codes. Kept here as
// reference in case a contract-level step is reinstated.
// const CONTRACT_CLEARANCE_SETTINGS: OnboardingDocumentSetting[] = [
// {
// code: "contract_clearance_import_container_with_customs",
// label: "Contract clearance documents (import container, with customs)",
// entity: CONTRACT_CLEARANCE_ENTITY,
// fields: IMPORT_CONTAINER_FIELDS,
// },
// {
// code: "contract_clearance_export_container_with_customs",
// label: "Contract clearance documents (export container, with customs)",
// entity: CONTRACT_CLEARANCE_ENTITY,
// fields: EXPORT_CONTAINER_FIELDS,
// },
// {
// code: "contract_clearance_import_bulk_with_customs",
// label: "Contract clearance documents (import bulk, with customs)",
// entity: CONTRACT_CLEARANCE_ENTITY,
// fields: IMPORT_BULK_FIELDS,
// },
// {
// code: "contract_clearance_export_bulk_with_customs",
// label: "Contract clearance documents (export bulk, with customs)",
// entity: CONTRACT_CLEARANCE_ENTITY,
// fields: EXPORT_BULK_FIELDS,
// },
// ];
// ── Path A self-clearance settings (no EDR customs service) ──────────────────
// When the contract does NOT bundle customs clearance, the customer clears the
// cargo himself and uploads his OWN clearance proof on the contract. Operations
// (not GL) reviews this smaller set before the customer may create the booking.
// Resolved by contract-clearance.util.ts as contract_clearance_selfclear_{op}_{freight}.
const SELF_CLEARANCE_IMPORT_FIELDS: OnboardingField[] = [
clearanceField("customs_declaration", "Customs Declaration (IM4/IM5)", 1),
clearanceField("import_release", "Import Release Permit", 2),
clearanceField("duty_tax_receipt", "Duty & Tax Payment Receipt", 3, {
required: false,
}),
clearanceField("delivery_order", "Delivery Order", 4, { required: false }),
clearanceField("supporting_document", "Other Clearance Document", 5, {
required: false,
}),
];
// GL ET output sets uploaded during pre-booking clearance — commented out
// per request. NOTE: still resolved/looked up at runtime by
// contractClearanceOutputSettingCode() in contract-clearance.util.ts,
// called from contract-clearance.service.ts (finalize, uploadOutputDocuments)
// — reachable from contracts.controller.ts. `finalize` does not catch
// getByCode()'s NotFoundException, so finalizing a customs-enabled contract
// will 500 once these rows are gone from the DB too.
// const CONTRACT_CLEARANCE_OUTPUT_SETTINGS: OnboardingDocumentSetting[] = [
// {
// code: "contract_clearance_output_import_container",
// label: "Contract customs output documents (import container)",
// entity: CONTRACT_CLEARANCE_ENTITY,
// fields: IMPORT_CONTAINER_OUTPUT_FIELDS,
// },
// {
// code: "contract_clearance_output_export_container",
// label: "Contract customs output documents (export container)",
// entity: CONTRACT_CLEARANCE_ENTITY,
// fields: EXPORT_CONTAINER_OUTPUT_FIELDS,
// },
// {
// code: "contract_clearance_output_import_bulk",
// label: "Contract customs output documents (import bulk)",
// entity: CONTRACT_CLEARANCE_ENTITY,
// fields: IMPORT_CONTAINER_OUTPUT_FIELDS,
// },
// {
// code: "contract_clearance_output_export_bulk",
// label: "Contract customs output documents (export bulk)",
// entity: CONTRACT_CLEARANCE_ENTITY,
// fields: EXPORT_CONTAINER_OUTPUT_FIELDS,
// },
// ];
const SELF_CLEARANCE_EXPORT_FIELDS: OnboardingField[] = [
clearanceField("customs_declaration", "Customs Declaration (EX3/EX8)", 1),
clearanceField("export_release", "Export Release", 2),
clearanceField("transit_document", "Transit Document (T1)", 3, {
required: false,
}),
clearanceField("supporting_document", "Other Clearance Document", 4, {
required: false,
}),
];
const SELF_CLEARANCE_SETTINGS: OnboardingDocumentSetting[] = [
{
code: "contract_clearance_selfclear_import_container",
label: "Self-clearance documents (import container)",
entity: CONTRACT_CLEARANCE_ENTITY,
fields: SELF_CLEARANCE_IMPORT_FIELDS,
},
{
code: "contract_clearance_selfclear_export_container",
label: "Self-clearance documents (export container)",
entity: CONTRACT_CLEARANCE_ENTITY,
fields: SELF_CLEARANCE_EXPORT_FIELDS,
},
{
code: "contract_clearance_selfclear_import_bulk",
label: "Self-clearance documents (import bulk)",
entity: CONTRACT_CLEARANCE_ENTITY,
fields: SELF_CLEARANCE_IMPORT_FIELDS,
},
{
code: "contract_clearance_selfclear_export_bulk",
label: "Self-clearance documents (export bulk)",
entity: CONTRACT_CLEARANCE_ENTITY,
fields: SELF_CLEARANCE_EXPORT_FIELDS,
},
];
// ── Path A self-clearance settings — removed (contract-level clearance input
// codes no longer exist; see CONTRACT_CLEARANCE_SETTINGS above). Kept as
// reference in case a contract-level step is reinstated.
// const SELF_CLEARANCE_IMPORT_FIELDS: OnboardingField[] = [
// clearanceField("customs_declaration", "Customs Declaration (IM4/IM5)", 1),
// clearanceField("import_release", "Import Release Permit", 2),
// clearanceField("duty_tax_receipt", "Duty & Tax Payment Receipt", 3, {
// required: false,
// }),
// clearanceField("delivery_order", "Delivery Order", 4, { required: false }),
// clearanceField("supporting_document", "Other Clearance Document", 5, {
// required: false,
// }),
// ];
// const SELF_CLEARANCE_EXPORT_FIELDS: OnboardingField[] = [
// clearanceField("customs_declaration", "Customs Declaration (EX3/EX8)", 1),
// clearanceField("export_release", "Export Release", 2),
// clearanceField("transit_document", "Transit Document (T1)", 3, {
// required: false,
// }),
// clearanceField("supporting_document", "Other Clearance Document", 4, {
// required: false,
// }),
// ];
// const SELF_CLEARANCE_SETTINGS: OnboardingDocumentSetting[] = [
// {
// code: "contract_clearance_import_container_without_customs",
// label: "Contract clearance documents (import container, without customs)",
// entity: CONTRACT_CLEARANCE_ENTITY,
// fields: SELF_CLEARANCE_IMPORT_FIELDS,
// },
// {
// code: "contract_clearance_export_container_without_customs",
// label: "Contract clearance documents (export container, without customs)",
// entity: CONTRACT_CLEARANCE_ENTITY,
// fields: SELF_CLEARANCE_EXPORT_FIELDS,
// },
// {
// code: "contract_clearance_import_bulk_without_customs",
// label: "Contract clearance documents (import bulk, without customs)",
// entity: CONTRACT_CLEARANCE_ENTITY,
// fields: SELF_CLEARANCE_IMPORT_FIELDS,
// },
// {
// code: "contract_clearance_export_bulk_without_customs",
// label: "Contract clearance documents (export bulk, without customs)",
// entity: CONTRACT_CLEARANCE_ENTITY,
// fields: SELF_CLEARANCE_EXPORT_FIELDS,
// },
// ];
// ── Contract intake settings ────────────────────────────────────────────────
// Commercial/framework documents attached at contract submission (wizard step 5),
// distinct from the post-sign clearance docs above.
const CONTRACT_INTAKE_ENTITY = "contract_intake";
const CONTRACT_INTAKE_FIELDS: OnboardingField[] = [
clearanceField(
"commercial_framework",
"Commercial Framework / Agreement",
1,
{
required: false,
},
),
clearanceField("onboarding_attachment", "Onboarding Attachment", 2, {
required: false,
}),
clearanceField("supporting_document", "Supporting Document", 3, {
required: false,
}),
];
const CONTRACT_INTAKE_SETTINGS: OnboardingDocumentSetting[] = [
{
code: "contract_intake_documents",
label: "Contract intake documents",
entity: CONTRACT_INTAKE_ENTITY,
fields: CONTRACT_INTAKE_FIELDS,
},
];
// Removed — unused. Nothing resolves/looks up `contract_intake_documents` by
// code anywhere in the API or web apps.
// const CONTRACT_INTAKE_FIELDS: OnboardingField[] = [
// clearanceField(
// "commercial_framework",
// "Commercial Framework / Agreement",
// 1,
// {
// required: false,
// },
// ),
// clearanceField("onboarding_attachment", "Onboarding Attachment", 2, {
// required: false,
// }),
// clearanceField("supporting_document", "Supporting Document", 3, {
// required: false,
// }),
// ];
// const CONTRACT_INTAKE_SETTINGS: OnboardingDocumentSetting[] = [
// {
// code: "contract_intake_documents",
// label: "Contract intake documents",
// entity: CONTRACT_INTAKE_ENTITY,
// fields: CONTRACT_INTAKE_FIELDS,
// },
// ];
const CLEARANCE_DESCRIPTION =
"Operation/clearance documents collected after contract execution, by operation, freight type and customs.";
@@ -614,21 +628,6 @@ export class FileUploadSettingsSeeder {
...s,
description: CLEARANCE_DESCRIPTION,
})),
...CONTRACT_CLEARANCE_SETTINGS.map((s) => ({
...s,
description:
"Pre-booking clearance documents collected on the contract (Path B), by operation and freight type.",
})),
...SELF_CLEARANCE_SETTINGS.map((s) => ({
...s,
description:
"Customer self-clearance documents (Path A, no EDR customs service), reviewed by Operations.",
})),
...CONTRACT_INTAKE_SETTINGS.map((s) => ({
...s,
description:
"Commercial/framework documents attached at contract submission.",
})),
...DRIVER_DOCUMENT_SETTINGS.map((s) => ({
...s,
description: