From f72a014c61181da71f1eb4af9f481a0a41ed494c Mon Sep 17 00:00:00 2001 From: Chan Jin Date: Mon, 6 Feb 2023 00:04:41 +0900 Subject: [PATCH 1/3] =?UTF-8?q?refactor=20:=20=EC=A3=BC=EB=AC=B8=20?= =?UTF-8?q?=EC=8A=B9=EC=9D=B8=20=ED=9B=84=20=ED=8B=B0=EC=BC=93=20=EB=B0=9C?= =?UTF-8?q?=EA=B8=89=20=EA=B3=BC=EC=A0=95=EC=97=90=EC=84=9C=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=EC=8B=9C=20=EB=B3=B4=EC=83=81=ED=8A=B8=EB=9E=9C?= =?UTF-8?q?=EC=9E=AD=EC=85=98=20=EC=8B=A4=ED=96=89=20(#282)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor : 오더 컨펌 티켓 발급 이벤트 상단으로 이동 * style :spotless * feat: 주문 실패 시 티켓 취소 추가 * fix: 발급 티켓 쿼리 락 안으로 수정 * style: spotless 적용 * feat : 주문 실패 시 쿠폰 복구 로직 * refactor : 옵션 검증만 도메인 이벤트 발행 이후로 미루기 * refactor : 티켓 발급 이벤트 리스너 트랜잭션 리스너말고 기본으로 설정 --------- Co-authored-by: 김민준 Co-authored-by: bryn --- .../coupon/adaptor/IssuedCouponAdaptor.java | 4 ++-- .../coupon/service/RecoveryCouponService.java | 6 +++--- .../coupon/service/UseCouponService.java | 6 +++--- .../service/IssuedTicketDomainService.java | 15 +++++++++++++++ .../service/handlers/OrderEventHandler.java | 7 ++----- .../domain/domains/order/domain/Order.java | 6 +++--- .../order/domain/validator/OrderValidator.java | 7 ++++++- .../handler/ConfirmOrderFailHandler.java | 17 ++++++++++++++++- 8 files changed, 50 insertions(+), 18 deletions(-) diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/adaptor/IssuedCouponAdaptor.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/adaptor/IssuedCouponAdaptor.java index 96e9e388..3ef5eab2 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/adaptor/IssuedCouponAdaptor.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/adaptor/IssuedCouponAdaptor.java @@ -31,9 +31,9 @@ public void exist(Long couponCampaignId, Long userId) { }); } - public IssuedCoupon query(Long couponCampaignId) { + public IssuedCoupon query(Long issuedCouponId) { return issuedCouponRepository - .findById(couponCampaignId) + .findById(issuedCouponId) .orElseThrow(() -> CouponNotFoundException.EXCEPTION); } } diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/service/RecoveryCouponService.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/service/RecoveryCouponService.java index 5db3fdff..1e7b1534 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/service/RecoveryCouponService.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/service/RecoveryCouponService.java @@ -13,10 +13,10 @@ public class RecoveryCouponService { private final IssuedCouponAdaptor issuedCouponAdaptor; @RedissonLock(LockName = "쿠폰", identifier = "couponId") - public Long execute(Long userId, Long couponId) { - IssuedCoupon coupon = issuedCouponAdaptor.query(couponId); + public Long execute(Long userId, Long issuedCouponId) { + IssuedCoupon coupon = issuedCouponAdaptor.query(issuedCouponId); coupon.validMine(userId); coupon.recovery(); - return couponId; + return issuedCouponId; } } diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/service/UseCouponService.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/service/UseCouponService.java index ddf89de9..61375359 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/service/UseCouponService.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/service/UseCouponService.java @@ -14,10 +14,10 @@ public class UseCouponService { private final IssuedCouponAdaptor issuedCouponAdaptor; @RedissonLock(LockName = "쿠폰", identifier = "couponId") - public Long execute(Long userId, Long couponId) { - IssuedCoupon coupon = issuedCouponAdaptor.query(couponId); + public Long execute(Long userId, Long issuedCouponId) { + IssuedCoupon coupon = issuedCouponAdaptor.query(issuedCouponId); coupon.validMine(userId); coupon.use(); - return couponId; + return issuedCouponId; } } diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/issuedTicket/service/IssuedTicketDomainService.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/issuedTicket/service/IssuedTicketDomainService.java index 0a555f0b..cb802018 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/issuedTicket/service/IssuedTicketDomainService.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/issuedTicket/service/IssuedTicketDomainService.java @@ -39,6 +39,21 @@ public void withdrawIssuedTicket(Long itemId, List issuedTickets) }); } + /* + 주문 승인 과정 중 티켓 아이템의 상태가 변해서 주문이 취소되는 경우 + 이미 발급된 티켓 취소 로직 + */ + @RedissonLock(LockName = "티켓관리", identifier = "itemId") + public void doneOrderEventAfterRollBackWithdrawIssuedTickets(Long itemId, String orderUuid) { + List failIssuedTickets = issuedTicketAdaptor.findAllByOrderUuid(orderUuid); + TicketItem ticketItem = ticketItemAdaptor.queryTicketItem(itemId); + failIssuedTickets.forEach( + issuedTicket -> { + ticketItem.increaseQuantity(1L); + issuedTicket.cancel(); + }); + } + @Transactional public IssuedTicketInfoVo processingEntranceIssuedTicket(Long eventId, Long issuedTicketId) { IssuedTicket issuedTicket = issuedTicketAdaptor.queryIssuedTicket(issuedTicketId); diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/issuedTicket/service/handlers/OrderEventHandler.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/issuedTicket/service/handlers/OrderEventHandler.java index 3ab7328c..c3a00174 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/issuedTicket/service/handlers/OrderEventHandler.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/issuedTicket/service/handlers/OrderEventHandler.java @@ -5,9 +5,8 @@ import band.gosrock.domain.domains.issuedTicket.service.IssuedTicketDomainService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; -import org.springframework.transaction.event.TransactionPhase; -import org.springframework.transaction.event.TransactionalEventListener; @Component @RequiredArgsConstructor @@ -16,9 +15,7 @@ public class OrderEventHandler { private final IssuedTicketDomainService issuedTicketDomainService; - @TransactionalEventListener( - classes = DoneOrderEvent.class, - phase = TransactionPhase.BEFORE_COMMIT) + @EventListener(classes = DoneOrderEvent.class) public void handleDoneOrderEvent(DoneOrderEvent doneOrderEvent) { log.info(doneOrderEvent.getOrderUuid() + "주문 상태 완료, 티켓 생성작업 진행"); issuedTicketDomainService.createIssuedTicket( diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/domain/Order.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/domain/Order.java index 67d9d180..7b31f2d8 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/domain/Order.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/domain/Order.java @@ -199,28 +199,28 @@ public void calculatePaymentInfo() { /** 결제 방식의 주문을 승인 합니다. */ public void confirmPayment( LocalDateTime approvedAt, PgPaymentInfo pgPaymentInfo, OrderValidator orderValidator) { + Events.raise(DoneOrderEvent.from(this)); orderValidator.validCanConfirmPayment(this); orderStatus = OrderStatus.CONFIRM; this.approvedAt = approvedAt; this.pgPaymentInfo = pgPaymentInfo; - Events.raise(DoneOrderEvent.from(this)); } /** 승인 방식의 주문을 승인합니다. */ public void approve(OrderValidator orderValidator) { + Events.raise(DoneOrderEvent.from(this)); orderValidator.validCanApproveOrder(this); this.approvedAt = LocalDateTime.now(); this.orderStatus = OrderStatus.APPROVED; - Events.raise(DoneOrderEvent.from(this)); } /** 선착순 방식의 0원 결제입니다. */ public void freeConfirm(Long currentUserId, OrderValidator orderValidator) { orderValidator.validOwner(this, currentUserId); + Events.raise(DoneOrderEvent.from(this)); orderValidator.validCanFreeConfirm(this); this.approvedAt = LocalDateTime.now(); this.orderStatus = OrderStatus.APPROVED; - Events.raise(DoneOrderEvent.from(this)); } /** 관리자가 주문을 취소 시킵니다 */ diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/domain/validator/OrderValidator.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/domain/validator/OrderValidator.java index eafd8179..65e8dd7b 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/domain/validator/OrderValidator.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/domain/validator/OrderValidator.java @@ -63,6 +63,7 @@ public void validCanCreate(Order order) { /** 모든 질문지 ( 옵션그룹 )에 응답했는지 검증합니다. ( 변화 했는지 검증 ) */ public void validOptionNotChange(Order order, TicketItem item) { List orderLineItems = order.getOrderLineItems(); + List itemsOptionGroupIds = item.getOptionGroupIds(); orderLineItems.forEach( orderLineItem -> { @@ -73,6 +74,11 @@ public void validOptionNotChange(Order order, TicketItem item) { }); } + public void validOptionNotChangeAfterDoneOrderEvent(Order order) { + TicketItem item = getItem(order); + validOptionNotChange(order, item); + } + /** 승인 가능한 주문인지 검증합니다. */ public void validCanApproveOrder(Order order) { validMethodIsCanApprove(order); @@ -107,7 +113,6 @@ public void validCanRefund(Order order) { validStatusCanRefund(getOrderStatus(order)); validCanWithDraw(order); } - /** ----------------------재료가 될 검증 메서드 ---------------------------- */ /** 주문을 완료할 수 있는지에 대한 공통검증 */ diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/service/handler/ConfirmOrderFailHandler.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/service/handler/ConfirmOrderFailHandler.java index a1974fd7..49cec4fb 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/service/handler/ConfirmOrderFailHandler.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/service/handler/ConfirmOrderFailHandler.java @@ -2,6 +2,9 @@ import band.gosrock.domain.common.events.order.DoneOrderEvent; +import band.gosrock.domain.domains.coupon.service.RecoveryCouponService; +import band.gosrock.domain.domains.issuedTicket.adaptor.IssuedTicketAdaptor; +import band.gosrock.domain.domains.issuedTicket.service.IssuedTicketDomainService; import band.gosrock.domain.domains.order.adaptor.OrderAdaptor; import band.gosrock.domain.domains.order.domain.Order; import band.gosrock.domain.domains.order.service.WithdrawPaymentService; @@ -19,8 +22,11 @@ public class ConfirmOrderFailHandler { private final WithdrawPaymentService cancelPaymentService; + private final IssuedTicketDomainService issuedTicketDomainService; + private final RecoveryCouponService recoveryCouponService; private final OrderAdaptor orderAdaptor; + private final IssuedTicketAdaptor issuedTicketAdaptor; @Async @TransactionalEventListener( @@ -32,7 +38,16 @@ public void handleDoneOrderFailEvent(DoneOrderEvent doneOrderEvent) { Order order = orderAdaptor.findByOrderUuid(doneOrderEvent.getOrderUuid()); order.fail(); - if (doneOrderEvent.getOrderMethod().isPayment()) { + + if (order.hasCoupon()) { // 쿠폰 사용했을 시 쿠폰 복구 + recoveryCouponService.execute( + order.getUserId(), order.getOrderCouponVo().getCouponId()); + } + + issuedTicketDomainService.doneOrderEventAfterRollBackWithdrawIssuedTickets( + doneOrderEvent.getItemId(), doneOrderEvent.getOrderUuid()); + + if (order.isPaid()) { log.info( doneOrderEvent.getOrderUuid() + ":" From 12bd4aa238606559060fee8555176ab014d10467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=B1=84=EB=A6=B0=20=28Bryn=29?= <67696767+cofls6581@users.noreply.github.com> Date: Mon, 6 Feb 2023 00:05:19 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat=20:=20=EC=BF=A0=ED=8F=B0=20=EC=B5=9C?= =?UTF-8?q?=EC=86=8C=20=EC=82=AC=EC=9A=A9=20=EA=B8=88=EC=95=A1=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=8A=88=ED=8D=BC?= =?UTF-8?q?=20=EC=96=B4=EB=93=9C=EB=AF=BC=20=EA=B2=80=EC=A6=9D=20(#295)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor : 안쓰는 파일 제거 * feat : 슈퍼 어드민만 쿠폰 캠페인 생성 가능하도록 로직 변경 * refactor : SecurityConfig role 검증에 맞춘 에러 메시지 문구 확장 * style : spotless 적용 * feat : CouponCampaign 테이블 minimumCost(최소결제금액) 칼럼 추가 * feat : 쿠폰 캠페인 생성 API minimumCost(최소결제금액) 값 추가 * feat : 내 쿠폰 조회 API minimumCost(최소결제금액) 응답값 추가 * feat : 쿠폰 사용 시 최소 결제 금액 검증 추가 --- .../api/config/security/SecurityConfig.java | 2 ++ .../reqeust/CreateCouponCampaignRequest.java | 13 ++++++------ .../CreateCouponCampaignResponse.java | 2 +- .../coupon/mapper/CouponCampaignMapper.java | 10 ++++++---- .../coupon/service/CreateCouponUseCase.java | 7 ++----- .../ReadMyPageIssuedCouponUseCase.java | 1 - .../common/exception/GlobalErrorCode.java | 4 ++-- .../domain/common/vo/IssuedCouponInfoVo.java | 3 +++ .../domains/coupon/domain/CouponCampaign.java | 12 +++++++---- .../domains/coupon/domain/IssuedCoupon.java | 20 ++++++++++--------- .../coupon/exception/CouponErrorCode.java | 5 +++-- .../NotApplicableCouponException.java | 12 ----------- .../SupplyLessThenDiscountException.java | 12 +++++++++++ .../SupplyLessThenMinimumException.java | 12 +++++++++++ 14 files changed, 68 insertions(+), 47 deletions(-) delete mode 100644 DuDoong-Api/src/main/java/band/gosrock/api/coupon/service/ReadMyPageIssuedCouponUseCase.java delete mode 100644 DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/NotApplicableCouponException.java create mode 100644 DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/SupplyLessThenDiscountException.java create mode 100644 DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/SupplyLessThenMinimumException.java diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/config/security/SecurityConfig.java b/DuDoong-Api/src/main/java/band/gosrock/api/config/security/SecurityConfig.java index 0b7a2d95..7e8d6082 100644 --- a/DuDoong-Api/src/main/java/band/gosrock/api/config/security/SecurityConfig.java +++ b/DuDoong-Api/src/main/java/band/gosrock/api/config/security/SecurityConfig.java @@ -37,6 +37,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .permitAll() .mvcMatchers(HttpMethod.GET, "/v1/events/{eventId:[\\d+]}/ticketItems") .permitAll() + .mvcMatchers(HttpMethod.POST, "/v1/coupons/campaigns") + .hasRole("SUPER_ADMIN") .anyRequest() .authenticated(); http.apply(filterConfig); diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/coupon/dto/reqeust/CreateCouponCampaignRequest.java b/DuDoong-Api/src/main/java/band/gosrock/api/coupon/dto/reqeust/CreateCouponCampaignRequest.java index cfcc9066..e6c94adf 100644 --- a/DuDoong-Api/src/main/java/band/gosrock/api/coupon/dto/reqeust/CreateCouponCampaignRequest.java +++ b/DuDoong-Api/src/main/java/band/gosrock/api/coupon/dto/reqeust/CreateCouponCampaignRequest.java @@ -5,10 +5,7 @@ import band.gosrock.domain.domains.coupon.domain.*; import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; -import javax.validation.constraints.Future; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Positive; +import javax.validation.constraints.*; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.lang.Nullable; @@ -17,9 +14,6 @@ @RequiredArgsConstructor public class CreateCouponCampaignRequest { - @NotNull(message = "host Id를 입력해주세요.") - private Long hostId; - @NotNull(message = "discountType을 입력해주세요.") private DiscountType discountType; @@ -54,4 +48,9 @@ public class CreateCouponCampaignRequest { @NotBlank(message = "couponCode를 입력해주세요.") private String couponCode; + + @Schema(description = "쿠폰 사용 가능한 최소 결제 금액(원단위, 10000원 이상부터 입력 가능)") + @NotNull(message = "minimumCost(원 단위)를 입력해주세요.") + @Min(value = 10000, message = "10000원 이상부터 입력 가능합니다.") + private Long minimumCost; } diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/coupon/dto/response/CreateCouponCampaignResponse.java b/DuDoong-Api/src/main/java/band/gosrock/api/coupon/dto/response/CreateCouponCampaignResponse.java index d67c8a02..faccaeb3 100644 --- a/DuDoong-Api/src/main/java/band/gosrock/api/coupon/dto/response/CreateCouponCampaignResponse.java +++ b/DuDoong-Api/src/main/java/band/gosrock/api/coupon/dto/response/CreateCouponCampaignResponse.java @@ -9,4 +9,4 @@ public record CreateCouponCampaignResponse( @Schema(description = "쿠폰 캠페인 ID") Long couponCampaignId, @Schema(description = "쿠폰 코드") String couponCode, @Schema(description = "생성한 쿠폰 총 매수") Long issuedAmount, - @Schema(description = "쿠폰 생성한 호스트 ID") Long hostId) {} + @Schema(description = "쿠폰 생성한 슈퍼 어드민 user ID") Long userId) {} diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/coupon/mapper/CouponCampaignMapper.java b/DuDoong-Api/src/main/java/band/gosrock/api/coupon/mapper/CouponCampaignMapper.java index 37c99cd4..8e50f807 100644 --- a/DuDoong-Api/src/main/java/band/gosrock/api/coupon/mapper/CouponCampaignMapper.java +++ b/DuDoong-Api/src/main/java/band/gosrock/api/coupon/mapper/CouponCampaignMapper.java @@ -15,12 +15,12 @@ public class CouponCampaignMapper { public static CreateCouponCampaignResponse toCreateCouponCampaignResponse( - CouponCampaign couponCampaign, Long hostId) { + CouponCampaign couponCampaign, Long userId) { return CreateCouponCampaignResponse.builder() .couponCampaignId(couponCampaign.getId()) .couponCode(couponCampaign.getCouponCode()) .issuedAmount(couponCampaign.getCouponStockInfo().getIssuedAmount()) - .hostId(hostId) + .userId(userId) .build(); } @@ -35,7 +35,8 @@ public static DateTimePeriod toDateTimePeriod(LocalDateTime startAt, LocalDateTi return DateTimePeriod.builder().startAt(startAt).endAt(endAt).build(); } - public CouponCampaign toEntity(CreateCouponCampaignRequest createCouponCampaignRequest) { + public CouponCampaign toEntity( + CreateCouponCampaignRequest createCouponCampaignRequest, Long userId) { CouponStockInfo couponStockInfo = toCouponStockInfo(createCouponCampaignRequest.getIssuedAmount()); @@ -45,7 +46,7 @@ public CouponCampaign toEntity(CreateCouponCampaignRequest createCouponCampaignR createCouponCampaignRequest.getEndAt()); return CouponCampaign.builder() - .hostId(createCouponCampaignRequest.getHostId()) + .userId(userId) .discountType(createCouponCampaignRequest.getDiscountType()) .applyTarget(createCouponCampaignRequest.getApplyTarget()) .validTerm(createCouponCampaignRequest.getValidTerm()) @@ -53,6 +54,7 @@ public CouponCampaign toEntity(CreateCouponCampaignRequest createCouponCampaignR .couponStockInfo(couponStockInfo) .discountAmount(createCouponCampaignRequest.getDiscountAmount()) .couponCode(createCouponCampaignRequest.getCouponCode()) + .minimumCost(createCouponCampaignRequest.getMinimumCost()) .build(); } } diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/coupon/service/CreateCouponUseCase.java b/DuDoong-Api/src/main/java/band/gosrock/api/coupon/service/CreateCouponUseCase.java index 7fd61c17..bc2e2c18 100644 --- a/DuDoong-Api/src/main/java/band/gosrock/api/coupon/service/CreateCouponUseCase.java +++ b/DuDoong-Api/src/main/java/band/gosrock/api/coupon/service/CreateCouponUseCase.java @@ -27,16 +27,13 @@ public CreateCouponCampaignResponse execute( CreateCouponCampaignRequest createCouponCampaignRequest) { // 존재하는 유저인지 검증 User user = userUtils.getCurrentUser(); - // 슈퍼 호스트인지 검증 - hostService.validateManagerHostUser(createCouponCampaignRequest.getHostId(), user.getId()); // 이미 생성된 쿠폰 코드인지 검증 createCouponCampaignDomainService.checkCouponCodeExists( createCouponCampaignRequest.getCouponCode()); // 쿠폰 생성 CouponCampaign couponCampaign = createCouponCampaignDomainService.createCouponCampaign( - couponCampaignMapper.toEntity(createCouponCampaignRequest)); - return CouponCampaignMapper.toCreateCouponCampaignResponse( - couponCampaign, couponCampaign.getHostId()); + couponCampaignMapper.toEntity(createCouponCampaignRequest, user.getId())); + return CouponCampaignMapper.toCreateCouponCampaignResponse(couponCampaign, user.getId()); } } diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/coupon/service/ReadMyPageIssuedCouponUseCase.java b/DuDoong-Api/src/main/java/band/gosrock/api/coupon/service/ReadMyPageIssuedCouponUseCase.java deleted file mode 100644 index 8b137891..00000000 --- a/DuDoong-Api/src/main/java/band/gosrock/api/coupon/service/ReadMyPageIssuedCouponUseCase.java +++ /dev/null @@ -1 +0,0 @@ - diff --git a/DuDoong-Common/src/main/java/band/gosrock/common/exception/GlobalErrorCode.java b/DuDoong-Common/src/main/java/band/gosrock/common/exception/GlobalErrorCode.java index 6b52f951..d71f7535 100644 --- a/DuDoong-Common/src/main/java/band/gosrock/common/exception/GlobalErrorCode.java +++ b/DuDoong-Common/src/main/java/band/gosrock/common/exception/GlobalErrorCode.java @@ -31,8 +31,8 @@ public enum GlobalErrorCode implements BaseErrorCode { @ExplainError("refreshToken 만료시 발생하는 오류입니다.") REFRESH_TOKEN_EXPIRED(FORBIDDEN, "AUTH_403_1", "인증 시간이 만료되었습니다. 재 로그인 해주세요."), - @ExplainError("헤더에 알맞은 형식으로 accessToken을 담지않았을 때 발생하는 오류") - ACCESS_TOKEN_NOT_EXIST(FORBIDDEN, "AUTH_403_2", "어세스토큰이 있는지 확인해 주세요."), + @ExplainError("헤더에 올바른 accessToken을 담지않았을 때 발생하는 오류(형식 불일치 등)") + ACCESS_TOKEN_NOT_EXIST(FORBIDDEN, "AUTH_403_2", "알맞은 accessToken을 넣어주세요."), @ExplainError("인증 토큰이 잘못됐을 때 발생하는 오류입니다.") INVALID_TOKEN(UNAUTHORIZED, "GLOBAL_401_1", "잘못된 토큰입니다. 재 로그인 해주세요"), diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/common/vo/IssuedCouponInfoVo.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/common/vo/IssuedCouponInfoVo.java index 4c0a7df0..ec65ea7e 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/common/vo/IssuedCouponInfoVo.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/common/vo/IssuedCouponInfoVo.java @@ -30,6 +30,8 @@ public class IssuedCouponInfoVo { // 쿠폰 사용 가능 마감 시각 @DateFormat private final LocalDateTime validDateTime; + private final Long minimumCost; + public static IssuedCouponInfoVo of(IssuedCoupon issuedCoupon) { return IssuedCouponInfoVo.builder() .issuedCouponId(issuedCoupon.getId()) @@ -39,6 +41,7 @@ public static IssuedCouponInfoVo of(IssuedCoupon issuedCoupon) { .discountType(issuedCoupon.getCouponCampaign().getDiscountType()) .discountAmount(issuedCoupon.getCouponCampaign().getDiscountAmount()) .validDateTime(issuedCoupon.calculateValidTerm()) + .minimumCost(issuedCoupon.getCouponCampaign().getMinimumCost()) .build(); } } diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/domain/CouponCampaign.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/domain/CouponCampaign.java index 7c23f570..b523eba6 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/domain/CouponCampaign.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/domain/CouponCampaign.java @@ -27,7 +27,7 @@ public class CouponCampaign extends BaseTimeEntity { @Column(name = "coupon_campaign_id") private Long id; - private Long hostId; + private Long userId; @Enumerated(EnumType.STRING) private DiscountType discountType; @@ -49,20 +49,23 @@ public class CouponCampaign extends BaseTimeEntity { private String couponCode; + private Long minimumCost = 10000L; + @OneToMany(mappedBy = "couponCampaign", cascade = CascadeType.ALL, fetch = FetchType.LAZY) private List issuedCoupons = new ArrayList<>(); @Builder public CouponCampaign( - Long hostId, + Long userId, DiscountType discountType, ApplyTarget applyTarget, Long validTerm, DateTimePeriod dateTimePeriod, CouponStockInfo couponStockInfo, Long discountAmount, - String couponCode) { - this.hostId = hostId; + String couponCode, + Long minimumCost) { + this.userId = userId; this.discountType = discountType; this.applyTarget = applyTarget; this.validTerm = validTerm; @@ -70,6 +73,7 @@ public CouponCampaign( this.couponStockInfo = couponStockInfo; this.discountAmount = discountAmount; this.couponCode = couponCode; + this.minimumCost = minimumCost; } // 정률 할인시 discountAmount 값이 100 이하인지 검증 diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/domain/IssuedCoupon.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/domain/IssuedCoupon.java index 757d429b..51a2d417 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/domain/IssuedCoupon.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/domain/IssuedCoupon.java @@ -3,10 +3,7 @@ import band.gosrock.domain.common.model.BaseTimeEntity; import band.gosrock.domain.common.vo.Money; -import band.gosrock.domain.domains.coupon.exception.AlreadyRecoveredCouponException; -import band.gosrock.domain.domains.coupon.exception.AlreadyUsedCouponException; -import band.gosrock.domain.domains.coupon.exception.NotApplicableCouponException; -import band.gosrock.domain.domains.coupon.exception.NotMyCouponException; +import band.gosrock.domain.domains.coupon.exception.*; import java.time.LocalDateTime; import java.util.Objects; import javax.persistence.*; @@ -36,19 +33,24 @@ public class IssuedCoupon extends BaseTimeEntity { /** 주문에서 사용하는 할인 금액 계산 함수, 할인 금액보다 결제 금액이 작을 경우 할인 불가로 에러 발생 */ public Money getDiscountAmount(Money supplyAmount) { if (couponCampaign.getDiscountType().equals(DiscountType.AMOUNT)) { // 정액 할인 - return checkSupplyIsGreaterThenDiscount( - supplyAmount, couponCampaign.getDiscountAmount()); + return checkSupplyAmount( + supplyAmount, + couponCampaign.getDiscountAmount(), + couponCampaign.getMinimumCost()); } // 정률 할인 Long discountAmount = supplyAmount.getDiscountAmountByPercentage( supplyAmount, couponCampaign.getDiscountAmount()); - return checkSupplyIsGreaterThenDiscount(supplyAmount, discountAmount); + return checkSupplyAmount(supplyAmount, discountAmount, couponCampaign.getMinimumCost()); } - public Money checkSupplyIsGreaterThenDiscount(Money supply, Long discount) { + public Money checkSupplyAmount(Money supply, Long discount, Long minimum) { if (supply.isLessThan(Money.wons(discount))) { - throw NotApplicableCouponException.EXCEPTION; + throw SupplyLessThenDiscountException.EXCEPTION; + } + if (supply.isLessThan(Money.wons(minimum))) { + throw SupplyLessThenMinimumException.EXCEPTION; } return Money.wons(discount); } diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/CouponErrorCode.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/CouponErrorCode.java index 75f1b434..e420ffac 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/CouponErrorCode.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/CouponErrorCode.java @@ -23,8 +23,9 @@ public enum CouponErrorCode implements BaseErrorCode { NOT_FOUND_COUPON(NOT_FOUND, "Coupon_404_2", "존재하지 않는 쿠폰 입니다."), NOT_MY_COUPON(BAD_REQUEST, "Coupon_400_7", "내 쿠폰이 아닙니다."), ALREADY_USED_COUPON(BAD_REQUEST, "Coupon_400_8", "이미 사용한 쿠폰입니다."), - NOT_APPLICABLE_COUPON(BAD_REQUEST, "Coupon_400_9", "적용 불가 쿠폰입니다. 할인 금액이 결제 금액보다 큽니다."), - ALREADY_RECOVERED_COUPON(BAD_REQUEST, "Coupon_400_10", "이미 복구한 쿠폰입니다."); + SUPPLY_LESS_THEN_DISCOUNT(BAD_REQUEST, "Coupon_400_9", "적용 불가 쿠폰입니다. 결제 금액이 할인 금액보다 작습니다."), + SUPPLY_LESS_THEN_MINIMUM(BAD_REQUEST, "Coupon_400_10", "적용 불가 쿠폰입니다. 결제 금액이 최소 결제 금액보다 작습니다."), + ALREADY_RECOVERED_COUPON(BAD_REQUEST, "Coupon_400_11", "이미 복구한 쿠폰입니다."); private final Integer status; private final String code; private final String reason; diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/NotApplicableCouponException.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/NotApplicableCouponException.java deleted file mode 100644 index c164c4d7..00000000 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/NotApplicableCouponException.java +++ /dev/null @@ -1,12 +0,0 @@ -package band.gosrock.domain.domains.coupon.exception; - - -import band.gosrock.common.exception.DuDoongCodeException; - -public class NotApplicableCouponException extends DuDoongCodeException { - public static final DuDoongCodeException EXCEPTION = new NotApplicableCouponException(); - - private NotApplicableCouponException() { - super(CouponErrorCode.NOT_APPLICABLE_COUPON); - } -} diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/SupplyLessThenDiscountException.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/SupplyLessThenDiscountException.java new file mode 100644 index 00000000..ea0f4c68 --- /dev/null +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/SupplyLessThenDiscountException.java @@ -0,0 +1,12 @@ +package band.gosrock.domain.domains.coupon.exception; + + +import band.gosrock.common.exception.DuDoongCodeException; + +public class SupplyLessThenDiscountException extends DuDoongCodeException { + public static final DuDoongCodeException EXCEPTION = new SupplyLessThenDiscountException(); + + private SupplyLessThenDiscountException() { + super(CouponErrorCode.SUPPLY_LESS_THEN_DISCOUNT); + } +} diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/SupplyLessThenMinimumException.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/SupplyLessThenMinimumException.java new file mode 100644 index 00000000..0f3b38ee --- /dev/null +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/coupon/exception/SupplyLessThenMinimumException.java @@ -0,0 +1,12 @@ +package band.gosrock.domain.domains.coupon.exception; + + +import band.gosrock.common.exception.DuDoongCodeException; + +public class SupplyLessThenMinimumException extends DuDoongCodeException { + public static final DuDoongCodeException EXCEPTION = new SupplyLessThenMinimumException(); + + private SupplyLessThenMinimumException() { + super(CouponErrorCode.SUPPLY_LESS_THEN_MINIMUM); + } +} From 4e7e56d5646a21b2f0fa60f493917f648f584374 Mon Sep 17 00:00:00 2001 From: Chan Jin Date: Mon, 6 Feb 2023 15:44:16 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feature=20:=20=EC=A3=BC=EB=AC=B8=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8,=20=ED=98=B8=EC=8A=A4=ED=8A=B8=20=EC=B4=88?= =?UTF-8?q?=EB=8C=80=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=20(#297)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat : footer 추가 * feat : 레이아웃 추가 * feat : 회원가입 포맷 만들기 * refactor : fragments 리팩터링 * refactor : mailFormat 리팩터링 * refactor : 마진값 조정 * feat : 타이틀 컴포넌트 생성 * refactor : 구조 잡기 * feat : 주문 승인 요청 메일 폼 * feat : 주문 승인 요청 알림 * feat : 승인 주문 생성시 이메일 알림 * style : spotless * feat : 주문관련, 호스트 초대이메일 알림 포맷 완료 * feat : 각 도메인 이벤트 핸들링 * feat : 호스트 초대 이메일 알림 * style : spotless * fix : 필터 순서 재조정 --- .../api/config/ServletFilterConfig.java | 11 +- .../gosrock/api/email/dto/OrderMailDto.java | 16 + .../handler/CreateOrderEventEmailHandler.java | 38 + .../handler/DoneOrderEventEmailHandler.java | 43 + ...ava => RegisterUserEventEmailHandler.java} | 2 +- .../WithDrawOrderEventEmailHandler.java | 42 + .../email/service/HostInviteEmailService.java | 24 + .../OrderApproveConfirmEmailService.java | 25 + .../OrderApproveRequestEmailService.java | 25 + .../email/service/OrderMailInfoHelper.java | 39 + .../service/OrderPaymentDoneEmailService.java | 25 + .../OrderWithDrawCancelEmailService.java | 25 + .../OrderWithDrawRefundEmailService.java | 25 + .../api/host/service/InviteHostUseCase.java | 18 +- .../api/order/controller/OrderController.java | 2 - .../email/RegisterUserEventHandlerTest.java | 4 +- .../common/events/order/CreateOrderEvent.java | 3 + .../domains/order/adaptor/OrderAdaptor.java | 4 + .../domain/domains/order/domain/Order.java | 6 + .../repository/OrderCustomRepository.java | 3 + .../repository/OrderCustomRepositoryImpl.java | 15 + .../domain/domains/user/domain/User.java | 5 + DuDoong-Infrastructure/build.gradle | 1 + .../config/mail/dto/EmailEventInfo.java | 12 + .../config/mail/dto/EmailOrderInfo.java | 15 + .../config/mail/dto/EmailUserInfo.java | 12 + .../resources/templates/fragments/button.html | 67 + .../templates/fragments/divider.html | 40 + .../resources/templates/fragments/footer.html | 114 + .../resources/templates/fragments/header.html | 21 + .../templates/fragments/orderInfo.html | 45 + .../templates/fragments/subTilte.html | 50 + .../resources/templates/fragments/title.html | 32 + .../main/resources/templates/hostInvite.html | 76 + .../templates/layouts/mailFormat.html | 60 + .../templates/orderApproveConfirm.html | 83 + .../templates/orderApproveRequest.html | 65 + .../resources/templates/orderPaymentDone.html | 83 + .../templates/orderWithdrawCancel.html | 68 + .../templates/orderWithdrawRefund.html | 63 + .../src/main/resources/templates/signUp.html | 2970 +++-------------- 41 files changed, 1821 insertions(+), 2456 deletions(-) create mode 100644 DuDoong-Api/src/main/java/band/gosrock/api/email/dto/OrderMailDto.java create mode 100644 DuDoong-Api/src/main/java/band/gosrock/api/email/handler/CreateOrderEventEmailHandler.java create mode 100644 DuDoong-Api/src/main/java/band/gosrock/api/email/handler/DoneOrderEventEmailHandler.java rename DuDoong-Api/src/main/java/band/gosrock/api/email/handler/{RegisterUserEventHandler.java => RegisterUserEventEmailHandler.java} (96%) create mode 100644 DuDoong-Api/src/main/java/band/gosrock/api/email/handler/WithDrawOrderEventEmailHandler.java create mode 100644 DuDoong-Api/src/main/java/band/gosrock/api/email/service/HostInviteEmailService.java create mode 100644 DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderApproveConfirmEmailService.java create mode 100644 DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderApproveRequestEmailService.java create mode 100644 DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderMailInfoHelper.java create mode 100644 DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderPaymentDoneEmailService.java create mode 100644 DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderWithDrawCancelEmailService.java create mode 100644 DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderWithDrawRefundEmailService.java create mode 100644 DuDoong-Infrastructure/src/main/java/band/gosrock/infrastructure/config/mail/dto/EmailEventInfo.java create mode 100644 DuDoong-Infrastructure/src/main/java/band/gosrock/infrastructure/config/mail/dto/EmailOrderInfo.java create mode 100644 DuDoong-Infrastructure/src/main/java/band/gosrock/infrastructure/config/mail/dto/EmailUserInfo.java create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/fragments/button.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/fragments/divider.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/fragments/footer.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/fragments/header.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/fragments/orderInfo.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/fragments/subTilte.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/fragments/title.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/hostInvite.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/layouts/mailFormat.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/orderApproveConfirm.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/orderApproveRequest.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/orderPaymentDone.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/orderWithdrawCancel.html create mode 100644 DuDoong-Infrastructure/src/main/resources/templates/orderWithdrawRefund.html diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/config/ServletFilterConfig.java b/DuDoong-Api/src/main/java/band/gosrock/api/config/ServletFilterConfig.java index caec73cd..d2bb6b64 100644 --- a/DuDoong-Api/src/main/java/band/gosrock/api/config/ServletFilterConfig.java +++ b/DuDoong-Api/src/main/java/band/gosrock/api/config/ServletFilterConfig.java @@ -11,6 +11,7 @@ import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; import org.springframework.web.filter.ForwardedHeaderFilter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter; @Configuration @RequiredArgsConstructor @@ -25,11 +26,19 @@ public FilterRegistrationBean securityFilterChain( @Qualifier(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME) Filter securityFilter) { FilterRegistrationBean registration = new FilterRegistrationBean(securityFilter); - registration.setOrder(Integer.MAX_VALUE - 2); + registration.setOrder(Integer.MAX_VALUE - 3); registration.setName(AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME); return registration; } + @Bean + public FilterRegistrationBean setResourceUrlEncodingFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean(); + registrationBean.setFilter(new ResourceUrlEncodingFilter()); + registrationBean.setOrder(Integer.MAX_VALUE - 2); + return registrationBean; + } + @Bean public FilterRegistrationBean setForwardedHeaderFilterOrder() { FilterRegistrationBean registrationBean = new FilterRegistrationBean(); diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/email/dto/OrderMailDto.java b/DuDoong-Api/src/main/java/band/gosrock/api/email/dto/OrderMailDto.java new file mode 100644 index 00000000..5fe97121 --- /dev/null +++ b/DuDoong-Api/src/main/java/band/gosrock/api/email/dto/OrderMailDto.java @@ -0,0 +1,16 @@ +package band.gosrock.api.email.dto; + + +import band.gosrock.infrastructure.config.mail.dto.EmailEventInfo; +import band.gosrock.infrastructure.config.mail.dto.EmailOrderInfo; +import band.gosrock.infrastructure.config.mail.dto.EmailUserInfo; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class OrderMailDto { + private final EmailUserInfo userInfo; + private final EmailOrderInfo orderInfo; + private final EmailEventInfo eventInfo; +} diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/CreateOrderEventEmailHandler.java b/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/CreateOrderEventEmailHandler.java new file mode 100644 index 00000000..db45d9f4 --- /dev/null +++ b/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/CreateOrderEventEmailHandler.java @@ -0,0 +1,38 @@ +package band.gosrock.api.email.handler; + + +import band.gosrock.api.email.service.OrderApproveRequestEmailService; +import band.gosrock.api.email.service.OrderMailInfoHelper; +import band.gosrock.domain.common.events.order.CreateOrderEvent; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +@Component +@RequiredArgsConstructor +@Slf4j +public class CreateOrderEventEmailHandler { + + private final OrderApproveRequestEmailService orderApproveRequestEmailService; + + private final OrderMailInfoHelper orderMailInfoHelper; + + @Async + @TransactionalEventListener( + classes = CreateOrderEvent.class, + phase = TransactionPhase.AFTER_COMMIT) + public void handleDoneOrderFailEvent(CreateOrderEvent createOrderEvent) { + log.info(createOrderEvent.getOrderUuid() + "주문 생성 이메일 요청"); + + // 승인 주문만 생성시에 이메일을 보낸다. + if (createOrderEvent.getOrderMethod().isPayment()) { + return; + } + + orderApproveRequestEmailService.execute( + orderMailInfoHelper.execute(createOrderEvent.getOrderUuid())); + } +} diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/DoneOrderEventEmailHandler.java b/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/DoneOrderEventEmailHandler.java new file mode 100644 index 00000000..7f24495c --- /dev/null +++ b/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/DoneOrderEventEmailHandler.java @@ -0,0 +1,43 @@ +package band.gosrock.api.email.handler; + + +import band.gosrock.api.email.dto.OrderMailDto; +import band.gosrock.api.email.service.OrderApproveConfirmEmailService; +import band.gosrock.api.email.service.OrderMailInfoHelper; +import band.gosrock.api.email.service.OrderPaymentDoneEmailService; +import band.gosrock.domain.common.events.order.DoneOrderEvent; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +@Component +@RequiredArgsConstructor +@Slf4j +public class DoneOrderEventEmailHandler { + + private final OrderMailInfoHelper orderMailInfoHelper; + + private final OrderApproveConfirmEmailService orderApproveConfirmEmailService; + private final OrderPaymentDoneEmailService orderPaymentDoneEmailService; + + @Async + @TransactionalEventListener( + classes = DoneOrderEvent.class, + phase = TransactionPhase.AFTER_COMMIT) + public void handleDoneOrderEvent(DoneOrderEvent doneOrderEvent) { + log.info(doneOrderEvent.getOrderUuid() + "주문 상태 완료, 이메일 보내기"); + OrderMailDto orderMailDto = orderMailInfoHelper.execute(doneOrderEvent.getOrderUuid()); + + // 결제용 + if (doneOrderEvent.getOrderMethod().isPayment()) { + orderPaymentDoneEmailService.execute(orderMailDto); + return; + } + // 승인용 + orderApproveConfirmEmailService.execute(orderMailDto); + log.info(doneOrderEvent.getOrderUuid() + "주문 상태 완료, 이메일 보내기 완료"); + } +} diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/RegisterUserEventHandler.java b/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/RegisterUserEventEmailHandler.java similarity index 96% rename from DuDoong-Api/src/main/java/band/gosrock/api/email/handler/RegisterUserEventHandler.java rename to DuDoong-Api/src/main/java/band/gosrock/api/email/handler/RegisterUserEventEmailHandler.java index c56737aa..efc78e84 100644 --- a/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/RegisterUserEventHandler.java +++ b/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/RegisterUserEventEmailHandler.java @@ -16,7 +16,7 @@ @Component @RequiredArgsConstructor @Slf4j -public class RegisterUserEventHandler { +public class RegisterUserEventEmailHandler { private final UserAdaptor userAdaptor; diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/WithDrawOrderEventEmailHandler.java b/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/WithDrawOrderEventEmailHandler.java new file mode 100644 index 00000000..dcefbdbe --- /dev/null +++ b/DuDoong-Api/src/main/java/band/gosrock/api/email/handler/WithDrawOrderEventEmailHandler.java @@ -0,0 +1,42 @@ +package band.gosrock.api.email.handler; + + +import band.gosrock.api.email.dto.OrderMailDto; +import band.gosrock.api.email.service.OrderMailInfoHelper; +import band.gosrock.api.email.service.OrderWithDrawCancelEmailService; +import band.gosrock.api.email.service.OrderWithDrawRefundEmailService; +import band.gosrock.domain.common.events.order.WithDrawOrderEvent; +import band.gosrock.domain.domains.order.domain.OrderStatus; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +@Component +@RequiredArgsConstructor +@Slf4j +public class WithDrawOrderEventEmailHandler { + + private final OrderWithDrawRefundEmailService orderWithDrawRefundEmailService; + private final OrderWithDrawCancelEmailService orderWithDrawCancelEmailService; + private final OrderMailInfoHelper orderMailInfoHelper; + + @Async + @TransactionalEventListener( + classes = WithDrawOrderEvent.class, + phase = TransactionPhase.AFTER_COMMIT) + public void handleWithDrawOrderEvent(WithDrawOrderEvent withDrawOrderEvent) { + OrderStatus orderStatus = withDrawOrderEvent.getOrderStatus(); + OrderMailDto orderMailDto = orderMailInfoHelper.execute(withDrawOrderEvent.getOrderUuid()); + + // 관리자에 의한 취소 + if (orderStatus == OrderStatus.CANCELED) { + orderWithDrawCancelEmailService.execute(orderMailDto); + return; + } + // 구매자에의한 환불 요청 + orderWithDrawRefundEmailService.execute(orderMailDto); + } +} diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/email/service/HostInviteEmailService.java b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/HostInviteEmailService.java new file mode 100644 index 00000000..ba2a6e1d --- /dev/null +++ b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/HostInviteEmailService.java @@ -0,0 +1,24 @@ +package band.gosrock.api.email.service; + + +import band.gosrock.domain.domains.host.domain.HostRole; +import band.gosrock.infrastructure.config.mail.dto.EmailUserInfo; +import band.gosrock.infrastructure.config.ses.AwsSesUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.thymeleaf.context.Context; + +@Service +@RequiredArgsConstructor +public class HostInviteEmailService { + private final AwsSesUtils awsSesUtils; + + public void execute(EmailUserInfo userInfo, String hostName, HostRole hostRole) { + Context context = new Context(); + context.setVariable("userInfo", userInfo); + context.setVariable("hostName", hostName); + context.setVariable("role", hostRole.getValue()); + awsSesUtils.singleEmailRequest( + userInfo.getEmail(), "두둥" + hostName + " 호스트 초대 알림 드립니다.", "hostInvite", context); + } +} diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderApproveConfirmEmailService.java b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderApproveConfirmEmailService.java new file mode 100644 index 00000000..9116ce33 --- /dev/null +++ b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderApproveConfirmEmailService.java @@ -0,0 +1,25 @@ +package band.gosrock.api.email.service; + + +import band.gosrock.api.email.dto.OrderMailDto; +import band.gosrock.infrastructure.config.mail.dto.EmailUserInfo; +import band.gosrock.infrastructure.config.ses.AwsSesUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.thymeleaf.context.Context; + +@Service +@RequiredArgsConstructor +public class OrderApproveConfirmEmailService { + private final AwsSesUtils awsSesUtils; + + public void execute(OrderMailDto orderMailDto) { + Context context = new Context(); + EmailUserInfo userInfo = orderMailDto.getUserInfo(); + context.setVariable("userInfo", userInfo); + context.setVariable("orderInfo", orderMailDto.getOrderInfo()); + context.setVariable("eventInfo", orderMailDto.getEventInfo()); + awsSesUtils.singleEmailRequest( + userInfo.getEmail(), "두둥 주문승인 완료 알림드립니다.", "orderApproveConfirm", context); + } +} diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderApproveRequestEmailService.java b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderApproveRequestEmailService.java new file mode 100644 index 00000000..d2ff9cce --- /dev/null +++ b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderApproveRequestEmailService.java @@ -0,0 +1,25 @@ +package band.gosrock.api.email.service; + + +import band.gosrock.api.email.dto.OrderMailDto; +import band.gosrock.infrastructure.config.mail.dto.EmailUserInfo; +import band.gosrock.infrastructure.config.ses.AwsSesUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.thymeleaf.context.Context; + +@Service +@RequiredArgsConstructor +public class OrderApproveRequestEmailService { + private final AwsSesUtils awsSesUtils; + + public void execute(OrderMailDto orderMailDto) { + Context context = new Context(); + EmailUserInfo userInfo = orderMailDto.getUserInfo(); + context.setVariable("userInfo", userInfo); + context.setVariable("orderInfo", orderMailDto.getOrderInfo()); + context.setVariable("eventInfo", orderMailDto.getEventInfo()); + awsSesUtils.singleEmailRequest( + userInfo.getEmail(), "두둥 주문승인 요청 알림드립니다.", "orderApproveRequest", context); + } +} diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderMailInfoHelper.java b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderMailInfoHelper.java new file mode 100644 index 00000000..c87d6421 --- /dev/null +++ b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderMailInfoHelper.java @@ -0,0 +1,39 @@ +package band.gosrock.api.email.service; + + +import band.gosrock.api.email.dto.OrderMailDto; +import band.gosrock.common.annotation.Helper; +import band.gosrock.domain.domains.event.adaptor.EventAdaptor; +import band.gosrock.domain.domains.event.domain.Event; +import band.gosrock.domain.domains.host.adaptor.HostAdaptor; +import band.gosrock.domain.domains.host.domain.Host; +import band.gosrock.domain.domains.order.adaptor.OrderAdaptor; +import band.gosrock.domain.domains.order.domain.Order; +import band.gosrock.domain.domains.user.adaptor.UserAdaptor; +import band.gosrock.domain.domains.user.domain.User; +import band.gosrock.infrastructure.config.mail.dto.EmailEventInfo; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@Helper +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class OrderMailInfoHelper { + private final OrderAdaptor orderAdaptor; + private final UserAdaptor userAdaptor; + private final EventAdaptor eventAdaptor; + private final HostAdaptor hostAdaptor; + + public OrderMailDto execute(String orderUuid) { + Order order = orderAdaptor.find(orderUuid); + User user = userAdaptor.queryUser(order.getUserId()); + Event event = eventAdaptor.findById(order.getEventId()); + Host host = hostAdaptor.findById(event.getHostId()); + return new OrderMailDto( + user.toEmailUserInfo(), order.toEmailOrderInfo(), getEventInfo(event, host)); + } + + private EmailEventInfo getEventInfo(Event event, Host host) { + return new EmailEventInfo(host.getProfile().getName(), event.getEventBasic().getName()); + } +} diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderPaymentDoneEmailService.java b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderPaymentDoneEmailService.java new file mode 100644 index 00000000..f3473d61 --- /dev/null +++ b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderPaymentDoneEmailService.java @@ -0,0 +1,25 @@ +package band.gosrock.api.email.service; + + +import band.gosrock.api.email.dto.OrderMailDto; +import band.gosrock.infrastructure.config.mail.dto.EmailUserInfo; +import band.gosrock.infrastructure.config.ses.AwsSesUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.thymeleaf.context.Context; + +@Service +@RequiredArgsConstructor +public class OrderPaymentDoneEmailService { + private final AwsSesUtils awsSesUtils; + + public void execute(OrderMailDto orderMailDto) { + Context context = new Context(); + EmailUserInfo userInfo = orderMailDto.getUserInfo(); + context.setVariable("userInfo", userInfo); + context.setVariable("orderInfo", orderMailDto.getOrderInfo()); + context.setVariable("eventInfo", orderMailDto.getEventInfo()); + awsSesUtils.singleEmailRequest( + userInfo.getEmail(), "두둥 주문 완료 알림드립니다.", "orderPaymentDone", context); + } +} diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderWithDrawCancelEmailService.java b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderWithDrawCancelEmailService.java new file mode 100644 index 00000000..91d42b8d --- /dev/null +++ b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderWithDrawCancelEmailService.java @@ -0,0 +1,25 @@ +package band.gosrock.api.email.service; + + +import band.gosrock.api.email.dto.OrderMailDto; +import band.gosrock.infrastructure.config.mail.dto.EmailUserInfo; +import band.gosrock.infrastructure.config.ses.AwsSesUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.thymeleaf.context.Context; + +@Service +@RequiredArgsConstructor +public class OrderWithDrawCancelEmailService { + private final AwsSesUtils awsSesUtils; + + public void execute(OrderMailDto orderMailDto) { + Context context = new Context(); + EmailUserInfo userInfo = orderMailDto.getUserInfo(); + context.setVariable("userInfo", userInfo); + context.setVariable("orderInfo", orderMailDto.getOrderInfo()); + context.setVariable("eventInfo", orderMailDto.getEventInfo()); + awsSesUtils.singleEmailRequest( + userInfo.getEmail(), "두둥 주문 철회 알림 드립니다.", "orderWithdrawCancel", context); + } +} diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderWithDrawRefundEmailService.java b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderWithDrawRefundEmailService.java new file mode 100644 index 00000000..528c392f --- /dev/null +++ b/DuDoong-Api/src/main/java/band/gosrock/api/email/service/OrderWithDrawRefundEmailService.java @@ -0,0 +1,25 @@ +package band.gosrock.api.email.service; + + +import band.gosrock.api.email.dto.OrderMailDto; +import band.gosrock.infrastructure.config.mail.dto.EmailUserInfo; +import band.gosrock.infrastructure.config.ses.AwsSesUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.thymeleaf.context.Context; + +@Service +@RequiredArgsConstructor +public class OrderWithDrawRefundEmailService { + private final AwsSesUtils awsSesUtils; + + public void execute(OrderMailDto orderMailDto) { + Context context = new Context(); + EmailUserInfo userInfo = orderMailDto.getUserInfo(); + context.setVariable("userInfo", userInfo); + context.setVariable("orderInfo", orderMailDto.getOrderInfo()); + context.setVariable("eventInfo", orderMailDto.getEventInfo()); + awsSesUtils.singleEmailRequest( + userInfo.getEmail(), "두둥 주문 철회 알림 드립니다.", "orderWithdrawRefund", context); + } +} diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/host/service/InviteHostUseCase.java b/DuDoong-Api/src/main/java/band/gosrock/api/host/service/InviteHostUseCase.java index ece8f67a..fc34087c 100644 --- a/DuDoong-Api/src/main/java/band/gosrock/api/host/service/InviteHostUseCase.java +++ b/DuDoong-Api/src/main/java/band/gosrock/api/host/service/InviteHostUseCase.java @@ -4,15 +4,18 @@ import static band.gosrock.api.common.aop.hostRole.HostQualification.MANAGER; import band.gosrock.api.common.aop.hostRole.HostRolesAllowed; +import band.gosrock.api.email.service.HostInviteEmailService; import band.gosrock.api.host.model.dto.request.InviteHostRequest; import band.gosrock.api.host.model.dto.response.HostDetailResponse; import band.gosrock.api.host.model.mapper.HostMapper; import band.gosrock.common.annotation.UseCase; import band.gosrock.domain.domains.host.adaptor.HostAdaptor; import band.gosrock.domain.domains.host.domain.Host; +import band.gosrock.domain.domains.host.domain.HostRole; import band.gosrock.domain.domains.host.domain.HostUser; import band.gosrock.domain.domains.host.service.HostService; import band.gosrock.domain.domains.user.adaptor.UserAdaptor; +import band.gosrock.domain.domains.user.domain.User; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @@ -25,17 +28,20 @@ public class InviteHostUseCase { private final HostAdaptor hostAdaptor; private final HostMapper hostMapper; + private final HostInviteEmailService inviteEmailService; + @Transactional @HostRolesAllowed(role = MANAGER, findHostFrom = HOST_ID) public HostDetailResponse execute(Long hostId, InviteHostRequest inviteHostRequest) { // 초대할 유저 - final Long inviteUserId = - userAdaptor.queryUserByEmail(inviteHostRequest.getEmail()).getId(); + User user = userAdaptor.queryUserByEmail(inviteHostRequest.getEmail()); + final Long inviteUserId = user.getId(); final Host host = hostAdaptor.findById(hostId); - final HostUser hostUser = - hostMapper.toHostUser(hostId, inviteUserId, inviteHostRequest.getRole()); - return hostMapper.toHostDetailResponse(hostService.addHostUser(host, hostUser)); + HostRole role = inviteHostRequest.getRole(); + final HostUser hostUser = hostMapper.toHostUser(hostId, inviteUserId, role); + // todo :: 도메인 이벤트로 빼야함..! , 비동기 처리도 + inviteEmailService.execute(user.toEmailUserInfo(), host.getProfile().getName(), role); - // todo :: 초대 성공 시 상대방에게 알림 이벤트 발송 + return hostMapper.toHostDetailResponse(hostService.addHostUser(host, hostUser)); } } diff --git a/DuDoong-Api/src/main/java/band/gosrock/api/order/controller/OrderController.java b/DuDoong-Api/src/main/java/band/gosrock/api/order/controller/OrderController.java index 1b9bd6d7..42066658 100644 --- a/DuDoong-Api/src/main/java/band/gosrock/api/order/controller/OrderController.java +++ b/DuDoong-Api/src/main/java/band/gosrock/api/order/controller/OrderController.java @@ -12,7 +12,6 @@ import band.gosrock.api.order.model.dto.response.CreateOrderResponse; import band.gosrock.api.order.model.dto.response.OrderBriefElement; import band.gosrock.api.order.model.dto.response.OrderResponse; -import band.gosrock.api.order.service.ApproveOrderUseCase; import band.gosrock.api.order.service.CancelOrderUseCase; import band.gosrock.api.order.service.ConfirmOrderUseCase; import band.gosrock.api.order.service.CreateOrderUseCase; @@ -48,7 +47,6 @@ public class OrderController { private final CreateOrderUseCase createOrderUseCase; private final ConfirmOrderUseCase confirmOrderUseCase; - private final ApproveOrderUseCase approveOrderUseCase; private final FreeOrderUseCase freeOrderUseCase; private final CancelOrderUseCase cancelOrderUseCase; diff --git a/DuDoong-Api/src/test/java/band/gosrock/api/email/RegisterUserEventHandlerTest.java b/DuDoong-Api/src/test/java/band/gosrock/api/email/RegisterUserEventHandlerTest.java index 159847bc..43cff085 100644 --- a/DuDoong-Api/src/test/java/band/gosrock/api/email/RegisterUserEventHandlerTest.java +++ b/DuDoong-Api/src/test/java/band/gosrock/api/email/RegisterUserEventHandlerTest.java @@ -3,7 +3,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.times; -import band.gosrock.api.email.handler.RegisterUserEventHandler; +import band.gosrock.api.email.handler.RegisterUserEventEmailHandler; import band.gosrock.api.supports.ApiIntegrateSpringBootTest; import band.gosrock.domain.domains.user.domain.OauthInfo; import band.gosrock.domain.domains.user.domain.Profile; @@ -17,7 +17,7 @@ class RegisterUserEventHandlerTest { @Autowired UserDomainService userDomainService; - @MockBean RegisterUserEventHandler registerUserEventHandler; + @MockBean RegisterUserEventEmailHandler registerUserEventHandler; @Test void 유저등록시도메인이벤트가발생해야한다() { diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/common/events/order/CreateOrderEvent.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/common/events/order/CreateOrderEvent.java index 8155e1d8..bb384316 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/common/events/order/CreateOrderEvent.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/common/events/order/CreateOrderEvent.java @@ -3,6 +3,7 @@ import band.gosrock.domain.common.aop.domainEvent.DomainEvent; import band.gosrock.domain.domains.order.domain.Order; +import band.gosrock.domain.domains.order.domain.OrderMethod; import lombok.Builder; import lombok.Getter; import org.springframework.lang.Nullable; @@ -16,6 +17,7 @@ public class CreateOrderEvent extends DomainEvent { private final Long userId; private final Boolean isUsingCoupon; + private final OrderMethod orderMethod; @Nullable private final Long issuedCouponId; @@ -26,6 +28,7 @@ public static CreateOrderEvent from(Order order) { .orderUuid(order.getUuid()) .isUsingCoupon(order.hasCoupon()) .issuedCouponId(order.getOrderCouponVo().getCouponId()) + .orderMethod(order.getOrderMethod()) .build(); } } diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/adaptor/OrderAdaptor.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/adaptor/OrderAdaptor.java index 900c0831..9720782e 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/adaptor/OrderAdaptor.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/adaptor/OrderAdaptor.java @@ -33,6 +33,10 @@ public Order findByOrderUuid(String uuid) { return orderRepository.findByUuid(uuid).orElseThrow(() -> OrderNotFoundException.EXCEPTION); } + public Order find(String uuid) { + return orderRepository.find(uuid).orElseThrow(() -> OrderNotFoundException.EXCEPTION); + } + public Optional findRecentOrderByUserId(Long userId) { return orderRepository.findFirstByUserIdOrderByIdDesc(userId); } diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/domain/Order.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/domain/Order.java index 7b31f2d8..199d0d68 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/domain/Order.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/domain/Order.java @@ -15,6 +15,7 @@ import band.gosrock.domain.domains.order.exception.NotPaymentOrderException; import band.gosrock.domain.domains.order.exception.OrderLineNotFountException; import band.gosrock.domain.domains.ticket_item.domain.TicketItem; +import band.gosrock.infrastructure.config.mail.dto.EmailOrderInfo; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -340,4 +341,9 @@ public List getDistinctItemIds() { public Long getTotalQuantity() { return orderLineItems.stream().map(OrderLineItem::getQuantity).reduce(0L, Long::sum); } + + public EmailOrderInfo toEmailOrderInfo() { + return new EmailOrderInfo( + orderName, getTotalQuantity(), getTotalPaymentPrice().toString(), getCreatedAt()); + } } diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/repository/OrderCustomRepository.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/repository/OrderCustomRepository.java index 8dd80412..33f2420e 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/repository/OrderCustomRepository.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/repository/OrderCustomRepository.java @@ -4,12 +4,15 @@ import band.gosrock.domain.domains.order.domain.Order; import band.gosrock.domain.domains.order.repository.condition.FindEventOrdersCondition; import band.gosrock.domain.domains.order.repository.condition.FindMyPageOrderCondition; +import java.util.Optional; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; public interface OrderCustomRepository { + Optional find(String orderUuid); + Slice findMyOrders(FindMyPageOrderCondition condition, Pageable pageable); Page findEventOrders(FindEventOrdersCondition condition, Pageable pageable); diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/repository/OrderCustomRepositoryImpl.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/repository/OrderCustomRepositoryImpl.java index 6c709df0..4b8386d2 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/repository/OrderCustomRepositoryImpl.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/order/repository/OrderCustomRepositoryImpl.java @@ -2,6 +2,7 @@ import static band.gosrock.domain.domains.event.domain.QEvent.event; import static band.gosrock.domain.domains.order.domain.QOrder.order; +import static band.gosrock.domain.domains.order.domain.QOrderLineItem.orderLineItem; import static band.gosrock.domain.domains.user.domain.QUser.user; import band.gosrock.domain.common.util.SliceUtil; @@ -15,6 +16,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import java.time.LocalDateTime; import java.util.List; +import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -26,6 +28,19 @@ public class OrderCustomRepositoryImpl implements OrderCustomRepository { private final JPAQueryFactory queryFactory; + @Override + public Optional find(String orderUuid) { + Order find = + queryFactory + .selectFrom(order) + .leftJoin(order.orderLineItems, orderLineItem) + .fetchJoin() + .where(order.uuid.eq(orderUuid)) + .fetchOne(); + + return Optional.ofNullable(find); + } + @Override public Slice findMyOrders(FindMyPageOrderCondition condition, Pageable pageable) { List orders = diff --git a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/user/domain/User.java b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/user/domain/User.java index 21fc225e..11b90742 100644 --- a/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/user/domain/User.java +++ b/DuDoong-Domain/src/main/java/band/gosrock/domain/domains/user/domain/User.java @@ -8,6 +8,7 @@ import band.gosrock.domain.common.vo.UserProfileVo; import band.gosrock.domain.domains.user.exception.AlreadyDeletedUserException; import band.gosrock.domain.domains.user.exception.ForbiddenUserException; +import band.gosrock.infrastructure.config.mail.dto.EmailUserInfo; import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; @@ -82,4 +83,8 @@ public UserInfoVo toUserInfoVo() { public UserProfileVo toUserProfileVo() { return UserProfileVo.from(this); } + + public EmailUserInfo toEmailUserInfo() { + return new EmailUserInfo(profile.getName(), profile.getEmail()); + } } diff --git a/DuDoong-Infrastructure/build.gradle b/DuDoong-Infrastructure/build.gradle index 2eb1514b..1a44bb6f 100644 --- a/DuDoong-Infrastructure/build.gradle +++ b/DuDoong-Infrastructure/build.gradle @@ -15,5 +15,6 @@ dependencies { //for email api 'org.springframework.boot:spring-boot-starter-thymeleaf' + api 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect' api group: 'software.amazon.awssdk', name: 'ses', version: "2.19.29" } \ No newline at end of file diff --git a/DuDoong-Infrastructure/src/main/java/band/gosrock/infrastructure/config/mail/dto/EmailEventInfo.java b/DuDoong-Infrastructure/src/main/java/band/gosrock/infrastructure/config/mail/dto/EmailEventInfo.java new file mode 100644 index 00000000..8d5d33b4 --- /dev/null +++ b/DuDoong-Infrastructure/src/main/java/band/gosrock/infrastructure/config/mail/dto/EmailEventInfo.java @@ -0,0 +1,12 @@ +package band.gosrock.infrastructure.config.mail.dto; + + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class EmailEventInfo { + private final String hostName; + private final String eventName; +} diff --git a/DuDoong-Infrastructure/src/main/java/band/gosrock/infrastructure/config/mail/dto/EmailOrderInfo.java b/DuDoong-Infrastructure/src/main/java/band/gosrock/infrastructure/config/mail/dto/EmailOrderInfo.java new file mode 100644 index 00000000..626559ca --- /dev/null +++ b/DuDoong-Infrastructure/src/main/java/band/gosrock/infrastructure/config/mail/dto/EmailOrderInfo.java @@ -0,0 +1,15 @@ +package band.gosrock.infrastructure.config.mail.dto; + + +import java.time.LocalDateTime; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class EmailOrderInfo { + private final String name; + private final Long quantity; + private final String money; + private final LocalDateTime createAt; +} diff --git a/DuDoong-Infrastructure/src/main/java/band/gosrock/infrastructure/config/mail/dto/EmailUserInfo.java b/DuDoong-Infrastructure/src/main/java/band/gosrock/infrastructure/config/mail/dto/EmailUserInfo.java new file mode 100644 index 00000000..3381f995 --- /dev/null +++ b/DuDoong-Infrastructure/src/main/java/band/gosrock/infrastructure/config/mail/dto/EmailUserInfo.java @@ -0,0 +1,12 @@ +package band.gosrock.infrastructure.config.mail.dto; + + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class EmailUserInfo { + private final String name; + private final String email; +} diff --git a/DuDoong-Infrastructure/src/main/resources/templates/fragments/button.html b/DuDoong-Infrastructure/src/main/resources/templates/fragments/button.html new file mode 100644 index 00000000..4cea2a21 --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/fragments/button.html @@ -0,0 +1,67 @@ + + + + + + + +
+
+ + + + + + +
+ 두둥 바로가기 +
+
+
+ diff --git a/DuDoong-Infrastructure/src/main/resources/templates/fragments/divider.html b/DuDoong-Infrastructure/src/main/resources/templates/fragments/divider.html new file mode 100644 index 00000000..156b6761 --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/fragments/divider.html @@ -0,0 +1,40 @@ + + + + + + + +
+ + + + + + +
+
+
+
+ diff --git a/DuDoong-Infrastructure/src/main/resources/templates/fragments/footer.html b/DuDoong-Infrastructure/src/main/resources/templates/fragments/footer.html new file mode 100644 index 00000000..c3146c55 --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/fragments/footer.html @@ -0,0 +1,114 @@ + + + + + + + +
+
+ +
+ + + +
+
두둥스튜디오 | 서울시 강서구 강서로 266 129동 503호
+
+ 대표 : 이찬진 | TEL : 0507-0177-0711 | Email : support@dudoong.com +
+
+ 사업자 번호 : 469-21-01595 | 통신판매업 신고번호 : 2022-서울강서-3669 +
+
+
© Dudoong. All rights reserved
+
+ + +
+
+ diff --git a/DuDoong-Infrastructure/src/main/resources/templates/fragments/header.html b/DuDoong-Infrastructure/src/main/resources/templates/fragments/header.html new file mode 100644 index 00000000..f0a5e09f --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/fragments/header.html @@ -0,0 +1,21 @@ + + + + + + + +
+
+ +
+
+
+ diff --git a/DuDoong-Infrastructure/src/main/resources/templates/fragments/orderInfo.html b/DuDoong-Infrastructure/src/main/resources/templates/fragments/orderInfo.html new file mode 100644 index 00000000..2a0d69ba --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/fragments/orderInfo.html @@ -0,0 +1,45 @@ + + + + + + + +
+
+
+ 주문 이름 : + 호스트이름 +
+
+ 수량 : + 수량 + +
+
+ 가격 : + 가격 +
+
+ 주문 일시 : + 주문일시 +
+
+
+ diff --git a/DuDoong-Infrastructure/src/main/resources/templates/fragments/subTilte.html b/DuDoong-Infrastructure/src/main/resources/templates/fragments/subTilte.html new file mode 100644 index 00000000..165a6161 --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/fragments/subTilte.html @@ -0,0 +1,50 @@ + + + + + + + +
+
+ 호스트이름 + + 이벤트 이름 + 텍스트 +
+
+
+ +
+
+ 호스트이름 + 호스트 + 텍스트 +
+
+
+ diff --git a/DuDoong-Infrastructure/src/main/resources/templates/fragments/title.html b/DuDoong-Infrastructure/src/main/resources/templates/fragments/title.html new file mode 100644 index 00000000..03c5de09 --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/fragments/title.html @@ -0,0 +1,32 @@ + + + + + + + +
+
+
두둥
+
타이틀
+
+
divider
+
+ diff --git a/DuDoong-Infrastructure/src/main/resources/templates/hostInvite.html b/DuDoong-Infrastructure/src/main/resources/templates/hostInvite.html new file mode 100644 index 00000000..fba0ce84 --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/hostInvite.html @@ -0,0 +1,76 @@ + + + + + + + + + +
+
divider
+ +
+ 안녕하세요 + 이름 + +
+
+
+ 이벤트 정보 +
+
+
+ 대상 계정 : + 대상계정 이메일 +
+
+ 권한 : + 권한 +
+
+ + +
+
+ 권한은 마스터, 매니저 , 게스트로 나누어집니다. +
+
+ 게스트는 관리자 공연에서 조회의 권한을 가집니다. +
+
+ 매니저는 게스트의 권한과 , 관리자 공연에서 수정과 생성 권한을 가집니다. +
+
+ 마스터는 매니저의 권한과 , 호스트의 멤버관리 권한을 가지고 있습니다. +
+
+ +
+ +
+ +
+ button +
+
+ + diff --git a/DuDoong-Infrastructure/src/main/resources/templates/layouts/mailFormat.html b/DuDoong-Infrastructure/src/main/resources/templates/layouts/mailFormat.html new file mode 100644 index 00000000..5d1c3526 --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/layouts/mailFormat.html @@ -0,0 +1,60 @@ + + + + + + + + + +
+
+
+
+ + + + + + +
+
+ header +
+
+ +
+ footer +
+
+
+
+
+
diff --git a/DuDoong-Infrastructure/src/main/resources/templates/orderApproveConfirm.html b/DuDoong-Infrastructure/src/main/resources/templates/orderApproveConfirm.html new file mode 100644 index 00000000..f457c48c --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/orderApproveConfirm.html @@ -0,0 +1,83 @@ + + + + + + + + + +
+
divider
+ +
+ 안녕하세요 + 이름 + +
+
+
+ 이벤트 정보 +
+
+ 주문 정보 +
+ +
+
+ 원할한 입장을 위해 QR코드를 미리 준비해 주세요 +
+
+ 마이페이지 -> 내 예매 내역 -> 예매확인 -> QR 코드 보기 +
+
+ 에서 각 티켓의 QR코드를 확인 할 수 있습니다. +
+
+ +
+
+ 철회기한 이전까지 수수료 없이 환불 가능합니다. +
+
+ 공연 입장확인이 된 티켓이 있을경우 환불이 불가합니다. +
+
+ 환불 방법 : 티켓 예매 상세내역 > 예매취소 +
+
+ 환불 금액 : 당사에서는 주문에 대해 즉시 취소를 하고, +
+
+ 취소 금액에 대한 입금은 카드사 영업일 기준 4~5일이 소요될 수 있습니다. +
+
+ +
+ +
+ +
+ button +
+
+ + diff --git a/DuDoong-Infrastructure/src/main/resources/templates/orderApproveRequest.html b/DuDoong-Infrastructure/src/main/resources/templates/orderApproveRequest.html new file mode 100644 index 00000000..ca9552c5 --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/orderApproveRequest.html @@ -0,0 +1,65 @@ + + + + + + + + + +
+
divider
+ +
+ 안녕하세요 + 이름 + +
+
+
+ 이벤트 정보 +
+
+ 주문 정보 +
+ +
+
+ 호스트 관리자가 주문을 승인 할 때 까지 기다려주세요! +
+
+ 승인이 완료되면 알림 메일을 보내 드립니다. +
+
+ 장기간 승인이 이루어지지 않는다면, 호스트 연락처를 통해 주문을 확인해 보세요! +
+
+ +
+ +
+ +
+ button +
+
+ + diff --git a/DuDoong-Infrastructure/src/main/resources/templates/orderPaymentDone.html b/DuDoong-Infrastructure/src/main/resources/templates/orderPaymentDone.html new file mode 100644 index 00000000..d42411d3 --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/orderPaymentDone.html @@ -0,0 +1,83 @@ + + + + + + + + + +
+
divider
+ +
+ 안녕하세요 + 이름 + +
+
+
+ 이벤트 정보 +
+
+ 주문 정보 +
+ +
+
+ 원할한 입장을 위해 QR코드를 미리 준비해 주세요 +
+
+ 마이페이지 -> 내 예매 내역 -> 예매확인 -> QR 코드 보기 +
+
+ 에서 각 티켓의 QR코드를 확인 할 수 있습니다. +
+
+ +
+
+ 철회기한 이전까지 수수료 없이 환불 가능합니다. +
+
+ 공연 입장확인이 된 티켓이 있을경우 환불이 불가합니다. +
+
+ 환불 방법 : 티켓 예매 상세내역 > 예매취소 +
+
+ 환불 금액 : 당사에서는 주문에 대해 즉시 취소를 하고, +
+
+ 취소 금액에 대한 입금은 카드사 영업일 기준 4~5일이 소요될 수 있습니다. +
+
+ +
+ +
+ +
+ button +
+
+ + diff --git a/DuDoong-Infrastructure/src/main/resources/templates/orderWithdrawCancel.html b/DuDoong-Infrastructure/src/main/resources/templates/orderWithdrawCancel.html new file mode 100644 index 00000000..571fc91a --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/orderWithdrawCancel.html @@ -0,0 +1,68 @@ + + + + + + + + + +
+
divider
+ +
+ 안녕하세요 + 이름 + +
+
+
+ 이벤트 정보 +
+
+ 주문 정보 +
+ +
+
+ 철회 사유에 대한 문의는 호스트 연락처를 통해 부탁드립니다. +
+
+ +
+
+ 당사에서는 주문에 대해 즉시 취소를 하고, +
+
+ 취소 금액에 대한 입금은 카드사 영업일 기준 4~5일이 소요될 수 있습니다. +
+
+ +
+ +
+ +
+ button +
+
+ + diff --git a/DuDoong-Infrastructure/src/main/resources/templates/orderWithdrawRefund.html b/DuDoong-Infrastructure/src/main/resources/templates/orderWithdrawRefund.html new file mode 100644 index 00000000..d7673d0c --- /dev/null +++ b/DuDoong-Infrastructure/src/main/resources/templates/orderWithdrawRefund.html @@ -0,0 +1,63 @@ + + + + + + + + + +
+
divider
+ +
+ 안녕하세요 + 이름 + +
+
+
+ 이벤트 정보 +
+
+ 주문 정보 +
+ + +
+
+ 당사에서는 주문에 대해 즉시 취소를 하고, +
+
+ 취소 금액에 대한 입금은 카드사 영업일 기준 4~5일이 소요될 수 있습니다. +
+
+ +
+ +
+ +
+ button +
+
+ + diff --git a/DuDoong-Infrastructure/src/main/resources/templates/signUp.html b/DuDoong-Infrastructure/src/main/resources/templates/signUp.html index f1a96e61..feda4e24 100644 --- a/DuDoong-Infrastructure/src/main/resources/templates/signUp.html +++ b/DuDoong-Infrastructure/src/main/resources/templates/signUp.html @@ -1,5 +1,10 @@ - + @@ -7,2474 +12,551 @@ -
-
-
- -
+ + + - - - - - - -
+ -
- - - - - - -
- - - - - - -
-
-

- - - -

-
-
-
- - - - - - -
- - - - - - -
-
- 이름 - 님, -   - - 두둥에 가입하신 것을 환영합니다! -
-
-
-
- - - - - - -
- - - - - - -
-
-
- 회원가입 기념으로 아래와 같이 구름EDU - 서비스를 이용하실 수 있는 쿠폰을 - 드립니다. -
-
-
- 구름을 통해 개발자 개인의 성장과 팀의 - 성장을 경험하세요. -
-
-
-
- - - - - - -
- - - - - - -
-
-
- 쿠폰코드 : -
-
-
-
- WELCOMEGOORMEDU -
-
-
-
-
- - - - - - -
-
- - - - - - -
- 프로모션 강좌 보기 -
-
-
- - - - - - -
- - - - - - -
-
- 구름EDU 쿠폰은 모든 강좌가 아닌 - 프로모션 강좌에 한해서 - 할인적용됩니다.
-
-
-
- - - - - - -
- - - - - - -
-
-
-
- - - - - - -
- - - - - - -
-
- 구름 서비스를 소개합니다 😀
-
-
-
- - - - - - -
- - - - - - -
-
-
- -
-
-
- 클라우드 통합 개발환경 - 서비스, 구름IDE
-
-
-
-
-
- -
-
-
- 온라인 프로그래밍 교육 서비스, 구름EDU
-
-
-
-
-
- - - - - - -
- - - - - - -
-
-
- -
-
-
- 개발 역량 평가 및 채용 서비스, 구름DEVTH
-
-
-
-
-
- -
-
-
- 프로그래밍 문제 풀이 서비스, 구름LEVEL
-
-
-
-
-
- - - - - - -
- - - - - - -
-
-
-
- - - - - - -
- - - - - - -
-
- 무료로 배송받자! 상큼한 알고리즘 퀴즈 🍋
-
-
-
- - - - - - -
- - - - - - -
-
-

- -

-
-
-
- - - - - - -
- - - - - - -
-
-
- 공부 의지만 가지고 시작하세요! 매주 - 잊지 않고 영양만점 알고리즘 비타민을 - 배송해드립니다. -
-
- 새로운 문제, 꼼꼼한 해설, 예시 - 코드까지 한 번에 받는 스페셜 - 패키지! -
-
-
-
- - - - - - -
-
- - - - - - -
- 비타알고 바로가기 -
-
-
- - - - - - -
- - - - - - -
-
-
-
- + +
+
+ 본인의 속한 그룹을  호스트 + 로 만들어 보세요!
+
+
+ +
+
+ -
- - - - -
- + +
+
+ 이벤트 -
- - - - -
-
- 잠깐! 구름 뉴스레터로 최신 개발 트렌드를 - 알아보세요 💎
-
-
-
- 를 열어 공연을 홍보 할 수 있어요 
+ + + + + + +
+ + + + - - - - -
+
+
+ -
- + +
+
+ 티켓 -
- - - - -
-
-
- -
-
-
- 1. 로그인후 내 정보 수정에 들어가세요.
-
-
-
-
-
- -
-
-
-
- 2. 이메일 수신 동의에 체크하고 -
-
- 저장 버튼을 누르세요. -
-
-
-
-
-
- 을 만들어 판매하세요! 
+ + + +
+
+ -
- - - - -
-
- - - - - - -
- 뉴스레터 받아보기 -
-
-
- + +
+
+ 예약한 사람의 명단을 손쉽게 조회할 수 있어요 + +
+
+
+ + + + +
+ + + + - - - - -
+
+
+ -
- + +
+
+ 옵션 -
- - - - -
-
- FOLLOW US!
-
-
-
- - - - - - -
-
- -
-
- 을 만들어 설문을 받아보세요 
+ + + +
+
+ -
- - - - -
- + +
+
+ QR코드 -
- - - - -
-
- 구름 서비스 사용에 대해 - 궁금하신가요?  도움말 바로가기
-
-
-
- 로 손쉽게 티켓을 체크해보세요 - - - - - -
- - - - - - -
-
-
- ⓒ goorm Corp. All Rights - Reserved.
-
-
- 경기도 성남시 분당구 판교로 242 PDC - A동 602호 -
-
- TELㅣ031-600-8586    - Emailㅣcontact@goorm.io -
-
-
-
-
- 수신거부  ㅣ  알림설정 -
-
-
-
-
-
+
+
+
+
+ + + + +
divider
+
+
+ 지금 바로! 이벤트를 만들어 관객들을 모집하세요! 
+
+ button +