mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 12:18:11 +00:00
- Implemented a method in to permanently delete wagons without history. - Added corresponding permissions for hard delete actions in . - Updated the UI components to include purge actions, ensuring they are only available to users with the appropriate permissions. - Created modals for confirming permanent deletions in and . - Enhanced API services to handle purge requests for locomotives, wagons, and routes. - Added tests for the purge functionality in both and services to ensure proper behavior and error handling.
113 lines
3.8 KiB
TypeScript
113 lines
3.8 KiB
TypeScript
import type { PaginatedResponse } from '@edr/types';
|
|
|
|
import { api as apiClient } from '../auth/http';
|
|
|
|
import { URL_CONSTANTS } from '@/constants/URLS';
|
|
import { ruleEngineService } from './ruleEngine/ruleEngine.service';
|
|
|
|
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;
|
|
label: string;
|
|
country?: string;
|
|
}
|
|
|
|
export interface RouteMilestone {
|
|
id: string;
|
|
routeId: string;
|
|
yardId: string;
|
|
sequenceNo: number;
|
|
distanceKm?: number | null;
|
|
yard?: YardRef | null;
|
|
}
|
|
|
|
export interface RouteRecord {
|
|
id: string;
|
|
status: RouteStatus;
|
|
direction?: RouteDirection;
|
|
originYardId: string;
|
|
destinationYardId: string;
|
|
originYard?: YardRef | null;
|
|
destinationYard?: YardRef | null;
|
|
milestones?: RouteMilestone[];
|
|
}
|
|
|
|
/** Segment km are resolved server-side from configured yard distances. */
|
|
export interface SaveRoutePayload {
|
|
milestones: Array<{ yardId: string }>;
|
|
status?: RouteStatus;
|
|
}
|
|
|
|
/**
|
|
* Human-readable route label: yard names, not yard codes. Staff read
|
|
* "Addis Ababa → Dire Dawa", not "ADDIS_ABABA → DIRE_DAWA". Falls back to the
|
|
* code only when a yard has no label.
|
|
*
|
|
* When milestones are present they ARE the full ordered corridor (origin first,
|
|
* destination last), so the label shows every stop:
|
|
* "Addis Ababa → Adama → Dire Dawa".
|
|
*/
|
|
export function formatRouteLabel(route: RouteRecord): string {
|
|
const stops = [...(route.milestones ?? [])]
|
|
.sort((a, b) => a.sequenceNo - b.sequenceNo)
|
|
.map((m) => m.yard?.label ?? m.yard?.code)
|
|
.filter((name): name is string => Boolean(name));
|
|
if (stops.length >= 2) return stops.join(' → ');
|
|
|
|
const origin =
|
|
route.originYard?.label ?? route.originYard?.code ?? 'Origin';
|
|
const dest =
|
|
route.destinationYard?.label ?? route.destinationYard?.code ?? 'Destination';
|
|
return `${origin} → ${dest}`;
|
|
}
|
|
|
|
export function totalRouteDistanceKm(route: RouteRecord): number {
|
|
return (route.milestones ?? []).reduce(
|
|
(sum, m) => sum + Number(m.distanceKm ?? 0),
|
|
0,
|
|
);
|
|
}
|
|
|
|
export const ROUTE_STATUS_OPTIONS: Array<{ value: RouteStatus; label: string }> = [
|
|
{ value: 'AVAILABLE', label: 'Available' },
|
|
{ value: 'MAINTENANCE', label: 'Maintenance' },
|
|
{ value: 'DAMAGED', label: 'Damaged' },
|
|
{ value: 'STOP_WORKING', label: 'Stop working' },
|
|
];
|
|
|
|
export interface RouteListFilters {
|
|
status?: RouteStatus;
|
|
search?: string;
|
|
page?: number;
|
|
pageSize?: number;
|
|
}
|
|
|
|
export const routesService = {
|
|
getAll: (params?: { status?: RouteStatus; search?: string }) =>
|
|
apiClient.get<RouteRecord[]>(URL_CONSTANTS.ROUTES.BASE, { params }),
|
|
/** Same filters as `getAll`, server-paginated ({items, meta}). */
|
|
getPaged: (params: RouteListFilters = {}) =>
|
|
apiClient.get<PaginatedResponse<RouteRecord>>(
|
|
`${URL_CONSTANTS.ROUTES.BASE}/paged`,
|
|
{ params },
|
|
),
|
|
getById: (id: string) => apiClient.get<RouteRecord>(URL_CONSTANTS.ROUTES.BY_ID(id)),
|
|
create: (data: SaveRoutePayload) => apiClient.post(URL_CONSTANTS.ROUTES.BASE, data),
|
|
update: (id: string, data: Partial<SaveRoutePayload>) =>
|
|
apiClient.patch(URL_CONSTANTS.ROUTES.BY_ID(id), data),
|
|
deactivate: (id: string) => apiClient.delete(URL_CONSTANTS.ROUTES.BY_ID(id)),
|
|
/** Irreversible purge — the API refuses it while any train schedule uses the route. */
|
|
purge: (id: string) =>
|
|
apiClient.delete(`${URL_CONSTANTS.ROUTES.BY_ID(id)}/permanent`),
|
|
/** All active yards (page-walked — the yards list API caps pageSize at 100). */
|
|
getYards: async (): Promise<YardRef[]> => {
|
|
const rows = await ruleEngineService.listAll("yards", { isActive: true });
|
|
return rows as unknown as YardRef[];
|
|
},
|
|
};
|