mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 21:08:12 +00:00
Merge branch 'alpha' of github.com:Tria-plc/edr-platform into alpha
This commit is contained in:
@@ -398,10 +398,24 @@ export class SearchService {
|
||||
this.calculateFaresForSegment(schedule, originStationId, destinationStationId, nationality),
|
||||
]);
|
||||
|
||||
// Compute per-class availability using the pre-computed free seat set
|
||||
// Compute per-class availability using the pre-computed free seat set. A coach type
|
||||
// has separate seat classes per nationality tier (e.g. "VIP Bed Upper (Local)" AND
|
||||
// "VIP Bed Upper (Intl)" on the same coach) — filter to the searching passenger's own
|
||||
// nationality first, otherwise a name-based `.find()` across both tiers would credit
|
||||
// all availability to whichever tier happens to come first in the query result,
|
||||
// leaving the other tier's class permanently at 0 ("Fully booked") even when seats
|
||||
// are actually free. Matched via the class's own bedPosition field (case-insensitive:
|
||||
// Seat.bedPosition is lowercase, SeatClass.bedPosition is uppercase) rather than a
|
||||
// name substring, since that's an exact, unambiguous signal.
|
||||
const nationalityUpper = (nationality ?? '').toUpperCase();
|
||||
const resolvedNationalityType = (nationalityUpper === 'ETHIOPIAN' || nationalityUpper === 'DJIBOUTIAN')
|
||||
? 'LOCAL' : 'INTERNATIONAL';
|
||||
|
||||
const availabilityByClass: Record<string, number> = {};
|
||||
for (const assignment of schedule.coachAssignments) {
|
||||
const seatClassNames = assignment.coach.coachType?.seatClasses?.map((sc: any) => sc.name) || ['Standard'];
|
||||
const seatClasses = (assignment.coach.coachType?.seatClasses ?? []).filter(
|
||||
(sc: any) => !sc.nationalityType || sc.nationalityType === resolvedNationalityType,
|
||||
);
|
||||
const isBedCoach = assignment.coach.seats.some((s: any) => s.bedPosition);
|
||||
|
||||
if (isBedCoach) {
|
||||
@@ -412,8 +426,8 @@ export class SearchService {
|
||||
if (freeSeats.has(seat.id)) count++;
|
||||
}
|
||||
if (count > 0) {
|
||||
const matchingClass = seatClassNames.find((n: string) => n.toLowerCase().includes(bedPosition));
|
||||
if (matchingClass) availabilityByClass[matchingClass] = (availabilityByClass[matchingClass] ?? 0) + count;
|
||||
const matchingClass = seatClasses.find((sc: any) => sc.bedPosition?.toLowerCase() === bedPosition);
|
||||
if (matchingClass) availabilityByClass[matchingClass.name] = (availabilityByClass[matchingClass.name] ?? 0) + count;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -422,11 +436,12 @@ export class SearchService {
|
||||
if (seat.status === 'BLOCKED' || !seat.seatNumber?.trim()) continue;
|
||||
if (freeSeats.has(seat.id)) available++;
|
||||
}
|
||||
for (const name of seatClassNames) availabilityByClass[name] = (availabilityByClass[name] ?? 0) + available;
|
||||
const names = seatClasses.length > 0 ? seatClasses.map((sc: any) => sc.name) : ['Standard'];
|
||||
for (const name of names) availabilityByClass[name] = (availabilityByClass[name] ?? 0) + available;
|
||||
}
|
||||
}
|
||||
|
||||
const coachTypes = this.buildCoachTypeDetails(schedule, faresByClass, nationality);
|
||||
const coachTypes = this.buildCoachTypeDetails(schedule, faresByClass, nationality, availabilityByClass);
|
||||
const legDepartureAt = originStop.plannedDepartureAt ?? schedule.departureAt;
|
||||
const legArrivalAt = destStop.plannedArrivalAt ?? schedule.arrivalAt;
|
||||
|
||||
@@ -748,12 +763,13 @@ export class SearchService {
|
||||
schedule: ScheduleWithIncludes,
|
||||
faresByClass: Array<{ seatClassName: string; baseFareMinor: number; displayCurrency: Currency; displayAmountMinor: number }>,
|
||||
nationality?: string,
|
||||
availabilityByClass: Record<string, number> = {},
|
||||
): Array<{
|
||||
coachTypeId: string;
|
||||
coachTypeName: string;
|
||||
coachTypeCode: string;
|
||||
coachId: string;
|
||||
classes: Array<{ name: string; baseFareMinor: number; displayCurrency: Currency; displayAmountMinor: number }>;
|
||||
classes: Array<{ name: string; baseFareMinor: number; displayCurrency: Currency; displayAmountMinor: number; available: number }>;
|
||||
}> {
|
||||
const coachTypeMap = new Map<
|
||||
string,
|
||||
@@ -795,9 +811,10 @@ export class SearchService {
|
||||
baseFareMinor: fareInfo.baseFareMinor,
|
||||
displayCurrency: fareInfo.displayCurrency,
|
||||
displayAmountMinor: fareInfo.displayAmountMinor,
|
||||
available: availabilityByClass[className] ?? 0,
|
||||
};
|
||||
})
|
||||
.filter((c): c is { name: string; baseFareMinor: number; displayCurrency: Currency; displayAmountMinor: number } => c !== null)
|
||||
.filter((c): c is { name: string; baseFareMinor: number; displayCurrency: Currency; displayAmountMinor: number; available: number } => c !== null)
|
||||
.sort((a, b) => a.baseFareMinor - b.baseFareMinor);
|
||||
|
||||
if (classes.length === 0) continue;
|
||||
|
||||
Reference in New Issue
Block a user