diff --git a/src/main/java/com/eactive/apim/portal/apps/community/qna/repository/InquiryRepository.java b/src/main/java/com/eactive/apim/portal/apps/community/qna/repository/InquiryRepository.java index 78ed916..7d1dffc 100644 --- a/src/main/java/com/eactive/apim/portal/apps/community/qna/repository/InquiryRepository.java +++ b/src/main/java/com/eactive/apim/portal/apps/community/qna/repository/InquiryRepository.java @@ -3,6 +3,7 @@ package com.eactive.apim.portal.apps.community.qna.repository; import com.eactive.apim.portal.portaluser.entity.PortalUser; import com.eactive.apim.portal.qna.entity.Inquiry; import com.eactive.eai.rms.data.EMSDataSource; +import java.util.List; import java.util.Optional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; @@ -17,4 +18,7 @@ public interface InquiryRepository extends JpaRepository, JpaSp @Transactional long deleteByInquirer_Id(String inquirerId); + + /** 4010 테스트 cleanup 전용 — 작성자 + 제목 접두사로 테스트 문의글만 좁혀 조회한다. */ + List findAllByInquirer_IdAndInquirySubjectStartingWith(String inquirerId, String subjectPrefix); } diff --git a/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/repository/InquiryCommentRepository.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/repository/InquiryCommentRepository.java index 3f5319d..80bf9a3 100644 --- a/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/repository/InquiryCommentRepository.java +++ b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/repository/InquiryCommentRepository.java @@ -21,4 +21,8 @@ public interface InquiryCommentRepository extends JpaRepository inquiryIds); } diff --git a/src/main/java/com/eactive/apim/portal/djb/testcleanup/controller/TestCleanupInternalController.java b/src/main/java/com/eactive/apim/portal/djb/testcleanup/controller/TestCleanupInternalController.java index d17a4b8..ad1458d 100644 --- a/src/main/java/com/eactive/apim/portal/djb/testcleanup/controller/TestCleanupInternalController.java +++ b/src/main/java/com/eactive/apim/portal/djb/testcleanup/controller/TestCleanupInternalController.java @@ -226,6 +226,33 @@ public class TestCleanupInternalController { return ResponseEntity.ok(body); } + /** + * 4010 재실행 전(또는 종료 후 최종 정리), 해당 계정이 작성한 테스트 문의글만 삭제한다(댓글 포함). + * 대상은 이메일(작성자)과 {@code 새글 작성 테스트} 로 시작하는 제목 접두사로 이중 한정한다. + */ + @PostMapping("/inquiry") + public ResponseEntity> deleteInquiries( + @RequestParam String email, @RequestParam String subjectPrefix, HttpServletRequest request) { + ResponseEntity> guardFailure = checkGuards(request); + if (guardFailure != null) { + return guardFailure; + } + if (StringUtils.isBlank(email) || StringUtils.isBlank(subjectPrefix)) { + return badRequest("email 과 subjectPrefix 는 필수입니다."); + } + + TestCleanupResult result = testCleanupService.deleteInquiriesByEmail(email, subjectPrefix); + log.info("테스트 정리(inquiry) 실행 - email: {}, subjectPrefix: {}, found: {}, from: {}", + email, subjectPrefix, result.isFound(), request.getRemoteAddr()); + + Map body = baseBody(); + body.put("email", email); + body.put("subjectPrefix", subjectPrefix); + body.put("inquiryFound", result.isFound()); + body.put("deletedCounts", result.getDeletedCounts()); + return ResponseEntity.ok(body); + } + /** * 휴대폰 번호로 남아 있는 초대 레코드를 삭제한다. 1020 재실행 전 초대중 중복을 정리하는 용도다. */ diff --git a/src/main/java/com/eactive/apim/portal/djb/testcleanup/service/TestCleanupService.java b/src/main/java/com/eactive/apim/portal/djb/testcleanup/service/TestCleanupService.java index a3b1eb7..52eb0dc 100644 --- a/src/main/java/com/eactive/apim/portal/djb/testcleanup/service/TestCleanupService.java +++ b/src/main/java/com/eactive/apim/portal/djb/testcleanup/service/TestCleanupService.java @@ -26,9 +26,11 @@ import com.eactive.apim.portal.portaluser.repository.PortalUserPrivacyAgreementR import com.eactive.apim.portal.portaluser.repository.PortalUserRepository; import com.eactive.apim.portal.portaluser.repository.UserPasswordHistoryRepository; import com.eactive.apim.portal.portaluser.repository.UserRoleHistoryRepository; +import com.eactive.apim.portal.qna.entity.Inquiry; import com.eactive.apim.portal.user.repository.UserLogRepository; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Profile; @@ -275,6 +277,44 @@ public class TestCleanupService { return result; } + /** + * 4010 재실행 전(또는 종료 후 최종 정리) 특정 계정이 작성한 테스트 문의글만 삭제한다(댓글 포함). + * 운영 글 오삭제를 막기 위해 이메일(작성자)과 {@code 새글 작성 테스트} 로 시작하는 제목 접두사를 모두 요구한다. + * 답변완료(RESPONDED)로 전환된 문의는 포털 자가삭제(PENDING + 작성자 전용)가 막히므로, 4010 종료 시점의 + * 최종 정리도 이 API를 재사용한다. + */ + public TestCleanupResult deleteInquiriesByEmail(String email, String subjectPrefix) { + assertNonProdProfile(); + if (subjectPrefix == null || !subjectPrefix.startsWith("새글 작성 테스트")) { + throw new IllegalArgumentException("테스트 문의글 제목 접두사(새글 작성 테스트*)만 정리할 수 있습니다."); + } + + Optional userOpt = portalUserRepository.findPortalUserByEmailAddr(email); + if (!userOpt.isPresent()) { + return TestCleanupResult.notFound(); + } + PortalUser user = userOpt.get(); + + List targets = + inquiryRepository.findAllByInquirer_IdAndInquirySubjectStartingWith(user.getId(), subjectPrefix); + if (targets.isEmpty()) { + TestCleanupResult empty = TestCleanupResult.notFound(); + empty.put("PTL_INQUIRY", 0L); + empty.put("PTL_INQUIRY_COMMENT", 0L); + return empty; + } + + List ids = targets.stream().map(Inquiry::getId).collect(Collectors.toList()); + long comments = inquiryCommentRepository.deleteByInquiry_IdIn(ids); + inquiryRepository.deleteAll(targets); + + TestCleanupResult result = TestCleanupResult.found(user.getId()); + result.put("PTL_INQUIRY", (long) targets.size()); + result.put("PTL_INQUIRY_COMMENT", comments); + log.info("테스트 정리 - 문의글 삭제 완료: email={}, prefix={}, count={}", email, subjectPrefix, targets.size()); + return result; + } + private TestCleanupResult deleteUserCascadeInternal(PortalUser user) { TestCleanupResult result = TestCleanupResult.found(user.getId()); result.put("PTL_INQUIRY_COMMENT", inquiryCommentRepository.deleteByInquiry_Inquirer_Id(user.getId()));