From a8426de1dff4cf9acbff0799d6ac576fe92eb7eb Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sun, 2 Feb 2025 19:56:44 +0900 Subject: [PATCH 01/15] =?UTF-8?q?feat:=20CS=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=EC=97=90=20=EA=B4=80=EB=A6=AC=EC=9E=90=20=EA=B3=B5=EC=A7=80?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=ED=83=80=EC=9E=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/cs-board.entity.ts | 3 +++ src/enums/cs-type.enum.ts | 1 + src/features/cs-board/cs-board.service.ts | 7 ++++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/entities/cs-board.entity.ts b/src/entities/cs-board.entity.ts index 9e538581..1351cd99 100644 --- a/src/entities/cs-board.entity.ts +++ b/src/entities/cs-board.entity.ts @@ -29,6 +29,9 @@ @OneToMany(() => CsComment, (csComment) => csComment.csBoard) csComments: CsComment[]; + @Column('bool', { default: true }) // 마지막 댓글 작성자가 관리자인지 여부에 따라 업데이트 (관리자 페이지) + isUserWaiting: boolean; + @Column({default: false}) isSecret: boolean; diff --git a/src/enums/cs-type.enum.ts b/src/enums/cs-type.enum.ts index 8022e951..b13f2097 100644 --- a/src/enums/cs-type.enum.ts +++ b/src/enums/cs-type.enum.ts @@ -4,6 +4,7 @@ export enum CsType { Payment='payment', Delivery='delivery', Extra='extra', + Announcement = 'announcement', } \ No newline at end of file diff --git a/src/features/cs-board/cs-board.service.ts b/src/features/cs-board/cs-board.service.ts index 5392cfcc..252b808c 100644 --- a/src/features/cs-board/cs-board.service.ts +++ b/src/features/cs-board/cs-board.service.ts @@ -70,7 +70,12 @@ export class CsBoardService { // 게시자가 관리자일 경우 : 댓글 막기 if(user.isAdmin){ csBoard.isComplete = true; - } + } + // 관리자 공지사항 + if(CsType.Announcement == createCsBoard.csType) { + csBoard.isComplete = true; + csBoard.isUserWaiting = false; + } const newBoard = await this.csRepository.save(csBoard); console.log("Save new Board >>> ", newBoard); return newBoard From 62cfee2438bb73bf8131606bee81a420bdcff4df Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sun, 2 Feb 2025 21:25:17 +0900 Subject: [PATCH 02/15] =?UTF-8?q?feat:=20CSBoard=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1/=EC=82=AD=EC=A0=9C=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/cs-board.entity.ts | 3 ++ src/features/cs-board/cs-board.service.ts | 22 +++++++++- .../cs-comment/cs-comment.controller.ts | 6 ++- src/features/cs-comment/cs-comment.service.ts | 44 ++++++++++++++----- 4 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/entities/cs-board.entity.ts b/src/entities/cs-board.entity.ts index 1351cd99..b343156b 100644 --- a/src/entities/cs-board.entity.ts +++ b/src/entities/cs-board.entity.ts @@ -44,4 +44,7 @@ @CreateDateColumn() regAt: Date; + @Column({ type: 'timestamp', nullable: true }) // 마지막 댓글의 생성 날짜 (관리자 페이지) + lastComAt: Date; + } \ No newline at end of file diff --git a/src/features/cs-board/cs-board.service.ts b/src/features/cs-board/cs-board.service.ts index 252b808c..62856a12 100644 --- a/src/features/cs-board/cs-board.service.ts +++ b/src/features/cs-board/cs-board.service.ts @@ -9,6 +9,7 @@ import { GiftogetherExceptions } from 'src/filters/giftogether-exception'; import { UpdateCsBoardDto } from './dto/update-cs-board.dto'; import { InjectRepository } from '@nestjs/typeorm'; import { CsType } from 'src/enums/cs-type.enum'; +import { CsComment } from 'src/entities/cs-comment.entity'; @Injectable() export class CsBoardService { @@ -121,5 +122,24 @@ export class CsBoardService { // csBoard.isDel = true; // return await this.csRepository.save(csBoard); + // TODO 댓글 삭제 isDelete + + } + + + /** + * 댓글 생성/삭제에 따른 게시글 수정 + */ + async updateOnCsComment(csBoard: CsBoard, lastCsComment: CsComment, isNewComment: boolean) { + + let lastCommenterisAdmin = false; // 댓글이 없는 게시글 + if(lastCsComment != null) { // 댓글 있는 게시글 + lastCommenterisAdmin = lastCsComment.csComUser.isAdmin; + } + if(isNewComment) { + csBoard.lastComAt = lastCsComment.regAt; // 새로운 댓글 생성 날짜로 업데이트 + } + csBoard.isUserWaiting = lastCommenterisAdmin ? false : true; + await this.csRepository.save(csBoard); } -} +} \ No newline at end of file diff --git a/src/features/cs-comment/cs-comment.controller.ts b/src/features/cs-comment/cs-comment.controller.ts index 90e640ce..6f8aa78a 100644 --- a/src/features/cs-comment/cs-comment.controller.ts +++ b/src/features/cs-comment/cs-comment.controller.ts @@ -43,12 +43,16 @@ export class CsCommentController { } @Delete(':cscomId') + @UseGuards(JwtExtendedAuthGuard) async deleteCsBoard( + @Req() req: Request, @Param('cscomId', ParseIntPipe) cscomId: number, ): Promise{ + const user = req.user as { user: User } as any; + return { message: "CS 댓글 삭제 완료", - data: await this.csComService.delete(cscomId), + data: await this.csComService.delete(cscomId, user.userId), } } diff --git a/src/features/cs-comment/cs-comment.service.ts b/src/features/cs-comment/cs-comment.service.ts index db4b1083..e2f9fb44 100644 --- a/src/features/cs-comment/cs-comment.service.ts +++ b/src/features/cs-comment/cs-comment.service.ts @@ -7,6 +7,7 @@ import { GiftogetherExceptions } from 'src/filters/giftogether-exception'; import { InjectRepository } from '@nestjs/typeorm'; import { CsComment } from 'src/entities/cs-comment.entity'; import { CsBoardService } from '../cs-board/cs-board.service'; +import { CsBoard } from 'src/entities/cs-board.entity'; @Injectable() export class CsCommentService { @@ -35,8 +36,12 @@ export class CsCommentService { console.log("create CsComment >>> ", csComment); const newComment = await this.csComRepository.save(csComment); + const lastCsComment = await this.findLastCsComment(csBoard); + + await this.csBoardService.updateOnCsComment(csBoard, lastCsComment, true); + console.log("Save new Comment >>> ", newComment); - return newComment + return newComment; } async update(csComId: number, updateCsComment: CsCommentDto, userId: number) { @@ -53,26 +58,45 @@ export class CsCommentService { } Object.assign(beforeCsComment, updateCsComment); + beforeCsComment.isMod = true; console.log("After update csBoard >>> ", beforeCsComment); return await this.csComRepository.save(beforeCsComment); } - async delete(csComId: number) { + async delete(csComId: number, userId: number) { const csComment = await this.csComRepository.findOne({ where: { csComId }, + relations: ['csBoard', "csComUser"] }); - return await this.csComRepository.delete({csComId}); // console.log("find target csComment >>> ", csComment); // await this.validCheck.verifyUserMatch(csComment.csComUser.userId, userId); - - // if (!csComment) { - // throw this.g2gException.AccountNotFound; - // } - // csComment.isDel = true; - // return await this.csComRepository.save(csComment); + // if (!csComment) { + // throw this.g2gException.AccountNotFound; + // } + + + // 1. 삭제할 댓글 찾기 (게시글 정보 포함) + + const csBoard = csComment.csBoard; + + csComment.isDel = true; + await this.csComRepository.save(csComment); + + const lastCsComment = await this.findLastCsComment(csBoard); + await this.csBoardService.updateOnCsComment(csBoard, lastCsComment, false); + + return await this.csComRepository.delete({csComId}); + } + + async findLastCsComment(csBoard: CsBoard) { + return await this.csComRepository.findOne({ + where: { csBoard: csBoard, isDel: false }, // 삭제되지 않은 최신 댓글 조회 + order: { regAt: "DESC" }, + relations: ["csComUser"], + }); } -} +} \ No newline at end of file From a1e1cd9d710d636d8837d861f520a5e43b6952b0 Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 15:12:17 +0900 Subject: [PATCH 03/15] =?UTF-8?q?refactor:=20CsBoard.create=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=83=80=EC=9E=85=20DTO=20=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20fundUuid=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/cs-board.entity.ts | 3 ++ src/features/cs-board/cs-board.service.ts | 30 +++++++++++++---- .../cs-board/dto/create-cs-board.dto.ts | 2 ++ src/features/cs-board/dto/cs-board.dto.ts | 32 ++++++++----------- 4 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/entities/cs-board.entity.ts b/src/entities/cs-board.entity.ts index b343156b..8938b7c0 100644 --- a/src/entities/cs-board.entity.ts +++ b/src/entities/cs-board.entity.ts @@ -40,6 +40,9 @@ @Column('bool', { default: false }) isDel: boolean; + + @Column({nullable: true}) + fundUuid: string; @CreateDateColumn() regAt: Date; diff --git a/src/features/cs-board/cs-board.service.ts b/src/features/cs-board/cs-board.service.ts index 62856a12..35d769e4 100644 --- a/src/features/cs-board/cs-board.service.ts +++ b/src/features/cs-board/cs-board.service.ts @@ -10,6 +10,25 @@ import { UpdateCsBoardDto } from './dto/update-cs-board.dto'; import { InjectRepository } from '@nestjs/typeorm'; import { CsType } from 'src/enums/cs-type.enum'; import { CsComment } from 'src/entities/cs-comment.entity'; +import { CsCommentDto } from '../cs-comment/dto/cs-comment.dto'; + + +function convertToCsBoardDto(csBoard: CsBoard, csComments: CsCommentDto[]): CsBoardDto { + + return new CsBoardDto( + csBoard.csId, + csBoard.csUser.userNick, + csBoard.csTitle, + csBoard.csCont, + csBoard.csType, + csBoard.isSecret, + csBoard.isUserWaiting, + csBoard.isComplete, + csBoard.regAt, + csBoard.fundUuid, + csComments + ); +} @Injectable() export class CsBoardService { @@ -39,8 +58,8 @@ export class CsBoardService { // async findOneCsBoard(csId: number, userId: number) { const csBoard = await this.findCsBoardByCsId(csId, userId); - const responseBoard = new CsBoardDto(); - responseBoard.userNick = csBoard.csUser.userNick; + const responseBoard = null; + responseBoard.csUser = csBoard.csUser.userNick; return Object.assign(responseBoard, csBoard); } @@ -70,16 +89,15 @@ export class CsBoardService { // 게시자가 관리자일 경우 : 댓글 막기 if(user.isAdmin){ - csBoard.isComplete = true; + csBoard.isComplete = true; } // 관리자 공지사항 if(CsType.Announcement == createCsBoard.csType) { csBoard.isComplete = true; csBoard.isUserWaiting = false; } - const newBoard = await this.csRepository.save(csBoard); - console.log("Save new Board >>> ", newBoard); - return newBoard + const savedBoard = await this.csRepository.save(csBoard); + return convertToCsBoardDto(savedBoard, null) } async update(csId: number, updateCsBoardDto: UpdateCsBoardDto, userId: number) { diff --git a/src/features/cs-board/dto/create-cs-board.dto.ts b/src/features/cs-board/dto/create-cs-board.dto.ts index 53f751cc..839f1722 100644 --- a/src/features/cs-board/dto/create-cs-board.dto.ts +++ b/src/features/cs-board/dto/create-cs-board.dto.ts @@ -14,4 +14,6 @@ export class CreateCsBoardDto { @IsNotEmpty() isSecret: boolean; + public fundUuid: string + } \ No newline at end of file diff --git a/src/features/cs-board/dto/cs-board.dto.ts b/src/features/cs-board/dto/cs-board.dto.ts index 65c40971..251d16ef 100644 --- a/src/features/cs-board/dto/cs-board.dto.ts +++ b/src/features/cs-board/dto/cs-board.dto.ts @@ -1,24 +1,20 @@ import { IsNotEmpty } from "class-validator"; import { CsType } from "src/enums/cs-type.enum"; +import { CsCommentDto } from "src/features/cs-comment/dto/cs-comment.dto"; export class CsBoardDto { - csId: number; - userNick: string; - - @IsNotEmpty() - csTitle: string; - - @IsNotEmpty() - csCont: string; - - @IsNotEmpty() - csType:CsType; - - // csComments: CsCommentDto[]; - - @IsNotEmpty() - isSecret: boolean; - - regAt: Date; + constructor( + public csBoardId: number, + public csUser: string, + public csTitle: string, + public csCont: string, + public csType: CsType, + public isSecret: boolean, + public isUserWaiting: boolean, + public isComplete: boolean, + public regAt: Date, + public fundUuid: string, + public csComments: CsCommentDto[] + ) {} } \ No newline at end of file From 4392837f615a85b57ad61fef4051bcaeb892b436 Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 15:17:01 +0900 Subject: [PATCH 04/15] =?UTF-8?q?feat:=20CsBoard.uptAt=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/entities/cs-board.entity.ts | 5 ++++- src/features/cs-board/cs-board.service.ts | 1 + src/features/cs-board/dto/cs-board.dto.ts | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/entities/cs-board.entity.ts b/src/entities/cs-board.entity.ts index 8938b7c0..e5b475ac 100644 --- a/src/entities/cs-board.entity.ts +++ b/src/entities/cs-board.entity.ts @@ -1,5 +1,5 @@ import { CsType } from "src/enums/cs-type.enum"; - import { Column, CreateDateColumn, DeleteDateColumn, Entity, JoinColumn, ManyToOne, OneToMany, PrimaryGeneratedColumn } from "typeorm"; + import { Column, CreateDateColumn, DeleteDateColumn, Entity, JoinColumn, ManyToOne, OneToMany, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm"; import { CsComment } from "./cs-comment.entity"; import { User } from "./user.entity"; @@ -47,6 +47,9 @@ @CreateDateColumn() regAt: Date; + @UpdateDateColumn() + uptAt: Date; + @Column({ type: 'timestamp', nullable: true }) // 마지막 댓글의 생성 날짜 (관리자 페이지) lastComAt: Date; diff --git a/src/features/cs-board/cs-board.service.ts b/src/features/cs-board/cs-board.service.ts index 35d769e4..7cc3c108 100644 --- a/src/features/cs-board/cs-board.service.ts +++ b/src/features/cs-board/cs-board.service.ts @@ -25,6 +25,7 @@ function convertToCsBoardDto(csBoard: CsBoard, csComments: CsCommentDto[]): CsBo csBoard.isUserWaiting, csBoard.isComplete, csBoard.regAt, + csBoard.uptAt, csBoard.fundUuid, csComments ); diff --git a/src/features/cs-board/dto/cs-board.dto.ts b/src/features/cs-board/dto/cs-board.dto.ts index 251d16ef..2dca14d3 100644 --- a/src/features/cs-board/dto/cs-board.dto.ts +++ b/src/features/cs-board/dto/cs-board.dto.ts @@ -13,6 +13,7 @@ export class CsBoardDto { public isUserWaiting: boolean, public isComplete: boolean, public regAt: Date, + public uptAt: Date, public fundUuid: string, public csComments: CsCommentDto[] ) {} From ef70cf2107e0549523e096df5650524039e3ec07 Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 16:34:19 +0900 Subject: [PATCH 05/15] =?UTF-8?q?refactor:=20CsComment.create=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 게시글 작성자와 댓글 작성자의 일치 유효성 검사 - 반환 시, DTO 로 변환 --- .../cs-comment/cs-comment.controller.ts | 5 +- src/features/cs-comment/cs-comment.service.ts | 50 ++++++++++++++----- .../cs-comment/dto/create-cs-comment.dto.ts | 7 +++ src/features/cs-comment/dto/cs-comment.dto.ts | 10 ++-- 4 files changed, 55 insertions(+), 17 deletions(-) create mode 100644 src/features/cs-comment/dto/create-cs-comment.dto.ts diff --git a/src/features/cs-comment/cs-comment.controller.ts b/src/features/cs-comment/cs-comment.controller.ts index 6f8aa78a..96043aa8 100644 --- a/src/features/cs-comment/cs-comment.controller.ts +++ b/src/features/cs-comment/cs-comment.controller.ts @@ -5,6 +5,7 @@ import { CommonResponse } from 'src/interfaces/common-response.interface'; import { Request } from 'express'; import { User } from 'src/entities/user.entity'; import { JwtExtendedAuthGuard } from '../auth/guard/jwt-extended-auth-guard'; +import { CreateCsCommentDto } from './dto/create-cs-comment.dto'; @Controller('cscomment') export class CsCommentController { @@ -17,13 +18,13 @@ export class CsCommentController { async createCsBoard( @Req() req: Request, @Param('csId', ParseIntPipe) csId: number, - @Body() createCsComment: CsCommentDto + @Body() createCsComment: CreateCsCommentDto ): Promise{ const user = req.user as { user: User } as any; return { message: "CS 댓글 생성 완료", - data: await this.csComService.create(csId, createCsComment, user.userId), + data: await this.csComService.create(csId, createCsComment, user), } } diff --git a/src/features/cs-comment/cs-comment.service.ts b/src/features/cs-comment/cs-comment.service.ts index e2f9fb44..74d99644 100644 --- a/src/features/cs-comment/cs-comment.service.ts +++ b/src/features/cs-comment/cs-comment.service.ts @@ -8,13 +8,25 @@ import { InjectRepository } from '@nestjs/typeorm'; import { CsComment } from 'src/entities/cs-comment.entity'; import { CsBoardService } from '../cs-board/cs-board.service'; import { CsBoard } from 'src/entities/cs-board.entity'; - +import { CreateCsCommentDto } from './dto/create-cs-comment.dto'; + +function convertToCsCommentDto(csComment: CsComment): CsCommentDto { + return new CsCommentDto( + csComment.csComId, + csComment.csComUser.userNick, + csComment.csComCont, + csComment.regAt, + csComment.isMod + ) +} @Injectable() export class CsCommentService { constructor( private readonly csBoardService: CsBoardService, + @InjectRepository(CsBoard) + private readonly csRepository: Repository, @InjectRepository(CsComment) private readonly csComRepository: Repository, @@ -23,25 +35,39 @@ export class CsCommentService { ){} - async create(csId: number, createCsBoard: CsCommentDto, user: User) { + async create(csId: number, createCsBoard: CreateCsCommentDto, user: User) { + + console.log(user) + const csBoard = await this.csRepository + .createQueryBuilder('csBoard') + .leftJoinAndSelect('csBoard.csUser', 'csUser') + .where('csBoard.csId = :csId AND csBoard.isDel = false', {csId}) + .getOne(); + + if (!csBoard) { + console.log("Failed to find CsBoard") + throw this.g2gException.CsBoardNotFound; + } // 비밀글) 게시자와 댓글 작성자가 동일해야 한다. + 관리자 제외 - const csBoard = await this.csBoardService.findCsBoardByCsId(csId, user.userId); + if (csBoard.isSecret && !user.isAdmin) { + this.validCheck.verifyUserMatch(csBoard.csUser.userId, user.userId) + } + // 댓글 저장 let csComment = new CsComment(); csComment.csBoard = csBoard; csComment.csComCont = createCsBoard.csComCont; csComment.csComUser = user; - - console.log("create CsComment >>> ", csComment); - const newComment = await this.csComRepository.save(csComment); - const lastCsComment = await this.findLastCsComment(csBoard); - - await this.csBoardService.updateOnCsComment(csBoard, lastCsComment, true); - - console.log("Save new Comment >>> ", newComment); - return newComment; + console.log("create CsComment >>> ", newComment); + + // 게시글 정보 업데이트 + csBoard.lastComAt = newComment.regAt; + csBoard.isUserWaiting = user.isAdmin ? false : true; + await this.csRepository.save(csBoard) + console.log("Update CsBoard >>> ", csId); + return convertToCsCommentDto(newComment); } async update(csComId: number, updateCsComment: CsCommentDto, userId: number) { diff --git a/src/features/cs-comment/dto/create-cs-comment.dto.ts b/src/features/cs-comment/dto/create-cs-comment.dto.ts new file mode 100644 index 00000000..3047cd82 --- /dev/null +++ b/src/features/cs-comment/dto/create-cs-comment.dto.ts @@ -0,0 +1,7 @@ +import { IsNotEmpty } from "class-validator"; + +export class CreateCsCommentDto { + @IsNotEmpty() + csComCont: string; + +} \ No newline at end of file diff --git a/src/features/cs-comment/dto/cs-comment.dto.ts b/src/features/cs-comment/dto/cs-comment.dto.ts index 58d08677..c0f7434b 100644 --- a/src/features/cs-comment/dto/cs-comment.dto.ts +++ b/src/features/cs-comment/dto/cs-comment.dto.ts @@ -1,8 +1,12 @@ import { IsNotEmpty } from "class-validator"; export class CsCommentDto { - - @IsNotEmpty() - csComCont: string; + constructor( + public csComId: number, + public csComUser: string, + public csComCont: string, + public regAt: Date, + public isMod: boolean, + ) {} } \ No newline at end of file From 590b9129749c625c0def8e7b7fc18893d4b11a1d Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 16:47:34 +0900 Subject: [PATCH 06/15] =?UTF-8?q?refactor=20:=20CsBoard.delete=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EC=8B=9C,=20=EB=8C=93=EA=B8=80=20=ED=8F=AC?= =?UTF-8?q?=ED=95=A8=ED=95=9C=20=EC=82=AD=EC=A0=9C=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 반환 타입 DTO 로 수정 --- src/features/cs-board/cs-board.controller.ts | 5 +- src/features/cs-board/cs-board.service.ts | 56 +++++++++++++------- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/features/cs-board/cs-board.controller.ts b/src/features/cs-board/cs-board.controller.ts index e2514358..1418a314 100644 --- a/src/features/cs-board/cs-board.controller.ts +++ b/src/features/cs-board/cs-board.controller.ts @@ -67,12 +67,15 @@ export class CsBoardController { } @Delete(':csId') + @UseGuards(JwtExtendedAuthGuard) async deleteCsBoard( + @Req() req: Request, @Param('csId', ParseIntPipe) csId: number, ): Promise{ + const user = req.user as { user: User } as any; return { message: "CS 게시글 삭제 완료", - data: await this.csService.delete(csId), + data: await this.csService.delete(csId, user), } } diff --git a/src/features/cs-board/cs-board.service.ts b/src/features/cs-board/cs-board.service.ts index 7cc3c108..954f3c25 100644 --- a/src/features/cs-board/cs-board.service.ts +++ b/src/features/cs-board/cs-board.service.ts @@ -30,12 +30,22 @@ function convertToCsBoardDto(csBoard: CsBoard, csComments: CsCommentDto[]): CsBo csComments ); } - +function convertToCsCommentsDto(csComment: CsComment): CsCommentDto { + return new CsCommentDto( + csComment.csComId, + csComment.csComUser.userNick, + csComment.csComCont, + csComment.regAt, + csComment.isMod + ) +} @Injectable() export class CsBoardService { constructor( @InjectRepository(CsBoard) private readonly csRepository: Repository, + @InjectRepository(CsComment) + private readonly csComRepository: Repository, private readonly validCheck: ValidCheck, private readonly g2gException: GiftogetherExceptions @@ -121,28 +131,38 @@ export class CsBoardService { return await this.csRepository.save(beforeCsBoard); } - async delete(csId: number) { - const userId = 1; - + async delete(csId: number, user: User) { const csBoard = await this.csRepository.findOne({ - where: { csId }, - // relations: ['csUser'] + where: { csId, isDel: false } , + relations: ['csUser', 'csComments', 'csComments.csComUser'] }); - // return await this.csRepository.delete(csBoard); - return await this.csRepository.delete({ - csId: csId - }); - // console.log("find target csBoard >>> ", csBoard); - // await this.validCheck.verifyUserMatch(csBoard.csUser.userId, userId); - // if (!csBoard) { - // throw this.g2gException.AccountNotFound; - // } + if (!csBoard) { + throw this.g2gException.CsBoardNotFound; + } + + console.log("find target csBoard before Delete >>> ", csBoard.csId); + if (!user.isAdmin) { + await this.validCheck.verifyUserMatch(csBoard.csUser.userId, user.userId); + } + + csBoard.isDel = true; + const csComments = csBoard.csComments; + + for (let csComment of csComments) { + csComment.isDel = true; + } + + await this.csComRepository.save(csComments) + await this.csRepository.save(csBoard); - // csBoard.isDel = true; - // return await this.csRepository.save(csBoard); - // TODO 댓글 삭제 isDelete + console.log("Success Delete CsBoard >> ", csBoard.csId); + const convertCsComments: CsCommentDto[] = []; + for (const csComment of csComments) { + convertCsComments.push(convertToCsCommentsDto(csComment)); + } + return convertToCsBoardDto(csBoard, convertCsComments); } From da468ec730e64f7eed2283e98088e5539572024b Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 16:59:15 +0900 Subject: [PATCH 07/15] =?UTF-8?q?refactor:=20CsBoard.findOne=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=83=80=EC=9E=85=20=EB=B0=8F=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EA=B8=80=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/cs-board/cs-board.controller.ts | 2 +- src/features/cs-board/cs-board.service.ts | 21 ++++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/features/cs-board/cs-board.controller.ts b/src/features/cs-board/cs-board.controller.ts index 1418a314..623ef462 100644 --- a/src/features/cs-board/cs-board.controller.ts +++ b/src/features/cs-board/cs-board.controller.ts @@ -24,7 +24,7 @@ export class CsBoardController { const user = req.user as { user: User } as any; return { message: "CS 게시글 조회 완료", - data: await this.csService.findOneCsBoard(csId, user.userId), + data: await this.csService.findOne(csId, user), } } diff --git a/src/features/cs-board/cs-board.service.ts b/src/features/cs-board/cs-board.service.ts index 954f3c25..6dc659a4 100644 --- a/src/features/cs-board/cs-board.service.ts +++ b/src/features/cs-board/cs-board.service.ts @@ -66,12 +66,21 @@ export class CsBoardService { return csBoard; } - // - async findOneCsBoard(csId: number, userId: number) { - const csBoard = await this.findCsBoardByCsId(csId, userId); - const responseBoard = null; - responseBoard.csUser = csBoard.csUser.userNick; - return Object.assign(responseBoard, csBoard); + // 상세 조회 + async findOne(csId: number, user: User) { + const csBoard = await this.csRepository + .createQueryBuilder('csBoard') + .leftJoinAndSelect('csBoard.csUser', 'csUser') + .leftJoinAndSelect('csBoard.csComments', 'csComments', 'csComments.isDel = false') + .leftJoinAndSelect('csComments.csComUser', 'csComUser') + .where('csBoard.csId = :csId AND csBoard.isDel = false', { csId }) + .getOne(); + + if (csBoard.isSecret && user.isAdmin) { + await this.validCheck.verifyUserMatch(csBoard.csUser.userId, user.userId); + } + const csCommentsDto = csBoard?.csComments.map(convertToCsCommentsDto) ?? []; + return convertToCsBoardDto(csBoard, csCommentsDto); } From 491e4f23afc9b1f4ac6086d5e4fac2db42c7427a Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 17:40:05 +0900 Subject: [PATCH 08/15] =?UTF-8?q?fix:=20CreateCsBoard=20=EC=9D=98=20fundUu?= =?UTF-8?q?id=20optional=20=EC=B2=98=EB=A6=AC=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/cs-board/dto/create-cs-board.dto.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/features/cs-board/dto/create-cs-board.dto.ts b/src/features/cs-board/dto/create-cs-board.dto.ts index 839f1722..ae1fe8bd 100644 --- a/src/features/cs-board/dto/create-cs-board.dto.ts +++ b/src/features/cs-board/dto/create-cs-board.dto.ts @@ -1,4 +1,4 @@ -import { IsNotEmpty } from "class-validator"; +import { IsNotEmpty, IsOptional } from "class-validator"; import { CsType } from "src/enums/cs-type.enum"; export class CreateCsBoardDto { @@ -14,6 +14,7 @@ export class CreateCsBoardDto { @IsNotEmpty() isSecret: boolean; - public fundUuid: string + @IsOptional() + fundUuid?: string } \ No newline at end of file From 10d37c9081ca84bc04a6b32e106612cb2ee79453 Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 17:57:09 +0900 Subject: [PATCH 09/15] =?UTF-8?q?refactor:=20CsBoard.update=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=ED=83=80=EC=9E=85=20=EC=88=98=EC=A0=95=20=EB=B0=8F?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20=EC=9A=94=EC=B2=AD=20=EC=A4=91=20fundUu?= =?UTF-8?q?id=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/cs-board/cs-board.controller.ts | 2 +- src/features/cs-board/cs-board.service.ts | 31 ++++++++++++------- .../cs-board/dto/update-cs-board.dto.ts | 5 ++- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/features/cs-board/cs-board.controller.ts b/src/features/cs-board/cs-board.controller.ts index 623ef462..0e41032a 100644 --- a/src/features/cs-board/cs-board.controller.ts +++ b/src/features/cs-board/cs-board.controller.ts @@ -62,7 +62,7 @@ export class CsBoardController { const user = req.user as { user: User } as any; return { message: "CS 게시글 수정 완료", - data: await this.csService.update(csId, updateCsBoard, user.userId), + data: await this.csService.update(csId, updateCsBoard, user), } } diff --git a/src/features/cs-board/cs-board.service.ts b/src/features/cs-board/cs-board.service.ts index 6dc659a4..94784a9a 100644 --- a/src/features/cs-board/cs-board.service.ts +++ b/src/features/cs-board/cs-board.service.ts @@ -120,24 +120,31 @@ export class CsBoardService { return convertToCsBoardDto(savedBoard, null) } - async update(csId: number, updateCsBoardDto: UpdateCsBoardDto, userId: number) { + async update(csId: number, updateCsBoardDto: UpdateCsBoardDto, user: User) { - const beforeCsBoard = await this.csRepository.findOne({ - where: { csId }, - relations: ['csUser'] - }); - console.log("find target csBoard >>> ", beforeCsBoard); - await this.validCheck.verifyUserMatch(beforeCsBoard.csUser.userId, userId); + const csBoard = await this.csRepository + .createQueryBuilder('csBoard') + .leftJoinAndSelect('csBoard.csUser', 'csUser') + .where('csBoard.csId = :csId AND csBoard.isDel = false', { csId }) + .getOne(); + + if (!csBoard) { + throw this.g2gException.CsBoardNotFound; + } - if (!beforeCsBoard) { - throw this.g2gException.AccountNotFound; + console.log("find target csBoard.csId >>> ", csBoard.csId); + if (!user.isAdmin) { + await this.validCheck.verifyUserMatch(csBoard.csUser.userId, user.userId); } + + Object.assign(csBoard, updateCsBoardDto); + + await this.csRepository.save(csBoard); - Object.assign(beforeCsBoard, updateCsBoardDto); - console.log("After update csBoard >>> ", beforeCsBoard); + console.log("Success update csBoard >>> ", csId); - return await this.csRepository.save(beforeCsBoard); + return convertToCsBoardDto(csBoard, null) } async delete(csId: number, user: User) { diff --git a/src/features/cs-board/dto/update-cs-board.dto.ts b/src/features/cs-board/dto/update-cs-board.dto.ts index 1cb19f19..4bcfa4d5 100644 --- a/src/features/cs-board/dto/update-cs-board.dto.ts +++ b/src/features/cs-board/dto/update-cs-board.dto.ts @@ -16,5 +16,8 @@ export class UpdateCsBoardDto { isSecret: boolean; @IsOptional() - isComplete: boolean; + isComplete?: boolean; + + @IsOptional() + fundingUuid?: string; } \ No newline at end of file From ae44d917085f621bdc13d20c3c4c3245ab9fae2f Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 17:59:23 +0900 Subject: [PATCH 10/15] =?UTF-8?q?feat:=20CsBoardNotFound,=20CsCommentNotFo?= =?UTF-8?q?und=20=EC=98=88=EC=99=B8=20=EC=B6=94=EA=B0=80=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/enums/error-code.enum.ts | 4 ++++ src/enums/error-message.enum.ts | 4 ++++ src/filters/giftogether-exception.ts | 13 +++++++++++++ 3 files changed, 21 insertions(+) diff --git a/src/enums/error-code.enum.ts b/src/enums/error-code.enum.ts index 5a1a9a2a..cb5f1d35 100644 --- a/src/enums/error-code.enum.ts +++ b/src/enums/error-code.enum.ts @@ -86,4 +86,8 @@ export enum ErrorCode { InconsistentAggregationError = '1700', InvalidPage = '1701', InvalidLimit = '1702', + + // CsBoard & CsComment + CsBoardNotFound = "1900", + CsCommentNotFound = "1901" } diff --git a/src/enums/error-message.enum.ts b/src/enums/error-message.enum.ts index e04f5420..8fe00787 100644 --- a/src/enums/error-message.enum.ts +++ b/src/enums/error-message.enum.ts @@ -84,4 +84,8 @@ export enum ErrorMsg { InconsistentAggregationError = '애그리게이션이 일관적이지 않습니다.', InvalidPage = '잘못된 페이지 번호입니다.', InvalidLimit = '잘못된 페이지 크기입니다.', + + // CsBoard & CsComment + CsBoardNotFound = '문의 게시글이 존재하지 않습니다.', + CsCommentNotFound = '문의 댓글이 존재하지 않습니다.', } diff --git a/src/filters/giftogether-exception.ts b/src/filters/giftogether-exception.ts index 93125af0..dcbb0804 100644 --- a/src/filters/giftogether-exception.ts +++ b/src/filters/giftogether-exception.ts @@ -331,4 +331,17 @@ export class GiftogetherExceptions { ErrorCode.InvalidLimit, HttpStatus.BAD_REQUEST, ); + + // CSBoard & CsComment + CsBoardNotFound = new GiftogetherException( + ErrorMsg.CsBoardNotFound, + ErrorCode.CsBoardNotFound, + HttpStatus.NOT_FOUND + ); + + CsCommentNotFound = new GiftogetherException( + ErrorMsg.CsCommentNotFound, + ErrorCode.CsCommentNotFound, + HttpStatus.NOT_FOUND + ) } From 2162c668c2d9ef173edb4ee69051924f9d56db8c Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 18:05:22 +0900 Subject: [PATCH 11/15] =?UTF-8?q?refactor:=20CsComment.update=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - csComment 추가/업데이트용 dto 통합 - 반환 타입 DTO 로 수정 - CsCommentNotFound 예외 추가가 --- .../cs-comment/cs-comment.controller.ts | 6 ++-- src/features/cs-comment/cs-comment.service.ts | 33 ++++++++++--------- ...mment.dto.ts => cs-comment-request.dto.ts} | 2 +- 3 files changed, 22 insertions(+), 19 deletions(-) rename src/features/cs-comment/dto/{create-cs-comment.dto.ts => cs-comment-request.dto.ts} (71%) diff --git a/src/features/cs-comment/cs-comment.controller.ts b/src/features/cs-comment/cs-comment.controller.ts index 96043aa8..a703326b 100644 --- a/src/features/cs-comment/cs-comment.controller.ts +++ b/src/features/cs-comment/cs-comment.controller.ts @@ -5,7 +5,7 @@ import { CommonResponse } from 'src/interfaces/common-response.interface'; import { Request } from 'express'; import { User } from 'src/entities/user.entity'; import { JwtExtendedAuthGuard } from '../auth/guard/jwt-extended-auth-guard'; -import { CreateCsCommentDto } from './dto/create-cs-comment.dto'; +import { CsCommentReqeustDto } from './dto/cs-comment-request.dto'; @Controller('cscomment') export class CsCommentController { @@ -18,7 +18,7 @@ export class CsCommentController { async createCsBoard( @Req() req: Request, @Param('csId', ParseIntPipe) csId: number, - @Body() createCsComment: CreateCsCommentDto + @Body() createCsComment: CsCommentReqeustDto ): Promise{ const user = req.user as { user: User } as any; @@ -33,7 +33,7 @@ export class CsCommentController { async updateCsBoard( @Req() req: Request, @Param('cscomId', ParseIntPipe) cscomId: number, - @Body() updateCsComment: CsCommentDto + @Body() updateCsComment: CsCommentReqeustDto ): Promise{ const user = req.user as { user: User } as any; diff --git a/src/features/cs-comment/cs-comment.service.ts b/src/features/cs-comment/cs-comment.service.ts index 74d99644..c3e6fa9d 100644 --- a/src/features/cs-comment/cs-comment.service.ts +++ b/src/features/cs-comment/cs-comment.service.ts @@ -8,7 +8,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { CsComment } from 'src/entities/cs-comment.entity'; import { CsBoardService } from '../cs-board/cs-board.service'; import { CsBoard } from 'src/entities/cs-board.entity'; -import { CreateCsCommentDto } from './dto/create-cs-comment.dto'; +import { CsCommentReqeustDto } from './dto/cs-comment-request.dto'; function convertToCsCommentDto(csComment: CsComment): CsCommentDto { return new CsCommentDto( @@ -35,7 +35,7 @@ export class CsCommentService { ){} - async create(csId: number, createCsBoard: CreateCsCommentDto, user: User) { + async create(csId: number, createCsBoard: CsCommentReqeustDto, user: User) { console.log(user) const csBoard = await this.csRepository @@ -70,25 +70,28 @@ export class CsCommentService { return convertToCsCommentDto(newComment); } - async update(csComId: number, updateCsComment: CsCommentDto, userId: number) { + async update(csComId: number, updateCsComment: CsCommentReqeustDto, userId: number) { - const beforeCsComment = await this.csComRepository.findOne({ - where: { csComId }, + // 댓글 찾기 + const csComment = await this.csComRepository.findOne({ + where: { csComId, isDel: false }, relations: ['csComUser'] }); - console.log("find target csComment >>> ", beforeCsComment); - await this.validCheck.verifyUserMatch(beforeCsComment.csComUser.userId, userId); - - if (!beforeCsComment) { - throw this.g2gException.AccountNotFound; + if (!csComment) { + throw this.g2gException.CsCommentNotFound; } + console.log("find target csComment.csComId >>> ", csComment.csComId); - Object.assign(beforeCsComment, updateCsComment); - beforeCsComment.isMod = true; - - console.log("After update csBoard >>> ", beforeCsComment); + // 댓글 작성자 유효성 검사 + await this.validCheck.verifyUserMatch(csComment.csComUser.userId, userId); + + // 댓글 수정 + csComment.csComCont = updateCsComment.csComCont; + csComment.isMod = true; + await this.csComRepository.save(csComment) + console.log("After update csBoard.csComId >>> ", csComId); - return await this.csComRepository.save(beforeCsComment); + return convertToCsCommentDto(csComment); } async delete(csComId: number, userId: number) { diff --git a/src/features/cs-comment/dto/create-cs-comment.dto.ts b/src/features/cs-comment/dto/cs-comment-request.dto.ts similarity index 71% rename from src/features/cs-comment/dto/create-cs-comment.dto.ts rename to src/features/cs-comment/dto/cs-comment-request.dto.ts index 3047cd82..e9ea2901 100644 --- a/src/features/cs-comment/dto/create-cs-comment.dto.ts +++ b/src/features/cs-comment/dto/cs-comment-request.dto.ts @@ -1,6 +1,6 @@ import { IsNotEmpty } from "class-validator"; -export class CreateCsCommentDto { +export class CsCommentReqeustDto { @IsNotEmpty() csComCont: string; From 22169e5e6c442360460bad4425fcb6d6eb4486cf Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 18:46:54 +0900 Subject: [PATCH 12/15] =?UTF-8?q?refactor:=20CsCommnet.delete=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 댓글 삭제 시, 최신 댓글 정보로 CS 게시글 업데이트 - 반환 타입 DTO 로 수정정 --- src/features/cs-board/cs-board.service.ts | 33 +-------- .../cs-comment/cs-comment.controller.ts | 2 +- src/features/cs-comment/cs-comment.service.ts | 69 ++++++++++--------- 3 files changed, 38 insertions(+), 66 deletions(-) diff --git a/src/features/cs-board/cs-board.service.ts b/src/features/cs-board/cs-board.service.ts index 94784a9a..58a7b7d2 100644 --- a/src/features/cs-board/cs-board.service.ts +++ b/src/features/cs-board/cs-board.service.ts @@ -51,21 +51,6 @@ export class CsBoardService { ){} - async findCsBoardByCsId(csId: number, userId: number) { - const csBoard = await this.csRepository.findOne({ - where: { csId }, - relations: ['csUser', 'csComments'] - }); - // 비밀글 - if(csBoard.isSecret){ - // 작성자 & 관리자가 아닐 경우 - if(csBoard.csUser.userId != userId && ! csBoard.csUser.isAdmin) { - // throw this.g2gException.NoPermissionCsBoard; - } - } - return csBoard; - } - // 상세 조회 async findOne(csId: number, user: User) { const csBoard = await this.csRepository @@ -180,21 +165,5 @@ export class CsBoardService { return convertToCsBoardDto(csBoard, convertCsComments); } - - - /** - * 댓글 생성/삭제에 따른 게시글 수정 - */ - async updateOnCsComment(csBoard: CsBoard, lastCsComment: CsComment, isNewComment: boolean) { - - let lastCommenterisAdmin = false; // 댓글이 없는 게시글 - if(lastCsComment != null) { // 댓글 있는 게시글 - lastCommenterisAdmin = lastCsComment.csComUser.isAdmin; - } - if(isNewComment) { - csBoard.lastComAt = lastCsComment.regAt; // 새로운 댓글 생성 날짜로 업데이트 - } - csBoard.isUserWaiting = lastCommenterisAdmin ? false : true; - await this.csRepository.save(csBoard); - } + } \ No newline at end of file diff --git a/src/features/cs-comment/cs-comment.controller.ts b/src/features/cs-comment/cs-comment.controller.ts index a703326b..f28a86a2 100644 --- a/src/features/cs-comment/cs-comment.controller.ts +++ b/src/features/cs-comment/cs-comment.controller.ts @@ -53,7 +53,7 @@ export class CsCommentController { return { message: "CS 댓글 삭제 완료", - data: await this.csComService.delete(cscomId, user.userId), + data: await this.csComService.delete(cscomId, user), } } diff --git a/src/features/cs-comment/cs-comment.service.ts b/src/features/cs-comment/cs-comment.service.ts index c3e6fa9d..e048990d 100644 --- a/src/features/cs-comment/cs-comment.service.ts +++ b/src/features/cs-comment/cs-comment.service.ts @@ -6,7 +6,6 @@ import { ValidCheck } from 'src/util/valid-check'; import { GiftogetherExceptions } from 'src/filters/giftogether-exception'; import { InjectRepository } from '@nestjs/typeorm'; import { CsComment } from 'src/entities/cs-comment.entity'; -import { CsBoardService } from '../cs-board/cs-board.service'; import { CsBoard } from 'src/entities/cs-board.entity'; import { CsCommentReqeustDto } from './dto/cs-comment-request.dto'; @@ -23,8 +22,6 @@ function convertToCsCommentDto(csComment: CsComment): CsCommentDto { export class CsCommentService { constructor( - private readonly csBoardService: CsBoardService, - @InjectRepository(CsBoard) private readonly csRepository: Repository, @InjectRepository(CsComment) @@ -37,7 +34,6 @@ export class CsCommentService { async create(csId: number, createCsBoard: CsCommentReqeustDto, user: User) { - console.log(user) const csBoard = await this.csRepository .createQueryBuilder('csBoard') .leftJoinAndSelect('csBoard.csUser', 'csUser') @@ -94,38 +90,45 @@ export class CsCommentService { return convertToCsCommentDto(csComment); } - async delete(csComId: number, userId: number) { + async delete(csComId: number, user: User) { - const csComment = await this.csComRepository.findOne({ - where: { csComId }, - relations: ['csBoard', "csComUser"] + // 댓글 찾기 + const deleteComment = await this.csComRepository.findOne({ + where: { csComId, isDel: false }, + relations: ['csComUser', 'csBoard'] }); - // console.log("find target csComment >>> ", csComment); - // await this.validCheck.verifyUserMatch(csComment.csComUser.userId, userId); + if (!deleteComment) { + throw this.g2gException.CsCommentNotFound; + } + + // 댓글 삭제 + deleteComment.isDel = true; + await this.csComRepository.save(deleteComment); + + const csBoard = deleteComment.csBoard + const latestComment = await this.csComRepository + .createQueryBuilder('csComment') + .leftJoinAndSelect('csComment.csComUser', 'csComUser') + .where('csComment.csBoard = :csId', { csId: csBoard.csId }) + .andWhere('csComment.isDel = false') + .orderBy('csComment.regAt', 'DESC') + .getOne(); - // if (!csComment) { - // throw this.g2gException.AccountNotFound; - // } - - - // 1. 삭제할 댓글 찾기 (게시글 정보 포함) - - const csBoard = csComment.csBoard; - - csComment.isDel = true; - await this.csComRepository.save(csComment); - - const lastCsComment = await this.findLastCsComment(csBoard); - await this.csBoardService.updateOnCsComment(csBoard, lastCsComment, false); - - return await this.csComRepository.delete({csComId}); - } + // 댓글 없는 게시글 (위 삭제한 댓글이 첫번째 댓글) + if (!latestComment) { + csBoard.isUserWaiting = true; + csBoard.lastComAt = null; - async findLastCsComment(csBoard: CsBoard) { - return await this.csComRepository.findOne({ - where: { csBoard: csBoard, isDel: false }, // 삭제되지 않은 최신 댓글 조회 - order: { regAt: "DESC" }, - relations: ["csComUser"], - }); + } else { + const isLastestIsAdmin = latestComment.csComUser.isAdmin + + // 최신 댓글로 게시글 정보 업데이트 + csBoard.isUserWaiting = isLastestIsAdmin ? false : true; + csBoard.lastComAt = latestComment.regAt; + } + await this.csRepository.save(csBoard); + console.log("CsBoard update >> latestComment") + + return convertToCsCommentDto(deleteComment); } } \ No newline at end of file From 1a060988a245f6f5dd1a4b00052b166f42f2ec78 Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 18:56:46 +0900 Subject: [PATCH 13/15] =?UTF-8?q?refactor:=20CsBoard.findAll=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=83=80=EC=9E=85=20DTO=20=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 조회 시 CsType 으로 필터링 --- src/features/cs-board/cs-board.controller.ts | 3 +- src/features/cs-board/cs-board.service.ts | 30 +++++++++----------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/features/cs-board/cs-board.controller.ts b/src/features/cs-board/cs-board.controller.ts index 0e41032a..097f583a 100644 --- a/src/features/cs-board/cs-board.controller.ts +++ b/src/features/cs-board/cs-board.controller.ts @@ -35,9 +35,10 @@ export class CsBoardController { return { message: "CS 게시글 전체 조회 완료", - data: await this.csService.findAllCsBoards(csType), + data: await this.csService.findAll(csType), } } + @Post() @UseGuards(JwtExtendedAuthGuard) async createCsBoard( diff --git a/src/features/cs-board/cs-board.service.ts b/src/features/cs-board/cs-board.service.ts index 58a7b7d2..212c33d3 100644 --- a/src/features/cs-board/cs-board.service.ts +++ b/src/features/cs-board/cs-board.service.ts @@ -69,23 +69,21 @@ export class CsBoardService { } - // TODO 카테고리 조회 - async findAllCsBoards(csType:CsType) { - console.log(csType); - return await this.csRepository - .createQueryBuilder('csBoard') - .leftJoinAndSelect('csBoard.csUser', 'csUser') - .where('csBoard.csType = :csType', { csType }) - .andWhere('csBoard.isDel = :isDel', { isDel: false }) - .getMany(); - // console.log(">>>>> csBoard " , csBoards); - // const result = csBoards.map(() => new CsBoardDto()); - - // console.log("result >>>>> ", result) - - // return result; - + async findAll(csType: CsType | null): Promise { + const query = this.csRepository.createQueryBuilder('csBoard') + .leftJoinAndSelect('csBoard.csUser', 'csUser') + .andWhere('csBoard.isDel = false'); + + if (csType !== null) { + query.andWhere('csBoard.csType = :csType', { csType }); + } else { + query.andWhere('csBoard.csType IS NULL'); + } + + const csBoards = await query.getMany(); + return csBoards?.map(csBoard => convertToCsBoardDto(csBoard, null)) ?? []; } + async create(createCsBoard: CreateCsBoardDto, user: User) { From 1526ed9618bb4b09a13a695809aa38217cb0806d Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 19:10:51 +0900 Subject: [PATCH 14/15] =?UTF-8?q?feat:=20=EB=A7=88=EA=B0=90=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=EB=90=9C=20CsBoard=20=EC=97=90=20=EB=8C=93=EA=B8=80?= =?UTF-8?q?=20=EC=83=9D=EC=84=B1=20=EB=A7=89=EA=B8=B0=20(=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CsBoardIsComplete : BadRequest --- src/enums/cs-type.enum.ts | 1 + src/enums/error-code.enum.ts | 3 ++- src/enums/error-message.enum.ts | 1 + src/features/cs-comment/cs-comment.service.ts | 7 ++++++- src/filters/giftogether-exception.ts | 5 +++++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/enums/cs-type.enum.ts b/src/enums/cs-type.enum.ts index b13f2097..1e411ec5 100644 --- a/src/enums/cs-type.enum.ts +++ b/src/enums/cs-type.enum.ts @@ -5,6 +5,7 @@ export enum CsType { Delivery='delivery', Extra='extra', Announcement = 'announcement', + Refund = 'refund', } \ No newline at end of file diff --git a/src/enums/error-code.enum.ts b/src/enums/error-code.enum.ts index cb5f1d35..098ece51 100644 --- a/src/enums/error-code.enum.ts +++ b/src/enums/error-code.enum.ts @@ -89,5 +89,6 @@ export enum ErrorCode { // CsBoard & CsComment CsBoardNotFound = "1900", - CsCommentNotFound = "1901" + CsCommentNotFound = "1901", + CsBoardIsComplete = "1902", } diff --git a/src/enums/error-message.enum.ts b/src/enums/error-message.enum.ts index 8fe00787..7c7c6123 100644 --- a/src/enums/error-message.enum.ts +++ b/src/enums/error-message.enum.ts @@ -88,4 +88,5 @@ export enum ErrorMsg { // CsBoard & CsComment CsBoardNotFound = '문의 게시글이 존재하지 않습니다.', CsCommentNotFound = '문의 댓글이 존재하지 않습니다.', + CsBoardIsComplete = '마감된 문의 게시글입니다.' } diff --git a/src/features/cs-comment/cs-comment.service.ts b/src/features/cs-comment/cs-comment.service.ts index e048990d..123c6875 100644 --- a/src/features/cs-comment/cs-comment.service.ts +++ b/src/features/cs-comment/cs-comment.service.ts @@ -37,7 +37,8 @@ export class CsCommentService { const csBoard = await this.csRepository .createQueryBuilder('csBoard') .leftJoinAndSelect('csBoard.csUser', 'csUser') - .where('csBoard.csId = :csId AND csBoard.isDel = false', {csId}) + .where('csBoard.csId = :csId', {csId}) + .andWhere('csBoard.isDel = false') .getOne(); if (!csBoard) { @@ -45,6 +46,10 @@ export class CsCommentService { throw this.g2gException.CsBoardNotFound; } + if (!user.isAdmin && csBoard.isComplete) { + throw this.g2gException.CsBoardIsComplete; + } + // 비밀글) 게시자와 댓글 작성자가 동일해야 한다. + 관리자 제외 if (csBoard.isSecret && !user.isAdmin) { this.validCheck.verifyUserMatch(csBoard.csUser.userId, user.userId) diff --git a/src/filters/giftogether-exception.ts b/src/filters/giftogether-exception.ts index dcbb0804..19979ce4 100644 --- a/src/filters/giftogether-exception.ts +++ b/src/filters/giftogether-exception.ts @@ -344,4 +344,9 @@ export class GiftogetherExceptions { ErrorCode.CsCommentNotFound, HttpStatus.NOT_FOUND ) + CsBoardIsComplete = new GiftogetherException( + ErrorMsg.CsBoardIsComplete, + ErrorCode.CsBoardIsComplete, + HttpStatus.BAD_REQUEST + ); } From 6ff7e2cccb435e36412a64518a081baa7f237204 Mon Sep 17 00:00:00 2001 From: hjlee5701 Date: Sat, 15 Mar 2025 19:11:50 +0900 Subject: [PATCH 15/15] =?UTF-8?q?feat:=20=EB=A7=88=EA=B0=90=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=EB=90=9C=20CsBoard=20=EC=9D=98=20=EC=97=85=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=8A=B8=20=EB=A7=89=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 관리자는 가능하다. --- src/features/cs-board/cs-board.service.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/features/cs-board/cs-board.service.ts b/src/features/cs-board/cs-board.service.ts index 212c33d3..3758cbbe 100644 --- a/src/features/cs-board/cs-board.service.ts +++ b/src/features/cs-board/cs-board.service.ts @@ -108,13 +108,19 @@ export class CsBoardService { const csBoard = await this.csRepository .createQueryBuilder('csBoard') .leftJoinAndSelect('csBoard.csUser', 'csUser') - .where('csBoard.csId = :csId AND csBoard.isDel = false', { csId }) + .where('csBoard.csId = :csId', { csId }) + .andWhere('csBoard.isDel = false') + .andWhere('csBoard.isComplete = false') .getOne(); if (!csBoard) { throw this.g2gException.CsBoardNotFound; } + if (!user.isAdmin && csBoard.isComplete) { + throw this.g2gException.CsBoardIsComplete; + } + console.log("find target csBoard.csId >>> ", csBoard.csId); if (!user.isAdmin) { await this.validCheck.verifyUserMatch(csBoard.csUser.userId, user.userId);