mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 05:18:11 +00:00
feat: add wagon usage computation and maintenance logging features
- Implemented utility to calculate wagon usage metrics for train schedules. - Created for sending wagons to maintenance with optional notes. - Added unit tests for train builder maintenance functionalities, including formatting train run labels and building maintenance notes. - Developed component for merging train schedules with detailed previews and reasons for merging. - Introduced component for selecting wagons with search functionality and selection limits. - Created for displaying and filtering audit logs, including detailed views of individual log entries. - Added for handling API interactions related to audit logs, including fetching logs and entity types.
This commit is contained in:
@@ -1267,18 +1267,18 @@ export class BookingsController {
|
||||
|
||||
@Post(':id/clearance/delivery-order')
|
||||
@BookingStaff(FREIGHT_PERMS.contracts.clearanceDjActions)
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
@UseInterceptors(AnyFilesInterceptor())
|
||||
@ApiConsumes('multipart/form-data')
|
||||
async uploadBookingDeliveryOrder(
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@UploadedFiles() files: Express.Multer.File[],
|
||||
@Body('vesselArrivalDate') vesselArrivalDate: string | undefined,
|
||||
@Body('doCollectedDate') doCollectedDate: string | undefined,
|
||||
@CurrentUser() user: TCurrentUser,
|
||||
) {
|
||||
const booking = await this.bookingClearanceService.uploadDeliveryOrder(
|
||||
id,
|
||||
file,
|
||||
files ?? [],
|
||||
resolveAuthUserId(user),
|
||||
{ vesselArrivalDate, doCollectedDate },
|
||||
);
|
||||
@@ -1287,17 +1287,17 @@ export class BookingsController {
|
||||
|
||||
@Post(':id/clearance/release-order')
|
||||
@BookingStaff(FREIGHT_PERMS.contracts.clearanceDjActions)
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
@UseInterceptors(AnyFilesInterceptor())
|
||||
@ApiConsumes('multipart/form-data')
|
||||
async uploadBookingReleaseOrder(
|
||||
@Param('id', ParseUUIDPipe) id: string,
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@UploadedFiles() files: Express.Multer.File[],
|
||||
@Body('vesselDepartureDate') vesselDepartureDate: string,
|
||||
@CurrentUser() user: TCurrentUser,
|
||||
) {
|
||||
const result = await this.bookingClearanceService.uploadReleaseOrder(
|
||||
id,
|
||||
file,
|
||||
files ?? [],
|
||||
vesselDepartureDate,
|
||||
resolveAuthUserId(user),
|
||||
);
|
||||
|
||||
@@ -59,9 +59,11 @@ import { PdfRenderService } from '../billing/documents/pdf-render.service';
|
||||
import { buildTabularFallbackPdf } from '../billing/documents/styled-pdf.util';
|
||||
|
||||
/**
|
||||
* The allocated train as the backoffice booking detail page needs it: which
|
||||
* train, its window phase, and both the planned and actual clock. Attached by
|
||||
* `findById` only when the booking is on a schedule.
|
||||
* The train as the backoffice booking detail page needs it: which train, its
|
||||
* window phase, and both the planned and actual clock. Attached by `findById`
|
||||
* for the allocated train (`train_schedule_id`) or, before the batch engine has
|
||||
* allocated one, the train the customer picked at day-commit
|
||||
* (`requested_train_schedule_id`) — see `isRequested`.
|
||||
*/
|
||||
export interface TrainScheduleSummary {
|
||||
id: string;
|
||||
@@ -74,6 +76,12 @@ export interface TrainScheduleSummary {
|
||||
actualArrivalAt: string | null;
|
||||
windowPhase: string | null;
|
||||
paymentPhaseEndsAt: string | null;
|
||||
/**
|
||||
* True when this is the customer's requested train rather than a confirmed
|
||||
* allocation — the state staff review at OPERATION_REQUEST_PENDING, before
|
||||
* accepting the operation puts the booking into the batch pool.
|
||||
*/
|
||||
isRequested: boolean;
|
||||
}
|
||||
|
||||
/** Paginated booking list: flat `total` (backoffice) + `meta` block (portal). */
|
||||
@@ -2132,15 +2140,23 @@ export class BookingsService {
|
||||
// Surface the assigned train's operational status so the portal stepper
|
||||
// can show the Arrival stage: the booking status stays IN_TRANSIT from
|
||||
// dispatch until delivery, so arrival is only knowable from the schedule.
|
||||
if (booking.trainScheduleId) {
|
||||
// The allocated train, or — before the batch engine has allocated one — the
|
||||
// train the customer picked at day-commit. Staff reviewing an operation
|
||||
// request (OPERATION_REQUEST_PENDING) must see which train they are
|
||||
// accepting onto before they approve, and at that point only the requested
|
||||
// id is set.
|
||||
const summarySourceId = booking.trainScheduleId ?? booking.requestedTrainScheduleId;
|
||||
if (summarySourceId) {
|
||||
const schedule = await this.dataSource
|
||||
.getRepository(TrainSchedule)
|
||||
.findOne({ where: { id: booking.trainScheduleId } });
|
||||
.findOne({ where: { id: summarySourceId } });
|
||||
// trainScheduleStatus drives the portal's Arrival stage, so it stays tied
|
||||
// to a real allocation — a merely requested train has not departed.
|
||||
(booking as Booking & { trainScheduleStatus?: string | null }).trainScheduleStatus =
|
||||
schedule?.status ?? null;
|
||||
// Backoffice staff view: the allocated train's identity and clock, so the
|
||||
// detail page can state which train the booking rides and when it runs
|
||||
// without a second round-trip to the schedules API.
|
||||
booking.trainScheduleId ? (schedule?.status ?? null) : null;
|
||||
// Backoffice staff view: the train's identity and clock, so the detail
|
||||
// page can state which train the booking rides and when it runs without a
|
||||
// second round-trip to the schedules API.
|
||||
(
|
||||
booking as Booking & { trainScheduleSummary?: TrainScheduleSummary | null }
|
||||
).trainScheduleSummary = schedule
|
||||
@@ -2155,6 +2171,7 @@ export class BookingsService {
|
||||
actualArrivalAt: schedule.actualArrivalAt?.toISOString() ?? null,
|
||||
windowPhase: schedule.windowPhase ?? null,
|
||||
paymentPhaseEndsAt: schedule.paymentPhaseEndsAt?.toISOString() ?? null,
|
||||
isRequested: !booking.trainScheduleId,
|
||||
}
|
||||
: null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user