Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 모집글 삭제, 참여 취소 API 구현 #209

Merged
merged 1 commit into from
Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class HttpRequestBodyInterceptor implements NestInterceptor {
try {
accessToken = accessToken.split("Bearer")[1].trim();
const { userIdx } = this.jwtService.verifyAccessToken(accessToken);
if (request.method === "GET") {
if (request.method === "GET" || request.method === "DELETE") {
request.params.userId = userIdx;
}
if (request.method === "POST") {
Expand Down
5 changes: 4 additions & 1 deletion server/src/common/repositories/user_recruit.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ export class UserRecruitRepository extends Repository<UserRecruit> {
return false;
}
public async countCurrentPpl(recruitId: number) {
return await this.countBy({ recruitId });
return this.countBy({ recruitId });
}
public createUserRecruit(userRecruitEntity: UserRecruit) {
this.save(userRecruitEntity);
}
public deleteUserRecruit(userRecruitEntity: UserRecruit) {
this.delete(userRecruitEntity);
}
}
21 changes: 21 additions & 0 deletions server/src/recruit/dto/request/delete-recruit.request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Expose, Type } from "class-transformer";
import { IsNumber } from "class-validator";

export class DeleteRecruitRequestDto {
@Type(() => Number)
@IsNumber()
@Expose({ name: "id" })
private recruitId: number;

@Type(() => Number)
@IsNumber()
private userId: number;

getRecruitId() {
return this.recruitId;
}

getUserId() {
return this.userId;
}
}
26 changes: 26 additions & 0 deletions server/src/recruit/dto/request/unjoin-recruit.request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Expose, Type } from "class-transformer";
import { IsNumber } from "class-validator";
import { UserRecruit } from "../../../common/entities/user_recruit.entity";

export class UnjoinRecruitRequestDto {
@Type(() => Number)
@IsNumber()
@Expose({ name: "id" })
private recruitId: number;

@Type(() => Number)
@IsNumber()
private userId: number;

getRecruitId() {
return this.recruitId;
}

getUserId() {
return this.userId;
}

toEntity() {
return UserRecruit.of(this.userId, this.recruitId);
}
}
54 changes: 44 additions & 10 deletions server/src/recruit/recruit.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Body, Controller, Get, Post, Query, Param } from "@nestjs/common";
import { Body, Controller, Get, Post, Query, Param, Delete } from "@nestjs/common";
import { CreateRecruitRequestDto } from "./dto/request/create-recruit.request";
import { GetRecruitsRequestDto } from "./dto/request/get-recruits.request";
import { JoinRecruitRequestDto } from "./dto/request/join-recruit.request";
Expand All @@ -9,6 +9,8 @@ import { ResponseEntity } from "../common/response/response.entity";
import { GetRecruitsResponseDto } from "./dto/response/get-recruits.response";
import { GetRecruitResponseDto } from "./dto/response/get-recruit.response";
import { GetRecruitRequestDto } from "./dto/request/get-recruit.request";
import { DeleteRecruitRequestDto } from "./dto/request/delete-recruit.request";
import { UnjoinRecruitRequestDto } from "./dto/request/unjoin-recruit.request";

@Controller("recruit")
@ApiTags("모집글 관리")
Expand All @@ -31,28 +33,60 @@ export class RecruitController {
return ResponseEntity.CREATED_WITH_DATA(createRecruitResponseDto);
}

@ApiOperation({ summary: "모집 취소", description: "모집을 취소한다" })
@Delete(":id")
async delete(@Param() deleteRecruitRequestDto: DeleteRecruitRequestDto) {
if (!(await this.recruitService.isExistingRecruit(deleteRecruitRequestDto.getRecruitId()))) {
return ResponseEntity.NOT_FOUND("존재하지 않는 게시글입니다");
}
if (
!(await this.recruitService.isAuthorOfRecruit(
deleteRecruitRequestDto.getRecruitId(),
deleteRecruitRequestDto.getUserId(),
))
) {
return ResponseEntity.LOCKED("자신의 게시글만 삭제할 수 있습니다");
}
this.recruitService.delete(deleteRecruitRequestDto);
return ResponseEntity.OK();
}

@ApiOperation({ summary: "모집 참가", description: "모집글에 참여한다" })
@Post("join")
async register(@Body() joinRecruitDto: JoinRecruitRequestDto) {
const recruitId = joinRecruitDto.getRecruitId();
const userId = joinRecruitDto.getUserId();

if (!(await this.recruitService.isExistingRecruit(recruitId))) {
async register(@Body() joinRecruitRequestDto: JoinRecruitRequestDto) {
if (!(await this.recruitService.isExistingRecruit(joinRecruitRequestDto.getRecruitId()))) {
return ResponseEntity.NOT_FOUND("존재하지 않는 게시글입니다");
}
if (await this.recruitService.isAuthorOfRecruit(recruitId, userId)) {
if (
await this.recruitService.isAuthorOfRecruit(
joinRecruitRequestDto.getRecruitId(),
joinRecruitRequestDto.getUserId(),
)
) {
return ResponseEntity.LOCKED("자신의 게시글에 참가할 수 없습니다");
}
if (await this.recruitService.isParticipating(recruitId, userId)) {
if (
await this.recruitService.isParticipating(
joinRecruitRequestDto.getRecruitId(),
joinRecruitRequestDto.getUserId(),
)
) {
return ResponseEntity.LOCKED("이미 참여중인 게시글입니다");
}
if (!(await this.recruitService.isVacancy(recruitId))) {
if (!(await this.recruitService.isVacancy(joinRecruitRequestDto.getRecruitId()))) {
return ResponseEntity.LOCKED("모집 상한에 도달했습니다");
}
this.recruitService.join(joinRecruitDto);
this.recruitService.join(joinRecruitRequestDto);
return ResponseEntity.CREATED();
}

@ApiOperation({ summary: "모집 참여 취소", description: "모집 참여를 취소한다" })
@Delete(":id/join")
async unregister(@Param() unjoinRecruitRequestDto: UnjoinRecruitRequestDto) {
this.recruitService.unjoin(unjoinRecruitRequestDto);
return ResponseEntity.OK();
}

@ApiOperation({ summary: "모집 상세", description: "모집 상세내용을 가져온다" })
@Get(":id")
async getOne(@Param() getRecruitRequestDto: GetRecruitRequestDto) {
Expand Down
25 changes: 21 additions & 4 deletions server/src/recruit/recruit.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { DataSource } from "typeorm";
import { plainToInstance } from "class-transformer";
import { JoinRecruitRequestDto } from "./dto/request/join-recruit.request";
import { Recruit } from "../common/entities/recruit.entity";
import { DeleteRecruitRequestDto } from "./dto/request/delete-recruit.request";
import { UserRecruit } from "src/common/entities/user_recruit.entity";
import { UnjoinRecruitRequestDto } from "./dto/request/unjoin-recruit.request";
@Injectable()
export class RecruitService {
constructor(
Expand All @@ -16,13 +19,13 @@ export class RecruitService {
private dataSource: DataSource,
) {}

async create(createRecruitDto: CreateRecruitRequestDto) {
async create(createRecruitRequestDto: CreateRecruitRequestDto) {
const queryRunner = this.dataSource.createQueryRunner();
let recruitEntity: Recruit;

await queryRunner.connect();
await queryRunner.manager.transaction(async (manager) => {
recruitEntity = await manager.save(createRecruitDto.toEntity());
recruitEntity = await manager.save(createRecruitRequestDto.toEntity());
const userRecruitDto = plainToInstance(JoinRecruitRequestDto, {
userId: recruitEntity.userId,
recruitId: recruitEntity.id,
Expand All @@ -32,6 +35,16 @@ export class RecruitService {
return recruitEntity;
}

async delete(deleteRecruitRequestDto: DeleteRecruitRequestDto) {
const queryRunner = this.dataSource.createQueryRunner();

await queryRunner.connect();
await queryRunner.manager.transaction(async (manager) => {
const recruitEntity = await this.recruitRepository.findOneById(deleteRecruitRequestDto.getRecruitId());
await manager.remove(recruitEntity);
await manager.delete(UserRecruit, { recruitId: deleteRecruitRequestDto.getRecruitId() });
});
}
async getMany(queryParams: GetRecruitsRequestDto) {
if (queryParams.getQuery() === "") {
return [];
Expand Down Expand Up @@ -114,7 +127,11 @@ export class RecruitService {
return recruitEntity.userId === userId;
}

join(createUserRecruitDto: JoinRecruitRequestDto) {
this.userRecruitRepository.createUserRecruit(createUserRecruitDto.toEntity());
join(joinRecruitRequestDto: JoinRecruitRequestDto) {
this.userRecruitRepository.createUserRecruit(joinRecruitRequestDto.toEntity());
}

unjoin(unjoinRecruitRequestDto: UnjoinRecruitRequestDto) {
this.userRecruitRepository.deleteUserRecruit(unjoinRecruitRequestDto.toEntity());
}
}