mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 13:38:20 +00:00
Segment based seat assignement added
This commit is contained in:
@@ -3,9 +3,10 @@ import { SearchController } from './search.controller';
|
||||
import { SearchService } from './search.service';
|
||||
import { CurrencyModule } from '../currency/currency.module';
|
||||
import { FareEngineModule } from '../fare-engine/fare-engine.module';
|
||||
import { SegmentsModule } from '../segments/segments.module';
|
||||
|
||||
@Module({
|
||||
imports: [CurrencyModule, FareEngineModule],
|
||||
imports: [CurrencyModule, FareEngineModule, SegmentsModule],
|
||||
controllers: [SearchController],
|
||||
providers: [SearchService],
|
||||
exports: [SearchService],
|
||||
|
||||
@@ -3,6 +3,7 @@ import { PrismaService } from '../../common/prisma.service';
|
||||
import { SearchTripsDto, FareQuoteDto } from './search.dto';
|
||||
import { CurrencyService } from '../currency/currency.service';
|
||||
import { FareEngineService } from '../fare-engine/fare-engine.service';
|
||||
import { SegmentsService } from '../segments/segments.service';
|
||||
import { Currency } from '@prisma/client';
|
||||
|
||||
const POINTS_TO_MINOR = 10;
|
||||
@@ -13,6 +14,7 @@ export class SearchService {
|
||||
private prisma: PrismaService,
|
||||
private currencyService: CurrencyService,
|
||||
private fareEngine: FareEngineService,
|
||||
private segmentsService: SegmentsService,
|
||||
) {}
|
||||
|
||||
async searchTrips(dto: SearchTripsDto) {
|
||||
@@ -58,7 +60,8 @@ export class SearchService {
|
||||
|
||||
for (const seat of assignment.coach.seats) {
|
||||
if (seat.status === 'BLOCKED') continue;
|
||||
const free = await this.isSeatFreeForSegment(
|
||||
// Use segment-aware check — a seat booked A→B is still free for B→D
|
||||
const free = await this.segmentsService.isSeatFreeForLeg(
|
||||
schedule.id, seat.id,
|
||||
originStop.sequence, destStop.sequence,
|
||||
);
|
||||
@@ -237,70 +240,6 @@ export class SearchService {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the seat has no active hold or confirmed booking
|
||||
* whose segment range overlaps [fromSeq, toSeq).
|
||||
* Overlap condition: existingFrom < toSeq AND fromSeq < existingTo
|
||||
*/
|
||||
private async isSeatFreeForSegment(
|
||||
scheduleId: string,
|
||||
seatId: string,
|
||||
fromSeq: number,
|
||||
toSeq: number,
|
||||
): Promise<boolean> {
|
||||
// Check active holds that include this seat on this schedule
|
||||
const holds = await this.prisma.seatHold.findMany({
|
||||
where: { scheduleId, seatIds: { has: seatId }, expiresAt: { gt: new Date() } },
|
||||
});
|
||||
|
||||
for (const hold of holds) {
|
||||
// Resolve hold segment range from its stored origin/destination via JourneySegment
|
||||
// For holds we use the stop sequences stored on the hold's origin/destination
|
||||
// Since SeatHold doesn't store sequences directly, we check JourneySegments
|
||||
// that reference this seat on this schedule with PENDING_PAYMENT status
|
||||
const holdSegs = await this.prisma.journeySegment.findMany({
|
||||
where: { scheduleId, seatId },
|
||||
include: {
|
||||
journey: true,
|
||||
schedule: { include: { stopTimes: true } },
|
||||
},
|
||||
});
|
||||
|
||||
for (const js of holdSegs) {
|
||||
const depSeq = js.schedule.stopTimes.find(s => s.stationId === js.departureStationId)?.sequence;
|
||||
const arrSeq = js.schedule.stopTimes.find(s => s.stationId === js.arrivalStationId)?.sequence;
|
||||
if (depSeq !== undefined && arrSeq !== undefined) {
|
||||
if (depSeq < toSeq && fromSeq < arrSeq) return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If no journey segments yet (hold just created), treat the whole hold as blocking
|
||||
if (holdSegs.length === 0) return false;
|
||||
}
|
||||
|
||||
// Check confirmed/pending bookings via JourneySegment
|
||||
const bookedSegments = await this.prisma.journeySegment.findMany({
|
||||
where: {
|
||||
scheduleId,
|
||||
seatId,
|
||||
journey: { status: { in: ['CONFIRMED', 'PENDING_PAYMENT'] } },
|
||||
},
|
||||
include: {
|
||||
schedule: { include: { stopTimes: true } },
|
||||
},
|
||||
});
|
||||
|
||||
for (const js of bookedSegments) {
|
||||
const depSeq = js.schedule.stopTimes.find(s => s.stationId === js.departureStationId)?.sequence;
|
||||
const arrSeq = js.schedule.stopTimes.find(s => s.stationId === js.arrivalStationId)?.sequence;
|
||||
if (depSeq !== undefined && arrSeq !== undefined) {
|
||||
if (depSeq < toSeq && fromSeq < arrSeq) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private defaultFare(seatClassName: string): number {
|
||||
const fares: Record<string, number> = {
|
||||
'Economy Regular': 45000,
|
||||
|
||||
Reference in New Issue
Block a user