feat: 포인트 사용 로직 구현 (만료일 순 + 10포인트 단위 차감)

This commit is contained in:
Klaus 2025-04-22 15:39:45 +09:00
parent e2c70de2e0
commit 51dae0f02c
4 changed files with 83 additions and 2 deletions

View File

@ -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

View File

@ -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()
}
}

View File

@ -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
}

View File

@ -0,0 +1,5 @@
package kr.co.vividnext.sodalive.point
import org.springframework.data.jpa.repository.JpaRepository
interface UsePointRepository : JpaRepository<UsePoint, Long>