Cut off time configuration

This commit is contained in:
Muluhabt
2026-07-24 09:01:27 +03:00
parent 64e1130f7d
commit 7320c359d1
10 changed files with 618 additions and 207 deletions

View File

@@ -10,6 +10,7 @@ import { CurrencyService } from "../currency/currency.service";
import { FareEngineService } from "../fare-engine/fare-engine.service";
import { SegmentsService } from "../segments/segments.service";
import { resolveCurrencyFromNationality } from "../fare-engine/fare-engine.dto";
import { resolveCheckinCutoff } from "../../common/utils/checkin-cutoff.utils";
import { Currency, Prisma } from "@prisma/client";
const POINTS_TO_MINOR = 10;
@@ -554,23 +555,11 @@ export class SearchService {
// Segment-level cutoff: use the origin stop's own estimated arrival time, not the
// schedule's overall departureAt (which is station A's time). This lets
// B→D remain bookable even after A→D closes. The first stop has no arrival (nothing
// to arrive at), so it falls back to its own departure.
// Cutoff resolution: stop-level override → route default → 30 min fallback.
const now = new Date();
const segmentDepartureAt =
originStop.plannedArrivalAt ?? originStop.plannedDepartureAt ?? schedule.departureAt;
const routeStop = schedule.route?.stops?.find(
(s) => s.stationId === originStationId,
);
const checkinMinutes =
routeStop?.checkinMinutesBefore ??
schedule.route?.checkinMinutesBefore ??
30;
if (
segmentDepartureAt.getTime() - now.getTime() <=
checkinMinutes * 60 * 1000
)
// B→D remain bookable even after A→D closes. Stop-level checkinMinutesBefore override →
// route default → 30 min fallback — same resolution GuestBookingService applies at
// booking-creation time, so a segment shown as bookable here stays bookable through
// checkout instead of being rejected against a different, hardcoded cutoff.
if (Date.now() >= resolveCheckinCutoff(schedule, originStop, originStationId).cutoffAt.getTime())
return null;
// Collect all valid seat IDs upfront for a single batch availability check
@@ -682,8 +671,11 @@ export class SearchService {
nationality,
availabilityByClass,
);
const legDepartureAt = schedule.departureAt;
const legArrivalAt = schedule.arrivalAt;
// Use the selected stop's own planned time, not the schedule's full-route span —
// for stop-based (mid-route) boarding/alighting these differ from the train's
// overall origin departure / final destination arrival.
const legDepartureAt = originStop.plannedDepartureAt ?? schedule.departureAt;
const legArrivalAt = destStop.plannedArrivalAt ?? schedule.arrivalAt;
const displayCurrency =
faresByClass[0]?.displayCurrency ??