diff --git a/src/main/java/life/mosu/mosuserver/application/notify/NotifyVariableFactory.java b/src/main/java/life/mosu/mosuserver/application/notify/NotifyVariableFactory.java index 2f425bdc..18ab6beb 100644 --- a/src/main/java/life/mosu/mosuserver/application/notify/NotifyVariableFactory.java +++ b/src/main/java/life/mosu/mosuserver/application/notify/NotifyVariableFactory.java @@ -1,5 +1,6 @@ package life.mosu.mosuserver.application.notify; +import life.mosu.mosuserver.application.notify.dto.ApplicationGuestNotifyRequest; import life.mosu.mosuserver.application.notify.dto.ApplicationNotifyRequest; import life.mosu.mosuserver.application.notify.dto.Exam1DayBeforeNotifyRequest; import life.mosu.mosuserver.application.notify.dto.Exam1WeekBeforeNotifyRequest; @@ -39,6 +40,8 @@ public LunaNotificationVariable create(LunaNotificationEvent event) { case REFUND_SUCCESS -> createRefundVariable(event.targetId()); // case APPLICATION_SUCCESS -> createApplicationVariable(event.targetId()); // examApplicationId + case APPLICATION_GUEST_SUCCESS -> + createApplicationGuestVariable(event.targetId()); // examApplicationId case EXAM_1WEEK_BEFORE_REMINDER_INFO -> createExam1WeekBeforeVariable(event.targetId()); // examApplicationId case EXAM_3DAY_BEFORE_REMINDER_INFO -> @@ -81,6 +84,14 @@ private LunaNotificationVariable createApplicationVariable(Long targetId) { return ApplicationNotifyRequest.from(projection); } + private LunaNotificationVariable createApplicationGuestVariable(Long targetId) { + ExamApplicationNotifyProjection projection = examApplicationRepository.findExamAndPaymentByExamApplicationId( + targetId) + .orElseThrow( + () -> new CustomRuntimeException(ErrorCode.EXAM_APPLICATION_NOT_FOUND)); + return ApplicationGuestNotifyRequest.from(projection); + } + private LunaNotificationVariable createExam1WeekBeforeVariable(Long targetId) { ExamInfoProjection examInfo = examApplicationRepository.findExamInfo(targetId) .orElseThrow( diff --git a/src/main/java/life/mosu/mosuserver/application/notify/dto/ApplicationGuestNotifyRequest.java b/src/main/java/life/mosu/mosuserver/application/notify/dto/ApplicationGuestNotifyRequest.java new file mode 100644 index 00000000..1010512b --- /dev/null +++ b/src/main/java/life/mosu/mosuserver/application/notify/dto/ApplicationGuestNotifyRequest.java @@ -0,0 +1,45 @@ +package life.mosu.mosuserver.application.notify.dto; + + +import static life.mosu.mosuserver.infra.notify.constant.NotifyRedirectUrlConstants.WARNING_PAGE; + +import java.time.LocalDate; +import java.util.Map; +import life.mosu.mosuserver.domain.examapplication.projection.ExamApplicationNotifyProjection; +import life.mosu.mosuserver.infra.notify.dto.luna.LunaNotificationButtonUrls; +import life.mosu.mosuserver.infra.notify.dto.luna.LunaNotificationButtonUrls.NotificationButtonUrl; +import life.mosu.mosuserver.infra.notify.dto.luna.LunaNotificationVariable; + +public record ApplicationGuestNotifyRequest( + String paymentKey, + LocalDate examDate, + String schoolName, + String lunch +) implements LunaNotificationVariable { + + public static ApplicationGuestNotifyRequest from( + ExamApplicationNotifyProjection examApplication) { + + return new ApplicationGuestNotifyRequest(examApplication.paymentKey(), + examApplication.examDate(), examApplication.schoolName(), + examApplication.isLunchChecked() ? examApplication.lunchName() + : "선택 안 함"); + } + + @Override + public LunaNotificationButtonUrls getNotificationButtonUrls() { + return LunaNotificationButtonUrls.of( + NotificationButtonUrl.of(WARNING_PAGE, WARNING_PAGE) + ); + } + + @Override + public Map toMap() { + return Map.of( + "paymentKey", paymentKey, + "examDate", examDate.toString(), + "schoolName", schoolName, + "lunch", lunch + ); + } +} diff --git a/src/main/java/life/mosu/mosuserver/application/virtualaccount/event/DepositSuccessEventHandler.java b/src/main/java/life/mosu/mosuserver/application/virtualaccount/event/DepositSuccessEventHandler.java index 8ee5347e..4284a9e2 100644 --- a/src/main/java/life/mosu/mosuserver/application/virtualaccount/event/DepositSuccessEventHandler.java +++ b/src/main/java/life/mosu/mosuserver/application/virtualaccount/event/DepositSuccessEventHandler.java @@ -39,9 +39,9 @@ public void handle(DepositSuccessEvent event) { () -> new CustomRuntimeException(ErrorCode.EXAM_APPLICATION_NOT_FOUND)); LunaNotificationEvent lunaNotificationEvent = LunaNotificationEvent.create( - LunaNotificationStatus.APPLICATION_SUCCESS, + LunaNotificationStatus.APPLICATION_GUEST_SUCCESS, exam.getUserId(), exam.getId()); - + notifier.notify(lunaNotificationEvent); sendMail(log, event.getFormattedCreatedAt()); } diff --git a/src/main/java/life/mosu/mosuserver/domain/user/entity/UserJpaEntity.java b/src/main/java/life/mosu/mosuserver/domain/user/entity/UserJpaEntity.java index 6120db33..e66ad65e 100644 --- a/src/main/java/life/mosu/mosuserver/domain/user/entity/UserJpaEntity.java +++ b/src/main/java/life/mosu/mosuserver/domain/user/entity/UserJpaEntity.java @@ -119,6 +119,6 @@ public void changePassword(String newPassword) { } public String getPhoneNumber() { - return phoneNumber.replaceFirst("^.", ""); + return phoneNumber.replaceFirst("^[UG]", ""); } } diff --git a/src/main/java/life/mosu/mosuserver/infra/notify/component/luna/LunaNotifyWithSmsFallbackSender.java b/src/main/java/life/mosu/mosuserver/infra/notify/component/luna/LunaNotifyWithSmsFallbackSender.java index aac54d13..4301ba8b 100644 --- a/src/main/java/life/mosu/mosuserver/infra/notify/component/luna/LunaNotifyWithSmsFallbackSender.java +++ b/src/main/java/life/mosu/mosuserver/infra/notify/component/luna/LunaNotifyWithSmsFallbackSender.java @@ -1,5 +1,6 @@ package life.mosu.mosuserver.infra.notify.component.luna; +import static life.mosu.mosuserver.infra.notify.dto.luna.LunaNotificationStatus.APPLICATION_GUEST_SUCCESS; import static life.mosu.mosuserver.infra.notify.dto.luna.LunaNotificationStatus.APPLICATION_SUCCESS; import static life.mosu.mosuserver.infra.notify.dto.luna.LunaNotificationStatus.EXAM_1DAY_BEFORE_REMINDER_INFO; import static life.mosu.mosuserver.infra.notify.dto.luna.LunaNotificationStatus.EXAM_1WEEK_BEFORE_REMINDER_INFO; @@ -23,6 +24,7 @@ @Component @NotifyStrategyMapping({ APPLICATION_SUCCESS, + APPLICATION_GUEST_SUCCESS, REFUND_SUCCESS, EXAM_1DAY_BEFORE_REMINDER_INFO, EXAM_3DAY_BEFORE_REMINDER_INFO, diff --git a/src/main/java/life/mosu/mosuserver/infra/notify/dto/luna/LunaNotificationStatus.java b/src/main/java/life/mosu/mosuserver/infra/notify/dto/luna/LunaNotificationStatus.java index 927495c4..76c391de 100644 --- a/src/main/java/life/mosu/mosuserver/infra/notify/dto/luna/LunaNotificationStatus.java +++ b/src/main/java/life/mosu/mosuserver/infra/notify/dto/luna/LunaNotificationStatus.java @@ -8,6 +8,8 @@ public enum LunaNotificationStatus { // 성공 알림 SIGN_UP_SUCCESS("회원 가입 완료", LunaNotifyTemplateCode.SIGN_UP), APPLICATION_SUCCESS("신청 완료", LunaNotifyTemplateCode.APPLICATION), + APPLICATION_GUEST_SUCCESS("게스트 신청 완료", LunaNotifyTemplateCode.APPLICATION_GUEST), + REFUND_SUCCESS("환불 완료", LunaNotifyTemplateCode.REFUND), INQUIRY_ANSWER_SUCCESS("문의 답변 완료", LunaNotifyTemplateCode.INQUIRY_ANSWER), diff --git a/src/main/java/life/mosu/mosuserver/infra/notify/dto/luna/LunaNotifyTemplateCode.java b/src/main/java/life/mosu/mosuserver/infra/notify/dto/luna/LunaNotifyTemplateCode.java index 6e1e8654..9a6cb14f 100644 --- a/src/main/java/life/mosu/mosuserver/infra/notify/dto/luna/LunaNotifyTemplateCode.java +++ b/src/main/java/life/mosu/mosuserver/infra/notify/dto/luna/LunaNotifyTemplateCode.java @@ -11,6 +11,11 @@ public enum LunaNotifyTemplateCode { "notify.exam.application.complete.alimtalk", "notify.exam.application.complete.sms" ), + APPLICATION_GUEST( + 50051, + "notify.exam.guest.application.complete.alimtalk", + "notify.exam.guest.application.complete.sms" + ), EXAM_1DAY_BEFORE( 50047, "notify.exam.oneday.reminder.alimtalk", diff --git a/src/main/java/life/mosu/mosuserver/presentation/payment/PaymentWidgetController.java b/src/main/java/life/mosu/mosuserver/presentation/payment/PaymentWidgetController.java index 69f34047..b7887792 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/payment/PaymentWidgetController.java +++ b/src/main/java/life/mosu/mosuserver/presentation/payment/PaymentWidgetController.java @@ -3,6 +3,7 @@ import jakarta.validation.Valid; import life.mosu.mosuserver.application.payment.PaymentConfirmService; import life.mosu.mosuserver.application.payment.PaymentPrepareService; +import life.mosu.mosuserver.application.payment.cron.PaymentFailureLogDomainArchiveExecutor; import life.mosu.mosuserver.global.annotation.UserId; import life.mosu.mosuserver.global.util.ApiResponseWrapper; import life.mosu.mosuserver.presentation.payment.dto.PaymentPrepareResponse; @@ -23,12 +24,13 @@ public class PaymentWidgetController { private final PaymentPrepareService prepareService; private final PaymentConfirmService confirmService; + private final PaymentFailureLogDomainArchiveExecutor paymentFailureLogDomainArchiveExecutor; /** * 결제 준비 요청 *

- * 결제 준비 요청은 결제 시작을 위한 준비 단계로, 결제 금액과 주문 ID를 생성합니다. - * 이 단계에서는 실제 결제가 이루어지지 않으며, 결제 승인 요청을 위한 정보를 반환합니다. + * 결제 준비 요청은 결제 시작을 위한 준비 단계로, 결제 금액과 주문 ID를 생성합니다. 이 단계에서는 실제 결제가 이루어지지 않으며, 결제 승인 요청을 위한 정보를 + * 반환합니다. * * @param userId 사용자 ID * @param request 결제 준비 요청 정보 @@ -59,4 +61,12 @@ public ApiResponseWrapper confirm( confirmService.confirm(userId, request); return ApiResponseWrapper.success(HttpStatus.CREATED, "결제 승인 성공"); } + + + @PostMapping("/cleanup") + @PreAuthorize("isAuthenticated() and hasRole('ADMIN')") + public ApiResponseWrapper archivePaymentFailureLogs() { + paymentFailureLogDomainArchiveExecutor.archive(); + return ApiResponseWrapper.success(HttpStatus.CREATED, "게스트 결제 승인 성공"); + } } diff --git a/src/main/java/life/mosu/mosuserver/presentation/refund/RefundController.java b/src/main/java/life/mosu/mosuserver/presentation/refund/RefundController.java index ce09a8e4..9d5c294d 100644 --- a/src/main/java/life/mosu/mosuserver/presentation/refund/RefundController.java +++ b/src/main/java/life/mosu/mosuserver/presentation/refund/RefundController.java @@ -1,6 +1,7 @@ package life.mosu.mosuserver.presentation.refund; import life.mosu.mosuserver.application.refund.RefundService; +import life.mosu.mosuserver.application.refund.cron.RefundFailureLogDomainArchiveExecutor; import life.mosu.mosuserver.global.annotation.UserId; import life.mosu.mosuserver.global.util.ApiResponseWrapper; import life.mosu.mosuserver.presentation.refund.dto.MergedRefundRequest; @@ -26,6 +27,7 @@ public class RefundController { private final RefundService refundService; + private final RefundFailureLogDomainArchiveExecutor refundFailureLogDomainArchiveExecutor; @GetMapping() ResponseEntity> getRefundAmount( @@ -46,4 +48,11 @@ ResponseEntity> process( refundService.doProcess(userId, request); return ResponseEntity.ok(ApiResponseWrapper.success(HttpStatus.OK, "결제 취소 성공")); } + + @PostMapping("/cleanup") + @PreAuthorize("isAuthenticated() and hasRole('ADMIN')") + public ApiResponseWrapper archiveRefundFailureLogs() { + refundFailureLogDomainArchiveExecutor.archive(); + return ApiResponseWrapper.success(HttpStatus.CREATED, "게스트 결제 승인 성공"); + } } diff --git a/src/main/resources/messages_ko.properties b/src/main/resources/messages_ko.properties index 84f4aca7..b3f5008e 100644 --- a/src/main/resources/messages_ko.properties +++ b/src/main/resources/messages_ko.properties @@ -16,6 +16,21 @@ notify.exam.application.complete.sms=\ \uB9C8\uC774\uD398\uC774\uC9C0 \uBC14\uB85C\uAC00\uAE30: https://www.mosuedu.com/mypage\n\n\ \uC2DC\uD5D8 1\uC8FC\uC77C \uC804,\uC2DC\uD5D8 \uAD00\uB828 \uC720\uC758\uC0AC\uD56D\uACFC \uC218\uD5D8\uD45C \uC548\uB0B4 \uB9AC\uB9C8\uC778\uB4DC \uC54C\uB9BC\uC774 \uBC1C\uC1A1\uB420 \uC608\uC815\uC785\uB2C8\uB2E4.\n\ \uC720\uC758\uC0AC\uD56D \uBC14\uB85C\uAC00\uAE30: https://www.mosuedu.com/warning +notify.exam.guest.application.complete.alimtalk=\ +[\uBAA8\uC218] \uBAA8\uC758\uC218\uB2A5 \uC2E0\uCCAD\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4!\n\n\ +\u25A0 \uACB0\uC81C\uBC88\uD638: #{paymentKey}\n\ +\u25A0 \uC751\uC2DC\uC77C\uC790: #{examDate}\n\ +\u25A0 \uC2DC\uD5D8\uC7A5\uC18C: #{schoolName}\n\ +\u25A0 \uB3C4\uC2DC\uB77D: #{lunch}\n\n\ +\uC2DC\uD5D8 1\uC8FC\uC77C \uC804, \uC2DC\uD5D8 \uAD00\uB828 \uC720\uC758\uC0AC\uD56D\uACFC \uC218\uD5D8\uD45C \uC548\uB0B4 \uB9AC\uB9C8\uC778\uB4DC \uC54C\uB9BC\uC774 \uBC1C\uC1A1\uB420 \uC608\uC815\uC785\uB2C8\uB2E4. +notify.exam.guest.application.complete.sms=\ +[\uBAA8\uC218] \uBAA8\uC758\uC218\uB2A5 \uC2E0\uCCAD\uC774 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4!\n\n\ +\u25A0 \uACB0\uC81C\uBC88\uD638: #{paymentKey}\n\ +\u25A0 \uC751\uC2DC\uC77C\uC790: #{examDate}\n\ +\u25A0 \uC2DC\uD5D8\uC7A5\uC18C: #{schoolName}\n\ +\u25A0 \uB3C4\uC2DC\uB77D: #{lunch}\n\n\ +\uC2DC\uD5D8 1\uC8FC\uC77C \uC804, \uC2DC\uD5D8 \uAD00\uB828 \uC720\uC758\uC0AC\uD56D\uACFC \uC218\uD5D8\uD45C \uC548\uB0B4 \uB9AC\uB9C8\uC778\uB4DC \uC54C\uB9BC\uC774 \uBC1C\uC1A1\uB420 \uC608\uC815\uC785\uB2C8\uB2E4.\n\n\ +\uC720\uC758\uC0AC\uD56D \uBC14\uB85C\uAC00\uAE30 : https://www.mosuedu.com/warning notify.exam.oneweek.reminder.alimtalk=\ [\uBAA8\uC218] \uBAA8\uC758\uC218\uB2A5\uC774 1\uC8FC\uC77C \uC55E\uC73C\uB85C \uB2E4\uAC00\uC654\uC2B5\uB2C8\uB2E4!\n\n\ \u25A0 \uC2DC\uD5D8\uC77C\uC790: #{examDate}\n\