fix: 포인트 내역 리스트

- 유저의 포인트 보상내역, 사용내역 API 추가
This commit is contained in:
Klaus 2025-05-19 21:38:24 +09:00
parent 56542a7bf1
commit d6db862c9d
7 changed files with 172 additions and 1 deletions

View File

@ -0,0 +1,9 @@
package kr.co.vividnext.sodalive.point
import com.querydsl.core.annotations.QueryProjection
data class GetPointRewardStatusResponse @QueryProjection constructor(
val rewardPoint: String,
val date: String,
val method: String
)

View File

@ -0,0 +1,3 @@
package kr.co.vividnext.sodalive.point
data class GetPointStatusResponse(val point: Int)

View File

@ -0,0 +1,9 @@
package kr.co.vividnext.sodalive.point
import com.querydsl.core.annotations.QueryProjection
data class GetPointUseStatusResponse @QueryProjection constructor(
val title: String,
val date: String,
val point: Int
)

View File

@ -0,0 +1,49 @@
package kr.co.vividnext.sodalive.point
import kr.co.vividnext.sodalive.common.ApiResponse
import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.member.Member
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/point")
class PointController(private val service: PointService) {
@GetMapping("/status")
fun getPointStatus(
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) {
throw SodaException("로그인 정보를 확인해주세요.")
}
ApiResponse.ok(service.getPointStatus(member))
}
@GetMapping("/status/use")
fun getPointUseStatus(
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
@RequestParam("timezone") timezone: String
) = run {
if (member == null) {
throw SodaException("로그인 정보를 확인해주세요.")
}
ApiResponse.ok(service.getPointUseStatus(member, timezone))
}
@GetMapping("/status/reward")
fun getPointRewardStatus(
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
@RequestParam("timezone") timezone: String
) = run {
if (member == null) {
throw SodaException("로그인 정보를 확인해주세요.")
}
ApiResponse.ok(service.getPointRewardStatus(member, timezone))
}
}

View File

@ -1,7 +1,9 @@
package kr.co.vividnext.sodalive.point
import com.querydsl.core.types.dsl.Expressions
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.point.QPointGrantLog.pointGrantLog
import kr.co.vividnext.sodalive.point.QPointRewardPolicy.pointRewardPolicy
import org.springframework.data.jpa.repository.JpaRepository
import java.time.LocalDateTime
@ -14,6 +16,8 @@ interface PointGrantLogQueryRepository {
startDate: LocalDateTime,
orderId: Long? = null
): Int
fun getPointRewardStatusByMemberId(memberId: Long, timezone: String): List<GetPointRewardStatusResponse>
}
class PointGrantLogQueryRepositoryImpl(
@ -40,4 +44,30 @@ class PointGrantLogQueryRepositoryImpl(
.fetch()
.size
}
override fun getPointRewardStatusByMemberId(memberId: Long, timezone: String): List<GetPointRewardStatusResponse> {
val formattedDate = Expressions.stringTemplate(
"DATE_FORMAT({0}, {1})",
Expressions.dateTimeTemplate(
LocalDateTime::class.java,
"CONVERT_TZ({0},{1},{2})",
pointGrantLog.createdAt,
"UTC",
timezone
),
"%Y.%m.%d | %H:%i:%s"
)
return queryFactory
.select(
QGetPointRewardStatusResponse(
pointGrantLog.point.stringValue().concat(" 포인트"),
formattedDate,
pointRewardPolicy.title
)
)
.from(pointGrantLog)
.innerJoin(pointRewardPolicy).on(pointGrantLog.policyId.eq(pointRewardPolicy.id))
.fetch()
}
}

View File

@ -0,0 +1,29 @@
package kr.co.vividnext.sodalive.point
import kr.co.vividnext.sodalive.member.Member
import org.springframework.stereotype.Service
import java.time.LocalDateTime
@Service
class PointService(
private val pointGrantLogRepository: PointGrantLogRepository,
private val memberPointRepository: MemberPointRepository,
private val usePointRepository: UsePointRepository
) {
fun getPointStatus(member: Member): GetPointStatusResponse {
return GetPointStatusResponse(
point = memberPointRepository.findByMemberIdAndExpiresAtAfterOrderByExpiresAtAsc(
memberId = member.id!!,
expiresAt = LocalDateTime.now()
).sumOf { it.point }
)
}
fun getPointUseStatus(member: Member, timezone: String): List<GetPointUseStatusResponse> {
return usePointRepository.getPointUseStatusByMemberId(member.id!!, timezone)
}
fun getPointRewardStatus(member: Member, timezone: String): List<GetPointRewardStatusResponse> {
return pointGrantLogRepository.getPointRewardStatusByMemberId(member.id!!, timezone)
}
}

View File

@ -1,5 +1,47 @@
package kr.co.vividnext.sodalive.point
import com.querydsl.core.types.dsl.Expressions
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
import kr.co.vividnext.sodalive.content.order.QOrder.order
import kr.co.vividnext.sodalive.point.QUsePoint.usePoint
import org.springframework.data.jpa.repository.JpaRepository
import java.time.LocalDateTime
interface UsePointRepository : JpaRepository<UsePoint, Long>
interface UsePointRepository : JpaRepository<UsePoint, Long>, UsePointQueryRepository
interface UsePointQueryRepository {
fun getPointUseStatusByMemberId(memberId: Long, timezone: String): List<GetPointUseStatusResponse>
}
class UsePointQueryRepositoryImpl(
private val queryFactory: JPAQueryFactory
) : UsePointQueryRepository {
override fun getPointUseStatusByMemberId(memberId: Long, timezone: String): List<GetPointUseStatusResponse> {
val formattedDate = Expressions.stringTemplate(
"DATE_FORMAT({0}, {1})",
Expressions.dateTimeTemplate(
LocalDateTime::class.java,
"CONVERT_TZ({0},{1},{2})",
usePoint.createdAt,
"UTC",
timezone
),
"%Y.%m.%d | %H:%i:%s"
)
return queryFactory
.select(
QGetPointUseStatusResponse(
audioContent.title.prepend("[콘텐츠 대여] "),
formattedDate,
usePoint.amount
)
)
.from(usePoint)
.innerJoin(order).on(usePoint.orderId.eq(order.id))
.innerJoin(audioContent).on(order.audioContent.id.eq(audioContent.id))
.where(usePoint.memberId.eq(memberId))
.fetch()
}
}