Ajout endpoint mise à jour de solde

This commit is contained in:
Emmy D'Anello 2024-12-08 02:23:37 +01:00
parent 7fd2c4d7fe
commit 6a0b4049b6
Signed by: ynerant
GPG Key ID: 3A75C55819C8CF85
11 changed files with 250 additions and 6 deletions

View File

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

View File

@ -0,0 +1,31 @@
import { ApiProperty } from "@nestjs/swagger"
import { MoneyUpdateType } from "@prisma/client"
import { Type } from "class-transformer"
import { IsEnum, IsInt, IsOptional, IsUUID } from "class-validator"
export class CreateMoneyUpdateDto {
@IsInt()
@Type(() => Number)
@ApiProperty({ description: "Solde avant modification" })
before: number
@IsInt()
@Type(() => Number)
@ApiProperty({ description: "Solde après modification" })
after: number
@IsEnum(MoneyUpdateType)
@ApiProperty({ description: "Type de modification de solde" })
reason: MoneyUpdateType
@IsOptional()
@IsInt()
@Type(() => Number)
@ApiProperty({ description: "Identifiant de la réalisation de défi, si la mise à jour est liée à un défi", nullable: true })
actionId?: number
@IsOptional()
@IsUUID()
@ApiProperty({ description: "Identifiant du trajet acheté, si la mise à jour est liée à la réservation d'un train", nullable: true })
tripId?: string
}

View File

@ -0,0 +1,4 @@
import { PartialType } from '@nestjs/swagger'
import { CreateMoneyUpdateDto } from './create-money-update.dto'
export class UpdateMoneyUpdateDto extends PartialType(CreateMoneyUpdateDto) {}

View File

@ -0,0 +1,30 @@
import { ApiProperty } from "@nestjs/swagger"
import { MoneyUpdate, MoneyUpdateType } from "@prisma/client"
import { IsOptional } from "class-validator"
export class MoneyUpdateEntity implements MoneyUpdate {
constructor (partial: Partial<MoneyUpdateEntity>) {
Object.assign(this, partial)
}
@ApiProperty({ description: "Identifiant unique de la mise à jour de solde" })
id: number
@ApiProperty({ description: "Utilisateur⋅rice concerné⋅e par la mise à jour de solde" })
userId: number
@ApiProperty({ description: "Solde avant modification" })
before: number
@ApiProperty({ description: "Solde après modification" })
after: number
@ApiProperty({ description: "Type de modification de solde" })
reason: MoneyUpdateType
@ApiProperty({ description: "Identifiant de la réalisation de défi, si la mise à jour est liée à un défi", nullable: true })
actionId: number
@ApiProperty({ description: "Identifiant du trajet acheté, si la mise à jour est liée à la réservation d'un train", nullable: true })
tripId: string
}

View File

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

View File

@ -0,0 +1,76 @@
import { Controller, Get, Post, Body, Patch, Param, Delete, HttpCode, UseGuards, Query, NotFoundException, ParseIntPipe, Req } from '@nestjs/common'
import { MoneyUpdatesService } from './money-updates.service'
import { CreateMoneyUpdateDto } from './dto/create-money-update.dto'
import { UpdateMoneyUpdateDto } from './dto/update-money-update.dto'
import { AuthenticatedRequest, JwtAuthGuard } from 'src/auth/jwt-auth.guard'
import { ApiBearerAuth, ApiCreatedResponse, ApiForbiddenResponse, ApiNotFoundResponse, ApiOkResponse, ApiUnauthorizedResponse } from '@nestjs/swagger'
import { MoneyUpdateEntity } from './entities/money-update.entity'
import { ApiOkResponsePaginated, paginateOutput } from 'src/common/utils/pagination.utils'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { UserFilterDto } from 'src/common/dto/user_filter.dto'
import { PaginateOutputDto } from 'src/common/dto/pagination-output.dto'
@Controller('money-updates')
export class MoneyUpdatesController {
constructor(private readonly moneyUpdatesService: MoneyUpdatesService) {}
@Post()
@HttpCode(201)
@UseGuards(JwtAuthGuard)
@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> {
const moneyUpdate = await this.moneyUpdatesService.create(request.user, createMoneyUpdateDto)
return new MoneyUpdateEntity(moneyUpdate)
}
@Get()
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOkResponsePaginated(MoneyUpdateEntity)
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" })
async findAll(@Query() queryPagination: QueryPaginationDto, @Query() userFilter: UserFilterDto): Promise<PaginateOutputDto<MoneyUpdateEntity>> {
const [trains, total] = await this.moneyUpdatesService.findAll(queryPagination, userFilter)
return paginateOutput<MoneyUpdateEntity>(trains.map(train => new MoneyUpdateEntity(train)), total, queryPagination)
}
@Get(':id')
@UseGuards(JwtAuthGuard)
@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> {
const train = await this.moneyUpdatesService.findOne(id)
if (!train)
throw new NotFoundException(`Trajet en train inexistant avec l'identifiant ${id}`)
return new MoneyUpdateEntity(train)
}
@Patch(':id')
@UseGuards(JwtAuthGuard)
@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) {
return await this.moneyUpdatesService.update(id, updateMoneyUpdateDto)
}
@Delete(':id')
@HttpCode(204)
@UseGuards(JwtAuthGuard)
@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) {
await this.moneyUpdatesService.remove(id)
}
}

View File

@ -0,0 +1,11 @@
import { Module } from '@nestjs/common'
import { MoneyUpdatesService } from './money-updates.service'
import { MoneyUpdatesController } from './money-updates.controller'
import { PrismaModule } from 'src/prisma/prisma.module'
@Module({
controllers: [MoneyUpdatesController],
providers: [MoneyUpdatesService],
imports: [PrismaModule],
})
export class MoneyUpdatesModule {}

View File

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

View File

@ -0,0 +1,53 @@
import { Injectable } from '@nestjs/common'
import { CreateMoneyUpdateDto } from './dto/create-money-update.dto'
import { UpdateMoneyUpdateDto } from './dto/update-money-update.dto'
import { PrismaService } from 'src/prisma/prisma.service'
import { MoneyUpdate, User } from '@prisma/client'
import { QueryPaginationDto } from 'src/common/dto/pagination-query.dto'
import { UserFilterDto } from 'src/common/dto/user_filter.dto'
import { paginate } from 'src/common/utils/pagination.utils'
@Injectable()
export class MoneyUpdatesService {
constructor(private prisma: PrismaService) { }
async create(user: User, createMoneyUpdateDto: CreateMoneyUpdateDto): Promise<MoneyUpdate> {
return await this.prisma.moneyUpdate.create({
data: {
...createMoneyUpdateDto,
userId: user.id,
}
})
}
async findAll(queryPagination: QueryPaginationDto, userFilter: UserFilterDto): Promise<[MoneyUpdate[], number]> {
return [
await this.prisma.moneyUpdate.findMany({
where: userFilter,
...paginate(queryPagination),
}),
await this.prisma.moneyUpdate.count({
where: userFilter,
}),
]
}
async findOne(id: number): Promise<MoneyUpdate> {
return await this.prisma.moneyUpdate.findUnique({
where: { id },
})
}
async update(id: number, updateMoneyUpdateDto: UpdateMoneyUpdateDto): Promise<MoneyUpdate> {
return await this.prisma.moneyUpdate.update({
where: { id },
data: updateMoneyUpdateDto,
})
}
async remove(id: number): Promise<MoneyUpdate> {
return await this.prisma.moneyUpdate.delete({
where: { id },
})
}
}

View File

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

View File

@ -59,8 +59,8 @@ export class TrainsController {
@ApiUnauthorizedResponse({ description: "Non authentifié⋅e" }) @ApiUnauthorizedResponse({ description: "Non authentifié⋅e" })
@ApiForbiddenResponse({ description: "Permission refusée" }) @ApiForbiddenResponse({ description: "Permission refusée" })
@ApiNotFoundResponse({ description: "Objet non trouvé" }) @ApiNotFoundResponse({ description: "Objet non trouvé" })
async update(@Param('id') id: string, @Body() updateChallengeDto: UpdateTrainDto) { async update(@Param('id') id: string, @Body() updateTrainDto: UpdateTrainDto) {
return await this.trainsService.update(id, updateChallengeDto) return await this.trainsService.update(id, updateTrainDto)
} }
@Delete(':id') @Delete(':id')