feat: enhance train scheduling and contract management features

- 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.
This commit is contained in:
Marshal
2026-08-25 21:44:21 +00:00
parent d5a5085d6d
commit b926a3116e
67 changed files with 2998 additions and 255 deletions

View File

@@ -4,6 +4,7 @@ import {
IsArray,
IsBoolean,
IsDateString,
IsEmail,
IsIn,
IsInt,
IsNumber,
@@ -11,6 +12,7 @@ import {
IsString,
IsUUID,
Matches,
MaxLength,
Min,
ValidateNested,
} from 'class-validator';
@@ -208,6 +210,19 @@ export class CreateBookingUnderContractDto {
@Type(() => CreateBulkLineDto)
bulkLines?: CreateBulkLineDto[];
@ApiPropertyOptional({
minimum: 1,
description:
'NUMBER_OF_WAGONS bulk cargo only: how many wagons the shipment needs. ' +
'The weight spreads evenly across them; a PER_WAGON rate bills this count. ' +
'Required when the cargo type is measured by wagons, ignored otherwise.',
})
@IsOptional()
@IsInt()
@Min(1)
@Transform(({ value }) => (value == null || value === '' ? undefined : Number(value)))
requestedWagons?: number;
@ApiPropertyOptional({
description: 'What the containers carry — captured per booking (container freight).',
})
@@ -215,6 +230,29 @@ export class CreateBookingUnderContractDto {
@IsString()
cargoFreeText?: string;
@ApiPropertyOptional({
maxLength: 200,
description:
'Customs clearing agent name. Required at completion of a without-customs ' +
'import/export booking (the service enforces it); ignored on customs contracts.',
})
@IsOptional()
@IsString()
@MaxLength(200)
customsClearingAgent?: string;
@ApiPropertyOptional({ maxLength: 200, description: 'Customs clearing agent email.' })
@IsOptional()
@IsEmail()
@MaxLength(200)
customsClearingAgentEmail?: string;
@ApiPropertyOptional({ maxLength: 50, description: 'Customs clearing agent phone number.' })
@IsOptional()
@IsString()
@MaxLength(50)
customsClearingAgentPhone?: string;
@ApiPropertyOptional()
@IsOptional()
@IsString()