auto allocation and batch managemnt, tracking the train

This commit is contained in:
marshal
2026-06-12 11:42:46 +03:00
parent 8618ea2aa8
commit ef0abf1c41
61 changed files with 3541 additions and 378 deletions

View File

@@ -1,16 +1,25 @@
import { cargoService, type Cargo } from "@/services/cargoService";
import { containerService, type Container } from "@/services/containerService";
import { locomotivesService, type Locomotive } from "@/services/locomotives.service";
import {
locomotivesService,
type Locomotive,
type LocomotiveListFilters,
} from "@/services/locomotives.service";
import { trainService, type Train } from "@/services/trains.service";
import { wagonService, type Wagon } from "@/services/wagon.service";
import { wagonService, type Wagon, type WagonListFilters } from "@/services/wagon.service";
import type { FleetResourceSlug } from "@/pages/fleet/config/resources";
export type FleetRecord = Locomotive | Train | Wagon | Container | Cargo;
const listHandlers: Record<FleetResourceSlug, () => Promise<FleetRecord[]>> = {
locomotives: () => locomotivesService.getAll().then((r) => r.data),
export type FleetListFilters = WagonListFilters & LocomotiveListFilters;
const listHandlers: Record<
FleetResourceSlug,
(filters?: FleetListFilters) => Promise<FleetRecord[]>
> = {
locomotives: (filters) => locomotivesService.getAll(filters ?? {}).then((r) => r.data),
trains: () => trainService.getAll().then((r) => r.data),
wagons: () => wagonService.getAll().then((r) => r.data),
wagons: (filters) => wagonService.getAll(filters ?? {}).then((r) => r.data),
containers: () => containerService.getAll().then((r) => r.data),
cargoes: () => cargoService.getAll().then((r) => r.data),
};
@@ -43,7 +52,7 @@ const removeHandlers: Record<FleetResourceSlug, (id: string) => Promise<unknown>
};
export const fleetService = {
list: (slug: FleetResourceSlug) => listHandlers[slug](),
list: (slug: FleetResourceSlug, filters?: FleetListFilters) => listHandlers[slug](filters),
create: (slug: FleetResourceSlug, data: Record<string, unknown>) => createHandlers[slug](data),
update: (slug: FleetResourceSlug, id: string, data: Record<string, unknown>) =>
updateHandlers[slug](id, data),

View File

@@ -1,3 +1,5 @@
import type { Freight } from '@edr/types';
import { api as apiClient } from '../auth/http';
import { URL_CONSTANTS } from '@/constants/URLS';
@@ -9,12 +11,18 @@ export type LocomotiveStatus =
| 'ASSIGNED'
| 'OUT_OF_SERVICE';
export interface LocomotiveListFilters {
status?: LocomotiveStatus;
readiness?: Freight.WagonReadiness;
}
export interface Locomotive {
id: string;
code: string;
name?: string | null;
locomotiveType: LocomotiveType;
status: LocomotiveStatus;
readiness: Freight.WagonReadiness;
maxPullWeightTons: number;
maxTrainLengthMeters: number;
powerKw?: number | null;
@@ -30,7 +38,15 @@ export type SaveLocomotivePayload = Omit<
>;
export const locomotivesService = {
getAll: () => apiClient.get<Locomotive[]>(URL_CONSTANTS.LOCOMOTIVES.BASE),
getAll: (filters: LocomotiveListFilters = {}) => {
const params = new URLSearchParams();
if (filters.status) params.set('status', filters.status);
if (filters.readiness) params.set('readiness', filters.readiness);
const qs = params.toString();
return apiClient.get<Locomotive[]>(
`${URL_CONSTANTS.LOCOMOTIVES.BASE}${qs ? `?${qs}` : ''}`,
);
},
getById: (id: string) => apiClient.get<Locomotive>(URL_CONSTANTS.LOCOMOTIVES.BY_ID(id)),
create: (data: Partial<SaveLocomotivePayload>) =>
apiClient.post(URL_CONSTANTS.LOCOMOTIVES.BASE, data),

View File

@@ -3,6 +3,7 @@ import { unwrap } from '@/utils/endpoint';
import { URL_CONSTANTS } from '@/constants/URLS';
import type {
BatchBoardSchedule,
BatchBoardScheduleDetail,
BookableSchedule,
AssignBookingsPayload,
CreateTrainSchedulePayload,
@@ -18,6 +19,7 @@ import type {
TrainSchedulePreviewResponse,
TrainSchedulingGlobalRules,
TrainTrackResponse,
WagonAllocationAttemptResult,
YardOption,
} from '@/types/trainScheduling';
@@ -86,6 +88,13 @@ export const trainSchedulingService = {
return unwrap(response.data);
},
getBatchBoardDetail: async (scheduleId: string): Promise<BatchBoardScheduleDetail> => {
const response = await client.get<BatchBoardScheduleDetail>(
URL_CONSTANTS.TRAIN_SCHEDULING.BATCH_BOARD_DETAIL(scheduleId),
);
return unwrap(response.data);
},
getBookableSchedules: async (
originYardId?: string,
destinationYardId?: string,
@@ -97,14 +106,22 @@ export const trainSchedulingService = {
return unwrap(response.data);
},
runBatch: async (scheduleId: string): Promise<TrainScheduleDetail> => {
const response = await client.post<TrainScheduleDetail>(
runBatch: async (scheduleId: string): Promise<BatchBoardScheduleDetail> => {
const response = await client.post<BatchBoardScheduleDetail>(
URL_CONSTANTS.TRAIN_SCHEDULING.RUN_BATCH(scheduleId),
{},
);
return unwrap(response.data);
},
runAllocation: async (scheduleId: string): Promise<WagonAllocationAttemptResult> => {
const response = await client.post<WagonAllocationAttemptResult>(
URL_CONSTANTS.TRAIN_SCHEDULING.RUN_ALLOCATION(scheduleId),
{},
);
return unwrap(response.data);
},
setBookingWindow: async (
scheduleId: string,
status: "OPEN" | "CLOSED",
@@ -232,7 +249,14 @@ export const trainSchedulingService = {
return unwrap(response.data);
},
getAvailableLocomotives: async (): Promise<LocomotiveRecord[]> => {
getAvailableLocomotives: async (routeId?: string): Promise<LocomotiveRecord[]> => {
if (routeId) {
const response = await client.get<LocomotiveRecord[]>(
URL_CONSTANTS.TRAIN_SCHEDULING.AVAILABLE_LOCOMOTIVES,
{ params: { routeId } },
);
return unwrap(response.data);
}
const response = await client.get<LocomotiveRecord[]>(URL_CONSTANTS.LOCOMOTIVES.BASE, {
params: { status: 'AVAILABLE' },
});

View File

@@ -15,8 +15,25 @@ export interface Wagon {
notes?: string;
}
export interface WagonListFilters {
search?: string;
status?: Freight.WagonStatus;
readiness?: Freight.WagonReadiness;
wagonTypeId?: string;
trainId?: string;
}
export const wagonService = {
getAll: () => apiClient.get<Wagon[]>('/wagons'),
getAll: (filters: WagonListFilters = {}) => {
const params = new URLSearchParams();
if (filters.search?.trim()) params.set('search', filters.search.trim());
if (filters.status) params.set('status', filters.status);
if (filters.readiness) params.set('readiness', filters.readiness);
if (filters.wagonTypeId) params.set('wagonTypeId', filters.wagonTypeId);
if (filters.trainId) params.set('trainId', filters.trainId);
const qs = params.toString();
return apiClient.get<Wagon[]>(`/wagons${qs ? `?${qs}` : ''}`);
},
getById: (id: string) => apiClient.get<Wagon>(`/wagons/${id}`),
getByTrain: (trainId: string) => apiClient.get<Wagon[]>(`/wagons?trainId=${trainId}`),
assignToTrain: (wagonId: string, trainId: string, sequenceNumber?: number) =>