feat: 포인트 사용 로직 구현 (만료일 순 + 10포인트 단위 차감)
This commit is contained in:
		| @@ -10,6 +10,7 @@ import kr.co.vividnext.sodalive.content.comment.AudioContentCommentRepository | ||||
| import kr.co.vividnext.sodalive.content.like.AudioContentLikeRepository | ||||
| import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem | ||||
| import kr.co.vividnext.sodalive.member.Member | ||||
| import kr.co.vividnext.sodalive.point.PointUsageService | ||||
| import org.springframework.beans.factory.annotation.Value | ||||
| import org.springframework.stereotype.Service | ||||
| import org.springframework.transaction.annotation.Transactional | ||||
| @@ -19,6 +20,7 @@ import java.time.LocalDateTime | ||||
| @Transactional(readOnly = true) | ||||
| class OrderService( | ||||
|     private val repository: OrderRepository, | ||||
|     private val pointUsageService: PointUsageService, | ||||
|     private val canPaymentService: CanPaymentService, | ||||
|     private val audioContentRepository: AudioContentRepository, | ||||
|     private val audioContentCommentQueryRepository: AudioContentCommentRepository, | ||||
| @@ -41,9 +43,16 @@ class OrderService( | ||||
|             orderContent(orderType, content, member) | ||||
|         } | ||||
|  | ||||
|         val usedPoint = if (order.type == OrderType.RENTAL) { | ||||
|             pointUsageService.usePoint(member.id!!, order.can) | ||||
|         } else { | ||||
|             0 | ||||
|         } | ||||
|         order.point = usedPoint | ||||
|  | ||||
|         canPaymentService.spendCan( | ||||
|             memberId = member.id!!, | ||||
|             needCan = order.can, | ||||
|             needCan = order.can - (usedPoint / 10), | ||||
|             canUsage = CanUsage.ORDER_CONTENT, | ||||
|             order = order, | ||||
|             container = container | ||||
|   | ||||
| @@ -1,5 +1,29 @@ | ||||
| package kr.co.vividnext.sodalive.point | ||||
|  | ||||
| import com.querydsl.jpa.impl.JPAQueryFactory | ||||
| import kr.co.vividnext.sodalive.point.QMemberPoint.memberPoint | ||||
| import org.springframework.data.jpa.repository.JpaRepository | ||||
| import java.time.LocalDateTime | ||||
|  | ||||
| interface MemberPointRepository : JpaRepository<MemberPoint, Long> | ||||
| interface MemberPointRepository : JpaRepository<MemberPoint, Long>, MemberPointQueryRepository | ||||
|  | ||||
| interface MemberPointQueryRepository { | ||||
|     fun findByMemberIdAndExpiresAtAfterOrderByExpiresAtAsc(memberId: Long, expiresAt: LocalDateTime): List<MemberPoint> | ||||
| } | ||||
|  | ||||
| class MemberPointQueryRepositoryImpl( | ||||
|     private val queryFactory: JPAQueryFactory | ||||
| ) : MemberPointQueryRepository { | ||||
|     override fun findByMemberIdAndExpiresAtAfterOrderByExpiresAtAsc( | ||||
|         memberId: Long, | ||||
|         expiresAt: LocalDateTime | ||||
|     ): List<MemberPoint> { | ||||
|         return queryFactory | ||||
|             .selectFrom(memberPoint) | ||||
|             .where( | ||||
|                 memberPoint.memberId.eq(memberId), | ||||
|                 memberPoint.expiresAt.goe(expiresAt) | ||||
|             ) | ||||
|             .fetch() | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,43 @@ | ||||
| package kr.co.vividnext.sodalive.point | ||||
|  | ||||
| import org.springframework.stereotype.Service | ||||
| import java.time.LocalDateTime | ||||
|  | ||||
| @Service | ||||
| class PointUsageService( | ||||
|     private val memberPointRepository: MemberPointRepository, | ||||
|     private val usePointRepository: UsePointRepository | ||||
| ) { | ||||
|     fun usePoint(memberId: Long, contentPrice: Int): Int { | ||||
|         val now = LocalDateTime.now() | ||||
|         val maxUsablePoint = contentPrice * 10 | ||||
|  | ||||
|         val points = memberPointRepository.findByMemberIdAndExpiresAtAfterOrderByExpiresAtAsc( | ||||
|             memberId = memberId, | ||||
|             expiresAt = now | ||||
|         ) | ||||
|  | ||||
|         val totalAvailable = points.sumOf { it.point } | ||||
|         val usablePoint = minOf(totalAvailable, maxUsablePoint).floorToNearest10() | ||||
|  | ||||
|         var remaining = usablePoint | ||||
|         var used = 0 | ||||
|  | ||||
|         for (p in points) { | ||||
|             if (remaining <= 0) break | ||||
|             val usable = minOf(p.point, remaining) | ||||
|             p.point -= usable | ||||
|             remaining -= usable | ||||
|             used += usable | ||||
|         } | ||||
|  | ||||
|         if (used > 0) { | ||||
|             memberPointRepository.saveAll(points) | ||||
|             usePointRepository.save(UsePoint(memberId = memberId, amount = used)) | ||||
|         } | ||||
|  | ||||
|         return used | ||||
|     } | ||||
|  | ||||
|     private fun Int.floorToNearest10(): Int = (this / 10) * 10 | ||||
| } | ||||
| @@ -0,0 +1,5 @@ | ||||
| package kr.co.vividnext.sodalive.point | ||||
|  | ||||
| import org.springframework.data.jpa.repository.JpaRepository | ||||
|  | ||||
| interface UsePointRepository : JpaRepository<UsePoint, Long> | ||||
		Reference in New Issue
	
	Block a user