Boarding, payment methods, journey direction on seat hold, and more updates

This commit is contained in:
Stephanos A
2026-06-29 08:44:38 +03:00
parent 81ae99cee3
commit c6e56d1c4f
65 changed files with 6437 additions and 1425 deletions

View File

@@ -28,14 +28,16 @@ export class FareEngineService {
if (originStop.sequence >= destStop.sequence)
throw new BadRequestException('Origin must come before destination in the route sequence');
const legStops = route.stops.filter(
s => s.sequence > originStop.sequence && s.sequence <= destStop.sequence,
);
const seatClass = await this.prisma.seatClass.findUnique({ where: { id: dto.seatClassId } });
if (!seatClass) throw new NotFoundException('Seat class not found');
if (!seatClass.isActive) throw new BadRequestException('Seat class is not active');
// Calculate distance: distanceKm represents cumulative distance from route origin
// For a segment, distance = destination.distanceKm - origin.distanceKm
const totalDistanceKm = destStop.distanceKm! - originStop.distanceKm!;
if (totalDistanceKm < 0 || isNaN(totalDistanceKm))
throw new BadRequestException('Invalid distance calculation - check route stop distances');
// Resolve fare: FareRule (schedule-scoped → route-scoped) takes precedence over distance×rate
const now = new Date();
const [originStation, destStation] = await Promise.all([
@@ -64,23 +66,15 @@ export class FareEngineService {
let baseFarePerPassengerMinor: number;
let ratePerKmMinor: number;
let totalDistanceKm: number;
let fareSource: string;
if (fareRule) {
// Flat fare from FareRule — distance is informational only
baseFarePerPassengerMinor = fareRule.baseFareMinor;
totalDistanceKm = legStops.reduce((sum, s) => sum + (s.distanceKm ?? 0), 0);
ratePerKmMinor = totalDistanceKm > 0 ? Math.round(baseFarePerPassengerMinor / totalDistanceKm) : 0;
fareSource = fareRule.tripId ? 'SCHEDULE_FARE_RULE' : 'ROUTE_FARE_RULE';
} else {
// Distance × rate fallback
const missingDistance = legStops.filter(s => s.distanceKm === null || s.distanceKm === undefined);
if (missingDistance.length > 0)
throw new BadRequestException(
`Missing distanceKm on route stops at sequences: ${missingDistance.map(s => s.sequence).join(', ')}`,
);
totalDistanceKm = legStops.reduce((sum, s) => sum + (s.distanceKm ?? 0), 0);
ratePerKmMinor = seatClass.baseFareMinor;
baseFarePerPassengerMinor = totalDistanceKm * ratePerKmMinor;
fareSource = 'DISTANCE_RATE';