mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 11:55:42 +00:00
Merge branch 'dev' of github.com:Tria-plc/edr-platform into freight/feature/first_mile_invoice
This commit is contained in:
@@ -593,6 +593,52 @@ export const api = {
|
||||
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||
),
|
||||
|
||||
intercityCandidates: endpoint<
|
||||
{ scheduleId: string },
|
||||
import("@/types/trainScheduling").IntercityCandidatesResult
|
||||
>(
|
||||
"train-scheduling",
|
||||
"intercity-candidates",
|
||||
({ scheduleId }) => trainSchedulingService.getIntercityCandidates(scheduleId),
|
||||
({ scheduleId }) => ["train-scheduling", "intercity-candidates", scheduleId],
|
||||
),
|
||||
|
||||
acceptIntercityBookings: endpoint<
|
||||
{ scheduleId: string; bookingIds: string[] },
|
||||
import("@/types/trainScheduling").IntercityAcceptResult
|
||||
>(
|
||||
"train-scheduling",
|
||||
"intercity-accept",
|
||||
({ scheduleId, bookingIds }) =>
|
||||
trainSchedulingService.acceptIntercityBookings(scheduleId, bookingIds),
|
||||
undefined,
|
||||
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||
),
|
||||
|
||||
loadIntercityBooking: endpoint<
|
||||
{ scheduleId: string; bookingId: string },
|
||||
void
|
||||
>(
|
||||
"train-scheduling",
|
||||
"intercity-load",
|
||||
({ scheduleId, bookingId }) =>
|
||||
trainSchedulingService.loadIntercityBooking(scheduleId, bookingId),
|
||||
undefined,
|
||||
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||
),
|
||||
|
||||
unloadIntercityBooking: endpoint<
|
||||
{ scheduleId: string; bookingId: string },
|
||||
void
|
||||
>(
|
||||
"train-scheduling",
|
||||
"intercity-unload",
|
||||
({ scheduleId, bookingId }) =>
|
||||
trainSchedulingService.unloadIntercityBooking(scheduleId, bookingId),
|
||||
undefined,
|
||||
() => TRAIN_SCHEDULING_INVALIDATIONS,
|
||||
),
|
||||
|
||||
cancelSchedule: endpoint<
|
||||
{ id: string; freightType?: FreightType },
|
||||
TrainScheduleDetail
|
||||
|
||||
@@ -4,6 +4,9 @@ import { URL_CONSTANTS } from '@/constants/URLS';
|
||||
|
||||
export type RouteStatus = 'AVAILABLE' | 'MAINTENANCE' | 'DAMAGED' | 'STOP_WORKING';
|
||||
|
||||
/** Frozen from yard countries: ET→DJ EXPORT, DJ→ET IMPORT, same country DOMESTIC (intercity, disabled). */
|
||||
export type RouteDirection = 'IMPORT' | 'EXPORT' | 'DOMESTIC';
|
||||
|
||||
export interface YardRef {
|
||||
id: string;
|
||||
code: string;
|
||||
@@ -23,6 +26,7 @@ export interface RouteMilestone {
|
||||
export interface RouteRecord {
|
||||
id: string;
|
||||
status: RouteStatus;
|
||||
direction?: RouteDirection;
|
||||
originYardId: string;
|
||||
destinationYardId: string;
|
||||
originYard?: YardRef | null;
|
||||
|
||||
@@ -17,6 +17,8 @@ import type {
|
||||
ImportDjiboutiLoadList,
|
||||
ImportDjiboutiOperation,
|
||||
ImportLoadingBookingsResponse,
|
||||
IntercityAcceptResult,
|
||||
IntercityCandidatesResult,
|
||||
LoadingStatus,
|
||||
LocomotiveRecord,
|
||||
PinWagonsPayload,
|
||||
@@ -328,6 +330,46 @@ export const trainSchedulingService = {
|
||||
return unwrap(response.data);
|
||||
},
|
||||
|
||||
getIntercityCandidates: async (
|
||||
scheduleId: string,
|
||||
): Promise<IntercityCandidatesResult> => {
|
||||
const response = await client.get<IntercityCandidatesResult>(
|
||||
URL_CONSTANTS.TRAIN_SCHEDULING.INTERCITY_CANDIDATES(scheduleId),
|
||||
);
|
||||
return unwrap(response.data);
|
||||
},
|
||||
|
||||
acceptIntercityBookings: async (
|
||||
scheduleId: string,
|
||||
bookingIds: string[],
|
||||
): Promise<IntercityAcceptResult> => {
|
||||
const response = await client.post<IntercityAcceptResult>(
|
||||
URL_CONSTANTS.TRAIN_SCHEDULING.INTERCITY_ACCEPT(scheduleId),
|
||||
{ bookingIds },
|
||||
);
|
||||
return unwrap(response.data);
|
||||
},
|
||||
|
||||
loadIntercityBooking: async (
|
||||
scheduleId: string,
|
||||
bookingId: string,
|
||||
): Promise<void> => {
|
||||
await client.post(
|
||||
URL_CONSTANTS.TRAIN_SCHEDULING.INTERCITY_LOAD(scheduleId, bookingId),
|
||||
{},
|
||||
);
|
||||
},
|
||||
|
||||
unloadIntercityBooking: async (
|
||||
scheduleId: string,
|
||||
bookingId: string,
|
||||
): Promise<void> => {
|
||||
await client.post(
|
||||
URL_CONSTANTS.TRAIN_SCHEDULING.INTERCITY_UNLOAD(scheduleId, bookingId),
|
||||
{},
|
||||
);
|
||||
},
|
||||
|
||||
dispatchSchedule: async (
|
||||
scheduleId: string,
|
||||
): Promise<TrainScheduleDetail> => {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { Freight } from '@edr/types';
|
||||
|
||||
import { api as apiClient } from '../auth/http';
|
||||
|
||||
import { URL_CONSTANTS } from '@/constants/URLS';
|
||||
@@ -61,12 +63,126 @@ import type {
|
||||
WarehouseZone,
|
||||
} from '@/types/warehouse';
|
||||
|
||||
export type ContainerItemStage = 'PENDING' | 'RECEIVED' | 'GRN' | 'LOADED' | 'LEFT' | 'DELIVERED';
|
||||
|
||||
export interface ContainerItem {
|
||||
containerNumber: string;
|
||||
goods: string | null;
|
||||
stage: ContainerItemStage;
|
||||
grnNumber: string | null;
|
||||
truckAssignmentId: string | null;
|
||||
truckPlate: string | null;
|
||||
truckArrived: boolean;
|
||||
truckLeft: boolean;
|
||||
bookingReference: string | null;
|
||||
contractId: string | null;
|
||||
hasLastMile: boolean;
|
||||
}
|
||||
|
||||
/** A pre-dispatch EXPORT train that has inventory waiting to be loaded. */
|
||||
export interface LoadableTrain {
|
||||
scheduleId: string;
|
||||
trainNumber: string | null;
|
||||
origin: string | null;
|
||||
destination: string | null;
|
||||
status: string;
|
||||
departureTime: string | null;
|
||||
readyCount: number;
|
||||
loadedCount: number;
|
||||
}
|
||||
|
||||
/** A container/cargo inventory item assigned to a train, with its allocated wagon. */
|
||||
export interface TrainLoadableItem {
|
||||
id: string;
|
||||
bookingId: string | null;
|
||||
bookingReference: string | null;
|
||||
customerName: string | null;
|
||||
containerNumber: string | null;
|
||||
cargoType: string | null;
|
||||
weight: number | null;
|
||||
grnNumber: string | null;
|
||||
inspectionStatus: string | null;
|
||||
status: string;
|
||||
wagonId: string | null;
|
||||
wagonNumber: string | null;
|
||||
sequenceNo: number | null;
|
||||
loadable: boolean;
|
||||
}
|
||||
|
||||
export interface TrainLoadResult {
|
||||
loadedCount: number;
|
||||
skippedCount: number;
|
||||
results: { inventoryId: string; status: string; reason?: string }[];
|
||||
}
|
||||
|
||||
const cleanParams = (params: object) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(params).filter(([, value]) => value !== undefined && value !== '' && value !== null),
|
||||
);
|
||||
|
||||
export const warehouseService = {
|
||||
/** Customer self-haul trucks assigned to a booking (portal multi-truck). */
|
||||
getCustomerTrucks: async (bookingId: string): Promise<Freight.ICustomerTruck[]> => {
|
||||
const { data } = await apiClient.get(`/bookings/${bookingId}/customer-trucks`);
|
||||
return data?.data ?? data ?? [];
|
||||
},
|
||||
|
||||
/** Per-container/bulk items of a booking with lifecycle stage + refs. */
|
||||
getContainerItems: async (bookingId: string): Promise<ContainerItem[]> => {
|
||||
const { data } = await apiClient.get(
|
||||
`/warehouse-inventory/bookings/${bookingId}/container-items`,
|
||||
);
|
||||
return data?.data ?? data ?? [];
|
||||
},
|
||||
|
||||
/** Booking container numbers not yet loaded onto any truck. */
|
||||
getLoadableContainers: async (bookingId: string): Promise<string[]> => {
|
||||
const { data } = await apiClient.get(
|
||||
`/bookings/${bookingId}/customer-trucks/loadable-containers`,
|
||||
);
|
||||
return data?.data ?? data ?? [];
|
||||
},
|
||||
|
||||
/** Truck_dispatch: load selected containers onto a truck (after arrival). */
|
||||
loadTruck: async (
|
||||
bookingId: string,
|
||||
assignmentId: string,
|
||||
containerNumbers: string[],
|
||||
): Promise<Freight.ICustomerTruck[]> => {
|
||||
const { data } = await apiClient.post(
|
||||
`/bookings/${bookingId}/customer-trucks/${assignmentId}/load`,
|
||||
{ containerNumbers },
|
||||
);
|
||||
return data?.data ?? data ?? [];
|
||||
},
|
||||
|
||||
// ── Load to Train ─────────────────────────────────────────────────────────
|
||||
/** Pre-dispatch EXPORT trains with inventory waiting to be loaded. */
|
||||
getLoadableTrains: async (): Promise<LoadableTrain[]> => {
|
||||
const { data } = await apiClient.get('/warehouse-inventory/loadable-trains');
|
||||
return data?.data ?? data ?? [];
|
||||
},
|
||||
|
||||
/** Container/cargo items assigned to a train, with allocated wagon + stage. */
|
||||
getTrainLoadableItems: async (scheduleId: string): Promise<TrainLoadableItem[]> => {
|
||||
const { data } = await apiClient.get(
|
||||
`/warehouse-inventory/train/${scheduleId}/loadable-items`,
|
||||
);
|
||||
return data?.data ?? data ?? [];
|
||||
},
|
||||
|
||||
/** Load selected inventory items onto their allocated wagons for a train. */
|
||||
loadItemsOntoTrain: async (
|
||||
scheduleId: string,
|
||||
inventoryIds: string[],
|
||||
): Promise<TrainLoadResult> => {
|
||||
const { data } = await apiClient.post(
|
||||
`/warehouse-inventory/train/${scheduleId}/load`,
|
||||
{ inventoryIds },
|
||||
);
|
||||
return data?.data ?? data ?? { loadedCount: 0, skippedCount: 0, results: [] };
|
||||
},
|
||||
|
||||
// ── Warehouses ──────────────────────────────────────────────────────────
|
||||
list: (filter?: WarehouseFilter) =>
|
||||
apiClient.get<Warehouse[]>(URL_CONSTANTS.WAREHOUSES.BASE, {
|
||||
@@ -147,6 +263,11 @@ export const warehouseService = {
|
||||
apiClient.get<Blob>(URL_CONSTANTS.WAREHOUSE_INVENTORY.HANDOVER_DOCUMENT(id), {
|
||||
responseType: 'blob',
|
||||
}),
|
||||
/** Per-truck exit paper PDF (containers loaded on one customer truck). */
|
||||
downloadTruckExitPaper: (assignmentId: string) =>
|
||||
apiClient.get<Blob>(`/warehouse-inventory/customer-truck-exit-paper/${assignmentId}`, {
|
||||
responseType: 'blob',
|
||||
}),
|
||||
deliver: (id: string, payload: DeliverInventoryPayload) =>
|
||||
apiClient.post<WarehouseInventoryItem>(URL_CONSTANTS.WAREHOUSE_INVENTORY.DELIVER(id), payload),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user