From 65a262849ea7ed39d4785109c4bec95f8d999813 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Mon, 24 Aug 2026 17:51:36 +0900 Subject: [PATCH] =?UTF-8?q?-=204020-partnership=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80=20-=20=EB=93=B1=EB=A1=9D/?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C/=EC=82=AD=EC=A0=9C=20=EC=8B=9C=EB=82=98?= =?UTF-8?q?=EB=A6=AC=EC=98=A4=20=EA=B5=AC=ED=98=84=20-=20e2e/admin-partner?= =?UTF-8?q?ship.page.ts=20-=20admin=20=EC=A0=91=EA=B7=BC=20=EB=B0=8F=20?= =?UTF-8?q?=ED=99=95=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EC=9E=91=EC=84=B1=20?= =?UTF-8?q?-=20e2e/partnership-feedback.spec.ts=20-=20e2e=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../qna/repository/InquiryRepository.java | 4 ++ .../repository/InquiryCommentRepository.java | 4 ++ .../TestCleanupInternalController.java | 27 +++++++++++++ .../service/TestCleanupService.java | 40 +++++++++++++++++++ 4 files changed, 75 insertions(+) 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()));