import { Injectable, NotFoundException } from '@nestjs/common'; import { PrismaService } from '../../common/prisma.service'; import { CreateTripDto, CreateFareRuleDto, UpdateTripStatusDto } from './schedules.dto'; @Injectable() export class SchedulesService { constructor(private prisma: PrismaService) {} async createTrip(dto: CreateTripDto) { const dep = new Date(dto.departureAt), arr = new Date(dto.arrivalAt); return this.prisma.trip.create({ data: { serviceId: dto.serviceId, originStationId: dto.originStationId, destinationStationId: dto.destinationStationId, departureAt: dep, arrivalAt: arr, durationMinutes: Math.round((arr.getTime() - dep.getTime()) / 60000), stopsCount: dto.stopsCount ?? 0 }, include: { service: true, originStation: true, destinationStation: true }, }); } async getTrip(id: string) { const trip = await this.prisma.trip.findUnique({ where: { id }, include: { service: true, originStation: true, destinationStation: true, coaches: { include: { seats: true } }, stopTimes: { include: { station: true }, orderBy: { sequence: 'asc' } } } }); if (!trip) throw new NotFoundException('Trip not found'); return trip; } updateTripStatus(id: string, dto: UpdateTripStatusDto) { return this.prisma.trip.update({ where: { id }, data: { status: dto.status as any } }); } createFareRule(dto: CreateFareRuleDto) { return this.prisma.fareRule.create({ data: { ...dto, validFrom: new Date(dto.validFrom), validUntil: dto.validUntil ? new Date(dto.validUntil) : null } }); } async getFare(tripId: string, serviceClass: string) { const trip = await this.prisma.trip.findUnique({ where: { id: tripId }, include: { originStation: true, destinationStation: true } }); if (!trip) throw new NotFoundException('Trip not found'); const route = `${trip.originStation.code}-${trip.destinationStation.code}`; const rule = await this.prisma.fareRule.findFirst({ where: { serviceClass: serviceClass as any, validFrom: { lte: new Date() }, OR: [{ tripId }, { route }, { tripId: null, route: null }], AND: [{ OR: [{ validUntil: null }, { validUntil: { gte: new Date() } }] }] }, orderBy: { validFrom: 'desc' }, }); return rule ?? { baseFareMinor: 45000, currency: 'ETB', serviceClass }; } }