mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 19:58:11 +00:00
feat(train-scheduling): implement day-level booking pool
- Added `unplaced` method in `BookingNotifierService` to log warnings for bookings that cannot be placed on any train. - Introduced `getAvailableDays` method in `TrainSchedulingService` to retrieve distinct days with open departures for a given route. - Created `AvailableDaysQueryDto` for querying available days based on origin and destination yards. - Updated `TrainSchedulingController` to expose an endpoint for available days. - Modified frontend components to support day-level booking, allowing customers to select only a day without pinning to a specific train. - Removed references to train schedules in booking forms and review steps, emphasizing day selection. - Added a database migration to create an index for efficient querying of bookings by route and day.
This commit is contained in:
@@ -87,6 +87,7 @@ import {
|
||||
DEFAULT_BULK_WAGON_LENGTH_METERS,
|
||||
DEFAULT_CONTAINER_WAGON_LENGTH_METERS,
|
||||
} from './booking-batch.constants';
|
||||
import { eatDay } from './batch-window.util';
|
||||
import { TrainCheckpointEvent } from './entities/train-checkpoint-event.entity';
|
||||
import { TrainCheckpointEventsRepository } from './train-checkpoint-events.repository';
|
||||
import { RecordCheckpointDto } from './dto/record-checkpoint.dto';
|
||||
@@ -167,12 +168,28 @@ export class TrainSchedulingService {
|
||||
) {}
|
||||
|
||||
async getEligibleBookings(query: GetEligibleBookingsDto) {
|
||||
// Day-level pooling: when the wizard targets a schedule, surface the whole
|
||||
// (route, EAT day) pool — not just bookings pre-pinned to that train — by
|
||||
// resolving the schedule's route + day and filtering on the day instead.
|
||||
let day: string | undefined;
|
||||
let originStationId = query.originStationId;
|
||||
let destinationStationId = query.destinationStationId;
|
||||
if (query.trainScheduleId) {
|
||||
const schedule = await this.trainSchedulesRepository.findById(query.trainScheduleId);
|
||||
if (schedule?.scheduledDepartureDate) {
|
||||
day = eatDay(schedule.scheduledDepartureDate);
|
||||
originStationId = originStationId ?? schedule.originStationId;
|
||||
destinationStationId = destinationStationId ?? schedule.destinationStationId;
|
||||
}
|
||||
}
|
||||
|
||||
const bookings = await this.bookingsRepository.findEligibleForScheduling({
|
||||
freightType: query.freightType,
|
||||
originStationId: query.originStationId,
|
||||
destinationStationId: query.destinationStationId,
|
||||
originStationId,
|
||||
destinationStationId,
|
||||
schedulingStatus: query.schedulingStatus,
|
||||
trainScheduleId: query.trainScheduleId,
|
||||
day,
|
||||
});
|
||||
return { count: bookings.length, items: bookings.map((b) => this.mapEligibleBooking(b)) };
|
||||
}
|
||||
@@ -1989,6 +2006,33 @@ export class TrainSchedulingService {
|
||||
return filteredSchedules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Day-level pool: the distinct EAT calendar days that have ≥1 OPEN bookable
|
||||
* departure on the route. Customers pick a DAY (not a train) — so this returns
|
||||
* only the day strings, no capacity, counts or train info.
|
||||
*/
|
||||
async getAvailableDays(
|
||||
originYardId?: string,
|
||||
destinationYardId?: string,
|
||||
): Promise<{ days: string[] }> {
|
||||
const schedules = await this.getBookableSchedules(originYardId, destinationYardId);
|
||||
const days = new Set<string>();
|
||||
for (const s of schedules) {
|
||||
if (s.scheduleDate) days.add(eatDay(new Date(s.scheduleDate)));
|
||||
}
|
||||
return { days: [...days].sort() };
|
||||
}
|
||||
|
||||
/** Whether a route has ≥1 OPEN bookable departure on a given EAT day. */
|
||||
async existsOpenScheduleOnRouteDay(
|
||||
originYardId: string,
|
||||
destinationYardId: string,
|
||||
day: string,
|
||||
): Promise<boolean> {
|
||||
const { days } = await this.getAvailableDays(originYardId, destinationYardId);
|
||||
return days.includes(day);
|
||||
}
|
||||
|
||||
private async mapScheduleDetail(
|
||||
schedule: import('../train-schedules/entities/train-schedule.entity').TrainSchedule,
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user