feat: 유저 행동 기록 및 포인트 지급 로직 구현 + 회원가입 연동
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
package kr.co.vividnext.sodalive.useraction
|
||||
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||
import kr.co.vividnext.sodalive.useraction.QUserActionLog.userActionLog
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import java.time.LocalDateTime
|
||||
|
||||
interface UserActionLogRepository : JpaRepository<UserActionLog, Long>, UserActionLogQueryRepository
|
||||
|
||||
interface UserActionLogQueryRepository {
|
||||
fun countByMemberIdAndActionTypeAndCreatedAtBetween(
|
||||
memberId: Long,
|
||||
actionType: ActionType,
|
||||
startDate: LocalDateTime,
|
||||
endDate: LocalDateTime
|
||||
): Int
|
||||
}
|
||||
|
||||
class UserActionLogQueryRepositoryImpl(
|
||||
private val queryFactory: JPAQueryFactory
|
||||
) : UserActionLogQueryRepository {
|
||||
override fun countByMemberIdAndActionTypeAndCreatedAtBetween(
|
||||
memberId: Long,
|
||||
actionType: ActionType,
|
||||
startDate: LocalDateTime,
|
||||
endDate: LocalDateTime
|
||||
): Int {
|
||||
return queryFactory
|
||||
.select(userActionLog.id)
|
||||
.from(userActionLog)
|
||||
.where(
|
||||
userActionLog.memberId.eq(memberId)
|
||||
.and(userActionLog.actionType.eq(actionType))
|
||||
.and(userActionLog.createdAt.between(startDate, endDate))
|
||||
)
|
||||
.fetch()
|
||||
.size
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
package kr.co.vividnext.sodalive.useraction
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kr.co.vividnext.sodalive.point.MemberPoint
|
||||
import kr.co.vividnext.sodalive.point.MemberPointRepository
|
||||
import kr.co.vividnext.sodalive.point.PointGrantLog
|
||||
import kr.co.vividnext.sodalive.point.PointGrantLogRepository
|
||||
import kr.co.vividnext.sodalive.point.PointRewardPolicyRepository
|
||||
import org.springframework.stereotype.Service
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Service
|
||||
class UserActionService(
|
||||
private val repository: UserActionLogRepository,
|
||||
private val policyRepository: PointRewardPolicyRepository,
|
||||
private val grantLogRepository: PointGrantLogRepository,
|
||||
private val memberPointRepository: MemberPointRepository
|
||||
) {
|
||||
|
||||
private val coroutineScope = CoroutineScope(Dispatchers.IO)
|
||||
|
||||
fun recordAction(memberId: Long, actionType: ActionType) {
|
||||
coroutineScope.launch {
|
||||
val now = LocalDateTime.now()
|
||||
repository.save(UserActionLog(memberId, actionType))
|
||||
|
||||
val policy = policyRepository.findByActionTypeAndIsActiveTrue(actionType, now)
|
||||
if (policy != null) {
|
||||
val actionCount = repository.countByMemberIdAndActionTypeAndCreatedAtBetween(
|
||||
memberId = memberId,
|
||||
actionType = actionType,
|
||||
startDate = policy.startDate,
|
||||
endDate = policy.endDate ?: now
|
||||
)
|
||||
if (actionCount < policy.threshold) return@launch
|
||||
|
||||
val alreadyGranted = grantLogRepository.existsByMemberIdAndPolicyId(memberId, policy.id!!)
|
||||
if (alreadyGranted) return@launch
|
||||
|
||||
memberPointRepository.save(
|
||||
MemberPoint(
|
||||
memberId = memberId,
|
||||
point = policy.pointAmount,
|
||||
actionType = actionType,
|
||||
expiresAt = now.plusDays(3)
|
||||
)
|
||||
)
|
||||
|
||||
grantLogRepository.save(
|
||||
PointGrantLog(
|
||||
memberId = memberId,
|
||||
point = policy.pointAmount,
|
||||
actionType = actionType,
|
||||
policyId = policy.id!!
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user