diff --git a/backend/src/gtfs/dto/round-trip.dto.ts b/backend/src/gtfs/dto/round-trip.dto.ts new file mode 100644 index 0000000..d098e94 --- /dev/null +++ b/backend/src/gtfs/dto/round-trip.dto.ts @@ -0,0 +1,12 @@ +import { createZodDto } from 'nestjs-zod'; +import { z } from 'zod'; + +const RoundTripQuerySchema = z.object({ + orgStopId: z.string().min(1, 'Origin stop ID is required'), + destStopId: z.string().min(1, 'Destination stop ID is required'), + date: z + .string() + .regex(/^\d{4}-\d{2}-\d{2}$/, 'Date must be in YYYY-MM-DD format'), +}); + +export class RoundTripQueryDto extends createZodDto(RoundTripQuerySchema) {} diff --git a/backend/src/gtfs/gtfs.controller.ts b/backend/src/gtfs/gtfs.controller.ts new file mode 100644 index 0000000..09c9d1a --- /dev/null +++ b/backend/src/gtfs/gtfs.controller.ts @@ -0,0 +1,70 @@ +import { Controller, Get, Query } from '@nestjs/common'; +import { InjectRepository } from '@mikro-orm/nestjs'; +import { EntityRepository } from '@mikro-orm/postgresql'; +import { GTFSStopTime } from '../entities'; +import { RoundTripQueryDto } from './dto/round-trip.dto'; +import { ApiTags, ApiOkResponse } from '@nestjs/swagger'; + +@Controller('round_trip') +@ApiTags('GTFS - Round Trip') +export class RoundTripController { + constructor( + @InjectRepository(GTFSStopTime) + private readonly stopTimeRepository: EntityRepository, + ) {} + + @Get() + @ApiOkResponse({ + description: 'Returns stop times for origin and destination stops', + }) + async getRoundTrip(@Query() query: RoundTripQueryDto) { + const targetDate = new Date(query.date); + + const orgStopTimes = await this.stopTimeRepository.find( + { + stop: { stopid: query.orgStopId }, + trip: { + calendarDate: { + date: targetDate, + }, + }, + }, + { + populate: ['trip', 'stop'], + orderBy: { departureTime: 'ASC' }, + }, + ); + + const destStopTimes = await this.stopTimeRepository.find( + { + stop: { stopid: query.destStopId }, + trip: { + calendarDate: { + date: targetDate, + }, + }, + }, + { + populate: ['trip', 'stop'], + orderBy: { departureTime: 'ASC' }, + }, + ); + + return { + orgStopTimes: orgStopTimes.map((st) => ({ + id: st.id, + trip_id: st.trip.trip_id, + arrival_time: st.arrivalTime as unknown as string, + departure_time: st.departureTime as unknown as string, + stop_id: st.stop.stopid, + })), + destStopTimes: destStopTimes.map((st) => ({ + id: st.id, + trip_id: st.trip.trip_id, + arrival_time: st.arrivalTime as unknown as string, + departure_time: st.departureTime as unknown as string, + stop_id: st.stop.stopid, + })), + }; + } +} diff --git a/backend/src/gtfs/gtfs.module.ts b/backend/src/gtfs/gtfs.module.ts index e764f61..213d232 100644 --- a/backend/src/gtfs/gtfs.module.ts +++ b/backend/src/gtfs/gtfs.module.ts @@ -2,6 +2,7 @@ import { Module } from '@nestjs/common'; import { MikroOrmModule } from '@mikro-orm/nestjs'; import { GtfsService } from './gtfs.service'; +import { RoundTripController } from './gtfs.controller'; import { Agency, GTFSRoute, @@ -24,6 +25,7 @@ import { ConfigModule } from '@nestjs/config'; ]), ConfigModule, ], + controllers: [RoundTripController], providers: [GtfsService], exports: [GtfsService], })