mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
- Added StationWorkControls to manage loading/unloading phases in TrainScheduleV2DetailPage. - Implemented API endpoints for recording station work and managing wagon detach requests. - Updated contract templates to include Ethiopian customs handling options. - Enhanced shipment forms to collect customs clearing agent details for without-customs bookings. - Introduced NUMBER_OF_WAGONS as a unit of measure for bulk cargo, allowing customers to specify wagon counts. - Improved validation for customs clearing agent information in shipment forms. - Updated various components and services to accommodate new features and ensure data integrity.
150 lines
4.1 KiB
TypeScript
150 lines
4.1 KiB
TypeScript
import { api as client } from "../auth/http";
|
|
|
|
const BASE = "/contract-templates";
|
|
|
|
export const BULK_TEMPLATE_DIRECTIONS = ["IMPORT", "EXPORT", "INTERCITY"] as const;
|
|
|
|
export type BulkTemplateDirection = (typeof BULK_TEMPLATE_DIRECTIONS)[number];
|
|
|
|
export interface ContractTemplateArticle {
|
|
id: string;
|
|
title: string;
|
|
body: string;
|
|
order: number;
|
|
}
|
|
|
|
export interface ContractTemplate {
|
|
id: string;
|
|
// System container templates use the fixed DIRECTION_CONTAINER(_CUSTOMS)
|
|
// codes; staff-created bulk templates get generated BULK_<cargo>_* codes.
|
|
code: string;
|
|
name: string;
|
|
description?: string | null;
|
|
documentTitle: string;
|
|
whereasClauses: string[];
|
|
articles: ContractTemplateArticle[];
|
|
isActive: boolean;
|
|
/** Bulk templates only: the cargo type this template is written for. */
|
|
cargoTypeId?: string | null;
|
|
cargoType?: { id: string; cargoTypeName: string } | null;
|
|
/** Bulk templates only: IMPORT, EXPORT or INTERCITY. */
|
|
tradeDirection?: BulkTemplateDirection | null;
|
|
/**
|
|
* Bulk templates only: whether this is the with-customs-clearing variant.
|
|
* Null for intercity — domestic movements have no customs leg.
|
|
*/
|
|
withCustoms?: boolean | null;
|
|
/**
|
|
* Bulk templates only: the with-customs variant restricted to Ethiopian-side
|
|
* clearing (Djibouti stays with the client).
|
|
*/
|
|
ethiopianCustomsOnly?: boolean | null;
|
|
/** The seeded container templates — cannot be deleted. */
|
|
isSystem: boolean;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface CreateContractTemplatePayload {
|
|
cargoTypeId: string;
|
|
tradeDirection: BulkTemplateDirection;
|
|
/** Omitted for INTERCITY — the API rejects the flag there. */
|
|
withCustoms?: boolean;
|
|
/** Ethiopian-side clearing only; requires withCustoms: true. */
|
|
ethiopianCustomsOnly?: boolean;
|
|
name?: string;
|
|
description?: string;
|
|
}
|
|
|
|
export interface UpdateContractTemplatePayload {
|
|
name?: string;
|
|
description?: string;
|
|
documentTitle?: string;
|
|
whereasClauses?: string[];
|
|
isActive?: boolean;
|
|
}
|
|
|
|
export interface ArticlePayload {
|
|
title: string;
|
|
body: string;
|
|
position?: number;
|
|
}
|
|
|
|
export const contractTemplatesService = {
|
|
async list(): Promise<ContractTemplate[]> {
|
|
const { data } = await client.get<ContractTemplate[]>(BASE);
|
|
return data;
|
|
},
|
|
|
|
async create(payload: CreateContractTemplatePayload): Promise<ContractTemplate> {
|
|
const { data } = await client.post<ContractTemplate>(BASE, payload);
|
|
return data;
|
|
},
|
|
|
|
async remove(code: string): Promise<void> {
|
|
await client.delete(`${BASE}/${code}`);
|
|
},
|
|
|
|
async getByCode(code: string): Promise<ContractTemplate> {
|
|
const { data } = await client.get<ContractTemplate>(`${BASE}/${code}`);
|
|
return data;
|
|
},
|
|
|
|
async update(
|
|
code: string,
|
|
payload: UpdateContractTemplatePayload,
|
|
): Promise<ContractTemplate> {
|
|
const { data } = await client.patch<ContractTemplate>(
|
|
`${BASE}/${code}`,
|
|
payload,
|
|
);
|
|
return data;
|
|
},
|
|
|
|
async preview(code: string): Promise<{ html: string }> {
|
|
const { data } = await client.post<{ html: string }>(
|
|
`${BASE}/${code}/preview`,
|
|
{},
|
|
);
|
|
return data;
|
|
},
|
|
|
|
async addArticle(code: string, payload: ArticlePayload): Promise<ContractTemplate> {
|
|
const { data } = await client.post<ContractTemplate>(
|
|
`${BASE}/${code}/articles`,
|
|
payload,
|
|
);
|
|
return data;
|
|
},
|
|
|
|
async updateArticle(
|
|
code: string,
|
|
articleId: string,
|
|
payload: Partial<ArticlePayload>,
|
|
): Promise<ContractTemplate> {
|
|
const { data } = await client.patch<ContractTemplate>(
|
|
`${BASE}/${code}/articles/${articleId}`,
|
|
payload,
|
|
);
|
|
return data;
|
|
},
|
|
|
|
async removeArticle(code: string, articleId: string): Promise<ContractTemplate> {
|
|
const { data } = await client.delete<ContractTemplate>(
|
|
`${BASE}/${code}/articles/${articleId}`,
|
|
);
|
|
return data;
|
|
},
|
|
|
|
async replaceArticles(
|
|
code: string,
|
|
articles: Array<{ id?: string; title: string; body: string }>,
|
|
): Promise<ContractTemplate> {
|
|
const { data } = await client.put<ContractTemplate>(
|
|
`${BASE}/${code}/articles`,
|
|
{ articles },
|
|
);
|
|
return data;
|
|
},
|
|
};
|