mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 19:00:55 +00:00
51 lines
2.9 KiB
TypeScript
51 lines
2.9 KiB
TypeScript
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
import { PrismaService } from '../../common/prisma.service';
|
|
import { SearchTripsDto, FareQuoteDto } from './search.dto';
|
|
|
|
const POINTS_TO_MINOR = 10;
|
|
|
|
@Injectable()
|
|
export class SearchService {
|
|
constructor(private prisma: PrismaService) {}
|
|
|
|
async searchTrips(dto: SearchTripsDto) {
|
|
const date = new Date(dto.date), nextDay = new Date(date.getTime() + 86400000);
|
|
const trips = await this.prisma.trip.findMany({
|
|
where: { originStationId: dto.originStationId, destinationStationId: dto.destinationStationId, departureAt: { gte: date, lt: nextDay }, status: { in: ['SCHEDULED', 'BOARDING'] } },
|
|
include: { service: true, originStation: true, destinationStation: true, coaches: { include: { seats: true } } },
|
|
});
|
|
return trips.map((trip) => {
|
|
const seatsByClass = (cls: string) => trip.coaches.filter((c) => c.serviceClass === cls).flatMap((c) => c.seats);
|
|
const avail = (cls: string) => seatsByClass(cls).filter((s) => s.status === 'AVAILABLE').length;
|
|
return {
|
|
id: trip.id,
|
|
number: trip.service.number,
|
|
origin: { id: trip.originStation.id, code: trip.originStation.code, name: trip.originStation.name, city: trip.originStation.city },
|
|
destination: { id: trip.destinationStation.id, code: trip.destinationStation.code, name: trip.destinationStation.name, city: trip.destinationStation.city },
|
|
departureAt: trip.departureAt, arrivalAt: trip.arrivalAt, status: trip.status,
|
|
availability: { ECONOMY: avail('ECONOMY'), BUSINESS: avail('BUSINESS'), FIRST: avail('FIRST') },
|
|
fares: { ECONOMY: this.defaultFare('ECONOMY') / 100, BUSINESS: this.defaultFare('BUSINESS') / 100, FIRST: this.defaultFare('FIRST') / 100 },
|
|
};
|
|
});
|
|
}
|
|
|
|
async getFareQuote(dto: FareQuoteDto) {
|
|
const trip = await this.prisma.trip.findUnique({ where: { id: dto.tripId } });
|
|
if (!trip) throw new NotFoundException('Trip not found');
|
|
const count = dto.passengerCount ?? 1;
|
|
const baseFareMinor = this.defaultFare(dto.serviceClass) * count;
|
|
let discountMinor = 0;
|
|
if (dto.promoCode) {
|
|
const promo = await this.prisma.promotion.findUnique({ where: { code: dto.promoCode } });
|
|
if (promo?.active && promo.validUntil > new Date()) discountMinor = promo.percentOff ? Math.round(baseFareMinor * promo.percentOff / 100) : (promo.amountOffMinor ?? 0);
|
|
}
|
|
const loyaltyMinor = (dto.loyaltyRedemptionPoints ?? 0) * POINTS_TO_MINOR;
|
|
const taxesMinor = Math.round(baseFareMinor * 0.05);
|
|
return { tripId: dto.tripId, serviceClass: dto.serviceClass, passengerCount: count, baseFareMinor, discountMinor, loyaltyRedemptionMinor: loyaltyMinor, taxesFeesMinor: taxesMinor, totalMinor: Math.max(0, baseFareMinor - discountMinor - loyaltyMinor + taxesMinor), currency: 'ETB' };
|
|
}
|
|
|
|
private defaultFare(serviceClass: string): number {
|
|
return ({ ECONOMY: 45000, BUSINESS: 90000, FIRST: 135000 } as any)[serviceClass] ?? 45000;
|
|
}
|
|
}
|