From 171feee9ea5d45e477171d2eca3165f0218669fb Mon Sep 17 00:00:00 2001 From: Rinjae Date: Mon, 15 Jun 2026 18:49:14 +0900 Subject: [PATCH] =?UTF-8?q?Q&A=20=EB=8C=93=EA=B8=80=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81=20?= =?UTF-8?q?=EB=B0=8F=20=EC=97=AD=ED=95=A0=20=EA=B8=B0=EB=B0=98=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EC=84=A0=20-=20Inqui?= =?UTF-8?q?ryComment=20=EC=BD=94=EB=93=9C=20=EA=B5=AC=EC=A1=B0=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81=20=EB=B0=8F=20=EC=97=AD=ED=95=A0=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20-=20portal-admin=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EA=B0=9C=EC=84=A0=20-=20Inqui?= =?UTF-8?q?ryComment=20=EA=B4=80=EB=A0=A8=20=EB=B6=88=ED=95=84=EC=9A=94=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4/=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 - .../qna/service/InquiryFacadeImpl.java | 14 ++++- .../controller/InquiryCommentController.java | 0 .../dto/InquiryCommentCreateRequest.java | 0 .../qna/comment/dto/InquiryCommentDTO.java | 0 .../InquiryCommentCreatedAdminEvent.java | 2 +- .../repository/InquiryCommentRepository.java | 0 .../repository/UserInfoRepository.java | 22 +++++++ .../comment/service/InquiryAdminNotifier.java | 57 +++++++++++++++++++ .../comment/service/InquiryCommentFacade.java | 0 .../service/InquiryCommentFacadeImpl.java | 25 +++----- .../service/InquiryCommentService.java | 0 .../community/qna/constant/DjbAdminRole.java | 10 ++++ .../qna/constant/DjbInquiryStatus.java | 0 .../qna/exception/InquiryClosedException.java | 0 .../InquiryCommentNotOwnedException.java | 0 .../InquiryCommentPermissionChecker.java | 0 .../repository/UserInfoRepository.java | 9 --- 18 files changed, 110 insertions(+), 30 deletions(-) rename src/main/java/{djb => }/com/eactive/apim/portal/djb/community/qna/comment/controller/InquiryCommentController.java (100%) rename src/main/java/{djb => }/com/eactive/apim/portal/djb/community/qna/comment/dto/InquiryCommentCreateRequest.java (100%) rename src/main/java/{djb => }/com/eactive/apim/portal/djb/community/qna/comment/dto/InquiryCommentDTO.java (100%) rename src/main/java/{djb => }/com/eactive/apim/portal/djb/community/qna/comment/event/InquiryCommentCreatedAdminEvent.java (98%) rename src/main/java/{djb => }/com/eactive/apim/portal/djb/community/qna/comment/repository/InquiryCommentRepository.java (100%) create mode 100644 src/main/java/com/eactive/apim/portal/djb/community/qna/comment/repository/UserInfoRepository.java create mode 100644 src/main/java/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryAdminNotifier.java rename src/main/java/{djb => }/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentFacade.java (100%) rename src/main/java/{djb => }/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentFacadeImpl.java (88%) rename src/main/java/{djb => }/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentService.java (100%) create mode 100644 src/main/java/com/eactive/apim/portal/djb/community/qna/constant/DjbAdminRole.java rename src/main/java/{djb => }/com/eactive/apim/portal/djb/community/qna/constant/DjbInquiryStatus.java (100%) rename src/main/java/{djb => }/com/eactive/apim/portal/djb/community/qna/exception/InquiryClosedException.java (100%) rename src/main/java/{djb => }/com/eactive/apim/portal/djb/community/qna/exception/InquiryCommentNotOwnedException.java (100%) rename src/main/java/{djb => }/com/eactive/apim/portal/djb/community/qna/support/InquiryCommentPermissionChecker.java (100%) delete mode 100644 src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/repository/UserInfoRepository.java diff --git a/build.gradle b/build.gradle index 7f35e4b..26be4b9 100644 --- a/build.gradle +++ b/build.gradle @@ -135,7 +135,6 @@ sourceSets { main { java { srcDir 'src/main/java' - srcDir 'src/main/java/djb' } } } diff --git a/src/main/java/com/eactive/apim/portal/apps/community/qna/service/InquiryFacadeImpl.java b/src/main/java/com/eactive/apim/portal/apps/community/qna/service/InquiryFacadeImpl.java index 3d54094..be0f4fb 100644 --- a/src/main/java/com/eactive/apim/portal/apps/community/qna/service/InquiryFacadeImpl.java +++ b/src/main/java/com/eactive/apim/portal/apps/community/qna/service/InquiryFacadeImpl.java @@ -6,8 +6,10 @@ import com.eactive.apim.portal.apps.community.qna.mapper.InquiryMapper; import com.eactive.apim.portal.common.user.PortalAuthenticatedUser; import com.eactive.apim.portal.common.util.SecurityUtil; import com.eactive.apim.portal.common.util.StringMaskingUtil; +import com.eactive.apim.portal.djb.community.qna.comment.service.InquiryAdminNotifier; import com.eactive.apim.portal.portaluser.entity.PortalUserEnums; import com.eactive.apim.portal.qna.entity.Inquiry; +import com.eactive.apim.portal.template.entity.MessageCode; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -15,6 +17,8 @@ import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; @Service @RequiredArgsConstructor @@ -22,6 +26,7 @@ public class InquiryFacadeImpl implements InquiryFacade { private final InquiryService inquiryService; private final InquiryMapper inquiryMapper; + private final InquiryAdminNotifier inquiryAdminNotifier; @Override public Page getInquiries(InquirySearch search, Pageable pageable, PortalAuthenticatedUser user) { @@ -81,9 +86,16 @@ public class InquiryFacadeImpl implements InquiryFacade { @Override public void createInquiry(InquiryDTO inquiryDTO) throws IOException { + PortalAuthenticatedUser current = SecurityUtil.getPortalAuthenticatedUser(); Inquiry inquiry = inquiryMapper.toEntity(inquiryDTO); - inquiry.setInquirer(SecurityUtil.getPortalAuthenticatedUser()); + inquiry.setInquirer(current); inquiryService.createInquiry(inquiry); + + Map params = new HashMap<>(); + params.put("inquiryId", inquiry.getId()); + params.put("inquirySubject", inquiry.getInquirySubject()); + params.put("writerName", current.getUserName()); + inquiryAdminNotifier.notifyPortalAdmins(MessageCode.INQUIRY_CREATED, params); } @Override diff --git a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/controller/InquiryCommentController.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/controller/InquiryCommentController.java similarity index 100% rename from src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/controller/InquiryCommentController.java rename to src/main/java/com/eactive/apim/portal/djb/community/qna/comment/controller/InquiryCommentController.java diff --git a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/dto/InquiryCommentCreateRequest.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/dto/InquiryCommentCreateRequest.java similarity index 100% rename from src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/dto/InquiryCommentCreateRequest.java rename to src/main/java/com/eactive/apim/portal/djb/community/qna/comment/dto/InquiryCommentCreateRequest.java diff --git a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/dto/InquiryCommentDTO.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/dto/InquiryCommentDTO.java similarity index 100% rename from src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/dto/InquiryCommentDTO.java rename to src/main/java/com/eactive/apim/portal/djb/community/qna/comment/dto/InquiryCommentDTO.java diff --git a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/event/InquiryCommentCreatedAdminEvent.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/event/InquiryCommentCreatedAdminEvent.java similarity index 98% rename from src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/event/InquiryCommentCreatedAdminEvent.java rename to src/main/java/com/eactive/apim/portal/djb/community/qna/comment/event/InquiryCommentCreatedAdminEvent.java index 85990ac..7277aba 100644 --- a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/event/InquiryCommentCreatedAdminEvent.java +++ b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/event/InquiryCommentCreatedAdminEvent.java @@ -12,7 +12,7 @@ import java.util.Map; @Component public class InquiryCommentCreatedAdminEvent implements MessageEventHandler { - public static final MessageCode KEY = MessageCode.INQUIRY_COMMENT_CREATED_ADMIN; + public static final MessageCode KEY = MessageCode.INQUIRY_COMMENT_CREATED; @Override public MessageCode getKey() { diff --git a/src/main/java/djb/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 similarity index 100% rename from src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/repository/InquiryCommentRepository.java rename to src/main/java/com/eactive/apim/portal/djb/community/qna/comment/repository/InquiryCommentRepository.java diff --git a/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/repository/UserInfoRepository.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/repository/UserInfoRepository.java new file mode 100644 index 0000000..e1796e1 --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/repository/UserInfoRepository.java @@ -0,0 +1,22 @@ +package com.eactive.apim.portal.djb.community.qna.comment.repository; + +import com.eactive.apim.portal.user.entity.UserInfo; +import com.eactive.eai.data.jpa.BaseRepository; +import com.eactive.eai.rms.data.EMSDataSource; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +@EMSDataSource +public interface UserInfoRepository extends BaseRepository { + + /** + * TSEAIRM02.roleidnfiname 컬럼은 콤마로 구분된 복수 역할을 저장한다. + * (예: {@code "admin,portal-admin"}). Oracle native query로 콤마 토큰 매치. + */ + @Query(value = "SELECT * FROM TSEAIRM02 t" + + " WHERE ',' || t.ROLEIDNFINAME || ',' LIKE '%,' || :role || ',%'", + nativeQuery = true) + List findByRoleContaining(@Param("role") String role); +} diff --git a/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryAdminNotifier.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryAdminNotifier.java new file mode 100644 index 0000000..0a2c488 --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryAdminNotifier.java @@ -0,0 +1,57 @@ +package com.eactive.apim.portal.djb.community.qna.comment.service; + +import com.eactive.apim.portal.djb.community.qna.comment.repository.UserInfoRepository; +import com.eactive.apim.portal.djb.community.qna.constant.DjbAdminRole; +import com.eactive.apim.portal.template.entity.MessageCode; +import com.eactive.apim.portal.template.service.MessageHandlerService; +import com.eactive.apim.portal.template.service.MessageRecipient; +import com.eactive.apim.portal.user.entity.UserInfo; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** + * Q&A 등록/댓글 등록 시 portal-admin 역할(TSEAIRM02)을 가진 관리자 전원에게 + * 알림 메시지를 발행한다. 발송 실패는 트랜잭션 롤백을 유발하지 않는다. + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class InquiryAdminNotifier { + + private final UserInfoRepository userInfoRepository; + private final MessageHandlerService messageHandlerService; + + public void notifyPortalAdmins(MessageCode code, Map params) { + try { + List admins = userInfoRepository.findByRoleContaining(DjbAdminRole.PORTAL_ADMIN); + if (admins == null || admins.isEmpty()) { + log.warn("portal-admin 역할 관리자가 없습니다 — 알림 미발송 code={}", code.name()); + return; + } + for (UserInfo admin : admins) { + try { + MessageRecipient recipient = toRecipient(admin); + messageHandlerService.publishEvent(code, recipient, params); + } catch (Exception e) { + log.warn("portal-admin 개별 알림 발행 실패 — userid={}, code={}", + admin.getUserid(), code.name(), e); + } + } + } catch (Exception e) { + log.warn("portal-admin 알림 발행 실패 — code={}", code.name(), e); + } + } + + private MessageRecipient toRecipient(UserInfo admin) { + MessageRecipient r = new MessageRecipient(); + r.setUsername(admin.getUsername()); + r.setUserId(admin.getEmad()); + r.setPhone(admin.getCphnno()); + r.setMessengerId(admin.getUserid()); + return r; + } +} diff --git a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentFacade.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentFacade.java similarity index 100% rename from src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentFacade.java rename to src/main/java/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentFacade.java diff --git a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentFacadeImpl.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentFacadeImpl.java similarity index 88% rename from src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentFacadeImpl.java rename to src/main/java/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentFacadeImpl.java index e5b0883..aaf9e41 100644 --- a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentFacadeImpl.java +++ b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentFacadeImpl.java @@ -13,8 +13,6 @@ import com.eactive.apim.portal.portaluser.repository.PortalUserRepository; import com.eactive.apim.portal.qna.entity.Inquiry; import com.eactive.apim.portal.qna.entity.InquiryComment; import com.eactive.apim.portal.template.entity.MessageCode; -import com.eactive.apim.portal.template.service.MessageHandlerService; -import com.eactive.apim.portal.template.service.MessageRecipient; import com.eactive.apim.portal.user.entity.UserInfo; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -44,7 +42,7 @@ public class InquiryCommentFacadeImpl implements InquiryCommentFacade { private final InquiryCommentService commentService; private final InquiryCommentRepository commentRepository; private final InquiryCommentPermissionChecker permissionChecker; - private final MessageHandlerService messageHandlerService; + private final InquiryAdminNotifier adminNotifier; private final PortalUserRepository portalUserRepository; private final UserInfoRepository userInfoRepository; @@ -96,21 +94,12 @@ public class InquiryCommentFacadeImpl implements InquiryCommentFacade { } private void publishAdminNotification(Inquiry inquiry, InquiryComment comment, PortalAuthenticatedUser current) { - try { - Map params = new HashMap<>(); - params.put("inquiryId", inquiry.getId()); - params.put("inquirySubject", inquiry.getInquirySubject()); - params.put("commentContent", comment.getCommentDetail()); - params.put("writerName", current.getUserName()); - messageHandlerService.publishEvent( - MessageCode.INQUIRY_COMMENT_CREATED_ADMIN, - MessageRecipient.of(current), - params - ); - } catch (Exception e) { - log.warn("Q&A 댓글 등록 관리자 알림 발행 실패 — inquiryId={}, commentId={}", - inquiry.getId(), comment.getId(), e); - } + Map params = new HashMap<>(); + params.put("inquiryId", inquiry.getId()); + params.put("inquirySubject", inquiry.getInquirySubject()); + params.put("commentContent", comment.getCommentDetail()); + params.put("writerName", current.getUserName()); + adminNotifier.notifyPortalAdmins(MessageCode.INQUIRY_COMMENT_CREATED, params); } private Map resolveWriterNames(List comments) { diff --git a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentService.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentService.java similarity index 100% rename from src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentService.java rename to src/main/java/com/eactive/apim/portal/djb/community/qna/comment/service/InquiryCommentService.java diff --git a/src/main/java/com/eactive/apim/portal/djb/community/qna/constant/DjbAdminRole.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/constant/DjbAdminRole.java new file mode 100644 index 0000000..da10892 --- /dev/null +++ b/src/main/java/com/eactive/apim/portal/djb/community/qna/constant/DjbAdminRole.java @@ -0,0 +1,10 @@ +package com.eactive.apim.portal.djb.community.qna.constant; + +public final class DjbAdminRole { + + /** TSEAIRM02.roleidnfiname 컬럼에서 포털 관리자를 식별하는 값. */ + public static final String PORTAL_ADMIN = "portal-admin"; + + private DjbAdminRole() { + } +} diff --git a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/constant/DjbInquiryStatus.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/constant/DjbInquiryStatus.java similarity index 100% rename from src/main/java/djb/com/eactive/apim/portal/djb/community/qna/constant/DjbInquiryStatus.java rename to src/main/java/com/eactive/apim/portal/djb/community/qna/constant/DjbInquiryStatus.java diff --git a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/exception/InquiryClosedException.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/exception/InquiryClosedException.java similarity index 100% rename from src/main/java/djb/com/eactive/apim/portal/djb/community/qna/exception/InquiryClosedException.java rename to src/main/java/com/eactive/apim/portal/djb/community/qna/exception/InquiryClosedException.java diff --git a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/exception/InquiryCommentNotOwnedException.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/exception/InquiryCommentNotOwnedException.java similarity index 100% rename from src/main/java/djb/com/eactive/apim/portal/djb/community/qna/exception/InquiryCommentNotOwnedException.java rename to src/main/java/com/eactive/apim/portal/djb/community/qna/exception/InquiryCommentNotOwnedException.java diff --git a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/support/InquiryCommentPermissionChecker.java b/src/main/java/com/eactive/apim/portal/djb/community/qna/support/InquiryCommentPermissionChecker.java similarity index 100% rename from src/main/java/djb/com/eactive/apim/portal/djb/community/qna/support/InquiryCommentPermissionChecker.java rename to src/main/java/com/eactive/apim/portal/djb/community/qna/support/InquiryCommentPermissionChecker.java diff --git a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/repository/UserInfoRepository.java b/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/repository/UserInfoRepository.java deleted file mode 100644 index 9bb9452..0000000 --- a/src/main/java/djb/com/eactive/apim/portal/djb/community/qna/comment/repository/UserInfoRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.eactive.apim.portal.djb.community.qna.comment.repository; - -import com.eactive.apim.portal.user.entity.UserInfo; -import com.eactive.eai.data.jpa.BaseRepository; -import com.eactive.eai.rms.data.EMSDataSource; - -@EMSDataSource -public interface UserInfoRepository extends BaseRepository { -}