import { Injectable, NotAcceptableException } from '@nestjs/common' import { CreateTrainDto } from './dto/create-train.dto' import { UpdateTrainDto } from './dto/update-train.dto' import { PrismaService } from 'src/prisma/prisma.service' import { TrainTrip, User } from '@prisma/client' import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto' import { paginate } from 'src/common/utils/pagination.utils' import { ImportTrainDto } from './dto/import-train.dto' import { InterrailJourney, InterrailLegInfo, InterrailTravelInfo } from './dto/interrail-api.dto' import { JsonObject } from '@prisma/client/runtime/library' import { OSMRResponse } from './dto/osmr-api.dto' @Injectable() export class TrainsService { constructor(private prisma: PrismaService) { } async create(createTrainDto: CreateTrainDto): Promise { return await this.prisma.trainTrip.create({ data: createTrainDto }) } async findAll(queryPagination?: QueryPaginationDto): Promise<[TrainTrip[], number]> { return [ await this.prisma.trainTrip.findMany({ ...paginate(queryPagination), }), await this.prisma.trainTrip.count(), ] } async findOne(id: string): Promise { return await this.prisma.trainTrip.findUnique({ where: { id }, }) } async update(id: string, updateTrainDto: UpdateTrainDto): Promise { return await this.prisma.trainTrip.update({ where: { id }, data: updateTrainDto, }) } async remove(id: string): Promise { return await this.prisma.trainTrip.delete({ where: { id }, }) } async import(user: User, { id: trainId }: ImportTrainDto): Promise { const interrailResult: InterrailJourney = await fetch(`https://3uiwjsimnh.execute-api.eu-central-1.amazonaws.com/Prod/journey-import?id=${trainId}`) .then(data => data.json()) if (interrailResult.data.travels.length !== 1) throw new NotAcceptableException(`Ce voyage contient ${interrailResult.data.travels.length} trajets. Merci d'ajouter les trajets un à un.`) const travel = interrailResult.data.travels[0] if (travel.legs.length !== 1) throw new NotAcceptableException(`Ce trajet contient ${travel.legs.length} trains. Merci d'ajouter les trajets un à un.`) const leg = travel.legs[0] const travelInfoJson: InterrailTravelInfo = JSON.parse(travel.infoJson) const departure = new Date(`${travelInfoJson.date.year}-${travelInfoJson.date.month.toString().padStart(2, "0")}-${travelInfoJson.date.day.toString().padStart(2, "0")}` + `T${travelInfoJson.departureTime.hours.toString().padStart(2, "0")}:${travelInfoJson.departureTime.minutes.toString().padStart(2, "0")}:00+0100`) departure.setDate(departure.getDate() + travelInfoJson.departureTime.offset) const arrival = new Date(`${travelInfoJson.date.year}-${travelInfoJson.date.month.toString().padStart(2, "0")}-${travelInfoJson.date.day.toString().padStart(2, "0")}` + `T${travelInfoJson.arrivalTime.hours.toString().padStart(2, "0")}:${travelInfoJson.arrivalTime.minutes.toString().padStart(2, "0")}:00+0100`) arrival.setDate(arrival.getDate() + travelInfoJson.arrivalTime.offset) const legInfoJson: InterrailLegInfo = JSON.parse(leg.infoJson) const coordinatesString = legInfoJson.trainStopStations.map(trainStopStation => { return `${trainStopStation.coordinates.longitude},${trainStopStation.coordinates.latitude}` }).join(';') const osmrResult: OSMRResponse = await fetch(`https://signal.eu.org/osm/eu/route/v1/train/${coordinatesString}?overview=full&steps=true&exclude=highspeed`).then(result => result.json()) if (osmrResult?.code === "NoRoute") throw new NotAcceptableException("Aucune route n'a été trouvée avec https://signal.eu.org/osm/") const route = osmrResult.routes[0] const distance = route.distance const geometry = route.geometry return this.prisma.trainTrip.upsert({ where: { id: trainId, }, create: { id: trainId, userId: user.id, distance: distance, from: travel.from, to: travel.to, departureTime: departure, arrivalTime: arrival, infoJson: leg.infoJson, geometry: geometry, }, update: { userId: user.id, distance: distance, from: travel.from, to: travel.to, departureTime: departure, arrivalTime: arrival, infoJson: leg.infoJson, geometry: geometry, } }) } }