Skip to content

Commit

Permalink
feat: 쿠폰 사용 기능 구현 (#160)
Browse files Browse the repository at this point in the history
* Merge branch 'develop' into feature/#75-use-coupon

* feat: 쿠폰 지갑에서 특정 회원의 특정 쿠폰 조회 기능 구현 및 테스트

* feat: 쿠폰 지갑에 있는 쿠폰 사용하는 서비스 기능 구현 및 테스트

* feat: 쿠폰 사용 API 기능 구현 및 테스트

* fix: 테스트 코드 에러 수정

* test: RestDoc 업데이트

* refactor : 결제 쿠폰 사용 통합

* Submodule update

* test: 테스트 커버리지 추가
  • Loading branch information
hongdosan authored Nov 27, 2023
1 parent 2c7287d commit 076e022
Show file tree
Hide file tree
Showing 21 changed files with 390 additions and 69 deletions.
13 changes: 12 additions & 1 deletion src/docs/asciidoc/coupon.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ include::{snippets}/my-coupons/couponId/http-response.adoc[]

---

=== 쿠폰 사용 (진행 중)
=== 쿠폰을 사용

사용자가 자신의 보관함에 있는 쿠폰들을 사용합니다.

==== 요청

include::{snippets}/my-coupons/couponWalletId/http-request.adoc[]

[discrete]
==== 응답

include::{snippets}/my-coupons/couponWalletId/http-response.adoc[]

---
6 changes: 3 additions & 3 deletions src/main/java/com/moabam/api/application/bug/BugService.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import com.moabam.api.domain.bug.Bug;
import com.moabam.api.domain.bug.repository.BugHistoryRepository;
import com.moabam.api.domain.bug.repository.BugHistorySearchRepository;
import com.moabam.api.domain.coupon.Coupon;
import com.moabam.api.domain.coupon.CouponWallet;
import com.moabam.api.domain.payment.Payment;
import com.moabam.api.domain.payment.repository.PaymentRepository;
import com.moabam.api.domain.product.Product;
Expand Down Expand Up @@ -67,8 +67,8 @@ public PurchaseProductResponse purchaseBugProduct(Long memberId, Long productId,
Payment payment = PaymentMapper.toPayment(memberId, product);

if (!isNull(request.couponWalletId())) {
Coupon coupon = couponService.getByWalletIdAndMemberId(request.couponWalletId(), memberId);
payment.applyCoupon(coupon, request.couponWalletId());
CouponWallet couponWallet = couponService.getWalletByIdAndMemberId(request.couponWalletId(), memberId);
payment.applyCoupon(couponWallet);
}
paymentRepository.save(payment);

Expand Down
41 changes: 32 additions & 9 deletions src/main/java/com/moabam/api/application/coupon/CouponService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.moabam.api.application.member.MemberService;
import com.moabam.api.domain.bug.BugType;
import com.moabam.api.domain.coupon.Coupon;
import com.moabam.api.domain.coupon.CouponWallet;
import com.moabam.api.domain.coupon.repository.CouponRepository;
import com.moabam.api.domain.coupon.repository.CouponSearchRepository;
import com.moabam.api.domain.coupon.repository.CouponWalletRepository;
import com.moabam.api.domain.coupon.repository.CouponWalletSearchRepository;
import com.moabam.api.domain.member.Member;
import com.moabam.api.domain.member.Role;
import com.moabam.api.dto.coupon.CouponResponse;
import com.moabam.api.dto.coupon.CouponStatusRequest;
Expand All @@ -31,9 +35,11 @@
public class CouponService {

private final ClockHolder clockHolder;
private final MemberService memberService;
private final CouponManageService couponManageService;
private final CouponRepository couponRepository;
private final CouponSearchRepository couponSearchRepository;
private final CouponWalletRepository couponWalletRepository;
private final CouponWalletSearchRepository couponWalletSearchRepository;

@Transactional
Expand All @@ -47,6 +53,30 @@ public void create(AuthMember admin, CreateCouponRequest request) {
couponRepository.save(coupon);
}

@Transactional
public void use(Long memberId, Long couponWalletId) {
CouponWallet couponWallet = getWalletByIdAndMemberId(couponWalletId, memberId);
Coupon coupon = couponWallet.getCoupon();
BugType bugType = coupon.getType().getBugType();

Member member = memberService.findMember(memberId);
member.getBug().increase(bugType, coupon.getPoint());

couponWalletRepository.delete(couponWallet);
}

@Transactional
public void discount(Long memberId, Long couponWalletId) {
CouponWallet couponWallet = getWalletByIdAndMemberId(couponWalletId, memberId);
Coupon coupon = couponWallet.getCoupon();

if (!coupon.getType().isDiscount()) {
throw new BadRequestException(ErrorMessage.INVALID_BUG_COUPON);
}

couponWalletRepository.delete(couponWallet);
}

@Transactional
public void delete(AuthMember admin, Long couponId) {
validateAdminRole(admin);
Expand All @@ -56,12 +86,6 @@ public void delete(AuthMember admin, Long couponId) {
couponManageService.deleteCouponManage(coupon.getName());
}

@Transactional
public void use(Long memberId, Long couponWalletId) {
Coupon coupon = getByWalletIdAndMemberId(couponWalletId, memberId);
couponRepository.delete(coupon);
}

public CouponResponse getById(Long couponId) {
Coupon coupon = couponRepository.findById(couponId)
.orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_COUPON));
Expand All @@ -83,10 +107,9 @@ public List<MyCouponResponse> getWallet(Long couponId, AuthMember authMember) {
return CouponMapper.toMyResponses(couponWallets);
}

public Coupon getByWalletIdAndMemberId(Long couponWalletId, Long memberId) {
public CouponWallet getWalletByIdAndMemberId(Long couponWalletId, Long memberId) {
return couponWalletSearchRepository.findByIdAndMemberId(couponWalletId, memberId)
.orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_COUPON_WALLET))
.getCoupon();
.orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_COUPON_WALLET));
}

private void validatePeriod(LocalDate startAt, LocalDate openAt) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void confirm(Long memberId, ConfirmPaymentRequest request) {
payment.confirm(response.paymentKey(), response.approvedAt());

if (payment.isCouponApplied()) {
couponService.use(memberId, payment.getCouponWalletId());
couponService.discount(memberId, payment.getCouponWalletId());
}
bugService.charge(memberId, payment.getProduct());
} catch (MoabamException exception) {
Expand Down
30 changes: 26 additions & 4 deletions src/main/java/com/moabam/api/domain/coupon/CouponType.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import java.util.function.Function;
import java.util.stream.Collectors;

import com.moabam.api.domain.bug.BugType;
import com.moabam.global.error.exception.BadRequestException;
import com.moabam.global.error.exception.NotFoundException;
import com.moabam.global.error.model.ErrorMessage;

Expand All @@ -18,10 +20,10 @@
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public enum CouponType {

MORNING_COUPON("아침"),
NIGHT_COUPON("저녁"),
GOLDEN_COUPON("황금"),
DISCOUNT_COUPON("할인");
MORNING("아침"),
NIGHT("저녁"),
GOLDEN("황금"),
DISCOUNT("할인");

private final String name;
private static final Map<String, CouponType> COUPON_TYPE_MAP;
Expand All @@ -35,4 +37,24 @@ public static CouponType from(String name) {
return Optional.ofNullable(COUPON_TYPE_MAP.get(name))
.orElseThrow(() -> new NotFoundException(ErrorMessage.NOT_FOUND_COUPON_TYPE));
}

public boolean isDiscount() {
return this == CouponType.DISCOUNT;
}

public BugType getBugType() {
if (this == CouponType.MORNING) {
return BugType.MORNING;
}

if (this == CouponType.NIGHT) {
return BugType.NIGHT;
}

if (this == CouponType.GOLDEN) {
return BugType.GOLDEN;
}

throw new BadRequestException(ErrorMessage.INVALID_DISCOUNT_COUPON);
}
}
10 changes: 5 additions & 5 deletions src/main/java/com/moabam/api/domain/payment/Payment.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import com.moabam.api.domain.coupon.Coupon;
import com.moabam.api.domain.coupon.CouponWallet;
import com.moabam.api.domain.product.Product;
import com.moabam.global.error.exception.BadRequestException;

Expand Down Expand Up @@ -122,10 +122,10 @@ public boolean isCouponApplied() {
return !isNull(this.couponWalletId);
}

public void applyCoupon(Coupon coupon, Long couponWalletId) {
this.couponWalletId = couponWalletId;
this.discountAmount = coupon.getPoint();
this.totalAmount = Math.max(MIN_AMOUNT, this.totalAmount - coupon.getPoint());
public void applyCoupon(CouponWallet couponWallet) {
this.couponWalletId = couponWallet.getId();
this.discountAmount = couponWallet.getCoupon().getPoint();
this.totalAmount = Math.max(MIN_AMOUNT, this.totalAmount - this.discountAmount);
}

public void request(String orderId) {
Expand Down
12 changes: 10 additions & 2 deletions src/main/java/com/moabam/api/presentation/CouponController.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ public class CouponController {

@PostMapping("/admins/coupons")
@ResponseStatus(HttpStatus.CREATED)
public void createCoupon(@Auth AuthMember admin, @Valid @RequestBody CreateCouponRequest request) {
public void create(@Auth AuthMember admin, @Valid @RequestBody CreateCouponRequest request) {
couponService.create(admin, request);
}

@DeleteMapping("/admins/coupons/{couponId}")
@ResponseStatus(HttpStatus.OK)
public void deleteCoupon(@Auth AuthMember admin, @PathVariable("couponId") Long couponId) {
public void delete(@Auth AuthMember admin, @PathVariable("couponId") Long couponId) {
couponService.delete(admin, couponId);
}

Expand All @@ -56,13 +56,21 @@ public List<CouponResponse> getAllByStatus(@Valid @RequestBody CouponStatusReque
}

@PostMapping("/coupons")
@ResponseStatus(HttpStatus.OK)
public void registerQueue(@Auth AuthMember authMember, @RequestParam("couponName") String couponName) {
couponManageService.register(authMember, couponName);
}

@GetMapping({"/my-coupons", "/my-coupons/{couponId}"})
@ResponseStatus(HttpStatus.OK)
public List<MyCouponResponse> getWallet(@Auth AuthMember authMember,
@PathVariable(value = "couponId", required = false) Long couponId) {
return couponService.getWallet(couponId, authMember);
}

@PostMapping("/my-coupons/{couponWalletId}")
@ResponseStatus(HttpStatus.OK)
public void use(@Auth AuthMember authMember, @PathVariable("couponWalletId") Long couponWalletId) {
couponService.use(authMember.id(), couponWalletId);
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/moabam/global/error/model/ErrorMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ public enum ErrorMessage {
INVALID_COUPON_START_AT_PERIOD("쿠폰 발급 시작 날짜는 현재 날짜보다 이전이거나 같을 수 없습니다."),
INVALID_COUPON_OPEN_AT_PERIOD("쿠폰 정보 오픈 날짜는 시작 날짜보다 이전이여야 합니다."),
INVALID_COUPON_PERIOD("쿠폰 발급 가능 기간이 아닙니다."),
INVALID_DISCOUNT_COUPON("할인 쿠폰은 결제 시, 사용할 수 있습니다."),
INVALID_BUG_COUPON("벌레 쿠폰은 보관함에서 사용할 수 있습니다."),
CONFLICT_COUPON_NAME("쿠폰의 이름이 중복되었습니다."),
CONFLICT_COUPON_START_AT("쿠폰 발급 가능 날짜가 중복되었습니다."),
NOT_FOUND_COUPON_TYPE("존재하지 않는 쿠폰 종류입니다."),
Expand Down
Loading

0 comments on commit 076e022

Please sign in to comment.