Ajout endpoints défis
This commit is contained in:
		@@ -4,9 +4,11 @@ import { PrismaModule } from './prisma/prisma.module'
 | 
			
		||||
import { UsersModule } from './users/users.module'
 | 
			
		||||
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'
 | 
			
		||||
 | 
			
		||||
@Module({
 | 
			
		||||
  imports: [PrismaModule, UsersModule, AuthModule, GeolocationsModule],
 | 
			
		||||
  imports: [PrismaModule, UsersModule, AuthModule, GeolocationsModule, ChallengesModule, ChallengeActionsModule],
 | 
			
		||||
  providers: [PrismaService],
 | 
			
		||||
})
 | 
			
		||||
export class AppModule {}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,20 @@
 | 
			
		||||
import { Test, TestingModule } from '@nestjs/testing'
 | 
			
		||||
import { ChallengeActionsController } from './challenge-actions.controller'
 | 
			
		||||
import { ChallengeActionsService } from './challenge-actions.service'
 | 
			
		||||
 | 
			
		||||
describe('ChallengeActionsController', () => {
 | 
			
		||||
  let controller: ChallengeActionsController
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    const module: TestingModule = await Test.createTestingModule({
 | 
			
		||||
      controllers: [ChallengeActionsController],
 | 
			
		||||
      providers: [ChallengeActionsService],
 | 
			
		||||
    }).compile()
 | 
			
		||||
 | 
			
		||||
    controller = module.get<ChallengeActionsController>(ChallengeActionsController)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('should be defined', () => {
 | 
			
		||||
    expect(controller).toBeDefined()
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										76
									
								
								server/src/challenge-actions/challenge-actions.controller.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								server/src/challenge-actions/challenge-actions.controller.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
import { Controller, Get, Post, Body, Patch, Param, Delete, ParseIntPipe, HttpCode, UseGuards, Req, Query, NotFoundException } from '@nestjs/common'
 | 
			
		||||
import { ChallengeActionsService } from './challenge-actions.service'
 | 
			
		||||
import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard'
 | 
			
		||||
import { ApiBearerAuth, ApiCreatedResponse, ApiForbiddenResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger'
 | 
			
		||||
import { ChallengeActionEntity } from './entities/challenge-action.entity'
 | 
			
		||||
import { CreateChallengeActionDto } from './dto/create-challenge-action.dto'
 | 
			
		||||
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'
 | 
			
		||||
import { UpdateChallengeActionDto } from './dto/update-challenge-action.dto'
 | 
			
		||||
 | 
			
		||||
@Controller('challenge-actions')
 | 
			
		||||
export class ChallengeActionsController {
 | 
			
		||||
  constructor(private readonly challengeActionsService: ChallengeActionsService) {}
 | 
			
		||||
 | 
			
		||||
  @Post()
 | 
			
		||||
  @HttpCode(201)
 | 
			
		||||
  @UseGuards(JwtAuthGuard)
 | 
			
		||||
  @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> {
 | 
			
		||||
    const user = request.user
 | 
			
		||||
    const challenge = await this.challengeActionsService.create(user, createChallengeActionDto)
 | 
			
		||||
    return new ChallengeActionEntity(challenge)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Get()
 | 
			
		||||
  @UseGuards(JwtAuthGuard)
 | 
			
		||||
  @ApiBearerAuth()
 | 
			
		||||
  @ApiOkResponsePaginated(ChallengeActionEntity)
 | 
			
		||||
  @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
 | 
			
		||||
  @ApiForbiddenResponse({ description: "Permission refusée" })
 | 
			
		||||
  async findAll(@Query() queryPagination?: QueryPaginationDto): Promise<PaginateOutputDto<ChallengeActionEntity>> {
 | 
			
		||||
    const [challengeActions, total] = await this.challengeActionsService.findAll(queryPagination)
 | 
			
		||||
    return paginateOutput<ChallengeActionEntity>(challengeActions.map(challengeAction => new ChallengeActionEntity(challengeAction)), total, queryPagination)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Get(':id')
 | 
			
		||||
  @UseGuards(JwtAuthGuard)
 | 
			
		||||
  @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> {
 | 
			
		||||
    const challenge = await this.challengeActionsService.findOne(id)
 | 
			
		||||
    if (!challenge)
 | 
			
		||||
      throw new NotFoundException(`Défi inexistant avec l'identifiant ${id}`)
 | 
			
		||||
    return new ChallengeActionEntity(challenge)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Patch(':id')
 | 
			
		||||
  @UseGuards(JwtAuthGuard)
 | 
			
		||||
  @ApiBearerAuth()
 | 
			
		||||
  @ApiOkResponse({ type: 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)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Delete(':id')
 | 
			
		||||
  @HttpCode(204)
 | 
			
		||||
  @UseGuards(JwtAuthGuard)
 | 
			
		||||
  @ApiBearerAuth()
 | 
			
		||||
  @ApiOkResponse({ type: ChallengeActionEntity })
 | 
			
		||||
  @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
 | 
			
		||||
  @ApiForbiddenResponse({ description: "Permission refusée" })
 | 
			
		||||
  @ApiNotFoundResponse({ description: "Objet non trouvé" })
 | 
			
		||||
  async remove(@Param('id', ParseIntPipe) id: number) {
 | 
			
		||||
    await this.challengeActionsService.remove(id)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								server/src/challenge-actions/challenge-actions.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								server/src/challenge-actions/challenge-actions.module.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
import { Module } from '@nestjs/common'
 | 
			
		||||
import { ChallengeActionsService } from './challenge-actions.service'
 | 
			
		||||
import { ChallengeActionsController } from './challenge-actions.controller'
 | 
			
		||||
import { PrismaModule } from 'src/prisma/prisma.module'
 | 
			
		||||
 | 
			
		||||
@Module({
 | 
			
		||||
  controllers: [ChallengeActionsController],
 | 
			
		||||
  providers: [ChallengeActionsService],
 | 
			
		||||
  imports: [PrismaModule],
 | 
			
		||||
})
 | 
			
		||||
export class ChallengeActionsModule {}
 | 
			
		||||
@@ -0,0 +1,18 @@
 | 
			
		||||
import { Test, TestingModule } from '@nestjs/testing'
 | 
			
		||||
import { ChallengeActionsService } from './challenge-actions.service'
 | 
			
		||||
 | 
			
		||||
describe('ChallengeActionsService', () => {
 | 
			
		||||
  let service: ChallengeActionsService
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    const module: TestingModule = await Test.createTestingModule({
 | 
			
		||||
      providers: [ChallengeActionsService],
 | 
			
		||||
    }).compile()
 | 
			
		||||
 | 
			
		||||
    service = module.get<ChallengeActionsService>(ChallengeActionsService)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('should be defined', () => {
 | 
			
		||||
    expect(service).toBeDefined()
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										41
									
								
								server/src/challenge-actions/challenge-actions.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								server/src/challenge-actions/challenge-actions.service.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
import { Injectable } from '@nestjs/common'
 | 
			
		||||
import { CreateChallengeActionDto } from './dto/create-challenge-action.dto'
 | 
			
		||||
import { UpdateChallengeActionDto } from './dto/update-challenge-action.dto'
 | 
			
		||||
import { ChallengeAction, User } from '@prisma/client'
 | 
			
		||||
import { PrismaService } from 'src/prisma/prisma.service'
 | 
			
		||||
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
 | 
			
		||||
import { paginate } from 'src/common/utils/pagination.utils'
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class ChallengeActionsService {
 | 
			
		||||
  constructor(private prisma: PrismaService) { }
 | 
			
		||||
 | 
			
		||||
  async create(authenticatedUser: User, createChallengeActionDto: CreateChallengeActionDto): Promise<ChallengeAction> {
 | 
			
		||||
    const data = { ...createChallengeActionDto, userId: authenticatedUser.id }
 | 
			
		||||
    return await this.prisma.challengeAction.create({ data: data })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async findAll(queryPagination?: QueryPaginationDto): Promise<[ChallengeAction[], number]> {
 | 
			
		||||
    return [
 | 
			
		||||
      await this.prisma.challengeAction.findMany({
 | 
			
		||||
        ...paginate(queryPagination),
 | 
			
		||||
      }),
 | 
			
		||||
      await this.prisma.challenge.count(),
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async findOne(id: number): Promise<ChallengeAction> {
 | 
			
		||||
    return await this.prisma.challengeAction.findUnique({ where: { id } })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async update(id: number, updateChallengeActionDto: UpdateChallengeActionDto): Promise<ChallengeAction> {
 | 
			
		||||
    return await this.prisma.challengeAction.update({
 | 
			
		||||
      where: { id },
 | 
			
		||||
      data: updateChallengeActionDto,
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async remove(id: number): Promise<ChallengeAction> {
 | 
			
		||||
    return await this.prisma.challengeAction.delete({ where: { id } })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,20 @@
 | 
			
		||||
import { ApiProperty } from "@nestjs/swagger"
 | 
			
		||||
import { Type } from "class-transformer"
 | 
			
		||||
import { IsBoolean, IsInt } from "class-validator"
 | 
			
		||||
 | 
			
		||||
export class CreateChallengeActionDto {
 | 
			
		||||
  @IsInt()
 | 
			
		||||
  @Type(() => Number)
 | 
			
		||||
  @ApiProperty({ description: "Identifiant du défi rattaché à l'action" })
 | 
			
		||||
  challengeId: number
 | 
			
		||||
 | 
			
		||||
  @IsBoolean()
 | 
			
		||||
  @Type(() => Boolean)
 | 
			
		||||
  @ApiProperty({ description: "Est-ce que le défi est actuellement en train d'être réalisé" })
 | 
			
		||||
  active: boolean
 | 
			
		||||
 | 
			
		||||
  @IsBoolean()
 | 
			
		||||
  @Type(() => Boolean)
 | 
			
		||||
  @ApiProperty({ description: "Est-ce que le défi a été réussi" })
 | 
			
		||||
  success: boolean
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,4 @@
 | 
			
		||||
import { PartialType } from '@nestjs/swagger'
 | 
			
		||||
import { CreateChallengeActionDto } from './create-challenge-action.dto'
 | 
			
		||||
 | 
			
		||||
export class UpdateChallengeActionDto extends PartialType(CreateChallengeActionDto) {}
 | 
			
		||||
@@ -0,0 +1,23 @@
 | 
			
		||||
import { ApiProperty } from "@nestjs/swagger"
 | 
			
		||||
import { ChallengeAction } from "@prisma/client"
 | 
			
		||||
 | 
			
		||||
export class ChallengeActionEntity implements ChallengeAction {
 | 
			
		||||
  constructor(partial: Partial<ChallengeActionEntity>) {
 | 
			
		||||
    Object.assign(this, partial)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @ApiProperty({ description: "Identifiant unique" })
 | 
			
		||||
  id: number
 | 
			
		||||
 | 
			
		||||
  @ApiProperty({ description: "Identifiant de l'utilisateur⋅rice effectuant le défi" })
 | 
			
		||||
  userId: number
 | 
			
		||||
 | 
			
		||||
  @ApiProperty({ description: "Identifiant du défi rattaché à l'action" })
 | 
			
		||||
  challengeId: number
 | 
			
		||||
 | 
			
		||||
  @ApiProperty({ description: "Est-ce que le défi est actuellement en train d'être réalisé" })
 | 
			
		||||
  active: boolean
 | 
			
		||||
 | 
			
		||||
  @ApiProperty({ description: "Est-ce que le défi a été réussi" })
 | 
			
		||||
  success: boolean
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										20
									
								
								server/src/challenges/challenges.controller.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								server/src/challenges/challenges.controller.spec.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
import { Test, TestingModule } from '@nestjs/testing'
 | 
			
		||||
import { ChallengesController } from './challenges.controller'
 | 
			
		||||
import { ChallengesService } from './challenges.service'
 | 
			
		||||
 | 
			
		||||
describe('ChallengesController', () => {
 | 
			
		||||
  let controller: ChallengesController
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    const module: TestingModule = await Test.createTestingModule({
 | 
			
		||||
      controllers: [ChallengesController],
 | 
			
		||||
      providers: [ChallengesService],
 | 
			
		||||
    }).compile()
 | 
			
		||||
 | 
			
		||||
    controller = module.get<ChallengesController>(ChallengesController)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('should be defined', () => {
 | 
			
		||||
    expect(controller).toBeDefined()
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										75
									
								
								server/src/challenges/challenges.controller.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								server/src/challenges/challenges.controller.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
import { Controller, Get, Post, Body, Patch, Param, Delete, ParseIntPipe, HttpCode, UseGuards, Req, Query, NotFoundException } from '@nestjs/common'
 | 
			
		||||
import { ChallengesService } from './challenges.service'
 | 
			
		||||
import { CreateChallengeDto } from './dto/create-challenge.dto'
 | 
			
		||||
import { UpdateChallengeDto } from './dto/update-challenge.dto'
 | 
			
		||||
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard'
 | 
			
		||||
import { ApiBearerAuth, ApiCreatedResponse, ApiForbiddenResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger'
 | 
			
		||||
import { ChallengeEntity } from './entities/challenge.entity'
 | 
			
		||||
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('challenges')
 | 
			
		||||
export class ChallengesController {
 | 
			
		||||
  constructor(private readonly challengesService: ChallengesService) {}
 | 
			
		||||
 | 
			
		||||
  @Post()
 | 
			
		||||
  @HttpCode(201)
 | 
			
		||||
  @UseGuards(JwtAuthGuard)
 | 
			
		||||
  @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> {
 | 
			
		||||
    const challenge = await this.challengesService.create(createChallengeDto)
 | 
			
		||||
    return new ChallengeEntity(challenge)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Get()
 | 
			
		||||
  @UseGuards(JwtAuthGuard)
 | 
			
		||||
  @ApiBearerAuth()
 | 
			
		||||
  @ApiOkResponsePaginated(ChallengeEntity)
 | 
			
		||||
  @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
 | 
			
		||||
  @ApiForbiddenResponse({ description: "Permission refusée" })
 | 
			
		||||
  async findAll(@Query() queryPagination?: QueryPaginationDto): Promise<PaginateOutputDto<ChallengeEntity>> {
 | 
			
		||||
    const [challenges, total] = await this.challengesService.findAll(queryPagination)
 | 
			
		||||
    return paginateOutput<ChallengeEntity>(challenges.map(challenge => new ChallengeEntity(challenge)), total, queryPagination)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Get(':id')
 | 
			
		||||
  @UseGuards(JwtAuthGuard)
 | 
			
		||||
  @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> {
 | 
			
		||||
    const challenge = await this.challengesService.findOne(id)
 | 
			
		||||
    if (!challenge)
 | 
			
		||||
      throw new NotFoundException(`Défi inexistant avec l'identifiant ${id}`)
 | 
			
		||||
    return new ChallengeEntity(challenge)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Patch(':id')
 | 
			
		||||
  @UseGuards(JwtAuthGuard)
 | 
			
		||||
  @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) {
 | 
			
		||||
    return await this.challengesService.update(id, updateChallengeDto)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Delete(':id')
 | 
			
		||||
  @HttpCode(204)
 | 
			
		||||
  @UseGuards(JwtAuthGuard)
 | 
			
		||||
  @ApiBearerAuth()
 | 
			
		||||
  @ApiOkResponse({ type: ChallengeEntity })
 | 
			
		||||
  @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
 | 
			
		||||
  @ApiForbiddenResponse({ description: "Permission refusée" })
 | 
			
		||||
  @ApiNotFoundResponse({ description: "Objet non trouvé" })
 | 
			
		||||
  async remove(@Param('id', ParseIntPipe) id: number) {
 | 
			
		||||
    await this.challengesService.remove(id)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								server/src/challenges/challenges.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								server/src/challenges/challenges.module.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
import { Module } from '@nestjs/common'
 | 
			
		||||
import { ChallengesService } from './challenges.service'
 | 
			
		||||
import { ChallengesController } from './challenges.controller'
 | 
			
		||||
import { PrismaModule } from 'src/prisma/prisma.module'
 | 
			
		||||
 | 
			
		||||
@Module({
 | 
			
		||||
  controllers: [ChallengesController],
 | 
			
		||||
  providers: [ChallengesService],
 | 
			
		||||
  imports: [PrismaModule],
 | 
			
		||||
})
 | 
			
		||||
export class ChallengesModule {}
 | 
			
		||||
							
								
								
									
										18
									
								
								server/src/challenges/challenges.service.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								server/src/challenges/challenges.service.spec.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
import { Test, TestingModule } from '@nestjs/testing'
 | 
			
		||||
import { ChallengesService } from './challenges.service'
 | 
			
		||||
 | 
			
		||||
describe('ChallengesService', () => {
 | 
			
		||||
  let service: ChallengesService
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    const module: TestingModule = await Test.createTestingModule({
 | 
			
		||||
      providers: [ChallengesService],
 | 
			
		||||
    }).compile()
 | 
			
		||||
 | 
			
		||||
    service = module.get<ChallengesService>(ChallengesService)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('should be defined', () => {
 | 
			
		||||
    expect(service).toBeDefined()
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										41
									
								
								server/src/challenges/challenges.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								server/src/challenges/challenges.service.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
import { Injectable } from '@nestjs/common'
 | 
			
		||||
import { CreateChallengeDto } from './dto/create-challenge.dto'
 | 
			
		||||
import { UpdateChallengeDto } from './dto/update-challenge.dto'
 | 
			
		||||
import { Challenge } from '@prisma/client'
 | 
			
		||||
import { PrismaService } from 'src/prisma/prisma.service'
 | 
			
		||||
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
 | 
			
		||||
import { paginate } from 'src/common/utils/pagination.utils'
 | 
			
		||||
 | 
			
		||||
@Injectable()
 | 
			
		||||
export class ChallengesService {
 | 
			
		||||
  constructor(private prisma: PrismaService) { }
 | 
			
		||||
 | 
			
		||||
  async create(createChallengeDto: CreateChallengeDto): Promise<Challenge> {
 | 
			
		||||
    const data = { ...createChallengeDto }
 | 
			
		||||
    return await this.prisma.challenge.create({ data: data })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async findAll(queryPagination?: QueryPaginationDto): Promise<[Challenge[], number]> {
 | 
			
		||||
    return [
 | 
			
		||||
      await this.prisma.challenge.findMany({
 | 
			
		||||
        ...paginate(queryPagination),
 | 
			
		||||
      }),
 | 
			
		||||
      await this.prisma.challenge.count(),
 | 
			
		||||
    ]
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async findOne(id: number): Promise<Challenge> {
 | 
			
		||||
    return await this.prisma.challenge.findUnique({ where: { id } })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async update(id: number, updateChallengeDto: UpdateChallengeDto): Promise<Challenge> {
 | 
			
		||||
    return await this.prisma.challenge.update({
 | 
			
		||||
      where: { id },
 | 
			
		||||
      data: updateChallengeDto,
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async remove(id: number): Promise<Challenge> {
 | 
			
		||||
    return await this.prisma.challenge.delete({ where: { id } })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								server/src/challenges/dto/create-challenge.dto.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								server/src/challenges/dto/create-challenge.dto.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
import { ApiProperty } from "@nestjs/swagger"
 | 
			
		||||
import { Type } from "class-transformer"
 | 
			
		||||
import { IsInt, IsString } from "class-validator"
 | 
			
		||||
 | 
			
		||||
export class CreateChallengeDto {
 | 
			
		||||
  @IsString()
 | 
			
		||||
  @ApiProperty({ description: "Titre du défi" })
 | 
			
		||||
  title: string
 | 
			
		||||
 | 
			
		||||
  @IsString()
 | 
			
		||||
  @ApiProperty({ description: "Description du défi, de l'action à réaliser" })
 | 
			
		||||
  description: string
 | 
			
		||||
 | 
			
		||||
  @IsInt()
 | 
			
		||||
  @Type(() => Number)
 | 
			
		||||
  @ApiProperty({ description: "Récompense en nombre de points en cas de réussite de læ joueur⋅se" })
 | 
			
		||||
  reward: number
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								server/src/challenges/dto/update-challenge.dto.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								server/src/challenges/dto/update-challenge.dto.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
import { PartialType } from '@nestjs/swagger'
 | 
			
		||||
import { CreateChallengeDto } from './create-challenge.dto'
 | 
			
		||||
 | 
			
		||||
export class UpdateChallengeDto extends PartialType(CreateChallengeDto) {}
 | 
			
		||||
							
								
								
									
										20
									
								
								server/src/challenges/entities/challenge.entity.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								server/src/challenges/entities/challenge.entity.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
import { ApiProperty } from "@nestjs/swagger"
 | 
			
		||||
import { Challenge } from "@prisma/client"
 | 
			
		||||
 | 
			
		||||
export class ChallengeEntity implements Challenge {
 | 
			
		||||
  constructor(partial: Partial<ChallengeEntity>) {
 | 
			
		||||
    Object.assign(this, partial)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @ApiProperty({ description: "Identifiant unique" })
 | 
			
		||||
  id: number
 | 
			
		||||
 | 
			
		||||
  @ApiProperty({ description: "Titre du challenger" })
 | 
			
		||||
  title: string
 | 
			
		||||
 | 
			
		||||
  @ApiProperty({ description: "Description du challenge, de l'action à réaliser" })
 | 
			
		||||
  description: string
 | 
			
		||||
 | 
			
		||||
  @ApiProperty({ description: "Récompense en nombre de points en cas de réussite du challenger" })
 | 
			
		||||
  reward: number
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import { Type } from "class-transformer";
 | 
			
		||||
import { IsNumber, IsOptional } from "class-validator";
 | 
			
		||||
import { Type } from "class-transformer"
 | 
			
		||||
import { IsNumber, IsOptional } from "class-validator"
 | 
			
		||||
 | 
			
		||||
export class UserFilterDto {
 | 
			
		||||
  @IsOptional()
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,6 @@ export class GeolocationsController {
 | 
			
		||||
  @ApiCreatedResponse({ type: GeolocationEntity, description: "Objet créé avec succès" })
 | 
			
		||||
  @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
 | 
			
		||||
  @ApiForbiddenResponse({ description: "Permission refusée" })
 | 
			
		||||
  @ApiNotFoundResponse({ description: "Object non trouvé" })
 | 
			
		||||
  async create(@Req() request: AuthenticatedRequest, @Body() createGeolocationDto: CreateGeolocationDto): Promise<GeolocationEntity> {
 | 
			
		||||
    const user = request.user
 | 
			
		||||
    const geolocation = await this.geolocationsService.create(user, createGeolocationDto)
 | 
			
		||||
@@ -33,7 +32,6 @@ export class GeolocationsController {
 | 
			
		||||
  @ApiOkResponsePaginated(GeolocationEntity)
 | 
			
		||||
  @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
 | 
			
		||||
  @ApiForbiddenResponse({ description: "Permission refusée" })
 | 
			
		||||
  @ApiNotFoundResponse({ description: "Objet non trouvé" })
 | 
			
		||||
  async findAll(@Query() queryPagination?: QueryPaginationDto, @Query() userFilter?: UserFilterDto): Promise<PaginateOutputDto<GeolocationEntity>> {
 | 
			
		||||
    const [geolocations, total] = await this.geolocationsService.findAll(queryPagination, userFilter)
 | 
			
		||||
    return paginateOutput<GeolocationEntity>(geolocations.map(geolocation => new GeolocationEntity(geolocation)), total, queryPagination)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
import { Injectable } from '@nestjs/common'
 | 
			
		||||
import { CreateGeolocationDto } from './dto/create-geolocation.dto'
 | 
			
		||||
import { PrismaService } from 'src/prisma/prisma.service'
 | 
			
		||||
import { Geolocation, User } from '@prisma/client'
 | 
			
		||||
import { Geolocation, Prisma, User } from '@prisma/client'
 | 
			
		||||
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
 | 
			
		||||
import { paginate } from 'src/common/utils/pagination.utils'
 | 
			
		||||
import { UserFilterDto } from 'src/common/dto/user_filter.dto'
 | 
			
		||||
@@ -17,7 +17,8 @@ export class GeolocationsService {
 | 
			
		||||
 | 
			
		||||
  async findAll(queryPagination?: QueryPaginationDto, userFilter?: UserFilterDto): Promise<[Geolocation[], number]> {
 | 
			
		||||
    const filter = {
 | 
			
		||||
      where: userFilter?.userId ? { userId: userFilter.userId } : {}
 | 
			
		||||
      where: (userFilter?.userId ? { userId: userFilter.userId } : {}),
 | 
			
		||||
      orderBy: { timestamp: Prisma.SortOrder.desc },
 | 
			
		||||
    }
 | 
			
		||||
    return [
 | 
			
		||||
      await this.prisma.geolocation.findMany({
 | 
			
		||||
@@ -35,7 +36,7 @@ export class GeolocationsService {
 | 
			
		||||
  async findLastLocation(userId: number): Promise<Geolocation> {
 | 
			
		||||
    return await this.prisma.geolocation.findFirst({
 | 
			
		||||
      where: { userId: userId },
 | 
			
		||||
      orderBy: { timestamp: "desc" },
 | 
			
		||||
      orderBy: { timestamp: Prisma.SortOrder.desc },
 | 
			
		||||
      take: 1
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user