import { api as apiClient } from '../auth/http'; import { URL_CONSTANTS } from '@/constants/URLS'; import type { AllocationCriteria, AllocationPreviewResult, AllocationRule, ArrivalQueueItem, AutoLoadResult, AutoUnloadResult, FeePreview, FeeRule, InspectionAttachment, InspectionReport, InspectionReportPayload, SaveAllocationRulePayload, SaveFeeRulePayload, WarehouseFeeInvoice, WarehouseInvoiceFilter, PayInvoicePayload, InitiateWarehouseInvoicePaymentPayload, WarehouseInvoicePaymentResponse, BookingScheduleView, InventoryFilter, InventoryInquiryFilter, InventoryInquiryResult, InventoryMovement, LoadableWagon, LoadInventoryPayload, MoveInventoryPayload, ReceiveInventoryPayload, ReleaseOrderPayload, DeliverInventoryPayload, EligibleBooking, BulkReceivePayload, BulkReceiveResult, LoadPassedExportResult, BulkInspectPayload, BulkInspectResult, ReadyToLoadRow, BulkDispatchResult, AutoUnloadExportDjiboutiResult, ExportTrain, ExportTrainItem, ImportTrain, ImportTrainItem, ImportUnloadedItem, AutoUnloadArrivedResult, ReserveInventoryPayload, SaveWarehousePayload, SaveYardPayload, SaveZonePayload, Warehouse, WarehouseActivityLog, WarehouseDashboard, WarehouseFacility, WarehouseFilter, WarehouseInventoryItem, WarehouseLoading, WarehouseYard, WarehouseZone, } from '@/types/warehouse'; const cleanParams = (params: object) => Object.fromEntries( Object.entries(params).filter(([, value]) => value !== undefined && value !== '' && value !== null), ); export const warehouseService = { // ── Warehouses ────────────────────────────────────────────────────────── list: (filter?: WarehouseFilter) => apiClient.get(URL_CONSTANTS.WAREHOUSES.BASE, { params: cleanParams(filter ?? {}), }), dashboard: () => apiClient.get(URL_CONSTANTS.WAREHOUSES.DASHBOARD), getDashboardSummary: (_filter?: InventoryFilter) => apiClient.get(URL_CONSTANTS.WAREHOUSES.DASHBOARD), getById: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSES.BY_ID(id)), create: (payload: SaveWarehousePayload) => apiClient.post(URL_CONSTANTS.WAREHOUSES.BASE, payload), update: (id: string, payload: Partial) => apiClient.patch(URL_CONSTANTS.WAREHOUSES.BY_ID(id), payload), listFacilities: () => apiClient.get(URL_CONSTANTS.RULE_ENGINE.YARDS), // ── Yards ──────────────────────────────────────────────────────────────── listYards: (warehouseId: string) => apiClient.get(URL_CONSTANTS.WAREHOUSES.YARDS(warehouseId)), listAllYards: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_YARDS.BASE), createYard: (warehouseId: string, payload: SaveYardPayload) => apiClient.post(URL_CONSTANTS.WAREHOUSES.YARDS(warehouseId), payload), getYard: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_YARDS.BY_ID(id)), updateYard: (id: string, payload: Partial) => apiClient.patch(URL_CONSTANTS.WAREHOUSE_YARDS.BY_ID(id), payload), // ── Zones ────────────────────────────────────────────────────────────── listZones: (yardId: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_YARDS.ZONES(yardId)), listAllZones: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_ZONES.BASE), createZone: (yardId: string, payload: SaveZonePayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_YARDS.ZONES(yardId), payload), getZone: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_ZONES.BY_ID(id)), updateZone: (id: string, payload: Partial) => apiClient.patch(URL_CONSTANTS.WAREHOUSE_ZONES.BY_ID(id), payload), // ── Inventory ────────────────────────────────────────────────────────── listInventory: (filter?: InventoryFilter) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.BASE, { params: cleanParams(filter ?? {}), }), receiveInventory: (payload: ReceiveInventoryPayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.RECEIVE, payload), listReadyForLoading: (filter?: InventoryFilter) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.READY_FOR_LOADING, { params: cleanParams(filter ?? {}), }), inquiry: (filter: InventoryInquiryFilter) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.INQUIRY, { params: cleanParams(filter ?? {}), }), // ── Lifecycle (Batch 2) ────────────────────────────────────────────────── store: (id: string) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.STORE(id)), reserve: (payload: ReserveInventoryPayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.RESERVE, payload), markReadyForLoading: (id: string) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.MARK_READY(id)), load: (id: string, payload: LoadInventoryPayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.LOAD(id), payload), dispatch: (id: string) => apiClient.patch(URL_CONSTANTS.WAREHOUSE_INVENTORY.DISPATCH(id)), // ── Import branch (READY_FOR_PICKUP → DELIVERED) ───────────────────────── markReadyForPickup: (id: string) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.MARK_READY_PICKUP(id)), release: (id: string, payload: ReleaseOrderPayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.RELEASE(id), payload), downloadReleaseDocument: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.RELEASE_DOCUMENT(id), { responseType: 'blob', }), downloadGrnDocument: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.GRN_DOCUMENT(id), { responseType: 'blob', }), downloadHandoverDocument: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.HANDOVER_DOCUMENT(id), { responseType: 'blob', }), deliver: (id: string, payload: DeliverInventoryPayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.DELIVER(id), payload), // ── Receive (Import/Export bulk) ───────────────────────────────────────── eligibleBookings: (direction?: 'IMPORT' | 'EXPORT') => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.ELIGIBLE_BOOKINGS(direction)), receiveBulk: (payload: BulkReceivePayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.RECEIVE_BULK, payload), loadPassedExport: () => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.LOAD_PASSED_EXPORT, {}), bulkMarkInspected: (payload: BulkInspectPayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.BULK_MARK_INSPECTED, payload), receivedExport: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.RECEIVED_EXPORT), readyToLoadExport: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.READY_TO_LOAD_EXPORT), loadedExport: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.LOADED_EXPORT), bulkDispatchExport: (inventoryIds: string[]) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.BULK_DISPATCH_EXPORT, { inventoryIds, }), importArriveQueue: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.IMPORT_ARRIVE_QUEUE), importTrainItems: (scheduleId: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.IMPORT_TRAIN_ITEMS(scheduleId)), autoUnloadArrivedBookings: (payload: { scheduleId: string; warehouseId?: string; assignments?: { bookingId: string; warehouseId: string; yardId: string; zoneId: string }[]; }) => apiClient.post( URL_CONSTANTS.WAREHOUSE_INVENTORY.IMPORT_AUTO_UNLOAD_ARRIVED, payload, ), importUnloadedQueue: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.IMPORT_UNLOADED_QUEUE), importPickupReadyQueue: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.IMPORT_PICKUP_READY_QUEUE), exportDjiboutiArrivalQueue: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.EXPORT_DJIBOUTI_ARRIVAL_QUEUE), exportDjiboutiTrainItems: (scheduleId: string) => apiClient.get( URL_CONSTANTS.WAREHOUSE_INVENTORY.EXPORT_DJIBOUTI_TRAIN_ITEMS(scheduleId), ), autoUnloadExportAtDjibouti: (scheduleId: string) => apiClient.post( URL_CONSTANTS.WAREHOUSE_INVENTORY.EXPORT_AUTO_UNLOAD_AT_DJIBOUTI, { scheduleId }, ), move: (id: string, payload: MoveInventoryPayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.MOVE(id), payload), movements: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.MOVEMENTS(id)), activity: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.ACTIVITY(id)), // ── Loading (Batch 3) ───────────────────────────────────────────────────── loadableWagons: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.LOADABLE_WAGONS), bookingSchedule: (bookingId: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.BOOKING_SCHEDULE(bookingId)), inventoryLoadings: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.LOADINGS(id)), loadings: (params?: { bookingId?: string; wagonId?: string }) => apiClient.get(URL_CONSTANTS.WAREHOUSE_LOADINGS.BASE, { params: cleanParams(params ?? {}), }), // ── Batch 4.5: Arrival / Unload / Load automation ────────────────────────── arrivalQueue: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.ARRIVAL_QUEUE), autoUnloadArrived: () => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.AUTO_UNLOAD_ARRIVED), autoLoadReady: () => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVENTORY.AUTO_LOAD_READY), unloadBooking: (bookingId: string, payload?: Record) => apiClient.post( URL_CONSTANTS.WAREHOUSE_INVENTORY.UNLOAD_BOOKING(bookingId), payload ?? {}, ), // ── Batch 4.5: Inspection reports ────────────────────────────────────────── listInspectionReports: (inventoryId: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVENTORY.INSPECTION_REPORTS(inventoryId)), createInspectionReport: (inventoryId: string, payload: InspectionReportPayload) => apiClient.post( URL_CONSTANTS.WAREHOUSE_INVENTORY.INSPECTION_REPORTS(inventoryId), payload, ), getInspectionReport: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INSPECTION.BY_ID(id)), uploadInspectionAttachments: (id: string, files: File[]) => { const form = new FormData(); files.forEach((file) => form.append('files', file)); return apiClient.post( URL_CONSTANTS.WAREHOUSE_INSPECTION.ATTACHMENTS(id), form, { headers: { 'Content-Type': 'multipart/form-data' } }, ); }, // ── Batch 5: Allocation + Fee rules / previews ───────────────────────────── listAllocationRules: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_RULES.ALLOCATION), createAllocationRule: (payload: SaveAllocationRulePayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_RULES.ALLOCATION, payload), updateAllocationRule: (id: string, payload: Partial) => apiClient.patch(URL_CONSTANTS.WAREHOUSE_RULES.ALLOCATION_BY_ID(id), payload), deleteAllocationRule: (id: string) => apiClient.delete(URL_CONSTANTS.WAREHOUSE_RULES.ALLOCATION_BY_ID(id)), previewAllocation: (criteria: AllocationCriteria) => apiClient.post(URL_CONSTANTS.WAREHOUSE_RULES.ALLOCATION_PREVIEW, criteria), listFeeRules: () => apiClient.get(URL_CONSTANTS.WAREHOUSE_RULES.FEES), createFeeRule: (payload: SaveFeeRulePayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_RULES.FEES, payload), updateFeeRule: (id: string, payload: Partial) => apiClient.patch(URL_CONSTANTS.WAREHOUSE_RULES.FEES_BY_ID(id), payload), deleteFeeRule: (id: string) => apiClient.delete(URL_CONSTANTS.WAREHOUSE_RULES.FEES_BY_ID(id)), feePreview: (inventoryId: string, billingCurrency?: 'ETB' | 'USD') => apiClient.get(URL_CONSTANTS.WAREHOUSE_RULES.FEE_PREVIEW(inventoryId), { params: cleanParams({ billingCurrency }), }), // ── Batch 6: Warehouse fee invoices ──────────────────────────────────────── listInvoices: (filter?: WarehouseInvoiceFilter) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVOICES.BASE, { params: cleanParams(filter ?? {}), }), getInvoice: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVOICES.BY_ID(id)), downloadInvoiceDocument: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVOICES.DOCUMENT(id), { responseType: 'blob', }), downloadInvoiceReceipt: (id: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVOICES.RECEIPT(id), { responseType: 'blob', }), invoicesForInventory: (inventoryId: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVOICES.FOR_INVENTORY(inventoryId)), invoicesForBooking: (bookingId: string) => apiClient.get(URL_CONSTANTS.WAREHOUSE_INVOICES.FOR_BOOKING(bookingId)), generateInvoice: (inventoryId: string, confirmZero = false, billingCurrency?: 'ETB' | 'USD') => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVOICES.GENERATE(inventoryId), { confirmZero, billingCurrency, }), cancelInvoice: (id: string) => apiClient.patch(URL_CONSTANTS.WAREHOUSE_INVOICES.CANCEL(id)), payInvoice: (id: string, payload: PayInvoicePayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVOICES.PAY(id), payload), payInvoiceOnline: (id: string, payload: InitiateWarehouseInvoicePaymentPayload) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVOICES.PAY_ONLINE(id), payload), gateClearance: (inventoryId: string) => apiClient.post(URL_CONSTANTS.WAREHOUSE_INVOICES.GATE_CLEARANCE(inventoryId), {}), };