Ajout endpoint trajets en train

This commit is contained in:
Emmy D'Anello 2024-12-07 22:07:46 +01:00
parent 4349a1b61a
commit e052b06c83
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
9 changed files with 256 additions and 1 deletions

View File

@ -6,9 +6,10 @@ import { AuthModule } from './auth/auth.module'
import { GeolocationsModule } from './geolocations/geolocations.module'
import { ChallengesModule } from './challenges/challenges.module'
import { ChallengeActionsModule } from './challenge-actions/challenge-actions.module'
import { TrainsModule } from './trains/trains.module';
@Module({
imports: [PrismaModule, UsersModule, AuthModule, GeolocationsModule, ChallengesModule, ChallengeActionsModule],
imports: [PrismaModule, UsersModule, AuthModule, GeolocationsModule, ChallengesModule, ChallengeActionsModule, TrainsModule],
providers: [PrismaService],
})
export class AppModule {}

View File

@ -0,0 +1,46 @@
import { ApiProperty } from "@nestjs/swagger"
import { JsonValue } from "@prisma/client/runtime/library"
import { Type } from "class-transformer"
import { IsDate, IsInt, IsJSON, IsNumber, IsString } from "class-validator"
export class CreateTrainDto {
@IsString()
@ApiProperty({ description: "Identifiant du train, donné par l'identifiant de partage Interrail" })
id: string
@IsInt()
@Type(() => Number)
@ApiProperty({ description: "Identifiant de l'utilisateur⋅rice effectuant le trajet" })
userId: number
@IsNumber()
@Type(() => Number)
@ApiProperty({ description: "Distance en mètres du trajet, calculé sur https://signal.eu.org/osm/" })
distance: number
@IsString()
@ApiProperty({ description: "Nom de la gare de départ" })
from: string
@IsString()
@ApiProperty({ description: "Nom de la gare d'arrivée" })
to: string
@IsDate()
@Type(() => Date)
@ApiProperty({ description: "Date et heure de départ du train" })
departureTime: Date
@IsDate()
@Type(() => Date)
@ApiProperty({ description: "Date et heure d'arrivée du train" })
arrivalTime: Date
@IsJSON()
@ApiProperty({ description: "Informations JSON supplémentaires transmises par Interrail" })
infoJson: JsonValue
@IsString()
@ApiProperty({ description: "Géométrie de la course, obtenue par https://signal.eu.org/osm/" })
geometry: string
}

View File

@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/swagger';
import { CreateTrainDto } from './create-train.dto';
export class UpdateTrainDto extends PartialType(CreateTrainDto) {}

View File

@ -0,0 +1,36 @@
import { ApiProperty } from "@nestjs/swagger"
import { TrainTrip } from "@prisma/client"
import { JsonValue } from "@prisma/client/runtime/library"
export class TrainEntity implements TrainTrip {
constructor (partial: Partial<TrainEntity>) {
Object.assign(this, partial)
}
@ApiProperty({ description: "Identifiant du train, donné par l'identifiant de partage Interrail" })
id: string
@ApiProperty({ description: "Identifiant de l'utilisateur⋅rice effectuant le trajet" })
userId: number
@ApiProperty({ description: "Distance en mètres du trajet, calculé sur https://signal.eu.org/osm/" })
distance: number
@ApiProperty({ description: "Nom de la gare de départ" })
from: string
@ApiProperty({ description: "Nom de la gare d'arrivée" })
to: string
@ApiProperty({ description: "Date et heure de départ du train" })
departureTime: Date
@ApiProperty({ description: "Date et heure d'arrivée du train" })
arrivalTime: Date
@ApiProperty({ description: "Informations JSON supplémentaires transmises par Interrail" })
infoJson: JsonValue
@ApiProperty({ description: "Géométrie de la course, obtenue par https://signal.eu.org/osm/" })
geometry: string
}

View File

@ -0,0 +1,20 @@
import { Test, TestingModule } from '@nestjs/testing'
import { TrainsController } from './trains.controller'
import { TrainsService } from './trains.service'
describe('TrainsController', () => {
let controller: TrainsController
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [TrainsController],
providers: [TrainsService],
}).compile()
controller = module.get<TrainsController>(TrainsController)
})
it('should be defined', () => {
expect(controller).toBeDefined()
})
})

View File

@ -0,0 +1,75 @@
import { Controller, Get, Post, Body, Patch, Param, Delete, HttpCode, UseGuards, Query, ParseIntPipe, NotFoundException } from '@nestjs/common'
import { TrainsService } from './trains.service'
import { CreateTrainDto } from './dto/create-train.dto'
import { UpdateTrainDto } from './dto/update-train.dto'
import { TrainEntity } from './entities/train.entity'
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard'
import { ApiBearerAuth, ApiCreatedResponse, ApiForbiddenResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger'
import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { PaginateOutputDto } from 'src/common/dto/pagination-output.dto'
@Controller('trains')
export class TrainsController {
constructor(private readonly trainsService: TrainsService) {}
@Post()
@HttpCode(201)
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiCreatedResponse({ type: TrainEntity, description: "Objet créé avec succès" })
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
async create(@Body() createTrainDto: CreateTrainDto): Promise<TrainEntity> {
const train = await this.trainsService.create(createTrainDto)
return new TrainEntity(train)
}
@Get()
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOkResponsePaginated(TrainEntity)
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
async findAll(@Query() queryPagination?: QueryPaginationDto): Promise<PaginateOutputDto<TrainEntity>> {
const [trains, total] = await this.trainsService.findAll(queryPagination)
return paginateOutput<TrainEntity>(trains.map(train => new TrainEntity(train)), total, queryPagination)
}
@Get(':id')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOkResponse({ type: TrainEntity })
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
@ApiNotFoundResponse({ description: "Objet non trouvé" })
async findOne(@Param('id') id: string): Promise<TrainEntity> {
const train = await this.trainsService.findOne(id)
if (!train)
throw new NotFoundException(`Trajet en train inexistant avec l'identifiant ${id}`)
return new TrainEntity(train)
}
@Patch(':id')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOkResponse({ type: TrainEntity })
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
@ApiNotFoundResponse({ description: "Objet non trouvé" })
async update(@Param('id') id: string, @Body() updateChallengeDto: UpdateTrainDto) {
return await this.trainsService.update(id, updateChallengeDto)
}
@Delete(':id')
@HttpCode(204)
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOkResponse({ type: TrainEntity })
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
@ApiNotFoundResponse({ description: "Objet non trouvé" })
async remove(@Param('id') id: string) {
await this.trainsService.remove(id)
}
}

View File

@ -0,0 +1,11 @@
import { Module } from '@nestjs/common'
import { TrainsService } from './trains.service'
import { TrainsController } from './trains.controller'
import { PrismaModule } from 'src/prisma/prisma.module'
@Module({
controllers: [TrainsController],
providers: [TrainsService],
imports: [PrismaModule],
})
export class TrainsModule {}

View File

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing'
import { TrainsService } from './trains.service'
describe('TrainsService', () => {
let service: TrainsService
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [TrainsService],
}).compile()
service = module.get<TrainsService>(TrainsService)
})
it('should be defined', () => {
expect(service).toBeDefined()
})
})

View File

@ -0,0 +1,44 @@
import { Injectable } 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 } from '@prisma/client'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { paginate } from 'src/common/utils/pagination.utils'
@Injectable()
export class TrainsService {
constructor(private prisma: PrismaService) { }
async create(createTrainDto: CreateTrainDto): Promise<TrainTrip> {
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.challenge.count(),
]
}
async findOne(id: string): Promise<TrainTrip> {
return await this.prisma.trainTrip.findUnique({
where: { id },
})
}
async update(id: string, updateTrainDto: UpdateTrainDto): Promise<TrainTrip> {
return await this.prisma.trainTrip.update({
where: { id },
data: updateTrainDto,
})
}
async remove(id: string): Promise<TrainTrip> {
return await this.prisma.trainTrip.delete({
where: { id },
})
}
}