mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-01 15:53:27 +00:00
fix
This commit is contained in:
@@ -28,6 +28,11 @@ import type {
|
||||
UpdateFileUploadFieldDto,
|
||||
UpdateFileUploadSettingDto,
|
||||
} from "@/types/fileUploadSettings";
|
||||
import type {
|
||||
Invoice,
|
||||
InvoiceListFilter,
|
||||
PaginatedInvoices,
|
||||
} from "@/types/invoice";
|
||||
import type { IOverviewDashboard, OverviewRange } from "@/types/overview";
|
||||
import {
|
||||
RuleEngineListResult,
|
||||
@@ -43,6 +48,8 @@ import type {
|
||||
CreateTrainSchedulePayload,
|
||||
EligibleContainerBookingsResponse,
|
||||
FreightType,
|
||||
ImportLoadingBookingsResponse,
|
||||
LoadingStatus,
|
||||
LocomotiveRecord,
|
||||
PinWagonsPayload,
|
||||
RecordCheckpointPayload,
|
||||
@@ -128,6 +135,7 @@ import {
|
||||
import { containerTypesService } from "./container-types.service";
|
||||
import { containerService, type Container } from "./containerService";
|
||||
import { customersService } from "./customers.service";
|
||||
import { invoicesService } from "./invoices.service";
|
||||
import { dropdownSettingsService } from "./dropdownSettings.service";
|
||||
import { fileUploadSettingsService } from "./fileUploadSettings.service";
|
||||
import {
|
||||
@@ -197,7 +205,10 @@ const TRAIN_SCHEDULING_INVALIDATIONS: ReadonlyArray<readonly unknown[]> = [
|
||||
export const api = {
|
||||
trainScheduling: {
|
||||
// ── Queries ────────────────────────────────────────────────────────────
|
||||
scheduleList: endpoint<{ freightType?: FreightType }, TrainScheduleListItem[]>(
|
||||
scheduleList: endpoint<
|
||||
{ freightType?: FreightType },
|
||||
TrainScheduleListItem[]
|
||||
>(
|
||||
"train-scheduling",
|
||||
"schedules",
|
||||
({ freightType }) => trainSchedulingService.listSchedules(freightType),
|
||||
@@ -211,11 +222,16 @@ export const api = {
|
||||
() => QUERY_KEYS.TRAIN_SCHEDULING.batchBoard(),
|
||||
),
|
||||
|
||||
batchBoardDetail: endpoint<{ scheduleId: string }, BatchBoardScheduleDetail>(
|
||||
batchBoardDetail: endpoint<
|
||||
{ scheduleId: string },
|
||||
BatchBoardScheduleDetail
|
||||
>(
|
||||
"train-scheduling",
|
||||
"batch-board-detail",
|
||||
({ scheduleId }) => trainSchedulingService.getBatchBoardDetail(scheduleId),
|
||||
({ scheduleId }) => QUERY_KEYS.TRAIN_SCHEDULING.batchBoardDetail(scheduleId),
|
||||
({ scheduleId }) =>
|
||||
trainSchedulingService.getBatchBoardDetail(scheduleId),
|
||||
({ scheduleId }) =>
|
||||
QUERY_KEYS.TRAIN_SCHEDULING.batchBoardDetail(scheduleId),
|
||||
),
|
||||
|
||||
scheduleDetail: endpoint<
|
||||
@@ -343,8 +359,30 @@ export const api = {
|
||||
QUERY_KEYS.TRAIN_SCHEDULING.compositionRemovals(scheduleId),
|
||||
),
|
||||
|
||||
importLoadingBookings: endpoint<{ id: string }, ImportLoadingBookingsResponse>(
|
||||
"train-scheduling",
|
||||
"import-loading-bookings",
|
||||
({ id }) => trainSchedulingService.getImportLoadingBookings(id),
|
||||
({ id }) => QUERY_KEYS.TRAIN_SCHEDULING.importLoadingBookings(id),
|
||||
),
|
||||
|
||||
updateImportLoadingStatus: endpoint<
|
||||
{ id: string; bookingIds: string[]; loadingStatus: LoadingStatus },
|
||||
ImportLoadingBookingsResponse
|
||||
>(
|
||||
"train-scheduling",
|
||||
"update-import-loading-status",
|
||||
({ id, bookingIds, loadingStatus }) =>
|
||||
trainSchedulingService.updateImportLoadingStatus(id, { bookingIds, loadingStatus }),
|
||||
undefined,
|
||||
({ id }) => [QUERY_KEYS.TRAIN_SCHEDULING.importLoadingBookings(id)],
|
||||
),
|
||||
|
||||
// ── Mutations ──────────────────────────────────────────────────────────
|
||||
runAllocation: endpoint<{ scheduleId: string }, WagonAllocationAttemptResult>(
|
||||
runAllocation: endpoint<
|
||||
{ scheduleId: string },
|
||||
WagonAllocationAttemptResult
|
||||
>(
|
||||
"train-scheduling",
|
||||
"run-allocation",
|
||||
({ scheduleId }) => trainSchedulingService.runAllocation(scheduleId),
|
||||
@@ -360,6 +398,14 @@ export const api = {
|
||||
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||
),
|
||||
|
||||
completeDocReview: endpoint<string, BatchBoardScheduleDetail>(
|
||||
"train-scheduling",
|
||||
"doc-review-complete",
|
||||
(id) => trainSchedulingService.completeDocReview(id),
|
||||
undefined,
|
||||
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||
),
|
||||
|
||||
setBookingWindow: endpoint<
|
||||
{ id: string; status: "OPEN" | "CLOSED" },
|
||||
TrainScheduleDetail
|
||||
@@ -454,7 +500,10 @@ export const api = {
|
||||
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||
),
|
||||
|
||||
pinWagons: endpoint<{ id: string; payload: PinWagonsPayload }, TrainScheduleDetail>(
|
||||
pinWagons: endpoint<
|
||||
{ id: string; payload: PinWagonsPayload },
|
||||
TrainScheduleDetail
|
||||
>(
|
||||
"train-scheduling",
|
||||
"pin-wagons",
|
||||
({ id, payload }) => trainSchedulingService.pinWagons(id, payload),
|
||||
@@ -550,8 +599,10 @@ export const api = {
|
||||
({ id }) => warehouseService.getById(id).then((r) => r.data),
|
||||
),
|
||||
|
||||
dashboard: endpoint<void, WarehouseDashboard>("warehouses", "dashboard", () =>
|
||||
warehouseService.dashboard().then((r) => r.data),
|
||||
dashboard: endpoint<void, WarehouseDashboard>(
|
||||
"warehouses",
|
||||
"dashboard",
|
||||
() => warehouseService.dashboard().then((r) => r.data),
|
||||
),
|
||||
|
||||
create: endpoint<SaveWarehousePayload, Warehouse>(
|
||||
@@ -642,10 +693,8 @@ export const api = {
|
||||
listInventory: endpoint<
|
||||
{ filter?: InventoryFilter },
|
||||
WarehouseInventoryItem[]
|
||||
>(
|
||||
"warehouse-inventory",
|
||||
"list",
|
||||
({ filter }) => warehouseService.listInventory(filter).then((r) => r.data),
|
||||
>("warehouse-inventory", "list", ({ filter }) =>
|
||||
warehouseService.listInventory(filter).then((r) => r.data),
|
||||
),
|
||||
|
||||
inquiry: endpoint<
|
||||
@@ -658,11 +707,19 @@ export const api = {
|
||||
({ filter }) => ["warehouse-inventory", "inquiry", filter],
|
||||
),
|
||||
|
||||
eligibleBookings: endpoint<{ direction?: 'IMPORT' | 'EXPORT' } | void, EligibleBooking[]>(
|
||||
eligibleBookings: endpoint<
|
||||
{ direction?: "IMPORT" | "EXPORT" } | void,
|
||||
EligibleBooking[]
|
||||
>(
|
||||
"warehouse-inventory",
|
||||
"eligible-bookings",
|
||||
(input) => warehouseService.eligibleBookings(input?.direction).then((r) => r.data),
|
||||
(input) => ["warehouse-inventory", "eligible-bookings", input?.direction ?? "ALL"],
|
||||
(input) =>
|
||||
warehouseService.eligibleBookings(input?.direction).then((r) => r.data),
|
||||
(input) => [
|
||||
"warehouse-inventory",
|
||||
"eligible-bookings",
|
||||
input?.direction ?? "ALL",
|
||||
],
|
||||
),
|
||||
|
||||
readyToLoadExport: endpoint<void, ReadyToLoadRow[]>(
|
||||
@@ -698,7 +755,11 @@ export const api = {
|
||||
"import-train-items",
|
||||
({ scheduleId }) =>
|
||||
warehouseService.importTrainItems(scheduleId).then((r) => r.data),
|
||||
({ scheduleId }) => ["warehouse-inventory", "import-train-items", scheduleId],
|
||||
({ scheduleId }) => [
|
||||
"warehouse-inventory",
|
||||
"import-train-items",
|
||||
scheduleId,
|
||||
],
|
||||
),
|
||||
|
||||
importUnloadedQueue: endpoint<void, ImportUnloadedItem[]>(
|
||||
@@ -766,8 +827,11 @@ export const api = {
|
||||
"inspection-reports",
|
||||
({ inventoryId }) =>
|
||||
warehouseService.listInspectionReports(inventoryId).then((r) => r.data),
|
||||
({ inventoryId }) =>
|
||||
["warehouse-inventory", inventoryId, "inspection-reports"],
|
||||
({ inventoryId }) => [
|
||||
"warehouse-inventory",
|
||||
inventoryId,
|
||||
"inspection-reports",
|
||||
],
|
||||
),
|
||||
|
||||
allocationRules: endpoint<void, AllocationRule[]>(
|
||||
@@ -784,15 +848,28 @@ export const api = {
|
||||
() => ["warehouse-fee-rules"],
|
||||
),
|
||||
|
||||
feePreview: endpoint<{ inventoryId: string; billingCurrency?: 'ETB' | 'USD' }, FeePreview[]>(
|
||||
feePreview: endpoint<
|
||||
{ inventoryId: string; billingCurrency?: "ETB" | "USD" },
|
||||
FeePreview[]
|
||||
>(
|
||||
"warehouse-inventory",
|
||||
"fee-preview",
|
||||
({ inventoryId, billingCurrency }) =>
|
||||
warehouseService.feePreview(inventoryId, billingCurrency).then((r) => r.data),
|
||||
({ inventoryId, billingCurrency }) => ["warehouse-inventory", inventoryId, "fee-preview", billingCurrency ?? 'USD'],
|
||||
warehouseService
|
||||
.feePreview(inventoryId, billingCurrency)
|
||||
.then((r) => r.data),
|
||||
({ inventoryId, billingCurrency }) => [
|
||||
"warehouse-inventory",
|
||||
inventoryId,
|
||||
"fee-preview",
|
||||
billingCurrency ?? "USD",
|
||||
],
|
||||
),
|
||||
|
||||
invoices: endpoint<{ filter?: WarehouseInvoiceFilter }, WarehouseFeeInvoice[]>(
|
||||
invoices: endpoint<
|
||||
{ filter?: WarehouseInvoiceFilter },
|
||||
WarehouseFeeInvoice[]
|
||||
>(
|
||||
"warehouse-fee-invoices",
|
||||
"list",
|
||||
({ filter }) => warehouseService.listInvoices(filter).then((r) => r.data),
|
||||
@@ -821,7 +898,8 @@ export const api = {
|
||||
receiveInventory: endpoint<ReceiveInventoryPayload, WarehouseInventoryItem>(
|
||||
"warehouse-inventory",
|
||||
"receive",
|
||||
(payload) => warehouseService.receiveInventory(payload).then((r) => r.data),
|
||||
(payload) =>
|
||||
warehouseService.receiveInventory(payload).then((r) => r.data),
|
||||
undefined,
|
||||
() => [["warehouse-inventory"], ["warehouses"]],
|
||||
),
|
||||
@@ -856,7 +934,8 @@ export const api = {
|
||||
>(
|
||||
"warehouse-inventory",
|
||||
"load",
|
||||
({ id, payload }) => warehouseService.load(id, payload).then((r) => r.data),
|
||||
({ id, payload }) =>
|
||||
warehouseService.load(id, payload).then((r) => r.data),
|
||||
undefined,
|
||||
() => INVENTORY_INVALIDATIONS,
|
||||
),
|
||||
@@ -875,7 +954,8 @@ export const api = {
|
||||
>(
|
||||
"warehouse-inventory",
|
||||
"move",
|
||||
({ id, payload }) => warehouseService.move(id, payload).then((r) => r.data),
|
||||
({ id, payload }) =>
|
||||
warehouseService.move(id, payload).then((r) => r.data),
|
||||
undefined,
|
||||
() => INVENTORY_INVALIDATIONS,
|
||||
),
|
||||
@@ -931,7 +1011,8 @@ export const api = {
|
||||
bulkMarkInspected: endpoint<BulkInspectPayload, BulkInspectResult>(
|
||||
"warehouse-inventory",
|
||||
"bulk-mark-inspected",
|
||||
(payload) => warehouseService.bulkMarkInspected(payload).then((r) => r.data),
|
||||
(payload) =>
|
||||
warehouseService.bulkMarkInspected(payload).then((r) => r.data),
|
||||
undefined,
|
||||
() => INVENTORY_INVALIDATIONS,
|
||||
),
|
||||
@@ -949,7 +1030,12 @@ export const api = {
|
||||
{
|
||||
scheduleId: string;
|
||||
warehouseId?: string;
|
||||
assignments?: { bookingId: string; warehouseId: string; yardId: string; zoneId: string }[];
|
||||
assignments?: {
|
||||
bookingId: string;
|
||||
warehouseId: string;
|
||||
yardId: string;
|
||||
zoneId: string;
|
||||
}[];
|
||||
},
|
||||
AutoUnloadArrivedResult
|
||||
>(
|
||||
@@ -1021,11 +1107,11 @@ export const api = {
|
||||
),
|
||||
|
||||
// ── Allocation + fee rules ─────────────────────────────────────────────
|
||||
previewAllocation: endpoint<AllocationCriteria, AllocationPreviewResult | null>(
|
||||
"warehouse-allocation-rules",
|
||||
"preview",
|
||||
(criteria) =>
|
||||
warehouseService.previewAllocation(criteria).then((r) => r.data),
|
||||
previewAllocation: endpoint<
|
||||
AllocationCriteria,
|
||||
AllocationPreviewResult | null
|
||||
>("warehouse-allocation-rules", "preview", (criteria) =>
|
||||
warehouseService.previewAllocation(criteria).then((r) => r.data),
|
||||
),
|
||||
|
||||
createAllocationRule: endpoint<SaveAllocationRulePayload, AllocationRule>(
|
||||
@@ -1087,7 +1173,11 @@ export const api = {
|
||||
|
||||
// ── Invoices ───────────────────────────────────────────────────────────
|
||||
generateInvoice: endpoint<
|
||||
{ inventoryId: string; confirmZero?: boolean; billingCurrency?: 'ETB' | 'USD' },
|
||||
{
|
||||
inventoryId: string;
|
||||
confirmZero?: boolean;
|
||||
billingCurrency?: "ETB" | "USD";
|
||||
},
|
||||
WarehouseFeeInvoice
|
||||
>(
|
||||
"warehouse-fee-invoices",
|
||||
@@ -1143,7 +1233,10 @@ export const api = {
|
||||
},
|
||||
|
||||
routes: {
|
||||
list: endpoint<{ status?: import("./routes.service").RouteStatus } | void, RouteRecord[]>(
|
||||
list: endpoint<
|
||||
{ status?: import("./routes.service").RouteStatus } | void,
|
||||
RouteRecord[]
|
||||
>(
|
||||
"routes",
|
||||
"list",
|
||||
(input) =>
|
||||
@@ -1168,7 +1261,10 @@ export const api = {
|
||||
() => [["routes"]],
|
||||
),
|
||||
|
||||
update: endpoint<{ id: string; data: Partial<SaveRoutePayload> }, RouteRecord>(
|
||||
update: endpoint<
|
||||
{ id: string; data: Partial<SaveRoutePayload> },
|
||||
RouteRecord
|
||||
>(
|
||||
"routes",
|
||||
"update",
|
||||
({ id, data }) => routesService.update(id, data).then((r) => r.data),
|
||||
@@ -1281,10 +1377,8 @@ export const api = {
|
||||
({ trainId }) => ["wagons", "train", trainId],
|
||||
),
|
||||
|
||||
getById: endpoint<{ id: string }, Wagon>(
|
||||
"wagons",
|
||||
"getById",
|
||||
({ id }) => wagonService.getById(id).then((r) => r.data),
|
||||
getById: endpoint<{ id: string }, Wagon>("wagons", "getById", ({ id }) =>
|
||||
wagonService.getById(id).then((r) => r.data),
|
||||
),
|
||||
|
||||
assignToTrain: endpoint<
|
||||
@@ -1663,7 +1757,8 @@ export const api = {
|
||||
>(
|
||||
"file-upload-settings",
|
||||
"addField",
|
||||
({ settingId, dto }) => fileUploadSettingsService.addField(settingId, dto),
|
||||
({ settingId, dto }) =>
|
||||
fileUploadSettingsService.addField(settingId, dto),
|
||||
undefined,
|
||||
() => [["file-upload-settings"]],
|
||||
),
|
||||
@@ -1762,7 +1857,8 @@ export const api = {
|
||||
>(
|
||||
"dropdown-settings",
|
||||
"updateOption",
|
||||
({ optionId, dto }) => dropdownSettingsService.updateOption(optionId, dto),
|
||||
({ optionId, dto }) =>
|
||||
dropdownSettingsService.updateOption(optionId, dto),
|
||||
undefined,
|
||||
() => [["dropdown-settings"]],
|
||||
),
|
||||
@@ -1815,11 +1911,10 @@ export const api = {
|
||||
ruleEngineService.update(resource, id, payload),
|
||||
),
|
||||
|
||||
remove: endpoint<
|
||||
{ resource: RuleEngineResourceSlug; id: string },
|
||||
void
|
||||
>("rule-engine", "remove", ({ resource, id }) =>
|
||||
ruleEngineService.remove(resource, id),
|
||||
remove: endpoint<{ resource: RuleEngineResourceSlug; id: string }, void>(
|
||||
"rule-engine",
|
||||
"remove",
|
||||
({ resource, id }) => ruleEngineService.remove(resource, id),
|
||||
),
|
||||
|
||||
submitRate: endpoint<{ id: string }, RuleEngineRecord>(
|
||||
@@ -1842,14 +1937,21 @@ export const api = {
|
||||
),
|
||||
|
||||
reorder: endpoint<
|
||||
{ resource: RuleEngineResourceSlug; payload: { ids: string[]; requiresDirectorApproval?: boolean } },
|
||||
{
|
||||
resource: RuleEngineResourceSlug;
|
||||
payload: { ids: string[]; requiresDirectorApproval?: boolean };
|
||||
},
|
||||
void
|
||||
>("rule-engine", "reorder", ({ resource, payload }) =>
|
||||
ruleEngineService.reorder(resource, payload),
|
||||
),
|
||||
|
||||
moveOrder: endpoint<
|
||||
{ resource: RuleEngineResourceSlug; id: string; direction: "up" | "down" },
|
||||
{
|
||||
resource: RuleEngineResourceSlug;
|
||||
id: string;
|
||||
direction: "up" | "down";
|
||||
},
|
||||
void
|
||||
>("rule-engine", "moveOrder", ({ resource, id, direction }) =>
|
||||
ruleEngineService.moveOrder(resource, id, direction),
|
||||
@@ -1871,10 +1973,8 @@ export const api = {
|
||||
({ id }) => QUERY_KEYS.BOOKINGS.byId(id),
|
||||
),
|
||||
|
||||
remove: endpoint<{ id: string }, void>(
|
||||
"bookings",
|
||||
"remove",
|
||||
({ id }) => bookingsService.remove(id),
|
||||
remove: endpoint<{ id: string }, void>("bookings", "remove", ({ id }) =>
|
||||
bookingsService.remove(id),
|
||||
),
|
||||
|
||||
staffAccept: endpoint<{ id: string; validityDays: number }, BookingDetail>(
|
||||
@@ -1924,10 +2024,11 @@ export const api = {
|
||||
({ id }) => bookingsService.generateContract(id),
|
||||
),
|
||||
|
||||
getContractView: endpoint<{ id: string }, import("./bookings.service").ContractView>(
|
||||
"bookings",
|
||||
"getContractView",
|
||||
({ id }) => bookingsService.getContractView(id),
|
||||
getContractView: endpoint<
|
||||
{ id: string },
|
||||
import("./bookings.service").ContractView
|
||||
>("bookings", "getContractView", ({ id }) =>
|
||||
bookingsService.getContractView(id),
|
||||
),
|
||||
|
||||
signContract: endpoint<
|
||||
@@ -2011,7 +2112,8 @@ export const api = {
|
||||
>(
|
||||
"customers",
|
||||
"setProfileStatus",
|
||||
({ profileId, status }) => customersService.setProfileStatus(profileId, status),
|
||||
({ profileId, status }) =>
|
||||
customersService.setProfileStatus(profileId, status),
|
||||
undefined,
|
||||
(_input, data) => [
|
||||
QUERY_KEYS.CUSTOMERS.byId(data.companyId),
|
||||
@@ -2032,6 +2134,22 @@ export const api = {
|
||||
),
|
||||
},
|
||||
|
||||
invoices: {
|
||||
list: endpoint<{ filter: InvoiceListFilter }, PaginatedInvoices>(
|
||||
"invoices",
|
||||
"list",
|
||||
({ filter }) => invoicesService.list(filter),
|
||||
({ filter }) => QUERY_KEYS.INVOICES.list(filter),
|
||||
),
|
||||
|
||||
getById: endpoint<{ id: string }, Invoice>(
|
||||
"invoices",
|
||||
"getById",
|
||||
({ id }) => invoicesService.getById(id),
|
||||
({ id }) => QUERY_KEYS.INVOICES.byId(id),
|
||||
),
|
||||
},
|
||||
|
||||
overview: {
|
||||
get: endpoint<{ range?: OverviewRange }, IOverviewDashboard>(
|
||||
"overview",
|
||||
|
||||
@@ -362,9 +362,14 @@ export const bookingsService = {
|
||||
return unwrap(response.data) as BookingDetail;
|
||||
},
|
||||
|
||||
uploadDeliveryOrder: async (id: string, file: File): Promise<BookingDetail> => {
|
||||
uploadDeliveryOrder: async (
|
||||
id: string,
|
||||
file: File,
|
||||
vesselDepartureDate?: string,
|
||||
): Promise<BookingDetail> => {
|
||||
const form = new FormData();
|
||||
form.append("file", file);
|
||||
if (vesselDepartureDate) form.append("vesselDepartureDate", vesselDepartureDate);
|
||||
const response = await client.post(B.CLEARANCE_DELIVERY_ORDER(id), form, {
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
});
|
||||
|
||||
@@ -283,9 +283,11 @@ export const contractsService = {
|
||||
uploadDeliveryOrder: async (
|
||||
id: string,
|
||||
file: File,
|
||||
vesselDepartureDate?: string,
|
||||
): Promise<Freight.IContract> => {
|
||||
const form = new FormData();
|
||||
form.append("file", file);
|
||||
if (vesselDepartureDate) form.append("vesselDepartureDate", vesselDepartureDate);
|
||||
const response = await client.post(C.CLEARANCE_DELIVERY_ORDER(id), form, {
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
});
|
||||
@@ -354,6 +356,83 @@ export const contractsService = {
|
||||
return unwrap(response.data) as Freight.ClearanceT1State;
|
||||
},
|
||||
|
||||
/** Train schedules carrying customs bookings — GL DJ gate-pass table. */
|
||||
getDjClearanceSchedules: async (): Promise<Freight.DjClearanceSchedule[]> => {
|
||||
const response = await client.get(C.CLEARANCE_DJ_SCHEDULES);
|
||||
return unwrap(response.data) as Freight.DjClearanceSchedule[];
|
||||
},
|
||||
|
||||
/** Gate pass for every customs booking on a train schedule (captures time). */
|
||||
grantScheduleGatepass: async (
|
||||
scheduleId: string,
|
||||
gatepassAt?: string,
|
||||
): Promise<{ granted: number; skipped: Array<{ bookingId: string; error: string }> }> => {
|
||||
const response = await client.post(C.CLEARANCE_SCHEDULE_GATEPASS(scheduleId), {
|
||||
gatepassAt,
|
||||
});
|
||||
return unwrap(response.data) as {
|
||||
granted: number;
|
||||
skipped: Array<{ bookingId: string; error: string }>;
|
||||
};
|
||||
},
|
||||
|
||||
/** Gate pass for a single customs booking (captures time). */
|
||||
grantGatepass: async (
|
||||
bookingId: string,
|
||||
gatepassAt?: string,
|
||||
): Promise<{ bookingId: string; gatepassAt: string }> => {
|
||||
const response = await client.post(C.BOOKING_GATEPASS(bookingId), { gatepassAt });
|
||||
return unwrap(response.data) as { bookingId: string; gatepassAt: string };
|
||||
},
|
||||
|
||||
/** GL DJ raises the post-offload final invoice (amount + invoice document). */
|
||||
sendFinalInvoice: async (
|
||||
bookingId: string,
|
||||
payload: { amount: number; currency: string; description?: string; file: File },
|
||||
): Promise<Freight.ClearanceFinalInvoiceSummary> => {
|
||||
const form = new FormData();
|
||||
form.append("amount", String(payload.amount));
|
||||
form.append("currency", payload.currency);
|
||||
if (payload.description) form.append("description", payload.description);
|
||||
form.append("file", payload.file);
|
||||
const response = await client.post(C.BOOKING_FINAL_INVOICE(bookingId), form, {
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
});
|
||||
return unwrap(response.data) as Freight.ClearanceFinalInvoiceSummary;
|
||||
},
|
||||
|
||||
/** GL (ET or DJ) confirms the payment slip — settles the final invoice. */
|
||||
confirmFinalInvoicePaid: async (
|
||||
bookingId: string,
|
||||
): Promise<Freight.ClearanceFinalInvoiceSummary> => {
|
||||
const response = await client.post(C.BOOKING_FINAL_INVOICE_CONFIRM(bookingId));
|
||||
return unwrap(response.data) as Freight.ClearanceFinalInvoiceSummary;
|
||||
},
|
||||
|
||||
/** GL ET advises (or skips) the post-arrival additional duty/tax round (import). */
|
||||
adviseSecondDuty: async (
|
||||
bookingId: string,
|
||||
payload: {
|
||||
dutyRequired: boolean;
|
||||
amount?: number;
|
||||
currency?: string;
|
||||
declarationSerial?: string;
|
||||
attachment?: File | null;
|
||||
},
|
||||
): Promise<{ advised: boolean; skipped: boolean }> => {
|
||||
const form = new FormData();
|
||||
form.append("dutyRequired", String(payload.dutyRequired));
|
||||
if (payload.amount != null) form.append("amount", String(payload.amount));
|
||||
if (payload.currency) form.append("currency", payload.currency);
|
||||
if (payload.declarationSerial)
|
||||
form.append("declarationSerial", payload.declarationSerial);
|
||||
if (payload.attachment) form.append("attachment", payload.attachment);
|
||||
const response = await client.post(C.BOOKING_SECOND_DUTY(bookingId), form, {
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
});
|
||||
return unwrap(response.data) as { advised: boolean; skipped: boolean };
|
||||
},
|
||||
|
||||
// ── Path A self-clearance (Operations review) ──
|
||||
getOpsClearanceQueue: async (): Promise<PaginatedContracts> => {
|
||||
const response = await client.get<PaginatedContracts>(
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { api as apiClient } from "@/auth/http";
|
||||
import { URL_CONSTANTS } from "@/constants/URLS";
|
||||
import type {
|
||||
Invoice,
|
||||
InvoiceListFilter,
|
||||
PaginatedInvoices,
|
||||
} from "@/types/invoice";
|
||||
|
||||
const cleanParams = (params: object) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(params).filter(
|
||||
([, value]) => value !== undefined && value !== "" && value !== null,
|
||||
),
|
||||
);
|
||||
|
||||
export const invoicesService = {
|
||||
list(filter: InvoiceListFilter): Promise<PaginatedInvoices> {
|
||||
return apiClient
|
||||
.get<PaginatedInvoices>(URL_CONSTANTS.BILLING.INVOICES, {
|
||||
params: cleanParams(filter),
|
||||
})
|
||||
.then((r) => r.data);
|
||||
},
|
||||
|
||||
getById(id: string): Promise<Invoice> {
|
||||
return apiClient
|
||||
.get<Invoice>(URL_CONSTANTS.BILLING.INVOICE_BY_ID(id))
|
||||
.then((r) => r.data);
|
||||
},
|
||||
|
||||
downloadDocument(id: string) {
|
||||
return apiClient.get<Blob>(URL_CONSTANTS.BILLING.INVOICE_DOCUMENT(id), {
|
||||
responseType: "blob",
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -15,8 +15,6 @@ export interface Rate {
|
||||
proposedByStaffId: string;
|
||||
approvedByCeoId: string | null;
|
||||
approvedAt: string | null;
|
||||
effectiveFrom: string;
|
||||
effectiveTo: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
deletedAt: string | null;
|
||||
|
||||
@@ -15,6 +15,8 @@ import type {
|
||||
ImportDjiboutiActionPayload,
|
||||
ImportDjiboutiLoadList,
|
||||
ImportDjiboutiOperation,
|
||||
ImportLoadingBookingsResponse,
|
||||
LoadingStatus,
|
||||
LocomotiveRecord,
|
||||
PinWagonsPayload,
|
||||
RecordCheckpointPayload,
|
||||
@@ -158,6 +160,20 @@ export const trainSchedulingService = {
|
||||
return unwrap(response.data);
|
||||
},
|
||||
|
||||
/**
|
||||
* Staff finished reviewing documents early — runs the batch immediately
|
||||
* for the schedule's whole route-day group.
|
||||
*/
|
||||
completeDocReview: async (
|
||||
scheduleId: string,
|
||||
): Promise<BatchBoardScheduleDetail> => {
|
||||
const response = await client.post<BatchBoardScheduleDetail>(
|
||||
URL_CONSTANTS.TRAIN_SCHEDULING.DOC_REVIEW_COMPLETE(scheduleId),
|
||||
{},
|
||||
);
|
||||
return unwrap(response.data);
|
||||
},
|
||||
|
||||
runAllocation: async (
|
||||
scheduleId: string,
|
||||
): Promise<WagonAllocationAttemptResult> => {
|
||||
@@ -284,6 +300,26 @@ export const trainSchedulingService = {
|
||||
return unwrap(response.data);
|
||||
},
|
||||
|
||||
getImportLoadingBookings: async (
|
||||
scheduleId: string,
|
||||
): Promise<ImportLoadingBookingsResponse> => {
|
||||
const response = await client.get<ImportLoadingBookingsResponse>(
|
||||
URL_CONSTANTS.TRAIN_SCHEDULING.IMPORT_LOADING_BOOKINGS(scheduleId),
|
||||
);
|
||||
return unwrap(response.data);
|
||||
},
|
||||
|
||||
updateImportLoadingStatus: async (
|
||||
scheduleId: string,
|
||||
payload: { bookingIds: string[]; loadingStatus: LoadingStatus },
|
||||
): Promise<ImportLoadingBookingsResponse> => {
|
||||
const response = await client.patch<ImportLoadingBookingsResponse>(
|
||||
URL_CONSTANTS.TRAIN_SCHEDULING.IMPORT_LOADING_STATUS(scheduleId),
|
||||
payload,
|
||||
);
|
||||
return unwrap(response.data);
|
||||
},
|
||||
|
||||
getImportDjiboutiOperation: async (
|
||||
scheduleId: string,
|
||||
): Promise<ImportDjiboutiOperation> => {
|
||||
@@ -494,16 +530,7 @@ export const trainSchedulingService = {
|
||||
},
|
||||
|
||||
updateGlobalRules: async (
|
||||
payload: Partial<
|
||||
Pick<
|
||||
TrainSchedulingGlobalRules,
|
||||
| "maxTrainLengthMeters"
|
||||
| "maxTrainWeightTons"
|
||||
| "maxWagonsPerTrain"
|
||||
| "max20ftContainerWeightTons"
|
||||
| "max20ftPairWeightDiffTons"
|
||||
>
|
||||
>,
|
||||
payload: Partial<Omit<TrainSchedulingGlobalRules, "id">>,
|
||||
): Promise<TrainSchedulingGlobalRules> => {
|
||||
const response = await client.patch<TrainSchedulingGlobalRules>(
|
||||
URL_CONSTANTS.TRAIN_SCHEDULING.GLOBAL_RULES,
|
||||
|
||||
Reference in New Issue
Block a user