쿠폰 번호 사용 API 추가
This commit is contained in:
		| @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper | ||||
| import kr.co.bootpay.Bootpay | ||||
| import kr.co.vividnext.sodalive.can.CanRepository | ||||
| import kr.co.vividnext.sodalive.can.charge.event.ChargeSpringEvent | ||||
| import kr.co.vividnext.sodalive.can.coupon.CanCouponNumberRepository | ||||
| import kr.co.vividnext.sodalive.can.payment.Payment | ||||
| import kr.co.vividnext.sodalive.can.payment.PaymentGateway | ||||
| import kr.co.vividnext.sodalive.can.payment.PaymentStatus | ||||
| @@ -29,6 +30,8 @@ class ChargeService( | ||||
|     private val chargeRepository: ChargeRepository, | ||||
|     private val canRepository: CanRepository, | ||||
|     private val memberRepository: MemberRepository, | ||||
|     private val couponNumberRepository: CanCouponNumberRepository, | ||||
|  | ||||
|     private val objectMapper: ObjectMapper, | ||||
|     private val okHttpClient: OkHttpClient, | ||||
|     private val applicationEventPublisher: ApplicationEventPublisher, | ||||
| @@ -43,6 +46,31 @@ class ChargeService( | ||||
|     private val appleInAppVerifyUrl: String | ||||
| ) { | ||||
|  | ||||
|     @Transactional | ||||
|     fun chargeByCoupon(couponNumber: String, member: Member) { | ||||
|         val canCouponNumber = couponNumberRepository.findByCouponNumber(couponNumber = couponNumber) | ||||
|             ?: throw SodaException("잘못된 쿠폰번호입니다.\n고객센터로 문의해 주시기 바랍니다.") | ||||
|  | ||||
|         if (canCouponNumber.member != null) { | ||||
|             throw SodaException("이미 사용한 쿠폰번호 입니다.") | ||||
|         } | ||||
|  | ||||
|         val coupon = canCouponNumber.canCoupon!! | ||||
|         val couponCharge = Charge(0, coupon.can, status = ChargeStatus.COUPON) | ||||
|         couponCharge.title = "${coupon.can} 캔" | ||||
|         couponCharge.member = member | ||||
|  | ||||
|         val payment = Payment( | ||||
|             status = PaymentStatus.COMPLETE, | ||||
|             paymentGateway = PaymentGateway.PG | ||||
|         ) | ||||
|         payment.method = coupon.couponName | ||||
|         couponCharge.payment = payment | ||||
|         chargeRepository.save(couponCharge) | ||||
|  | ||||
|         member.charge(0, coupon.can, "pg") | ||||
|     } | ||||
|  | ||||
|     @Transactional | ||||
|     fun charge(member: Member, request: ChargeRequest): ChargeResponse { | ||||
|         val can = canRepository.findByIdOrNull(request.canId) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| package kr.co.vividnext.sodalive.can.charge | ||||
|  | ||||
| enum class ChargeStatus { | ||||
|     CHARGE, REFUND_CHARGE, EVENT, CANCEL, | ||||
|     CHARGE, REFUND_CHARGE, EVENT, COUPON, CANCEL, | ||||
|  | ||||
|     // 관리자 지급 | ||||
|     ADMIN, | ||||
|   | ||||
| @@ -89,4 +89,19 @@ class CanCouponController(private val service: CanCouponService) { | ||||
|             ) | ||||
|             .body(InputStreamResource(response)) | ||||
|     } | ||||
|  | ||||
|     @PostMapping("/use") | ||||
|     fun useCanCoupon( | ||||
|         @RequestBody request: UseCanCouponRequest, | ||||
|         @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? | ||||
|     ) = run { | ||||
|         if (member == null) throw SodaException("로그인 정보를 확인해주세요.") | ||||
|  | ||||
|         ApiResponse.ok( | ||||
|             service.useCanCoupon( | ||||
|                 couponNumber = request.couponNumber, | ||||
|                 memberId = member.id!! | ||||
|             ) | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,31 @@ | ||||
| package kr.co.vividnext.sodalive.can.coupon | ||||
|  | ||||
| import kr.co.vividnext.sodalive.common.SodaException | ||||
| import org.springframework.stereotype.Service | ||||
|  | ||||
| @Service | ||||
| class CanCouponIssueService(private val couponNumberRepository: CanCouponNumberRepository) { | ||||
|     fun validateAvailableUseCoupon(couponNumber: String, memberId: Long) { | ||||
|         val canCouponNumber = checkCanCouponNumber(couponNumber) | ||||
|  | ||||
|         if (!isMultipleUse(canCouponNumber)) { | ||||
|             val canCouponNumberList = couponNumberRepository.findByMemberId(memberId = memberId) | ||||
|             if (canCouponNumberList.isNotEmpty()) { | ||||
|                 throw SodaException("해당 쿠폰은 1회만 충전이 가능합니다.") | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun checkCanCouponNumber(couponNumber: String): CanCouponNumber { | ||||
|         val canCouponNumber = couponNumberRepository.findByCouponNumber(couponNumber = couponNumber) | ||||
|             ?: throw SodaException("잘못된 쿠폰번호입니다.\n고객센터로 문의해 주시기 바랍니다.") | ||||
|  | ||||
|         if (canCouponNumber.member != null) { | ||||
|             throw SodaException("이미 사용한 쿠폰번호 입니다.") | ||||
|         } | ||||
|  | ||||
|         return canCouponNumber | ||||
|     } | ||||
|  | ||||
|     private fun isMultipleUse(canCouponNumber: CanCouponNumber) = canCouponNumber.canCoupon!!.isMultipleUse | ||||
| } | ||||
| @@ -14,6 +14,10 @@ interface CanCouponNumberQueryRepository { | ||||
|     fun getCouponNumberList(couponId: Long, offset: Long, limit: Long): List<GetCouponNumberListItemResponse> | ||||
|  | ||||
|     fun getAllCouponNumberList(couponId: Long): List<GetCouponNumberListItemResponse> | ||||
|  | ||||
|     fun findByCouponNumber(couponNumber: String): CanCouponNumber? | ||||
|  | ||||
|     fun findByMemberId(memberId: Long): List<Long> | ||||
| } | ||||
|  | ||||
| class CanCouponNumberQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : CanCouponNumberQueryRepository { | ||||
| @@ -66,4 +70,19 @@ class CanCouponNumberQueryRepositoryImpl(private val queryFactory: JPAQueryFacto | ||||
|             .orderBy(canCouponNumber.id.asc()) | ||||
|             .fetch() | ||||
|     } | ||||
|  | ||||
|     override fun findByCouponNumber(couponNumber: String): CanCouponNumber? { | ||||
|         return queryFactory | ||||
|             .selectFrom(canCouponNumber) | ||||
|             .where(canCouponNumber.couponNumber.eq(couponNumber)) | ||||
|             .fetchFirst() | ||||
|     } | ||||
|  | ||||
|     override fun findByMemberId(memberId: Long): List<Long> { | ||||
|         return queryFactory | ||||
|             .select(canCouponNumber.id) | ||||
|             .from(canCouponNumber) | ||||
|             .where(canCouponNumber.member.id.eq(memberId)) | ||||
|             .fetch() | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,9 +3,12 @@ package kr.co.vividnext.sodalive.can.coupon | ||||
| import com.fasterxml.jackson.databind.ObjectMapper | ||||
| import kr.co.vividnext.sodalive.aws.sqs.SqsEvent | ||||
| import kr.co.vividnext.sodalive.aws.sqs.SqsEventType | ||||
| import kr.co.vividnext.sodalive.can.charge.ChargeService | ||||
| import kr.co.vividnext.sodalive.common.SodaException | ||||
| import kr.co.vividnext.sodalive.member.MemberRepository | ||||
| import org.apache.poi.xssf.usermodel.XSSFWorkbook | ||||
| import org.springframework.context.ApplicationEventPublisher | ||||
| import org.springframework.data.repository.findByIdOrNull | ||||
| import org.springframework.stereotype.Service | ||||
| import java.io.ByteArrayInputStream | ||||
| import java.io.ByteArrayOutputStream | ||||
| @@ -14,9 +17,14 @@ import java.time.format.DateTimeFormatter | ||||
|  | ||||
| @Service | ||||
| class CanCouponService( | ||||
|     private val issueService: CanCouponIssueService, | ||||
|     private val chargeService: ChargeService, | ||||
|  | ||||
|     private val repository: CanCouponRepository, | ||||
|     private val couponNumberRepository: CanCouponNumberRepository, | ||||
|  | ||||
|     private val memberRepository: MemberRepository, | ||||
|  | ||||
|     private val objectMapper: ObjectMapper, | ||||
|     private val applicationEventPublisher: ApplicationEventPublisher | ||||
| ) { | ||||
| @@ -91,6 +99,17 @@ class CanCouponService( | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fun useCanCoupon(couponNumber: String, memberId: Long) { | ||||
|         val member = memberRepository.findByIdOrNull(id = memberId) | ||||
|             ?: throw SodaException("로그인 정보를 확인해주세요.") | ||||
|  | ||||
|         if (member.auth == null) throw SodaException("쿠폰은 본인인증을 하셔야 사용이 가능합니다.") | ||||
|  | ||||
|         issueService.validateAvailableUseCoupon(couponNumber, memberId) | ||||
|  | ||||
|         chargeService.chargeByCoupon(couponNumber, member) | ||||
|     } | ||||
|  | ||||
|     private fun insertHyphens(input: String): String { | ||||
|         return input.chunked(4).joinToString("-") | ||||
|     } | ||||
|   | ||||
| @@ -0,0 +1,3 @@ | ||||
| package kr.co.vividnext.sodalive.can.coupon | ||||
|  | ||||
| data class UseCanCouponRequest(val couponNumber: String) | ||||
		Reference in New Issue
	
	Block a user