From f23251f5bb109f766ede13bee8e4e6e5b1515126 Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 16 May 2025 15:01:33 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EC=9C=A0=EC=A0=80=20=ED=96=89=EB=8F=99?= =?UTF-8?q?=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EA=B8=B0=EB=A1=9D=EC=8B=9C=20?= =?UTF-8?q?=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=A7=80=EA=B8=89=20=EC=A1=B0?= =?UTF-8?q?=EA=B1=B4=20=EC=88=98=EC=A0=95=20-=20=EC=A7=80=EA=B8=89?= =?UTF-8?q?=EC=9C=A0=ED=98=95(=EB=A7=A4=EC=9D=BC,=20=EC=A0=84=EC=B2=B4)=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20-=20=EC=B0=B8=EC=97=AC=EA=B0=80=EB=8A=A5?= =?UTF-8?q?=20=ED=9A=9F=EC=88=98=20=EC=B6=94=EA=B0=80=20-=20=EC=A3=BC?= =?UTF-8?q?=EB=AC=B8=ED=95=9C=20=EC=BD=98=ED=85=90=EC=B8=A0=EC=97=90=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=EC=9D=84=20=EC=93=B0=EB=A9=B4=20=ED=8F=AC?= =?UTF-8?q?=EC=9D=B8=ED=8A=B8=20=EC=A7=80=EA=B8=89=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=B4=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=A7=80=EA=B8=89=20?= =?UTF-8?q?=EC=9D=B4=EB=A0=A5=EC=97=90=20orderId=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../point/CreatePointRewardPolicyRequest.kt | 5 ++++ .../vividnext/sodalive/point/PointGrantLog.kt | 3 ++- .../sodalive/point/PointGrantLogRepository.kt | 10 ++++---- .../sodalive/point/PointRewardPolicy.kt | 4 ++++ .../sodalive/useraction/ActionType.kt | 5 +++- .../sodalive/useraction/PolicyType.kt | 6 +++++ .../sodalive/useraction/UserActionService.kt | 23 +++++++++++++++---- 7 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/useraction/PolicyType.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/point/CreatePointRewardPolicyRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/point/CreatePointRewardPolicyRequest.kt index 4c2cf73..0f80f8a 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/point/CreatePointRewardPolicyRequest.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/point/CreatePointRewardPolicyRequest.kt @@ -2,14 +2,17 @@ package kr.co.vividnext.sodalive.admin.point import kr.co.vividnext.sodalive.point.PointRewardPolicy import kr.co.vividnext.sodalive.useraction.ActionType +import kr.co.vividnext.sodalive.useraction.PolicyType import java.time.LocalDateTime import java.time.ZoneId import java.time.format.DateTimeFormatter data class CreatePointRewardPolicyRequest( val title: String, + val policyType: PolicyType, val actionType: ActionType, val threshold: Int, + val availableCount: Int, val pointAmount: Int, val startDate: String, val endDate: String @@ -19,8 +22,10 @@ data class CreatePointRewardPolicyRequest( return PointRewardPolicy( title = title, + policyType = policyType, actionType = actionType, threshold = threshold, + availableCount = availableCount, pointAmount = pointAmount, startDate = LocalDateTime.parse(startDate, dateTimeFormatter) .atZone(ZoneId.of("Asia/Seoul")) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/point/PointGrantLog.kt b/src/main/kotlin/kr/co/vividnext/sodalive/point/PointGrantLog.kt index 780eccc..83666c6 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/point/PointGrantLog.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/point/PointGrantLog.kt @@ -12,5 +12,6 @@ data class PointGrantLog( val point: Int, @Enumerated(EnumType.STRING) val actionType: ActionType, - val policyId: Long? + val policyId: Long?, + val orderId: Long? ) : BaseEntity() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/point/PointGrantLogRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/point/PointGrantLogRepository.kt index 361a873..8862ab6 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/point/PointGrantLogRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/point/PointGrantLogRepository.kt @@ -3,25 +3,27 @@ package kr.co.vividnext.sodalive.point import com.querydsl.jpa.impl.JPAQueryFactory import kr.co.vividnext.sodalive.point.QPointGrantLog.pointGrantLog import org.springframework.data.jpa.repository.JpaRepository +import java.time.LocalDateTime interface PointGrantLogRepository : JpaRepository, PointGrantLogQueryRepository interface PointGrantLogQueryRepository { - fun existsByMemberIdAndPolicyId(memberId: Long, policyId: Long): Boolean + fun countByMemberIdAndPolicyIdAndStartDate(memberId: Long, policyId: Long, startDate: LocalDateTime): Int } class PointGrantLogQueryRepositoryImpl( private val queryFactory: JPAQueryFactory ) : PointGrantLogQueryRepository { - override fun existsByMemberIdAndPolicyId(memberId: Long, policyId: Long): Boolean { + override fun countByMemberIdAndPolicyIdAndStartDate(memberId: Long, policyId: Long, startDate: LocalDateTime): Int { return queryFactory .select(pointGrantLog.id) .from(pointGrantLog) .where( pointGrantLog.memberId.eq(memberId), - pointGrantLog.policyId.eq(policyId) + pointGrantLog.policyId.eq(policyId), + pointGrantLog.createdAt.goe(startDate) ) .fetch() - .isNotEmpty() + .size } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/point/PointRewardPolicy.kt b/src/main/kotlin/kr/co/vividnext/sodalive/point/PointRewardPolicy.kt index a898e1c..2fd9bd9 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/point/PointRewardPolicy.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/point/PointRewardPolicy.kt @@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.point import kr.co.vividnext.sodalive.common.BaseEntity import kr.co.vividnext.sodalive.useraction.ActionType +import kr.co.vividnext.sodalive.useraction.PolicyType import java.time.LocalDateTime import javax.persistence.Entity import javax.persistence.EnumType @@ -11,8 +12,11 @@ import javax.persistence.Enumerated data class PointRewardPolicy( var title: String, @Enumerated(EnumType.STRING) + val policyType: PolicyType, + @Enumerated(EnumType.STRING) val actionType: ActionType, val threshold: Int, + val availableCount: Int, val pointAmount: Int, var startDate: LocalDateTime, var endDate: LocalDateTime? = null, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/useraction/ActionType.kt b/src/main/kotlin/kr/co/vividnext/sodalive/useraction/ActionType.kt index a9365c4..5933be9 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/useraction/ActionType.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/useraction/ActionType.kt @@ -2,5 +2,8 @@ package kr.co.vividnext.sodalive.useraction enum class ActionType(val displayName: String) { SIGN_UP("회원가입"), - USER_AUTHENTICATION("본인인증") + USER_AUTHENTICATION("본인인증"), + CONTENT_COMMENT("콘텐츠 댓글"), + ORDER_CONTENT_COMMENT("구매한 콘텐츠 댓글"), + LIVE_CONTINUOUS_LISTEN_30("라이브 연속 청취 30분") } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/useraction/PolicyType.kt b/src/main/kotlin/kr/co/vividnext/sodalive/useraction/PolicyType.kt new file mode 100644 index 0000000..81f4982 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/useraction/PolicyType.kt @@ -0,0 +1,6 @@ +package kr.co.vividnext.sodalive.useraction + +enum class PolicyType(val displayName: String) { + DAILY("기간 내 매일"), + TOTAL("기간 내 전체") +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/useraction/UserActionService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/useraction/UserActionService.kt index b3f0236..3f1a33d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/useraction/UserActionService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/useraction/UserActionService.kt @@ -24,23 +24,35 @@ class UserActionService( private val coroutineScope = CoroutineScope(Dispatchers.IO) - fun recordAction(memberId: Long, actionType: ActionType, pushToken: String?) { + fun recordAction(memberId: Long, actionType: ActionType, orderId: Long? = null, pushToken: String? = null) { coroutineScope.launch { val now = LocalDateTime.now() repository.save(UserActionLog(memberId, actionType)) val policy = policyRepository.findByActionTypeAndIsActiveTrue(actionType, now) if (policy != null) { + val policyType = policy.policyType + val todayAt15 = now.toLocalDate().atTime(15, 0) + val policyTypeDailyStartDate = if (now.toLocalTime().isBefore(todayAt15.toLocalTime())) { + now.toLocalDate().minusDays(1).atTime(15, 0) + } else { + todayAt15 + } + val actionCount = repository.countByMemberIdAndActionTypeAndCreatedAtBetween( memberId = memberId, actionType = actionType, - startDate = policy.startDate, + startDate = if (policyType == PolicyType.DAILY) policyTypeDailyStartDate else policy.startDate, endDate = policy.endDate ?: now ) if (actionCount < policy.threshold) return@launch - val alreadyGranted = grantLogRepository.existsByMemberIdAndPolicyId(memberId, policy.id!!) - if (alreadyGranted) return@launch + val grantedCount = grantLogRepository.countByMemberIdAndPolicyIdAndStartDate( + memberId, + policy.id!!, + startDate = if (policyType == PolicyType.DAILY) policyTypeDailyStartDate else policy.startDate + ) + if (grantedCount >= policy.availableCount) return@launch memberPointRepository.save( MemberPoint( @@ -56,7 +68,8 @@ class UserActionService( memberId = memberId, point = policy.pointAmount, actionType = actionType, - policyId = policy.id!! + policyId = policy.id!!, + orderId = orderId ) )