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

@@ -18,14 +18,19 @@ import {
TrainSchedulingCreate,
TrainSchedulingEditTrainNumber,
TrainSchedulingLoad,
TrainSchedulingLoadingEnd,
TrainSchedulingLoadingStart,
TrainSchedulingReschedule,
TrainSchedulingUnload,
TrainSchedulingUnloadingEnd,
TrainSchedulingUnloadingStart,
TrainSchedulingRulesManage,
TrainSchedulingUpdate,
TrainSchedulingView,
} from "../../../common/booking-guards";
import { FREIGHT_PERMS } from "../../../seed/freight-permissions.registry";
import { AcceptIntercityBookingsDto } from "../dto/accept-intercity-bookings.dto";
import { StationWorkDto } from "../dto/station-work.dto";
import { AssignBookingsDto } from "../dto/assign-bookings.dto";
import { AssignUnassignedBookingDto } from "../dto/assign-unassigned-booking.dto";
import { SwitchGovernmentBookingDto } from "../dto/switch-government-booking.dto";
@@ -614,6 +619,68 @@ export class TrainSchedulingController {
return this.bookingJourneyService.listYardWork(id);
}
@Post("schedules/:id/stations/:yardId/loading/start")
@TrainSchedulingLoadingStart()
@ApiOperation({
summary:
"Start (or correct, via `at`) this station's loading time window — required before bookings can be loaded there",
})
startStationLoading(
@Param("id", ParseUUIDPipe) id: string,
@Param("yardId", ParseUUIDPipe) yardId: string,
@Body() dto: StationWorkDto,
@CurrentUser() user: AuthUserPayload,
) {
return this.bookingJourneyService.recordStationWork(
id, yardId, "loading", "start", dto.at, resolveAuthUserId(user),
);
}
@Post("schedules/:id/stations/:yardId/loading/end")
@TrainSchedulingLoadingEnd()
@ApiOperation({ summary: "End (or correct, via `at`) this station's loading time window" })
endStationLoading(
@Param("id", ParseUUIDPipe) id: string,
@Param("yardId", ParseUUIDPipe) yardId: string,
@Body() dto: StationWorkDto,
@CurrentUser() user: AuthUserPayload,
) {
return this.bookingJourneyService.recordStationWork(
id, yardId, "loading", "end", dto.at, resolveAuthUserId(user),
);
}
@Post("schedules/:id/stations/:yardId/unloading/start")
@TrainSchedulingUnloadingStart()
@ApiOperation({
summary:
"Start (or correct, via `at`) this station's unloading time window — required before bookings can be unloaded there",
})
startStationUnloading(
@Param("id", ParseUUIDPipe) id: string,
@Param("yardId", ParseUUIDPipe) yardId: string,
@Body() dto: StationWorkDto,
@CurrentUser() user: AuthUserPayload,
) {
return this.bookingJourneyService.recordStationWork(
id, yardId, "unloading", "start", dto.at, resolveAuthUserId(user),
);
}
@Post("schedules/:id/stations/:yardId/unloading/end")
@TrainSchedulingUnloadingEnd()
@ApiOperation({ summary: "End (or correct, via `at`) this station's unloading time window" })
endStationUnloading(
@Param("id", ParseUUIDPipe) id: string,
@Param("yardId", ParseUUIDPipe) yardId: string,
@Body() dto: StationWorkDto,
@CurrentUser() user: AuthUserPayload,
) {
return this.bookingJourneyService.recordStationWork(
id, yardId, "unloading", "end", dto.at, resolveAuthUserId(user),
);
}
@Post("schedules/:id/bookings/:bookingId/load")
@TrainSchedulingLoad()
@ApiOperation({