diff --git a/src/controllers/participations.controller.ts b/src/controllers/participations.controller.ts index 60e2bbf..fb035cf 100644 --- a/src/controllers/participations.controller.ts +++ b/src/controllers/participations.controller.ts @@ -1,4 +1,12 @@ -import { Body, Controller, Post } from "@nestjs/common"; +import { + Body, + Controller, + Delete, + Get, + NotFoundException, + Param, + Post, +} from "@nestjs/common"; import { CurrentMemberDecorator } from "@APP/common/decorators/current-member.decorator"; import { CreateParticipationDto } from "@APP/dtos/create-participation.dto"; @@ -12,6 +20,23 @@ export class ParticipationsController { private readonly articlesService: ArticlesService, ) {} + @Get(":participationId") + async getParticipation( + @Param("participationId") participationId: number, + @CurrentMemberDecorator("id") currentMemberId: number, + ) { + const participation = await this.participationsService.getParticipation( + participationId, + currentMemberId, + ); + + if (!participation) { + throw new NotFoundException("참여 정보를 찾을 수 없습니다."); + } + + return participation; + } + @Post() async postParticipation( @Body() body: CreateParticipationDto, @@ -24,4 +49,15 @@ export class ParticipationsController { body, ); } + + @Delete(":participationId") + async deleteParticipation( + @Param("participationId") participationId: number, + @CurrentMemberDecorator("id") currentMemberId: number, + ) { + return await this.participationsService.deleteParticipation( + participationId, + currentMemberId, + ); + } } diff --git a/src/services/participations.service.ts b/src/services/participations.service.ts index 16f86a1..cf502a7 100644 --- a/src/services/participations.service.ts +++ b/src/services/participations.service.ts @@ -1,5 +1,10 @@ -import { Injectable } from "@nestjs/common"; +import { + ConflictException, + Injectable, + NotFoundException, +} from "@nestjs/common"; +import { ParticipationStatus } from "@APP/common/enum/participation-status.enum"; import { CreateParticipationDto } from "@APP/dtos/create-participation.dto"; import { ParticipationRepository } from "@APP/repositories/participation.repository"; @@ -9,25 +14,79 @@ export class ParticipationsService { private readonly participationsRepository: ParticipationRepository, ) {} + async getParticipation(participationId: number, currentMemberId: number) { + return await this.participationsRepository.findOne({ + where: { id: participationId, memberId: currentMemberId }, + }); + } + async createParticipation( currentMemberId: number, body: CreateParticipationDto, ) { - const newParticipation = this.createParticipationEntity( - currentMemberId, - body, - ); + const participation = await this.participationsRepository.findOne({ + where: { + memberId: currentMemberId, + articleId: body.articleId, + }, + }); + + if (!participation) { + const newParticipation = this.createParticipationEntity( + currentMemberId, + body, + ); + + return await this.participationsRepository.save(newParticipation); + } + + if (participation.status === ParticipationStatus.CANCELLED) { + const updatedParticipation = this.createParticipationEntity( + currentMemberId, + body, + ParticipationStatus.ACTIVE, + ); + + return await this.participationsRepository.save( + updatedParticipation, + ); + } - return await this.participationsRepository.save(newParticipation); + throw new ConflictException("이미 참여한 게시글입니다."); } private createParticipationEntity( currentMemberId: number, body: CreateParticipationDto, + status?: ParticipationStatus, ) { return this.participationsRepository.create({ memberId: currentMemberId, ...body, + status, }); } + + async deleteParticipation( + participationId: number, + currentMemberId: number, + ) { + const participation = await this.participationsRepository.findOne({ + where: { id: participationId, memberId: currentMemberId }, + }); + + if (!participation) { + throw new NotFoundException("참여 정보를 찾을 수 없습니다."); + } + + await this.participationsRepository.update( + { + id: participationId, + memberId: currentMemberId, + }, + { + status: ParticipationStatus.CANCELLED, + }, + ); + } }