diff --git a/src/main/java/com/dnd/accompany/domain/qna100/api/QnaController.java b/src/main/java/com/dnd/accompany/domain/qna100/api/QnaController.java index 0482e12..9b7bda0 100644 --- a/src/main/java/com/dnd/accompany/domain/qna100/api/QnaController.java +++ b/src/main/java/com/dnd/accompany/domain/qna100/api/QnaController.java @@ -2,6 +2,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -9,6 +10,7 @@ import com.dnd.accompany.domain.auth.dto.jwt.JwtAuthentication; import com.dnd.accompany.domain.qna100.api.dto.CreateAndUpdateQnaRequest; +import com.dnd.accompany.domain.qna100.api.dto.DeleteQnaRequest; import com.dnd.accompany.domain.qna100.service.QnaService; import io.swagger.v3.oas.annotations.Operation; @@ -32,4 +34,13 @@ public ResponseEntity createAndUpdate( qnaService.saveAndUpdate(user.getId(), request); return ResponseEntity.ok().build(); } + + @Operation(summary = "백문백답 삭제") + @DeleteMapping + public ResponseEntity delete( + @RequestBody @Valid DeleteQnaRequest request, + @AuthenticationPrincipal JwtAuthentication user) { + qnaService.delete(user.getId(), request); + return ResponseEntity.ok().build(); + } } diff --git a/src/main/java/com/dnd/accompany/domain/qna100/api/dto/DeleteQnaRequest.java b/src/main/java/com/dnd/accompany/domain/qna100/api/dto/DeleteQnaRequest.java new file mode 100644 index 0000000..43a93c6 --- /dev/null +++ b/src/main/java/com/dnd/accompany/domain/qna100/api/dto/DeleteQnaRequest.java @@ -0,0 +1,8 @@ +package com.dnd.accompany.domain.qna100.api.dto; + +import java.util.List; + +public record DeleteQnaRequest( + List ids +) { +} diff --git a/src/main/java/com/dnd/accompany/domain/qna100/exception/Qna100AccessDeniedException.java b/src/main/java/com/dnd/accompany/domain/qna100/exception/Qna100AccessDeniedException.java new file mode 100644 index 0000000..4b283f5 --- /dev/null +++ b/src/main/java/com/dnd/accompany/domain/qna100/exception/Qna100AccessDeniedException.java @@ -0,0 +1,10 @@ +package com.dnd.accompany.domain.qna100.exception; + +import com.dnd.accompany.global.common.exception.BusinessException; +import com.dnd.accompany.global.common.response.ErrorCode; + +public class Qna100AccessDeniedException extends BusinessException { + public Qna100AccessDeniedException(ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/com/dnd/accompany/domain/qna100/exception/Qna100NotFoundException.java b/src/main/java/com/dnd/accompany/domain/qna100/exception/Qna100NotFoundException.java new file mode 100644 index 0000000..ea431e6 --- /dev/null +++ b/src/main/java/com/dnd/accompany/domain/qna100/exception/Qna100NotFoundException.java @@ -0,0 +1,10 @@ +package com.dnd.accompany.domain.qna100.exception; + +import com.dnd.accompany.global.common.exception.BusinessException; +import com.dnd.accompany.global.common.response.ErrorCode; + +public class Qna100NotFoundException extends BusinessException { + public Qna100NotFoundException(ErrorCode errorCode) { + super(errorCode); + } +} diff --git a/src/main/java/com/dnd/accompany/domain/qna100/infrastructure/QnaRepository.java b/src/main/java/com/dnd/accompany/domain/qna100/infrastructure/QnaRepository.java index d137efc..09bcc1c 100644 --- a/src/main/java/com/dnd/accompany/domain/qna100/infrastructure/QnaRepository.java +++ b/src/main/java/com/dnd/accompany/domain/qna100/infrastructure/QnaRepository.java @@ -1,5 +1,8 @@ package com.dnd.accompany.domain.qna100.infrastructure; +import java.util.List; +import java.util.Optional; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -8,5 +11,6 @@ @Repository public interface QnaRepository extends JpaRepository, QnaRepositoryCustom { - void deleteAllByUserId(Long userId); + Optional findFirstByUserId(Long userId); + void deleteByIdIn(List ids); } diff --git a/src/main/java/com/dnd/accompany/domain/qna100/service/QnaService.java b/src/main/java/com/dnd/accompany/domain/qna100/service/QnaService.java index 1551a1e..18547d9 100644 --- a/src/main/java/com/dnd/accompany/domain/qna100/service/QnaService.java +++ b/src/main/java/com/dnd/accompany/domain/qna100/service/QnaService.java @@ -10,8 +10,12 @@ import org.springframework.transaction.annotation.Transactional; import com.dnd.accompany.domain.qna100.api.dto.CreateAndUpdateQnaRequest; +import com.dnd.accompany.domain.qna100.api.dto.DeleteQnaRequest; import com.dnd.accompany.domain.qna100.entity.Qna100; +import com.dnd.accompany.domain.qna100.exception.Qna100AccessDeniedException; +import com.dnd.accompany.domain.qna100.exception.Qna100NotFoundException; import com.dnd.accompany.domain.qna100.infrastructure.QnaRepository; +import com.dnd.accompany.global.common.response.ErrorCode; import lombok.RequiredArgsConstructor; @@ -41,4 +45,16 @@ public void saveAndUpdate(Long userId, CreateAndUpdateQnaRequest request) { qnaRepository.saveAll(newQnas); } + + @Transactional + public void delete(Long userId, DeleteQnaRequest request) { + Qna100 qna = qnaRepository.findFirstByUserId(userId) + .orElseThrow(() -> new Qna100NotFoundException(ErrorCode.QNA100_NOT_FOUND)); + + if(!userId.equals(qna.getUserId())){ + throw new Qna100AccessDeniedException(ErrorCode.QNA100_ACCESS_DENIED); + } + + qnaRepository.deleteByIdIn(request.ids()); + } } diff --git a/src/main/java/com/dnd/accompany/global/common/response/ErrorCode.java b/src/main/java/com/dnd/accompany/global/common/response/ErrorCode.java index f2e1cf0..ff8638f 100644 --- a/src/main/java/com/dnd/accompany/global/common/response/ErrorCode.java +++ b/src/main/java/com/dnd/accompany/global/common/response/ErrorCode.java @@ -38,6 +38,10 @@ public enum ErrorCode { // ---- 동행 신청서 ---- // ACCOMPANY_REQUEST_NOT_FOUND(MatripConstant.NOT_FOUND, "ACCOMPANY_REQUEST-001", "동행 신청서를 찾을 수 없습니다."), + // ---- 백문백답 ---- // + QNA100_NOT_FOUND(MatripConstant.NOT_FOUND, "QNA100-001", "백문백답을 찾을 수 없습니다."), + QNA100_ACCESS_DENIED(MatripConstant.FORBIDDEN, "QNA100-002", "백문백답 접근 권한이 없습니다."), + // ---- 이미지 ---- // IMAGE_NOT_EXISTS(MatripConstant.NOT_FOUND, "IMAGE-001", "이미지를 찾을 수 없습니다."), FILE_IO_EXCEPTION(MatripConstant.INTERNAL_SERVER_ERROR, "IMAGE-002", "파일 생성에 실패했습니다."),