Compare commits
	
		
			4 Commits
		
	
	
		
			b93b8b4c04
			...
			481400d404
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 481400d404 | |||
| 77b33144f6 | |||
| 83d3a573ca | |||
| 3af1e498ac | 
| @@ -3,6 +3,14 @@ | |||||||
|   "collection": "@nestjs/schematics", |   "collection": "@nestjs/schematics", | ||||||
|   "sourceRoot": "src", |   "sourceRoot": "src", | ||||||
|   "compilerOptions": { |   "compilerOptions": { | ||||||
|     "deleteOutDir": true |     "deleteOutDir": true, | ||||||
|  |     "plugins": [ | ||||||
|  |       { | ||||||
|  |         "name": "@nestjs/swagger", | ||||||
|  |         "options": { | ||||||
|  |           "introspectComments": true | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     ] | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| import { Body, Controller, Post } from '@nestjs/common' | import { Body, Controller, Post } from '@nestjs/common' | ||||||
| import { AuthService } from './auth.service' | import { AuthService } from './auth.service' | ||||||
| import { ApiOkResponse, ApiTags } from '@nestjs/swagger' | import { ApiTags } from '@nestjs/swagger' | ||||||
| import { AuthEntity } from './entity/auth.entity' | import { AuthEntity } from './entity/auth.entity' | ||||||
| import { LoginDto } from './dto/login.dto' | import { LoginDto } from './dto/login.dto' | ||||||
|  |  | ||||||
| @@ -9,9 +9,13 @@ import { LoginDto } from './dto/login.dto' | |||||||
| export class AuthController { | export class AuthController { | ||||||
|   constructor(private readonly authService: AuthService) {} |   constructor(private readonly authService: AuthService) {} | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Se connecter par nom et mot de passe pour récupérer un jeton de connexion. | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Mot de passe incorrect. | ||||||
|  |    */ | ||||||
|   @Post('login') |   @Post('login') | ||||||
|   @ApiOkResponse({ type: AuthEntity }) |   async login(@Body() { name, password }: LoginDto): Promise<AuthEntity> { | ||||||
|   login(@Body() { name, password }: LoginDto) { |     return await this.authService.login(name, password) | ||||||
|     return this.authService.login(name, password) |  | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,14 +1,9 @@ | |||||||
| import { ApiProperty } from '@nestjs/swagger' | import { IsNotEmpty } from 'class-validator' | ||||||
| import { IsNotEmpty, IsString } from 'class-validator' |  | ||||||
|  |  | ||||||
| export class LoginDto { | export class LoginDto { | ||||||
|   @IsString() |  | ||||||
|   @IsNotEmpty() |   @IsNotEmpty() | ||||||
|   @ApiProperty() |  | ||||||
|   name: string |   name: string | ||||||
|  |  | ||||||
|   @IsString() |  | ||||||
|   @IsNotEmpty() |   @IsNotEmpty() | ||||||
|   @ApiProperty() |  | ||||||
|   password: string |   password: string | ||||||
| } | } | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| import { ApiProperty } from '@nestjs/swagger' |  | ||||||
|  |  | ||||||
| export class AuthEntity { | export class AuthEntity { | ||||||
|   @ApiProperty() |   /** | ||||||
|  |    * Jeton d'accès à l'API, valable 12h. | ||||||
|  |    */ | ||||||
|   accessToken: string |   accessToken: string | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import { Controller, Get, Post, Body, Patch, Param, Delete, ParseIntPipe, HttpCode, UseGuards, Req, Query, NotFoundException } from '@nestjs/common' | import { Controller, Get, Post, Body, Patch, Param, Delete, ParseIntPipe, HttpCode, UseGuards, Req, Query, NotFoundException } from '@nestjs/common' | ||||||
| import { ChallengeActionsService } from './challenge-actions.service' | import { ChallengeActionsService } from './challenge-actions.service' | ||||||
| import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard' | import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard' | ||||||
| import { ApiBearerAuth, ApiCreatedResponse, ApiForbiddenResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger' | import { ApiBearerAuth, ApiNoContentResponse } from '@nestjs/swagger' | ||||||
| import { ChallengeActionEntity } from './entities/challenge-action.entity' | import { ChallengeActionEntity } from './entities/challenge-action.entity' | ||||||
| import { CreateChallengeActionDto } from './dto/create-challenge-action.dto' | import { CreateChallengeActionDto } from './dto/create-challenge-action.dto' | ||||||
| import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils' | import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils' | ||||||
| @@ -15,36 +15,44 @@ import { EndChallengeActionDto } from './dto/end-challenge-action.dto' | |||||||
| export class ChallengeActionsController { | export class ChallengeActionsController { | ||||||
|   constructor(private readonly challengeActionsService: ChallengeActionsService) {} |   constructor(private readonly challengeActionsService: ChallengeActionsService) {} | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Création d'une action de défi | ||||||
|  |    *  | ||||||
|  |    * @throws {400} Erreurs dans le formulaire de création | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Post() |   @Post() | ||||||
|   @HttpCode(201) |   @HttpCode(201) | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiCreatedResponse({ type: ChallengeActionEntity, description: "Objet créé avec succès" }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async create(@Req() request: AuthenticatedRequest, @Body() createChallengeActionDto: CreateChallengeActionDto): Promise<ChallengeActionEntity> { |   async create(@Req() request: AuthenticatedRequest, @Body() createChallengeActionDto: CreateChallengeActionDto): Promise<ChallengeActionEntity> { | ||||||
|     const challenge = await this.challengeActionsService.create(request.user, createChallengeActionDto) |     const challenge = await this.challengeActionsService.create(request.user, createChallengeActionDto) | ||||||
|     return new ChallengeActionEntity(challenge) |     return new ChallengeActionEntity(challenge) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Recherche d'actions de défi | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Get() |   @Get() | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponsePaginated(ChallengeActionEntity) |   @ApiOkResponsePaginated(ChallengeActionEntity) | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async findAll(@Query() queryPagination: QueryPaginationDto, @Query() filterChallengeActions: FilterChallengeActionsDto): Promise<PaginateOutputDto<ChallengeActionEntity>> { |   async findAll(@Query() queryPagination: QueryPaginationDto, @Query() filterChallengeActions: FilterChallengeActionsDto): Promise<PaginateOutputDto<ChallengeActionEntity>> { | ||||||
|     const [challengeActions, total] = await this.challengeActionsService.findAll(queryPagination, filterChallengeActions) |     const [challengeActions, total] = await this.challengeActionsService.findAll(queryPagination, filterChallengeActions) | ||||||
|     return paginateOutput<ChallengeActionEntity>(challengeActions.map(challengeAction => new ChallengeActionEntity(challengeAction)), total, queryPagination) |     return paginateOutput<ChallengeActionEntity>(challengeActions.map(challengeAction => new ChallengeActionEntity(challengeAction)), total, queryPagination) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Recherche d'une action de défi par identifiant | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Action de défi non trouvée | ||||||
|  |    */ | ||||||
|   @Get(':id') |   @Get(':id') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: ChallengeActionEntity }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async findOne(@Param('id', ParseIntPipe) id: number): Promise<ChallengeActionEntity> { |   async findOne(@Param('id', ParseIntPipe) id: number): Promise<ChallengeActionEntity> { | ||||||
|     const challenge = await this.challengeActionsService.findOne(id) |     const challenge = await this.challengeActionsService.findOne(id) | ||||||
|     if (!challenge) |     if (!challenge) | ||||||
| @@ -52,36 +60,44 @@ export class ChallengeActionsController { | |||||||
|     return new ChallengeActionEntity(challenge) |     return new ChallengeActionEntity(challenge) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Modification d'une action de défi par identifiant | ||||||
|  |    *  | ||||||
|  |    * @throws {400} Erreurs dans le formulaire de modification | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Action de défi non trouvée | ||||||
|  |    */ | ||||||
|   @Patch(':id') |   @Patch(':id') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: ChallengeActionEntity }) |   async update(@Param('id', ParseIntPipe) id: number, @Body() updateChallengeActionDto: UpdateChallengeActionDto): Promise<ChallengeActionEntity> { | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async update(@Param('id', ParseIntPipe) id: number, @Body() updateChallengeActionDto: UpdateChallengeActionDto) { |  | ||||||
|     return await this.challengeActionsService.update(id, updateChallengeActionDto) |     return await this.challengeActionsService.update(id, updateChallengeActionDto) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Suppression d'une action de défi par identifiant | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Action de défi non trouvée | ||||||
|  |    */ | ||||||
|   @Delete(':id') |   @Delete(':id') | ||||||
|   @HttpCode(204) |   @HttpCode(204) | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: ChallengeActionEntity }) |   @ApiNoContentResponse({ description: "Action de défi supprimée avec succès" }) | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |   async remove(@Param('id', ParseIntPipe) id: number): Promise<void> { | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async remove(@Param('id', ParseIntPipe) id: number) { |  | ||||||
|     await this.challengeActionsService.remove(id) |     await this.challengeActionsService.remove(id) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Terminer l'action de défi en cours | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {409} Aucun défi à terminer n'est en cours | ||||||
|  |    */ | ||||||
|   @Post('/end-current') |   @Post('/end-current') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: ChallengeActionEntity }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async endCurrent(@Req() request: AuthenticatedRequest, @Body() { success }: EndChallengeActionDto): Promise<ChallengeActionEntity> { |   async endCurrent(@Req() request: AuthenticatedRequest, @Body() { success }: EndChallengeActionDto): Promise<ChallengeActionEntity> { | ||||||
|     const challengeAction = await this.challengeActionsService.endCurrentChallenge(request.user, success) |     const challengeAction = await this.challengeActionsService.endCurrentChallenge(request.user, success) | ||||||
|     return new ChallengeActionEntity(challengeAction) |     return new ChallengeActionEntity(challengeAction) | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import { Injectable, NotAcceptableException } from '@nestjs/common' | import { BadRequestException, Injectable, NotFoundException, UnprocessableEntityException } from '@nestjs/common' | ||||||
| import { CreateChallengeActionDto } from './dto/create-challenge-action.dto' | import { CreateChallengeActionDto } from './dto/create-challenge-action.dto' | ||||||
| import { UpdateChallengeActionDto } from './dto/update-challenge-action.dto' | import { UpdateChallengeActionDto } from './dto/update-challenge-action.dto' | ||||||
| import { ChallengeAction, Player } from '@prisma/client' | import { ChallengeAction, Player } from '@prisma/client' | ||||||
| @@ -35,6 +35,8 @@ export class ChallengeActionsService { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   async update(id: number, updateChallengeActionDto: UpdateChallengeActionDto): Promise<ChallengeAction> { |   async update(id: number, updateChallengeActionDto: UpdateChallengeActionDto): Promise<ChallengeAction> { | ||||||
|  |     if (!this.findOne(id)) | ||||||
|  |       throw new NotFoundException(`Aucune action de défi trouvée avec l'identifiant ${id}`) | ||||||
|     return await this.prisma.challengeAction.update({ |     return await this.prisma.challengeAction.update({ | ||||||
|       where: { id }, |       where: { id }, | ||||||
|       data: updateChallengeActionDto, |       data: updateChallengeActionDto, | ||||||
| @@ -42,6 +44,8 @@ export class ChallengeActionsService { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   async remove(id: number): Promise<ChallengeAction> { |   async remove(id: number): Promise<ChallengeAction> { | ||||||
|  |     if (!this.findOne(id)) | ||||||
|  |       throw new NotFoundException(`Aucune action de défi trouvée avec l'identifiant ${id}`) | ||||||
|     return await this.prisma.challengeAction.delete({ |     return await this.prisma.challengeAction.delete({ | ||||||
|       where: { id }, |       where: { id }, | ||||||
|     }) |     }) | ||||||
| @@ -55,7 +59,7 @@ export class ChallengeActionsService { | |||||||
|       } |       } | ||||||
|     }) |     }) | ||||||
|     if (!challengeAction) |     if (!challengeAction) | ||||||
|       throw new NotAcceptableException("Aucun défi n'est en cours") |       throw new BadRequestException("Aucun défi n'est en cours") | ||||||
|     let data |     let data | ||||||
|     const now = new Date() |     const now = new Date() | ||||||
|     if  (success) { |     if  (success) { | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import { ChallengesService } from './challenges.service' | |||||||
| import { CreateChallengeDto } from './dto/create-challenge.dto' | import { CreateChallengeDto } from './dto/create-challenge.dto' | ||||||
| import { UpdateChallengeDto } from './dto/update-challenge.dto' | import { UpdateChallengeDto } from './dto/update-challenge.dto' | ||||||
| import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard' | import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard' | ||||||
| import { ApiBearerAuth, ApiCreatedResponse, ApiForbiddenResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger' | import { ApiBearerAuth, ApiNoContentResponse } from '@nestjs/swagger' | ||||||
| import { ChallengeEntity } from './entities/challenge.entity' | import { ChallengeEntity } from './entities/challenge.entity' | ||||||
| import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils' | import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils' | ||||||
| import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto' | import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto' | ||||||
| @@ -13,36 +13,44 @@ import { PaginateOutputDto } from 'src/common/dto/pagination-output.dto' | |||||||
| export class ChallengesController { | export class ChallengesController { | ||||||
|   constructor(private readonly challengesService: ChallengesService) {} |   constructor(private readonly challengesService: ChallengesService) {} | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Création d'un défi | ||||||
|  |    *  | ||||||
|  |    * @throws {400} Erreurs dans le formulaire de création | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Post() |   @Post() | ||||||
|   @HttpCode(201) |   @HttpCode(201) | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiCreatedResponse({ type: ChallengeEntity, description: "Objet créé avec succès" }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async create(@Body() createChallengeDto: CreateChallengeDto): Promise<ChallengeEntity> { |   async create(@Body() createChallengeDto: CreateChallengeDto): Promise<ChallengeEntity> { | ||||||
|     const challenge = await this.challengesService.create(createChallengeDto) |     const challenge = await this.challengesService.create(createChallengeDto) | ||||||
|     return new ChallengeEntity(challenge) |     return new ChallengeEntity(challenge) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Recherche de défis | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Get() |   @Get() | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponsePaginated(ChallengeEntity) |   @ApiOkResponsePaginated(ChallengeEntity) | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async findAll(@Query() queryPagination?: QueryPaginationDto): Promise<PaginateOutputDto<ChallengeEntity>> { |   async findAll(@Query() queryPagination?: QueryPaginationDto): Promise<PaginateOutputDto<ChallengeEntity>> { | ||||||
|     const [challenges, total] = await this.challengesService.findAll(queryPagination) |     const [challenges, total] = await this.challengesService.findAll(queryPagination) | ||||||
|     return paginateOutput<ChallengeEntity>(challenges.map(challenge => new ChallengeEntity(challenge)), total, queryPagination) |     return paginateOutput<ChallengeEntity>(challenges.map(challenge => new ChallengeEntity(challenge)), total, queryPagination) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Recherche d'un défi par identifiant | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Défi non trouvé | ||||||
|  |    */ | ||||||
|   @Get(':id') |   @Get(':id') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: ChallengeEntity }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async findOne(@Param('id', ParseIntPipe) id: number): Promise<ChallengeEntity> { |   async findOne(@Param('id', ParseIntPipe) id: number): Promise<ChallengeEntity> { | ||||||
|     const challenge = await this.challengesService.findOne(id) |     const challenge = await this.challengesService.findOne(id) | ||||||
|     if (!challenge) |     if (!challenge) | ||||||
| @@ -50,36 +58,47 @@ export class ChallengesController { | |||||||
|     return new ChallengeEntity(challenge) |     return new ChallengeEntity(challenge) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Modification d'un défi par identifiant | ||||||
|  |    *  | ||||||
|  |    * @throws {400} Erreurs dans le formulaire de modification | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Défi non trouvé | ||||||
|  |    */ | ||||||
|   @Patch(':id') |   @Patch(':id') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: ChallengeEntity }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async update(@Param('id', ParseIntPipe) id: number, @Body() updateChallengeDto: UpdateChallengeDto) { |   async update(@Param('id', ParseIntPipe) id: number, @Body() updateChallengeDto: UpdateChallengeDto) { | ||||||
|     return await this.challengesService.update(id, updateChallengeDto) |     return await this.challengesService.update(id, updateChallengeDto) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Suppression d'un défi par identifiant | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Défi non trouvé | ||||||
|  |    */ | ||||||
|   @Delete(':id') |   @Delete(':id') | ||||||
|   @HttpCode(204) |   @HttpCode(204) | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: ChallengeEntity }) |   @ApiNoContentResponse({ description: "Le défi a bien été supprimé" }) | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async remove(@Param('id', ParseIntPipe) id: number) { |   async remove(@Param('id', ParseIntPipe) id: number) { | ||||||
|     await this.challengesService.remove(id) |     await this.challengesService.remove(id) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Tirage d'un nouveau défi aléatoire | ||||||
|  |    *  | ||||||
|  |    * @remarks Aucun défi ne doit être en cours. | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Plus aucun défi n'est disponible | ||||||
|  |    * @throws {409} Un défi est déjà en cours d'accomplissement | ||||||
|  |    */ | ||||||
|   @Post('/draw-random') |   @Post('/draw-random') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: ChallengeEntity }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async drawRandom(@Req() request: AuthenticatedRequest): Promise<ChallengeEntity> { |   async drawRandom(@Req() request: AuthenticatedRequest): Promise<ChallengeEntity> { | ||||||
|     const challenge = await this.challengesService.drawRandom(request.user) |     const challenge = await this.challengesService.drawRandom(request.user) | ||||||
|     return new ChallengeEntity(challenge) |     return new ChallengeEntity(challenge) | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import { Injectable, NotAcceptableException, NotFoundException } from '@nestjs/common' | import { ConflictException, Injectable, NotFoundException } from '@nestjs/common' | ||||||
| import { CreateChallengeDto } from './dto/create-challenge.dto' | import { CreateChallengeDto } from './dto/create-challenge.dto' | ||||||
| import { UpdateChallengeDto } from './dto/update-challenge.dto' | import { UpdateChallengeDto } from './dto/update-challenge.dto' | ||||||
| import { Challenge, Player } from '@prisma/client' | import { Challenge, Player } from '@prisma/client' | ||||||
| @@ -38,6 +38,8 @@ export class ChallengesService { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   async update(id: number, updateChallengeDto: UpdateChallengeDto): Promise<Challenge> { |   async update(id: number, updateChallengeDto: UpdateChallengeDto): Promise<Challenge> { | ||||||
|  |     if (!this.findOne(id)) | ||||||
|  |       throw new NotFoundException(`Aucun défi n'existe avec l'identifiant ${id}`) | ||||||
|     return await this.prisma.challenge.update({ |     return await this.prisma.challenge.update({ | ||||||
|       where: { id }, |       where: { id }, | ||||||
|       data: updateChallengeDto, |       data: updateChallengeDto, | ||||||
| @@ -48,6 +50,8 @@ export class ChallengesService { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   async remove(id: number): Promise<Challenge> { |   async remove(id: number): Promise<Challenge> { | ||||||
|  |     if (!this.findOne(id)) | ||||||
|  |       throw new NotFoundException(`Aucun défi n'existe avec l'identifiant ${id}`) | ||||||
|     return await this.prisma.challenge.delete({ |     return await this.prisma.challenge.delete({ | ||||||
|       where: { id }, |       where: { id }, | ||||||
|       include: { |       include: { | ||||||
| @@ -64,7 +68,7 @@ export class ChallengesService { | |||||||
|       } |       } | ||||||
|     }) |     }) | ||||||
|     if (currentChallengeAction) |     if (currentChallengeAction) | ||||||
|       throw new NotAcceptableException("Un défi est déjà en cours d'accomplissement") |       throw new ConflictException("Un défi est déjà en cours d'accomplissement") | ||||||
|     const remaningChallenges = await this.prisma.challenge.count({ |     const remaningChallenges = await this.prisma.challenge.count({ | ||||||
|       where: { |       where: { | ||||||
|         action: null, |         action: null, | ||||||
|   | |||||||
| @@ -1,19 +1,63 @@ | |||||||
| import { Controller, Get, UseGuards } from '@nestjs/common' | import { Controller, Delete, Get, HttpCode, Post, UseGuards } from '@nestjs/common' | ||||||
| import { GameService } from './game.service' | import { GameService } from './game.service' | ||||||
| import { JwtAuthGuard } from 'src/auth/jwt-auth.guard' | import { JwtAuthGuard } from 'src/auth/jwt-auth.guard' | ||||||
| import { ApiBearerAuth, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger' | import { ApiBearerAuth, ApiNoContentResponse, ApiOkResponse, ApiOperation, ApiUnauthorizedResponse } from '@nestjs/swagger' | ||||||
| import { GameEntity } from './entities/game.entity' | import { GameEntity } from './entities/game.entity' | ||||||
|  |  | ||||||
| @Controller('game') | @Controller('game') | ||||||
| export class GameController { | export class GameController { | ||||||
|   constructor(private readonly gameService: GameService) {} |   constructor(private readonly gameService: GameService) {} | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Récupérer l'objet du jeu | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Get() |   @Get() | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: GameEntity }) |   async find(): Promise<GameEntity> { | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   async find() { |  | ||||||
|     return new GameEntity(await this.gameService.find()) |     return new GameEntity(await this.gameService.find()) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Démarrer le jeu | ||||||
|  |    * @remarks Lance le jeu, tire au sort læ joueur⋅se de départ et donne un solde initial pour acheter des trains. Le jeu ne doit pas être déjà démarré. | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {409} La partie est déjà démarrée | ||||||
|  |    */ | ||||||
|  |   @Post('/start') | ||||||
|  |   @UseGuards(JwtAuthGuard) | ||||||
|  |   @ApiBearerAuth() | ||||||
|  |   async start(): Promise<GameEntity> { | ||||||
|  |     return new GameEntity(await this.gameService.start()) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Arrêter le jeu | ||||||
|  |    * @remarks Arrête le jeu (si déjà lancé), à n'utiliser qu'en fin de partie. | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {409} La partie n'est pas démarrée | ||||||
|  |    */ | ||||||
|  |   @Post('/stop') | ||||||
|  |   @UseGuards(JwtAuthGuard) | ||||||
|  |   @ApiBearerAuth() | ||||||
|  |   async stop(): Promise<GameEntity> { | ||||||
|  |     return new GameEntity(await this.gameService.stop()) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Réinitialiser le jeu | ||||||
|  |    * @remarks Réinitialise toutes les données de jeu, supprimant les trains parcourus et les défis accomplis. À utiliser avec précaution. | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|  |   @Delete('/reset') | ||||||
|  |   @UseGuards(JwtAuthGuard) | ||||||
|  |   @ApiBearerAuth() | ||||||
|  |   async reset(): Promise<GameEntity> { | ||||||
|  |     return new GameEntity(await this.gameService.reset()) | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| import { Injectable } from '@nestjs/common' | import { ConflictException, Injectable } from '@nestjs/common' | ||||||
|  | import { MoneyUpdateType } from '@prisma/client' | ||||||
| import { PrismaService } from 'src/prisma/prisma.service' | import { PrismaService } from 'src/prisma/prisma.service' | ||||||
|  |  | ||||||
| @Injectable() | @Injectable() | ||||||
| @@ -8,4 +9,59 @@ export class GameService { | |||||||
|   async find() { |   async find() { | ||||||
|     return await this.prisma.game.findUnique({ where: { id: 1 } }) |     return await this.prisma.game.findUnique({ where: { id: 1 } }) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   async start() { | ||||||
|  |     const game = await this.find() | ||||||
|  |     if (game.started) | ||||||
|  |       throw new ConflictException("La partie a déjà démarré.") | ||||||
|  |     const players = await this.prisma.player.findMany() | ||||||
|  |     const alreadyStarted = game.currentRunnerId !== null | ||||||
|  |     if (!alreadyStarted) { | ||||||
|  |       for (const player of players) { | ||||||
|  |         await this.prisma.moneyUpdate.create({ | ||||||
|  |           data: { | ||||||
|  |             playerId: player.id, | ||||||
|  |             amount: 2000, | ||||||
|  |             reason: MoneyUpdateType.START, | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     const runnerId = alreadyStarted ? game.currentRunnerId : players[Math.trunc(players.length * Math.random())].id | ||||||
|  |     return await this.prisma.game.update({ | ||||||
|  |       where: { id: 1 }, | ||||||
|  |       data: { | ||||||
|  |         started: true, | ||||||
|  |         currentRunnerId: runnerId, | ||||||
|  |       }, | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   async stop() { | ||||||
|  |     const game = await this.find() | ||||||
|  |     if (!game.started) | ||||||
|  |       throw new ConflictException("La partie n'a pas encore démarré.") | ||||||
|  |     return await this.prisma.game.update({ | ||||||
|  |       where: { id: 1 }, | ||||||
|  |       data: { | ||||||
|  |         started: false, | ||||||
|  |       }, | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   async reset() { | ||||||
|  |     await this.prisma.moneyUpdate.deleteMany() | ||||||
|  |     await this.prisma.challengeAction.deleteMany() | ||||||
|  |     await this.prisma.trainTrip.deleteMany() | ||||||
|  |     await this.prisma.geolocation.deleteMany() | ||||||
|  |     await this.prisma.player.updateMany({ data: { money: 0 } }) | ||||||
|  |     await this.prisma.game.update({ | ||||||
|  |       where: { id: 1 }, | ||||||
|  |       data: { | ||||||
|  |         started: false, | ||||||
|  |         currentRunnerId: null, | ||||||
|  |       }, | ||||||
|  |     }) | ||||||
|  |     return await this.find() | ||||||
|  |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| import { Controller, Get, Post, Body, Patch, Param, Delete, ParseIntPipe, UseGuards, HttpCode, Req, NotFoundException, Query } from '@nestjs/common' | import { Controller, Get, Post, Body, Param, Delete, ParseIntPipe, UseGuards, HttpCode, Req, NotFoundException, Query } from '@nestjs/common' | ||||||
| import { GeolocationsService } from './geolocations.service' | import { GeolocationsService } from './geolocations.service' | ||||||
| import { CreateGeolocationDto } from './dto/create-geolocation.dto' | import { CreateGeolocationDto } from './dto/create-geolocation.dto' | ||||||
| import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard' | import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard' | ||||||
| import { ApiBearerAuth, ApiCreatedResponse, ApiForbiddenResponse, ApiNoContentResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger' | import { ApiBearerAuth, ApiNoContentResponse } from '@nestjs/swagger' | ||||||
| import { GeolocationEntity } from './entities/geolocation.entity' | import { GeolocationEntity } from './entities/geolocation.entity' | ||||||
| import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils' | import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils' | ||||||
| import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto' | import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto' | ||||||
| @@ -13,36 +13,44 @@ import { PlayerFilterDto } from 'src/common/dto/player_filter.dto' | |||||||
| export class GeolocationsController { | export class GeolocationsController { | ||||||
|   constructor(private readonly geolocationsService: GeolocationsService) {} |   constructor(private readonly geolocationsService: GeolocationsService) {} | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Ajout d'une géolocalisation pour læ joueur⋅se connecté⋅e | ||||||
|  |    *  | ||||||
|  |    * @throws {400} Erreurs dans le formulaire de création | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Post() |   @Post() | ||||||
|   @HttpCode(201) |   @HttpCode(201) | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiCreatedResponse({ type: GeolocationEntity, description: "Objet créé avec succès" }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async create(@Req() request: AuthenticatedRequest, @Body() createGeolocationDto: CreateGeolocationDto): Promise<GeolocationEntity> { |   async create(@Req() request: AuthenticatedRequest, @Body() createGeolocationDto: CreateGeolocationDto): Promise<GeolocationEntity> { | ||||||
|     const geolocation = await this.geolocationsService.create(request.user, createGeolocationDto) |     const geolocation = await this.geolocationsService.create(request.user, createGeolocationDto) | ||||||
|     return new GeolocationEntity(geolocation) |     return new GeolocationEntity(geolocation) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Recherche de géolocalisations | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Get() |   @Get() | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponsePaginated(GeolocationEntity) |   @ApiOkResponsePaginated(GeolocationEntity) | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async findAll(@Query() queryPagination?: QueryPaginationDto, @Query() playerFilter?: PlayerFilterDto): Promise<PaginateOutputDto<GeolocationEntity>> { |   async findAll(@Query() queryPagination?: QueryPaginationDto, @Query() playerFilter?: PlayerFilterDto): Promise<PaginateOutputDto<GeolocationEntity>> { | ||||||
|     const [geolocations, total] = await this.geolocationsService.findAll(queryPagination, playerFilter) |     const [geolocations, total] = await this.geolocationsService.findAll(queryPagination, playerFilter) | ||||||
|     return paginateOutput<GeolocationEntity>(geolocations.map(geolocation => new GeolocationEntity(geolocation)), total, queryPagination) |     return paginateOutput<GeolocationEntity>(geolocations.map(geolocation => new GeolocationEntity(geolocation)), total, queryPagination) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Recherche d'une géolocalisation par identifiant | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Géolocalisation non trouvée | ||||||
|  |    */ | ||||||
|   @Get(':id') |   @Get(':id') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: GeolocationEntity }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async findOne(@Param('id', ParseIntPipe) id: number): Promise<GeolocationEntity> { |   async findOne(@Param('id', ParseIntPipe) id: number): Promise<GeolocationEntity> { | ||||||
|     const geolocation = await this.geolocationsService.findOne(id) |     const geolocation = await this.geolocationsService.findOne(id) | ||||||
|     if (!geolocation) |     if (!geolocation) | ||||||
| @@ -50,13 +58,15 @@ export class GeolocationsController { | |||||||
|     return new GeolocationEntity(geolocation) |     return new GeolocationEntity(geolocation) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Récupération de la dernière posititon | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Aucune localisation envoyée | ||||||
|  |    */ | ||||||
|   @Get('/last-location/:playerId') |   @Get('/last-location/:playerId') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: GeolocationEntity }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Aucune localisation trouvée" }) |  | ||||||
|   async findLastLocation(@Param('playerId', ParseIntPipe) playerId: number): Promise<GeolocationEntity> { |   async findLastLocation(@Param('playerId', ParseIntPipe) playerId: number): Promise<GeolocationEntity> { | ||||||
|     const geolocation = await this.geolocationsService.findLastLocation(playerId) |     const geolocation = await this.geolocationsService.findLastLocation(playerId) | ||||||
|     if (!geolocation) |     if (!geolocation) | ||||||
| @@ -64,14 +74,17 @@ export class GeolocationsController { | |||||||
|     return new GeolocationEntity(geolocation) |     return new GeolocationEntity(geolocation) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Suppression d'une localisation | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Géolocalisation non trouvée | ||||||
|  |    */ | ||||||
|   @Delete(':id') |   @Delete(':id') | ||||||
|   @HttpCode(204) |   @HttpCode(204) | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiNoContentResponse({ description: "Objet supprimé avec succès" }) |   @ApiNoContentResponse({ description: "La géolocalisation a bien été supprimée" }) | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async remove(@Param('id', ParseIntPipe) id: number): Promise<void> { |   async remove(@Param('id', ParseIntPipe) id: number): Promise<void> { | ||||||
|     await this.geolocationsService.remove(+id) |     await this.geolocationsService.remove(+id) | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import { Injectable } from '@nestjs/common' | import { Injectable, NotFoundException } from '@nestjs/common' | ||||||
| import { CreateGeolocationDto } from './dto/create-geolocation.dto' | import { CreateGeolocationDto } from './dto/create-geolocation.dto' | ||||||
| import { PrismaService } from 'src/prisma/prisma.service' | import { PrismaService } from 'src/prisma/prisma.service' | ||||||
| import { Geolocation, Player, Prisma } from '@prisma/client' | import { Geolocation, Player, Prisma } from '@prisma/client' | ||||||
| @@ -43,6 +43,8 @@ export class GeolocationsService { | |||||||
|  |  | ||||||
|  |  | ||||||
|   async remove(id: number): Promise<Geolocation> { |   async remove(id: number): Promise<Geolocation> { | ||||||
|  |     if (!this.findOne(id)) | ||||||
|  |       throw new NotFoundException(`Aucune géolocalisation n'existe avec l'identifiant ${id}`) | ||||||
|     return await this.prisma.geolocation.delete({ where: { id } }) |     return await this.prisma.geolocation.delete({ where: { id } }) | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import { MoneyUpdatesService } from './money-updates.service' | |||||||
| import { CreateMoneyUpdateDto } from './dto/create-money-update.dto' | import { CreateMoneyUpdateDto } from './dto/create-money-update.dto' | ||||||
| import { UpdateMoneyUpdateDto } from './dto/update-money-update.dto' | import { UpdateMoneyUpdateDto } from './dto/update-money-update.dto' | ||||||
| import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard' | import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard' | ||||||
| import { ApiBearerAuth, ApiCreatedResponse, ApiForbiddenResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger' | import { ApiBearerAuth, ApiNoContentResponse } from '@nestjs/swagger' | ||||||
| import { MoneyUpdateEntity } from './entities/money-update.entity' | import { MoneyUpdateEntity } from './entities/money-update.entity' | ||||||
| import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils' | import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils' | ||||||
| import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto' | import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto' | ||||||
| @@ -14,36 +14,44 @@ import { PaginateOutputDto } from 'src/common/dto/pagination-output.dto' | |||||||
| export class MoneyUpdatesController { | export class MoneyUpdatesController { | ||||||
|   constructor(private readonly moneyUpdatesService: MoneyUpdatesService) {} |   constructor(private readonly moneyUpdatesService: MoneyUpdatesService) {} | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Création d'une modification de solde | ||||||
|  |    *  | ||||||
|  |    * @throws {400} Erreurs dans le formulaire de création | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Post() |   @Post() | ||||||
|   @HttpCode(201) |   @HttpCode(201) | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiCreatedResponse({ type: MoneyUpdateEntity, description: "Objet créé avec succès" }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async create(@Req() request: AuthenticatedRequest, @Body() createMoneyUpdateDto: CreateMoneyUpdateDto): Promise<MoneyUpdateEntity> { |   async create(@Req() request: AuthenticatedRequest, @Body() createMoneyUpdateDto: CreateMoneyUpdateDto): Promise<MoneyUpdateEntity> { | ||||||
|     const moneyUpdate = await this.moneyUpdatesService.create(request.user, createMoneyUpdateDto) |     const moneyUpdate = await this.moneyUpdatesService.create(request.user, createMoneyUpdateDto) | ||||||
|     return new MoneyUpdateEntity(moneyUpdate) |     return new MoneyUpdateEntity(moneyUpdate) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Recherche de modifications de solde | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Get() |   @Get() | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponsePaginated(MoneyUpdateEntity) |   @ApiOkResponsePaginated(MoneyUpdateEntity) | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async findAll(@Query() queryPagination: QueryPaginationDto, @Query() playerFilter: PlayerFilterDto): Promise<PaginateOutputDto<MoneyUpdateEntity>> { |   async findAll(@Query() queryPagination: QueryPaginationDto, @Query() playerFilter: PlayerFilterDto): Promise<PaginateOutputDto<MoneyUpdateEntity>> { | ||||||
|     const [trains, total] = await this.moneyUpdatesService.findAll(queryPagination, playerFilter) |     const [trains, total] = await this.moneyUpdatesService.findAll(queryPagination, playerFilter) | ||||||
|     return paginateOutput<MoneyUpdateEntity>(trains.map(train => new MoneyUpdateEntity(train)), total, queryPagination) |     return paginateOutput<MoneyUpdateEntity>(trains.map(train => new MoneyUpdateEntity(train)), total, queryPagination) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Recherche d'une modification de solde | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Modification de solde non trouvée | ||||||
|  |    */ | ||||||
|   @Get(':id') |   @Get(':id') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: MoneyUpdateEntity }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async findOne(@Param('id', ParseIntPipe) id: number): Promise<MoneyUpdateEntity> { |   async findOne(@Param('id', ParseIntPipe) id: number): Promise<MoneyUpdateEntity> { | ||||||
|     const train = await this.moneyUpdatesService.findOne(id) |     const train = await this.moneyUpdatesService.findOne(id) | ||||||
|     if (!train) |     if (!train) | ||||||
| @@ -51,25 +59,31 @@ export class MoneyUpdatesController { | |||||||
|     return new MoneyUpdateEntity(train) |     return new MoneyUpdateEntity(train) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Modification d'une modification de solde | ||||||
|  |    *  | ||||||
|  |    * @throws {400} Erreurs dans le formulaire de modification | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Modification de solde non trouvée | ||||||
|  |    */ | ||||||
|   @Patch(':id') |   @Patch(':id') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: MoneyUpdateEntity }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async update(@Param('id', ParseIntPipe) id: number, @Body() updateMoneyUpdateDto: UpdateMoneyUpdateDto) { |   async update(@Param('id', ParseIntPipe) id: number, @Body() updateMoneyUpdateDto: UpdateMoneyUpdateDto) { | ||||||
|     return await this.moneyUpdatesService.update(id, updateMoneyUpdateDto) |     return await this.moneyUpdatesService.update(id, updateMoneyUpdateDto) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Suppression d'une modification de solde | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Modification de solde non trouvée | ||||||
|  |    */ | ||||||
|   @Delete(':id') |   @Delete(':id') | ||||||
|   @HttpCode(204) |   @HttpCode(204) | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|  |   @ApiNoContentResponse({ description: "La modification de solde a bien été supprimée" }) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: MoneyUpdateEntity }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async remove(@Param('id', ParseIntPipe) id: number) { |   async remove(@Param('id', ParseIntPipe) id: number) { | ||||||
|     await this.moneyUpdatesService.remove(id) |     await this.moneyUpdatesService.remove(id) | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import { Injectable } from '@nestjs/common' | import { Injectable, NotFoundException } from '@nestjs/common' | ||||||
| import { CreateMoneyUpdateDto } from './dto/create-money-update.dto' | import { CreateMoneyUpdateDto } from './dto/create-money-update.dto' | ||||||
| import { UpdateMoneyUpdateDto } from './dto/update-money-update.dto' | import { UpdateMoneyUpdateDto } from './dto/update-money-update.dto' | ||||||
| import { PrismaService } from 'src/prisma/prisma.service' | import { PrismaService } from 'src/prisma/prisma.service' | ||||||
| @@ -39,6 +39,8 @@ export class MoneyUpdatesService { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   async update(id: number, updateMoneyUpdateDto: UpdateMoneyUpdateDto): Promise<MoneyUpdate> { |   async update(id: number, updateMoneyUpdateDto: UpdateMoneyUpdateDto): Promise<MoneyUpdate> { | ||||||
|  |     if (!this.findOne(id)) | ||||||
|  |       throw new NotFoundException(`Aucune modification de solde n'existe avec l'identifiant ${id}`) | ||||||
|     return await this.prisma.moneyUpdate.update({ |     return await this.prisma.moneyUpdate.update({ | ||||||
|       where: { id }, |       where: { id }, | ||||||
|       data: updateMoneyUpdateDto, |       data: updateMoneyUpdateDto, | ||||||
| @@ -46,6 +48,8 @@ export class MoneyUpdatesService { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   async remove(id: number): Promise<MoneyUpdate> { |   async remove(id: number): Promise<MoneyUpdate> { | ||||||
|  |     if (!this.findOne(id)) | ||||||
|  |       throw new NotFoundException(`Aucune modification de solde n'existe avec l'identifiant ${id}`) | ||||||
|     return await this.prisma.moneyUpdate.delete({ |     return await this.prisma.moneyUpdate.delete({ | ||||||
|       where: { id }, |       where: { id }, | ||||||
|     }) |     }) | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| import { Body, Controller, Get, HttpCode, NotFoundException, Param, ParseIntPipe, Patch, Query, Req, UseGuards } from '@nestjs/common' | import { Body, Controller, Get, HttpCode, NotFoundException, Param, ParseIntPipe, Patch, Query, Req, UseGuards } from '@nestjs/common' | ||||||
| import { PlayersService } from './players.service' | import { PlayersService } from './players.service' | ||||||
| import { ApiBadRequestResponse, ApiBearerAuth, ApiForbiddenResponse, ApiNoContentResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger' | import { ApiBearerAuth, ApiNoContentResponse } from '@nestjs/swagger' | ||||||
| import { PlayerEntity } from './entities/player.entity' | import { PlayerEntity } from './entities/player.entity' | ||||||
| import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard' | import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard' | ||||||
| import { UpdatePasswordDto } from './dto/player_password.dto' | import { UpdatePasswordDto } from './dto/player_password.dto' | ||||||
| @@ -12,40 +12,48 @@ import { PaginateOutputDto } from 'src/common/dto/pagination-output.dto' | |||||||
| export class PlayersController { | export class PlayersController { | ||||||
|   constructor(private readonly playersService: PlayersService) {} |   constructor(private readonly playersService: PlayersService) {} | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Récupération de toustes les joueur⋅ses | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Get() |   @Get() | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponsePaginated(PlayerEntity) |   @ApiOkResponsePaginated(PlayerEntity) | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async findAll(@Query() queryPagination?: QueryPaginationDto): Promise<PaginateOutputDto<PlayerEntity>> { |   async findAll(@Query() queryPagination?: QueryPaginationDto): Promise<PaginateOutputDto<PlayerEntity>> { | ||||||
|     const [players, total] = await this.playersService.findAll(queryPagination) |     const [players, total] = await this.playersService.findAll(queryPagination) | ||||||
|     return paginateOutput<PlayerEntity>(players.map(player => new PlayerEntity(player)), total, queryPagination) |     return paginateOutput<PlayerEntity>(players.map(player => new PlayerEntity(player)), total, queryPagination) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Récupération d'un⋅e joueur⋅se par son identifiant | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Joueur⋅se non trouvé⋅e | ||||||
|  |    */ | ||||||
|   @Get(':id') |   @Get(':id') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: PlayerEntity }) |   async findOne(@Param('id', ParseIntPipe) id: number): Promise<PlayerEntity> { | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Joueur⋅se non trouvé⋅e" }) |  | ||||||
|   async findOne(@Param('id', ParseIntPipe) id: number) { |  | ||||||
|     const player = await this.playersService.findOne(id) |     const player = await this.playersService.findOne(id) | ||||||
|     if (!player) |     if (!player) | ||||||
|       throw new NotFoundException(`Læ joueur⋅se avec l'identifiant ${id} n'existe pas`) |       throw new NotFoundException(`Læ joueur⋅se avec l'identifiant ${id} n'existe pas`) | ||||||
|     return new PlayerEntity(player) |     return new PlayerEntity(player) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Modification du mot de passe | ||||||
|  |    *  | ||||||
|  |    * @throws {400} Mot de passe invalide | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Patch('/update-password') |   @Patch('/update-password') | ||||||
|   @HttpCode(204) |   @HttpCode(204) | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiNoContentResponse({ description: "Le mot de passe a bien été modifié." }) |   @ApiNoContentResponse({ description: "Le mot de passe a bien été modifié." }) | ||||||
|   @ApiBadRequestResponse({description: "Erreur dans la saisie du nouveau mot de passe."}) |   async updatePassword(@Req() request: AuthenticatedRequest, @Body() body: UpdatePasswordDto): Promise<void> { | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async updatePassword(@Req() request: AuthenticatedRequest, @Body() body: UpdatePasswordDto) { |  | ||||||
|     await this.playersService.updatePassword(request.user, body) |     await this.playersService.updatePassword(request.user, body) | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,10 +1,10 @@ | |||||||
| import { Controller, Get, Post, Body, Patch, Param, Delete, HttpCode, UseGuards, Query, ParseIntPipe, NotFoundException, Req } from '@nestjs/common' | import { Controller, Get, Post, Body, Patch, Param, Delete, HttpCode, UseGuards, Query, NotFoundException, Req } from '@nestjs/common' | ||||||
| import { TrainsService } from './trains.service' | import { TrainsService } from './trains.service' | ||||||
| import { CreateTrainDto } from './dto/create-train.dto' | import { CreateTrainDto } from './dto/create-train.dto' | ||||||
| import { UpdateTrainDto } from './dto/update-train.dto' | import { UpdateTrainDto } from './dto/update-train.dto' | ||||||
| import { TrainEntity } from './entities/train.entity' | import { TrainEntity } from './entities/train.entity' | ||||||
| import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard' | import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard' | ||||||
| import { ApiBearerAuth, ApiCreatedResponse, ApiForbiddenResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger' | import { ApiBearerAuth, ApiCreatedResponse, ApiNoContentResponse, ApiUnauthorizedResponse } from '@nestjs/swagger' | ||||||
| import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils' | import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils' | ||||||
| import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto' | import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto' | ||||||
| import { PaginateOutputDto } from 'src/common/dto/pagination-output.dto' | import { PaginateOutputDto } from 'src/common/dto/pagination-output.dto' | ||||||
| @@ -15,36 +15,46 @@ import { PlayerFilterDto } from 'src/common/dto/player_filter.dto' | |||||||
| export class TrainsController { | export class TrainsController { | ||||||
|   constructor(private readonly trainsService: TrainsService) {} |   constructor(private readonly trainsService: TrainsService) {} | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Création d'un trajet en train manuellement | ||||||
|  |    *  | ||||||
|  |    * @throws {400} Erreurs dans le formulaire de création | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Post() |   @Post() | ||||||
|   @HttpCode(201) |   @HttpCode(201) | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiCreatedResponse({ type: TrainEntity, description: "Objet créé avec succès" }) |   @ApiCreatedResponse({ type: TrainEntity, description: "Trajet en train créé avec succès" }) | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async create(@Body() createTrainDto: CreateTrainDto): Promise<TrainEntity> { |   async create(@Body() createTrainDto: CreateTrainDto): Promise<TrainEntity> { | ||||||
|     const train = await this.trainsService.create(createTrainDto) |     const train = await this.trainsService.create(createTrainDto) | ||||||
|     return new TrainEntity(train) |     return new TrainEntity(train) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Recherche de trajets en train | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    */ | ||||||
|   @Get() |   @Get() | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponsePaginated(TrainEntity) |   @ApiOkResponsePaginated(TrainEntity) | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async findAll(@Query() queryPagination: QueryPaginationDto, @Query() playerFilter: PlayerFilterDto): Promise<PaginateOutputDto<TrainEntity>> { |   async findAll(@Query() queryPagination: QueryPaginationDto, @Query() playerFilter: PlayerFilterDto): Promise<PaginateOutputDto<TrainEntity>> { | ||||||
|     const [trains, total] = await this.trainsService.findAll(queryPagination, playerFilter) |     const [trains, total] = await this.trainsService.findAll(queryPagination, playerFilter) | ||||||
|     return paginateOutput<TrainEntity>(trains.map(train => new TrainEntity(train)), total, queryPagination) |     return paginateOutput<TrainEntity>(trains.map(train => new TrainEntity(train)), total, queryPagination) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Recherche d'un trajet en train | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Trajet en train non trouvé | ||||||
|  |    */ | ||||||
|   @Get(':id') |   @Get(':id') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @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> { |   async findOne(@Param('id') id: string): Promise<TrainEntity> { | ||||||
|     const train = await this.trainsService.findOne(id) |     const train = await this.trainsService.findOne(id) | ||||||
|     if (!train) |     if (!train) | ||||||
| @@ -52,36 +62,45 @@ export class TrainsController { | |||||||
|     return new TrainEntity(train) |     return new TrainEntity(train) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Modification d'un trajet en train manuellement | ||||||
|  |    *  | ||||||
|  |    * @throws {400} Erreurs dans le formulaire de création | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Trajet en train non trouvé | ||||||
|  |    */ | ||||||
|   @Patch(':id') |   @Patch(':id') | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @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() updateTrainDto: UpdateTrainDto) { |   async update(@Param('id') id: string, @Body() updateTrainDto: UpdateTrainDto) { | ||||||
|     return await this.trainsService.update(id, updateTrainDto) |     return await this.trainsService.update(id, updateTrainDto) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Suppression d'un trajet en train | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {404} Trajet en train non trouvé | ||||||
|  |    */ | ||||||
|   @Delete(':id') |   @Delete(':id') | ||||||
|   @HttpCode(204) |   @HttpCode(204) | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiOkResponse({ type: TrainEntity }) |   @ApiNoContentResponse({ description: "Le trajet en train a bien été supprimé" }) | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   @ApiNotFoundResponse({ description: "Objet non trouvé" }) |  | ||||||
|   async remove(@Param('id') id: string) { |   async remove(@Param('id') id: string) { | ||||||
|     await this.trainsService.remove(id) |     await this.trainsService.remove(id) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Importation d'un trajet en train à partir de Rail Planner | ||||||
|  |    *  | ||||||
|  |    * @throws {401} Non authentifié⋅e | ||||||
|  |    * @throws {422} Le voyage Interrail à importer contient plusieurs trajets ou plusieurs trains | ||||||
|  |    */ | ||||||
|   @Post("/import") |   @Post("/import") | ||||||
|   @HttpCode(201) |   @HttpCode(201) | ||||||
|   @UseGuards(JwtAuthGuard) |   @UseGuards(JwtAuthGuard) | ||||||
|   @ApiBearerAuth() |   @ApiBearerAuth() | ||||||
|   @ApiCreatedResponse({ type: TrainEntity, description: "Train importé avec succès" }) |  | ||||||
|   @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) |  | ||||||
|   @ApiForbiddenResponse({ description: "Permission refusée" }) |  | ||||||
|   async import(@Req() request: AuthenticatedRequest, @Body() importTrainDto: ImportTrainDto): Promise<TrainEntity> { |   async import(@Req() request: AuthenticatedRequest, @Body() importTrainDto: ImportTrainDto): Promise<TrainEntity> { | ||||||
|     const train = await this.trainsService.import(request.user, importTrainDto) |     const train = await this.trainsService.import(request.user, importTrainDto) | ||||||
|     return new TrainEntity(train) |     return new TrainEntity(train) | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import { Injectable, NotAcceptableException } from '@nestjs/common' | import { Injectable, NotFoundException, UnprocessableEntityException } from '@nestjs/common' | ||||||
| import { CreateTrainDto } from './dto/create-train.dto' | import { CreateTrainDto } from './dto/create-train.dto' | ||||||
| import { UpdateTrainDto } from './dto/update-train.dto' | import { UpdateTrainDto } from './dto/update-train.dto' | ||||||
| import { PrismaService } from 'src/prisma/prisma.service' | import { PrismaService } from 'src/prisma/prisma.service' | ||||||
| @@ -37,6 +37,8 @@ export class TrainsService { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   async update(id: string, updateTrainDto: UpdateTrainDto): Promise<TrainTrip> { |   async update(id: string, updateTrainDto: UpdateTrainDto): Promise<TrainTrip> { | ||||||
|  |     if (!this.findOne(id)) | ||||||
|  |       throw new NotFoundException(`Le train à modifier n'existe pas avec l'identifiant ${id}`) | ||||||
|     return await this.prisma.trainTrip.update({ |     return await this.prisma.trainTrip.update({ | ||||||
|       where: { id }, |       where: { id }, | ||||||
|       data: updateTrainDto, |       data: updateTrainDto, | ||||||
| @@ -44,6 +46,8 @@ export class TrainsService { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   async remove(id: string): Promise<TrainTrip> { |   async remove(id: string): Promise<TrainTrip> { | ||||||
|  |     if (!this.findOne(id)) | ||||||
|  |       throw new NotFoundException(`Le train à supprimer n'existe pas avec l'identifiant ${id}`) | ||||||
|     return await this.prisma.trainTrip.delete({ |     return await this.prisma.trainTrip.delete({ | ||||||
|       where: { id }, |       where: { id }, | ||||||
|     }) |     }) | ||||||
| @@ -53,10 +57,10 @@ export class TrainsService { | |||||||
|     const interrailResult: InterrailJourney = await fetch(`https://3uiwjsimnh.execute-api.eu-central-1.amazonaws.com/Prod/journey-import?id=${trainId}`) |     const interrailResult: InterrailJourney = await fetch(`https://3uiwjsimnh.execute-api.eu-central-1.amazonaws.com/Prod/journey-import?id=${trainId}`) | ||||||
|       .then(data => data.json()) |       .then(data => data.json()) | ||||||
|     if (interrailResult.data.travels.length !== 1) |     if (interrailResult.data.travels.length !== 1) | ||||||
|       throw new NotAcceptableException(`Ce voyage contient ${interrailResult.data.travels.length} trajets. Merci d'ajouter les trajets un à un.`) |       throw new UnprocessableEntityException(`Ce voyage contient ${interrailResult.data.travels.length} trajets. Merci d'ajouter les trajets un à un.`) | ||||||
|     const travel = interrailResult.data.travels[0] |     const travel = interrailResult.data.travels[0] | ||||||
|     if (travel.legs.length !== 1) |     if (travel.legs.length !== 1) | ||||||
|       throw new NotAcceptableException(`Ce trajet contient ${travel.legs.length} trains. Merci d'ajouter les trajets un à un.`) |       throw new UnprocessableEntityException(`Ce trajet contient ${travel.legs.length} trains. Merci d'ajouter les trajets un à un.`) | ||||||
|     const leg = travel.legs[0] |     const leg = travel.legs[0] | ||||||
|  |  | ||||||
|     const travelInfoJson: InterrailTravelInfo = JSON.parse(travel.infoJson) |     const travelInfoJson: InterrailTravelInfo = JSON.parse(travel.infoJson) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user