feat: implement shipping line bookings management

- Add ShippingLineBookingsPage for listing and managing shipping line bookings.
- Create ShippingLineDocumentsModal for document uploads related to bookings.
- Introduce ShippingLineInitiateModal for initiating new shipping line bookings.
- Implement booking document state management with booking-doc-state utility.
- Add shipping line bookings service for API interactions.
- Update index to export new components and services.
- Enhance types for freight to include shipping line credits.
This commit is contained in:
marshalyordanos
2026-08-13 15:54:40 +03:00
parent 9aae132dd4
commit 9fff469ffa
50 changed files with 4485 additions and 77 deletions

View File

@@ -643,6 +643,21 @@ const INTERCITY_DOCUMENT_SETTINGS: OnboardingDocumentSetting[] = [
},
];
// ── Shipping line booking documents ─────────────────────────────────────────
// Collected on a shipping line's booking right after it is initiated. Shipping
// lines book without a contract, so this set — not a contract — is what
// Operations reviews before the booking may be completed. Fields start empty
// and are configured in the backoffice file-settings editor, like the sets
// above. `entity: "booking"` puts it alongside the other per-booking sets.
const SHIPPING_LINE_DOCUMENT_SETTINGS: OnboardingDocumentSetting[] = [
{
code: "shipping_line_booking_documents",
label: "Shipping line booking documents",
entity: "booking",
fields: [],
},
];
// ── Hazardous cargo documents ───────────────────────────────────────────────
// Asked for in the contract wizard the moment the customer flags the cargo as
// hazardous (ONE_TIME contracts only). Fields start empty and are configured in
@@ -701,6 +716,11 @@ export class FileUploadSettingsSeeder {
description:
"Intercity shipment documents — contract-level for ONE_TIME (after both signatures), per booking for GENERAL; reviewed by Operations.",
})),
...SHIPPING_LINE_DOCUMENT_SETTINGS.map((s) => ({
...s,
description:
"Documents a shipping line uploads on a booking it initiated. Reviewed by Operations; the booking can only be completed once they are approved.",
})),
];
const missing = allSettings.filter((s) => !existingCodes.has(s.code));

View File

@@ -513,6 +513,25 @@ export const FINANCE_PERMISSIONS: FreightPermissionSeed[] = [
"edr_freight_app:invoices:confirm_offline",
"Confirm offline (bank transfer) invoice payment",
),
// Shipping lines consume services on credit and are invoiced after the fact,
// so what they owe is its own Finance surface, separate from invoices:view —
// an unbilled credit is not an invoice yet.
perm(
"d2c00001-0001-4000-8000-000000000001",
"edr_freight_app:shipping_line_credits:view",
"View shipping-line credits and outstanding balance",
),
perm(
"d2c00001-0001-4000-8000-000000000002",
"edr_freight_app:shipping_line_credits:invoice",
"Generate an invoice from shipping-line credits",
),
// Erases a debt outright, which is why it is not folded into :invoice.
perm(
"d2c00001-0001-4000-8000-000000000003",
"edr_freight_app:shipping_line_credits:cancel",
"Cancel (write off) an unbilled shipping-line credit",
),
];
// E. First / last mile operations
@@ -1730,6 +1749,13 @@ export const FREIGHT_PERMS = {
update: "edr_freight_app:shipping_lines:update",
resetPassword: "edr_freight_app:shipping_lines:reset-password",
},
shippingLineCredits: {
view: "edr_freight_app:shipping_line_credits:view",
/** Turn a batch of unbilled credits into an invoice. */
invoice: "edr_freight_app:shipping_line_credits:invoice",
/** Write off an unbilled credit — separate grant: it erases a debt. */
cancel: "edr_freight_app:shipping_line_credits:cancel",
},
payments: {
view: "edr_freight_app:payments:view",
},