diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderService.kt index 630b22a..81e460f 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/order/OrderService.kt @@ -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 diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/point/MemberPointRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/point/MemberPointRepository.kt index 1fec31b..d8aec5d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/point/MemberPointRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/point/MemberPointRepository.kt @@ -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() + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/point/PointUsageService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/point/PointUsageService.kt new file mode 100644 index 0000000..ed02ca1 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/point/PointUsageService.kt @@ -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 +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/point/UsePointRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/point/UsePointRepository.kt new file mode 100644 index 0000000..49a5fcc --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/point/UsePointRepository.kt @@ -0,0 +1,5 @@ +package kr.co.vividnext.sodalive.point + +import org.springframework.data.jpa.repository.JpaRepository + +interface UsePointRepository : JpaRepository<UsePoint, Long>