mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 00:45:41 +00:00
Merge remote-tracking branch 'origin/dev' into Truckdetantion
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
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
import { api as apiClient } from '../auth/http';
|
||||
|
||||
export type ComplianceType =
|
||||
| 'INSPECTION'
|
||||
| 'INSURANCE'
|
||||
| 'ROADWORTHINESS'
|
||||
| 'PERMIT'
|
||||
| 'TAX';
|
||||
|
||||
export type ComplianceStatus = 'VALID' | 'EXPIRING' | 'EXPIRED';
|
||||
|
||||
export type AlertSeverity = 'OVERDUE' | 'DUE_SOON';
|
||||
|
||||
export interface ComplianceRecord {
|
||||
id: string;
|
||||
vehicleId: string;
|
||||
vehicle?: {
|
||||
id: string;
|
||||
plateNumber?: string | null;
|
||||
manufacturer?: string | null;
|
||||
model?: string | null;
|
||||
};
|
||||
type: ComplianceType;
|
||||
documentNumber?: string | null;
|
||||
issuedDate?: string | null;
|
||||
expiryDate: string;
|
||||
status: ComplianceStatus;
|
||||
notes?: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ComplianceAlert {
|
||||
vehicleId: string;
|
||||
vehiclePlate?: string;
|
||||
kind: string;
|
||||
label: string;
|
||||
expiryDate: string;
|
||||
daysUntil: number;
|
||||
severity: AlertSeverity;
|
||||
}
|
||||
|
||||
export interface ComplianceListFilters {
|
||||
vehicleId?: string;
|
||||
type?: ComplianceType;
|
||||
}
|
||||
|
||||
export interface SaveCompliancePayload {
|
||||
vehicleId: string;
|
||||
type: ComplianceType;
|
||||
documentNumber?: string;
|
||||
issuedDate?: string;
|
||||
expiryDate: string;
|
||||
status?: ComplianceStatus;
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
export const complianceService = {
|
||||
list: (filters: ComplianceListFilters = {}) => {
|
||||
const params = new URLSearchParams();
|
||||
if (filters.vehicleId) params.set('vehicleId', filters.vehicleId);
|
||||
if (filters.type) params.set('type', filters.type);
|
||||
const qs = params.toString();
|
||||
return apiClient.get<ComplianceRecord[]>(`/compliance${qs ? `?${qs}` : ''}`);
|
||||
},
|
||||
getAlerts: () => apiClient.get<ComplianceAlert[]>('/compliance/alerts'),
|
||||
getById: (id: string) => apiClient.get<ComplianceRecord>(`/compliance/${id}`),
|
||||
create: (data: SaveCompliancePayload) =>
|
||||
apiClient.post<ComplianceRecord>('/compliance', data),
|
||||
update: (id: string, data: Partial<SaveCompliancePayload>) =>
|
||||
apiClient.patch<ComplianceRecord>(`/compliance/${id}`, data),
|
||||
remove: (id: string) => apiClient.delete(`/compliance/${id}`),
|
||||
};
|
||||
@@ -39,6 +39,17 @@ export type SaveDriverPayload = Omit<
|
||||
'id' | 'createdAt' | 'updatedAt' | 'totalTrips' | 'rating'
|
||||
>;
|
||||
|
||||
/** A stored driver document (code "driver_docs"). */
|
||||
export interface DriverDocument {
|
||||
id: string;
|
||||
name: string;
|
||||
url: string;
|
||||
size: number;
|
||||
mimeType: string;
|
||||
code: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export const driversService = {
|
||||
getAll: (filters: DriverListFilters = {}) => {
|
||||
const params = new URLSearchParams();
|
||||
@@ -59,4 +70,18 @@ export const driversService = {
|
||||
update: (id: string, data: Partial<SaveDriverPayload>) =>
|
||||
apiClient.patch(URL_CONSTANTS.DRIVERS.BY_ID(id), data),
|
||||
delete: (id: string) => apiClient.delete(URL_CONSTANTS.DRIVERS.BY_ID(id)),
|
||||
|
||||
// ── Driver documents (upload area code "driver_docs") ──
|
||||
listDocuments: (id: string) =>
|
||||
apiClient.get<DriverDocument[]>(`${URL_CONSTANTS.DRIVERS.BY_ID(id)}/documents`),
|
||||
uploadDocuments: (id: string, files: File[]) => {
|
||||
const form = new FormData();
|
||||
for (const f of files) form.append('files', f);
|
||||
return apiClient.post<DriverDocument[]>(
|
||||
`${URL_CONSTANTS.DRIVERS.BY_ID(id)}/documents`,
|
||||
form,
|
||||
);
|
||||
},
|
||||
removeDocument: (id: string, fileId: string) =>
|
||||
apiClient.delete(`${URL_CONSTANTS.DRIVERS.BY_ID(id)}/documents/${fileId}`),
|
||||
};
|
||||
|
||||
@@ -47,6 +47,8 @@ export interface FirstMileVehicle {
|
||||
trailerPlateNo?: string | null;
|
||||
assignedDriverId?: string | null;
|
||||
assignedDriverName?: string | null;
|
||||
pricePerKm?: number | string | null;
|
||||
currency?: string | null;
|
||||
}
|
||||
|
||||
export interface FirstMileRecord {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { api } from "@/auth/http";
|
||||
|
||||
export interface GpsDevice {
|
||||
id: string;
|
||||
imei: string;
|
||||
name?: string | null;
|
||||
vehicleId?: string | null;
|
||||
vehicle?: {
|
||||
id: string;
|
||||
plateNumber?: string;
|
||||
code?: string | null;
|
||||
manufacturer?: string;
|
||||
model?: string;
|
||||
} | null;
|
||||
status: string;
|
||||
online: boolean;
|
||||
lastSeenAt?: string | null;
|
||||
lastLat?: number | string | null;
|
||||
lastLng?: number | string | null;
|
||||
lastSpeed?: number | string | null;
|
||||
lastCourse?: number | null;
|
||||
lastFixAt?: string | null;
|
||||
voltageLevel?: number | null;
|
||||
gsmLevel?: number | null;
|
||||
}
|
||||
|
||||
export interface GpsPosition {
|
||||
id: string;
|
||||
lat: number | string;
|
||||
lng: number | string;
|
||||
speed: number | string;
|
||||
course: number;
|
||||
satellites: number;
|
||||
gpsTime: string;
|
||||
alarm: number;
|
||||
}
|
||||
|
||||
export const gpsTrackingService = {
|
||||
latest: () => api.get<GpsDevice[]>("/gps/positions/latest"),
|
||||
listDevices: () => api.get<GpsDevice[]>("/gps/devices"),
|
||||
history: (vehicleId: string, limit = 200) =>
|
||||
api.get<GpsPosition[]>(`/gps/positions/${vehicleId}/history?limit=${limit}`),
|
||||
register: (data: { imei: string; name?: string; vehicleId?: string | null }) =>
|
||||
api.post<GpsDevice>("/gps/devices", data),
|
||||
update: (id: string, data: { name?: string; vehicleId?: string | null }) =>
|
||||
api.patch<GpsDevice>(`/gps/devices/${id}`, data),
|
||||
remove: (id: string) => api.delete<void>(`/gps/devices/${id}`),
|
||||
};
|
||||
@@ -0,0 +1,87 @@
|
||||
import { api } from '@/auth/http';
|
||||
|
||||
export type IncidentType = 'ACCIDENT' | 'BREAKDOWN' | 'TRAFFIC_VIOLATION' | 'THEFT' | 'OTHER';
|
||||
export type IncidentSeverity = 'MINOR' | 'MODERATE' | 'MAJOR' | 'CRITICAL';
|
||||
export type IncidentStatus =
|
||||
| 'REPORTED'
|
||||
| 'UNDER_REVIEW'
|
||||
| 'CLAIM_FILED'
|
||||
| 'RESOLVED'
|
||||
| 'CLOSED';
|
||||
|
||||
export interface Incident {
|
||||
id: string;
|
||||
vehicleId?: string | null;
|
||||
driverId?: string | null;
|
||||
bookingId?: string | null;
|
||||
type: IncidentType;
|
||||
severity: IncidentSeverity;
|
||||
occurredAt: string;
|
||||
location?: string | null;
|
||||
description: string;
|
||||
/** API sends numeric as string; coerce with Number. */
|
||||
damageEstimate?: number | string | null;
|
||||
status: IncidentStatus;
|
||||
insuranceClaimNumber?: string | null;
|
||||
reportedBy?: string | null;
|
||||
vehicle?: {
|
||||
id: string;
|
||||
plateNumber?: string | null;
|
||||
registrationNumber?: string | null;
|
||||
} | null;
|
||||
driver?: {
|
||||
id: string;
|
||||
firstName?: string | null;
|
||||
lastName?: string | null;
|
||||
} | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface IncidentFilters {
|
||||
vehicleId?: string;
|
||||
driverId?: string;
|
||||
status?: IncidentStatus;
|
||||
type?: IncidentType;
|
||||
}
|
||||
|
||||
export interface DriverIncidentStats {
|
||||
total: number;
|
||||
byType: Record<string, number>;
|
||||
lastIncidentAt: string | null;
|
||||
}
|
||||
|
||||
export interface SaveIncidentPayload {
|
||||
vehicleId?: string;
|
||||
driverId?: string;
|
||||
bookingId?: string;
|
||||
type: IncidentType;
|
||||
severity: IncidentSeverity;
|
||||
occurredAt: string;
|
||||
location?: string;
|
||||
description: string;
|
||||
damageEstimate?: number;
|
||||
status?: IncidentStatus;
|
||||
insuranceClaimNumber?: string;
|
||||
reportedBy?: string;
|
||||
}
|
||||
|
||||
export const incidentsService = {
|
||||
getAll: (filters: IncidentFilters = {}) => {
|
||||
const params = new URLSearchParams();
|
||||
if (filters.vehicleId) params.set('vehicleId', filters.vehicleId);
|
||||
if (filters.driverId) params.set('driverId', filters.driverId);
|
||||
if (filters.status) params.set('status', filters.status);
|
||||
if (filters.type) params.set('type', filters.type);
|
||||
const qs = params.toString();
|
||||
return api.get<Incident[]>(`/incidents${qs ? `?${qs}` : ''}`);
|
||||
},
|
||||
getByDriver: (driverId: string) => api.get<Incident[]>(`/incidents/driver/${driverId}`),
|
||||
getDriverStats: (driverId: string) =>
|
||||
api.get<DriverIncidentStats>(`/incidents/driver/${driverId}/stats`),
|
||||
getById: (id: string) => api.get<Incident>(`/incidents/${id}`),
|
||||
create: (data: SaveIncidentPayload) => api.post<Incident>('/incidents', data),
|
||||
update: (id: string, data: Partial<SaveIncidentPayload>) =>
|
||||
api.patch<Incident>(`/incidents/${id}`, data),
|
||||
delete: (id: string) => api.delete(`/incidents/${id}`),
|
||||
};
|
||||
@@ -48,6 +48,8 @@ export interface LastMileVehicle {
|
||||
trailerPlateNo?: string | null;
|
||||
assignedDriverId?: string | null;
|
||||
assignedDriverName?: string | null;
|
||||
pricePerKm?: number | string | null;
|
||||
currency?: string | null;
|
||||
}
|
||||
|
||||
export interface LastMileRecord {
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
import { api } from '@/auth/http';
|
||||
|
||||
export type WorkOrderStatus = 'OPEN' | 'IN_PROGRESS' | 'COMPLETED' | 'CANCELLED';
|
||||
export type WorkOrderPriority = 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT';
|
||||
|
||||
export interface WorkOrder {
|
||||
id: string;
|
||||
vehicleId: string;
|
||||
title: string;
|
||||
description?: string | null;
|
||||
status: WorkOrderStatus;
|
||||
priority: WorkOrderPriority;
|
||||
assignedTo?: string | null;
|
||||
openedAt: string;
|
||||
closedAt?: string | null;
|
||||
/** API sends numeric as string; coerce with Number. */
|
||||
laborCost?: number | string | null;
|
||||
partsCost?: number | string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface SaveWorkOrderPayload {
|
||||
vehicleId: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
status?: WorkOrderStatus;
|
||||
priority?: WorkOrderPriority;
|
||||
assignedTo?: string;
|
||||
openedAt?: string;
|
||||
closedAt?: string;
|
||||
laborCost?: number;
|
||||
partsCost?: number;
|
||||
}
|
||||
|
||||
export interface WorkOrderFilters {
|
||||
vehicleId?: string;
|
||||
status?: WorkOrderStatus;
|
||||
}
|
||||
|
||||
export interface Part {
|
||||
id: string;
|
||||
name: string;
|
||||
sku?: string | null;
|
||||
category?: string | null;
|
||||
quantityInStock: number;
|
||||
reorderLevel: number;
|
||||
/** API sends numeric as string; coerce with Number. */
|
||||
unitCost?: number | string | null;
|
||||
location?: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface SavePartPayload {
|
||||
name: string;
|
||||
sku?: string;
|
||||
category?: string;
|
||||
quantityInStock?: number;
|
||||
reorderLevel?: number;
|
||||
unitCost?: number;
|
||||
location?: string;
|
||||
}
|
||||
|
||||
export interface PartFilters {
|
||||
category?: string;
|
||||
lowStock?: boolean;
|
||||
}
|
||||
|
||||
export interface Warranty {
|
||||
id: string;
|
||||
vehicleId: string;
|
||||
component: string;
|
||||
provider?: string | null;
|
||||
startDate?: string | null;
|
||||
expiryDate: string;
|
||||
coverageNotes?: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface SaveWarrantyPayload {
|
||||
vehicleId: string;
|
||||
component: string;
|
||||
provider?: string;
|
||||
startDate?: string;
|
||||
expiryDate: string;
|
||||
coverageNotes?: string;
|
||||
}
|
||||
|
||||
export const maintenanceDepthService = {
|
||||
// Work Orders
|
||||
getWorkOrders: (filters: WorkOrderFilters = {}) => {
|
||||
const params = new URLSearchParams();
|
||||
if (filters.vehicleId) params.set('vehicleId', filters.vehicleId);
|
||||
if (filters.status) params.set('status', filters.status);
|
||||
const qs = params.toString();
|
||||
return api.get<WorkOrder[]>(`/maintenance/work-orders${qs ? `?${qs}` : ''}`);
|
||||
},
|
||||
getWorkOrder: (id: string) => api.get<WorkOrder>(`/maintenance/work-orders/${id}`),
|
||||
createWorkOrder: (data: SaveWorkOrderPayload) =>
|
||||
api.post<WorkOrder>('/maintenance/work-orders', data),
|
||||
updateWorkOrder: (id: string, data: Partial<SaveWorkOrderPayload>) =>
|
||||
api.patch<WorkOrder>(`/maintenance/work-orders/${id}`, data),
|
||||
deleteWorkOrder: (id: string) => api.delete(`/maintenance/work-orders/${id}`),
|
||||
|
||||
// Parts / Tires
|
||||
getParts: (filters: PartFilters = {}) => {
|
||||
const params = new URLSearchParams();
|
||||
if (filters.category) params.set('category', filters.category);
|
||||
if (filters.lowStock) params.set('lowStock', 'true');
|
||||
const qs = params.toString();
|
||||
return api.get<Part[]>(`/maintenance/parts${qs ? `?${qs}` : ''}`);
|
||||
},
|
||||
createPart: (data: SavePartPayload) => api.post<Part>('/maintenance/parts', data),
|
||||
updatePart: (id: string, data: Partial<SavePartPayload>) =>
|
||||
api.patch<Part>(`/maintenance/parts/${id}`, data),
|
||||
deletePart: (id: string) => api.delete(`/maintenance/parts/${id}`),
|
||||
|
||||
// Warranties
|
||||
getWarranties: (vehicleId?: string) => {
|
||||
const params = new URLSearchParams();
|
||||
if (vehicleId) params.set('vehicleId', vehicleId);
|
||||
const qs = params.toString();
|
||||
return api.get<Warranty[]>(`/maintenance/warranties${qs ? `?${qs}` : ''}`);
|
||||
},
|
||||
createWarranty: (data: SaveWarrantyPayload) =>
|
||||
api.post<Warranty>('/maintenance/warranties', data),
|
||||
deleteWarranty: (id: string) => api.delete(`/maintenance/warranties/${id}`),
|
||||
};
|
||||
@@ -0,0 +1,138 @@
|
||||
import { api } from "@/auth/http";
|
||||
|
||||
export type VendorType = "DEALER" | "LEASING" | "PARTS" | "SERVICE" | "OTHER";
|
||||
export type AcquisitionType = "PURCHASE" | "LEASE" | "RENTAL";
|
||||
export type AcquisitionStatus = "ACTIVE" | "LEASE_EXPIRING" | "DISPOSED";
|
||||
export type DisposalMethod = "SALE" | "SCRAP" | "RETURN_LEASE" | "TRADE_IN";
|
||||
|
||||
export interface Vendor {
|
||||
id: string;
|
||||
name: string;
|
||||
type?: VendorType | null;
|
||||
contactPerson?: string | null;
|
||||
phone?: string | null;
|
||||
email?: string | null;
|
||||
address?: string | null;
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface AssetAcquisition {
|
||||
id: string;
|
||||
vehicleId?: string | null;
|
||||
vendorId?: string | null;
|
||||
acquisitionType: AcquisitionType;
|
||||
acquisitionDate: string;
|
||||
cost?: number | null;
|
||||
usefulLifeMonths?: number | null;
|
||||
salvageValue?: number | null;
|
||||
leaseStart?: string | null;
|
||||
leaseEnd?: string | null;
|
||||
monthlyPayment?: number | null;
|
||||
status: AcquisitionStatus;
|
||||
notes?: string | null;
|
||||
vehicle?: {
|
||||
id: string;
|
||||
plateNumber?: string | null;
|
||||
registrationNumber?: string | null;
|
||||
manufacturer?: string | null;
|
||||
model?: string | null;
|
||||
} | null;
|
||||
vendor?: Vendor | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface AssetDisposal {
|
||||
id: string;
|
||||
vehicleId: string;
|
||||
disposalDate: string;
|
||||
method: DisposalMethod;
|
||||
salePrice?: number | null;
|
||||
buyer?: string | null;
|
||||
notes?: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface DepreciationResult {
|
||||
method: "STRAIGHT_LINE";
|
||||
cost: number;
|
||||
salvageValue: number;
|
||||
usefulLifeMonths: number;
|
||||
monthsElapsed: number;
|
||||
monthlyDepreciation: number;
|
||||
bookValue: number;
|
||||
}
|
||||
|
||||
export interface LifecycleResult {
|
||||
vehicleId: string;
|
||||
acquisition: AssetAcquisition | null;
|
||||
disposal: AssetDisposal | null;
|
||||
depreciation: DepreciationResult | null;
|
||||
}
|
||||
|
||||
export interface CreateVendorPayload {
|
||||
name: string;
|
||||
type?: VendorType;
|
||||
contactPerson?: string;
|
||||
phone?: string;
|
||||
email?: string;
|
||||
address?: string;
|
||||
isActive?: boolean;
|
||||
}
|
||||
|
||||
export interface CreateAcquisitionPayload {
|
||||
vehicleId?: string;
|
||||
vendorId?: string;
|
||||
acquisitionType: AcquisitionType;
|
||||
acquisitionDate: string;
|
||||
cost?: number;
|
||||
usefulLifeMonths?: number;
|
||||
salvageValue?: number;
|
||||
leaseStart?: string;
|
||||
leaseEnd?: string;
|
||||
monthlyPayment?: number;
|
||||
status?: AcquisitionStatus;
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
export interface CreateDisposalPayload {
|
||||
vehicleId: string;
|
||||
disposalDate: string;
|
||||
method: DisposalMethod;
|
||||
salePrice?: number;
|
||||
buyer?: string;
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
export const procurementService = {
|
||||
// Vendors
|
||||
listVendors: () => api.get<Vendor[]>("/procurement/vendors"),
|
||||
createVendor: (data: CreateVendorPayload) => api.post("/procurement/vendors", data),
|
||||
updateVendor: (id: string, data: Partial<CreateVendorPayload>) =>
|
||||
api.patch(`/procurement/vendors/${id}`, data),
|
||||
deleteVendor: (id: string) => api.delete(`/procurement/vendors/${id}`),
|
||||
|
||||
// Acquisitions
|
||||
listAcquisitions: (vehicleId?: string) =>
|
||||
api.get<AssetAcquisition[]>(
|
||||
`/procurement/acquisitions${vehicleId ? `?vehicleId=${vehicleId}` : ""}`,
|
||||
),
|
||||
getAcquisition: (id: string) => api.get<AssetAcquisition>(`/procurement/acquisitions/${id}`),
|
||||
createAcquisition: (data: CreateAcquisitionPayload) =>
|
||||
api.post("/procurement/acquisitions", data),
|
||||
updateAcquisition: (id: string, data: Partial<CreateAcquisitionPayload>) =>
|
||||
api.patch(`/procurement/acquisitions/${id}`, data),
|
||||
deleteAcquisition: (id: string) => api.delete(`/procurement/acquisitions/${id}`),
|
||||
|
||||
// Disposals
|
||||
listDisposals: () => api.get<AssetDisposal[]>("/procurement/disposals"),
|
||||
createDisposal: (data: CreateDisposalPayload) => api.post("/procurement/disposals", data),
|
||||
deleteDisposal: (id: string) => api.delete(`/procurement/disposals/${id}`),
|
||||
|
||||
// Lifecycle
|
||||
lifecycle: (vehicleId: string) =>
|
||||
api.get<LifecycleResult>(`/procurement/lifecycle/${vehicleId}`),
|
||||
};
|
||||
@@ -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> => {
|
||||
|
||||
@@ -38,6 +38,9 @@ export interface Vehicle {
|
||||
/** Odometer-derived distances (API sends numeric strings; coerce with Number). */
|
||||
estimatedDistanceKm?: number | null;
|
||||
actualDistanceKm?: number | null;
|
||||
/** Haulage rate per km + its currency (ETB | USD). */
|
||||
pricePerKm?: number | null;
|
||||
currency?: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user