refactor(can): 캔 사용 내역 조회 로직을 쿼리 기반으로 개선한다
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
package kr.co.vividnext.sodalive.can
|
package kr.co.vividnext.sodalive.can
|
||||||
|
|
||||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||||
|
import kr.co.vividnext.sodalive.audition.QAudition.audition
|
||||||
|
import kr.co.vividnext.sodalive.audition.QAuditionApplicant.auditionApplicant
|
||||||
|
import kr.co.vividnext.sodalive.audition.QAuditionRole.auditionRole
|
||||||
import kr.co.vividnext.sodalive.can.QCan.can1
|
import kr.co.vividnext.sodalive.can.QCan.can1
|
||||||
import kr.co.vividnext.sodalive.can.charge.Charge
|
import kr.co.vividnext.sodalive.can.charge.Charge
|
||||||
import kr.co.vividnext.sodalive.can.charge.ChargeStatus
|
import kr.co.vividnext.sodalive.can.charge.ChargeStatus
|
||||||
@@ -10,7 +13,12 @@ import kr.co.vividnext.sodalive.can.payment.PaymentStatus
|
|||||||
import kr.co.vividnext.sodalive.can.payment.QPayment.payment
|
import kr.co.vividnext.sodalive.can.payment.QPayment.payment
|
||||||
import kr.co.vividnext.sodalive.can.use.CanUsage
|
import kr.co.vividnext.sodalive.can.use.CanUsage
|
||||||
import kr.co.vividnext.sodalive.can.use.QUseCan.useCan
|
import kr.co.vividnext.sodalive.can.use.QUseCan.useCan
|
||||||
|
import kr.co.vividnext.sodalive.can.use.QUseCanCalculate.useCanCalculate
|
||||||
import kr.co.vividnext.sodalive.can.use.UseCan
|
import kr.co.vividnext.sodalive.can.use.UseCan
|
||||||
|
import kr.co.vividnext.sodalive.chat.character.QChatCharacter.chatCharacter
|
||||||
|
import kr.co.vividnext.sodalive.chat.character.image.QCharacterImage.characterImage
|
||||||
|
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
|
||||||
|
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.QCreatorCommunity.creatorCommunity
|
||||||
import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom
|
import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
import kr.co.vividnext.sodalive.member.QMember
|
import kr.co.vividnext.sodalive.member.QMember
|
||||||
@@ -24,7 +32,7 @@ interface CanRepository : JpaRepository<Can, Long>, CanQueryRepository
|
|||||||
|
|
||||||
interface CanQueryRepository {
|
interface CanQueryRepository {
|
||||||
fun findAllByStatusAndCurrency(status: CanStatus, currency: String?): List<CanResponse>
|
fun findAllByStatusAndCurrency(status: CanStatus, currency: String?): List<CanResponse>
|
||||||
fun getCanUseStatus(member: Member, pageable: Pageable): List<UseCan>
|
fun getCanUseStatus(member: Member, pageable: Pageable, container: String): List<UseCanQueryDto>
|
||||||
fun getCanChargeStatus(member: Member, pageable: Pageable, container: String): List<Charge>
|
fun getCanChargeStatus(member: Member, pageable: Pageable, container: String): List<Charge>
|
||||||
fun isExistPaidLiveRoom(memberId: Long, roomId: Long): UseCan?
|
fun isExistPaidLiveRoom(memberId: Long, roomId: Long): UseCan?
|
||||||
fun getCanUsedForLiveRoomNotRefund(memberId: Long, roomId: Long, canUsage: CanUsage = CanUsage.LIVE): UseCan?
|
fun getCanUsedForLiveRoomNotRefund(memberId: Long, roomId: Long, canUsage: CanUsage = CanUsage.LIVE): UseCan?
|
||||||
@@ -58,13 +66,68 @@ class CanQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : CanQue
|
|||||||
.fetch()
|
.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getCanUseStatus(member: Member, pageable: Pageable): List<UseCan> {
|
override fun getCanUseStatus(member: Member, pageable: Pageable, container: String): List<UseCanQueryDto> {
|
||||||
|
val qRoomMember = QMember("roomMember")
|
||||||
|
val qAudioContentMember = QMember("audioContentMember")
|
||||||
|
val qCommunityPostMember = QMember("communityPostMember")
|
||||||
|
val qRecipientMember = QMember("recipientMember")
|
||||||
|
|
||||||
|
val gatewayCondition = when (container) {
|
||||||
|
"aos" -> useCanCalculate.paymentGateway.`in`(
|
||||||
|
PaymentGateway.PG,
|
||||||
|
PaymentGateway.PAYVERSE,
|
||||||
|
PaymentGateway.GOOGLE_IAP
|
||||||
|
)
|
||||||
|
|
||||||
|
"ios" -> useCanCalculate.paymentGateway.`in`(
|
||||||
|
PaymentGateway.PG,
|
||||||
|
PaymentGateway.PAYVERSE,
|
||||||
|
PaymentGateway.APPLE_IAP
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> useCanCalculate.paymentGateway.`in`(PaymentGateway.PG, PaymentGateway.PAYVERSE)
|
||||||
|
}
|
||||||
|
|
||||||
return queryFactory
|
return queryFactory
|
||||||
.selectFrom(useCan)
|
.select(
|
||||||
.where(useCan.member.id.eq(member.id))
|
QUseCanQueryDto(
|
||||||
|
useCan.canUsage,
|
||||||
|
useCan.can,
|
||||||
|
useCan.rewardCan,
|
||||||
|
useCan.createdAt,
|
||||||
|
qRoomMember.nickname,
|
||||||
|
liveRoom.title,
|
||||||
|
qAudioContentMember.nickname,
|
||||||
|
audioContent.title,
|
||||||
|
qCommunityPostMember.nickname,
|
||||||
|
audition.title,
|
||||||
|
chatCharacter.name,
|
||||||
|
qRecipientMember.nickname
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.from(useCan)
|
||||||
|
.leftJoin(useCan.room, liveRoom)
|
||||||
|
.leftJoin(liveRoom.member, qRoomMember)
|
||||||
|
.leftJoin(useCan.audioContent, audioContent)
|
||||||
|
.leftJoin(audioContent.member, qAudioContentMember)
|
||||||
|
.leftJoin(useCan.communityPost, creatorCommunity)
|
||||||
|
.leftJoin(creatorCommunity.member, qCommunityPostMember)
|
||||||
|
.leftJoin(useCan.auditionApplicant, auditionApplicant)
|
||||||
|
.leftJoin(auditionApplicant.role, auditionRole)
|
||||||
|
.leftJoin(auditionRole.audition, audition)
|
||||||
|
.leftJoin(useCan.characterImage, characterImage)
|
||||||
|
.leftJoin(characterImage.chatCharacter, chatCharacter)
|
||||||
|
.innerJoin(useCan.useCanCalculates, useCanCalculate)
|
||||||
|
.leftJoin(qRecipientMember).on(useCanCalculate.recipientCreatorId.eq(qRecipientMember.id))
|
||||||
|
.where(
|
||||||
|
useCan.member.id.eq(member.id)
|
||||||
|
.and(useCan.can.add(useCan.rewardCan).gt(0))
|
||||||
|
.and(gatewayCondition)
|
||||||
|
)
|
||||||
.offset(pageable.offset)
|
.offset(pageable.offset)
|
||||||
.limit(pageable.pageSize.toLong())
|
.limit(pageable.pageSize.toLong())
|
||||||
.orderBy(useCan.id.desc())
|
.orderBy(useCan.id.desc())
|
||||||
|
.distinct()
|
||||||
.fetch()
|
.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
package kr.co.vividnext.sodalive.can
|
package kr.co.vividnext.sodalive.can
|
||||||
|
|
||||||
import kr.co.vividnext.sodalive.can.charge.ChargeStatus
|
import kr.co.vividnext.sodalive.can.charge.ChargeStatus
|
||||||
import kr.co.vividnext.sodalive.can.payment.PaymentGateway
|
|
||||||
import kr.co.vividnext.sodalive.can.use.CanUsage
|
import kr.co.vividnext.sodalive.can.use.CanUsage
|
||||||
import kr.co.vividnext.sodalive.common.CountryContext
|
import kr.co.vividnext.sodalive.common.CountryContext
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
|
||||||
import org.springframework.data.domain.Pageable
|
import org.springframework.data.domain.Pageable
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import java.time.ZoneId
|
import java.time.ZoneId
|
||||||
@@ -14,8 +12,7 @@ import java.time.format.DateTimeFormatter
|
|||||||
@Service
|
@Service
|
||||||
class CanService(
|
class CanService(
|
||||||
private val repository: CanRepository,
|
private val repository: CanRepository,
|
||||||
private val countryContext: CountryContext,
|
private val countryContext: CountryContext
|
||||||
private val memberRepository: MemberRepository
|
|
||||||
) {
|
) {
|
||||||
fun getCans(isNotSelectedCurrency: Boolean): List<CanResponse> {
|
fun getCans(isNotSelectedCurrency: Boolean): List<CanResponse> {
|
||||||
val currency = if (isNotSelectedCurrency) {
|
val currency = if (isNotSelectedCurrency) {
|
||||||
@@ -42,88 +39,94 @@ class CanService(
|
|||||||
timezone: String,
|
timezone: String,
|
||||||
container: String
|
container: String
|
||||||
): List<GetCanUseStatusResponseItem> {
|
): List<GetCanUseStatusResponseItem> {
|
||||||
val useCanList = repository.getCanUseStatus(member, pageable)
|
val zoneId = try {
|
||||||
.filter { (it.can + it.rewardCan) > 0 }
|
ZoneId.of(timezone)
|
||||||
.filter {
|
} catch (_: Exception) {
|
||||||
when (container) {
|
ZoneId.of("UTC")
|
||||||
"aos" -> {
|
|
||||||
it.useCanCalculates.any { useCanCalculate ->
|
|
||||||
useCanCalculate.paymentGateway == PaymentGateway.PG ||
|
|
||||||
useCanCalculate.paymentGateway == PaymentGateway.PAYVERSE ||
|
|
||||||
useCanCalculate.paymentGateway == PaymentGateway.GOOGLE_IAP
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"ios" -> {
|
return repository.getCanUseStatus(member, pageable, container)
|
||||||
it.useCanCalculates.any { useCanCalculate ->
|
|
||||||
useCanCalculate.paymentGateway == PaymentGateway.PG ||
|
|
||||||
useCanCalculate.paymentGateway == PaymentGateway.PAYVERSE ||
|
|
||||||
useCanCalculate.paymentGateway == PaymentGateway.APPLE_IAP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> it.useCanCalculates.any { useCanCalculate ->
|
|
||||||
useCanCalculate.paymentGateway == PaymentGateway.PG ||
|
|
||||||
useCanCalculate.paymentGateway == PaymentGateway.PAYVERSE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val channelDonationCreatorIds = useCanList
|
|
||||||
.asSequence()
|
|
||||||
.filter { it.canUsage == CanUsage.CHANNEL_DONATION }
|
|
||||||
.mapNotNull { it.useCanCalculates.firstOrNull()?.recipientCreatorId }
|
|
||||||
.distinct()
|
|
||||||
.toList()
|
|
||||||
|
|
||||||
val channelDonationCreatorNicknameMap = if (channelDonationCreatorIds.isEmpty()) {
|
|
||||||
emptyMap()
|
|
||||||
} else {
|
|
||||||
memberRepository.findAllById(channelDonationCreatorIds).associate { it.id!! to it.nickname }
|
|
||||||
}
|
|
||||||
|
|
||||||
return useCanList
|
|
||||||
.map {
|
.map {
|
||||||
val title: String = when (it.canUsage) {
|
val title: String = when (it.canUsage) {
|
||||||
CanUsage.HEART, CanUsage.DONATION, CanUsage.SPIN_ROULETTE -> {
|
CanUsage.HEART, CanUsage.DONATION, CanUsage.SPIN_ROULETTE -> {
|
||||||
if (it.room != null) {
|
if (it.roomMemberNickname != null) {
|
||||||
"[라이브 후원] ${it.room!!.member!!.nickname}"
|
"[라이브 후원] ${it.roomMemberNickname}"
|
||||||
} else if (it.audioContent != null) {
|
} else if (it.audioContentMemberNickname != null) {
|
||||||
"[콘텐츠 후원] ${it.audioContent!!.member!!.nickname}"
|
"[콘텐츠 후원] ${it.audioContentMemberNickname}"
|
||||||
} else {
|
} else {
|
||||||
"[후원]"
|
"[후원]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CanUsage.CHANNEL_DONATION -> {
|
CanUsage.CHANNEL_DONATION -> {
|
||||||
val creatorId = it.useCanCalculates.firstOrNull()?.recipientCreatorId
|
if (it.recipientCreatorNickname.isNullOrBlank()) {
|
||||||
val creatorNickname = creatorId?.let { id -> channelDonationCreatorNicknameMap[id] }
|
|
||||||
|
|
||||||
if (creatorNickname.isNullOrBlank()) {
|
|
||||||
"[채널 후원]"
|
"[채널 후원]"
|
||||||
} else {
|
} else {
|
||||||
"[채널 후원] $creatorNickname"
|
"[채널 후원] ${it.recipientCreatorNickname}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CanUsage.LIVE -> {
|
CanUsage.LIVE -> {
|
||||||
"[라이브] ${it.room!!.title}"
|
if (it.roomTitle != null) {
|
||||||
|
"[라이브] ${it.roomTitle}"
|
||||||
|
} else if (it.roomMemberNickname != null) {
|
||||||
|
"[라이브] ${it.roomMemberNickname}"
|
||||||
|
} else {
|
||||||
|
"[라이브]"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CanUsage.CHANGE_NICKNAME -> "닉네임 변경"
|
CanUsage.CHANGE_NICKNAME -> "닉네임 변경"
|
||||||
CanUsage.ALARM_SLOT -> "알람 슬롯 구매"
|
CanUsage.ALARM_SLOT -> "알람 슬롯 구매"
|
||||||
CanUsage.ORDER_CONTENT -> "[콘텐츠 구매] ${it.audioContent!!.title}"
|
CanUsage.ORDER_CONTENT -> {
|
||||||
CanUsage.PAID_COMMUNITY_POST -> "[게시글 보기] ${it.communityPost?.member?.nickname ?: ""}"
|
if (it.audioContentTitle != null) {
|
||||||
CanUsage.AUDITION_VOTE -> "[오디션 투표] ${it.auditionApplicant?.role?.audition?.title ?: ""}"
|
"[콘텐츠 구매] ${it.audioContentTitle}"
|
||||||
CanUsage.CHAT_MESSAGE_PURCHASE -> "[메시지 구매] ${it.characterImage?.chatCharacter?.name ?: ""}"
|
} else if (it.audioContentMemberNickname != null) {
|
||||||
CanUsage.CHARACTER_IMAGE_PURCHASE -> "[캐릭터 이미지 구매] ${it.characterImage?.chatCharacter?.name ?: ""}"
|
"[콘텐츠 구매] ${it.audioContentMemberNickname}"
|
||||||
|
} else {
|
||||||
|
"[콘텐츠 구매]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CanUsage.PAID_COMMUNITY_POST -> {
|
||||||
|
if (it.communityPostMemberNickname != null) {
|
||||||
|
"[게시글 보기] ${it.communityPostMemberNickname}"
|
||||||
|
} else {
|
||||||
|
"[게시글 보기]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CanUsage.AUDITION_VOTE -> {
|
||||||
|
if (it.auditionTitle != null) {
|
||||||
|
"[오디션 투표] ${it.auditionTitle}"
|
||||||
|
} else {
|
||||||
|
"[오디션 투표]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CanUsage.CHAT_MESSAGE_PURCHASE -> {
|
||||||
|
if (it.characterName != null) {
|
||||||
|
"[메시지 구매] ${it.characterName}"
|
||||||
|
} else {
|
||||||
|
"[메시지 구매]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CanUsage.CHARACTER_IMAGE_PURCHASE -> {
|
||||||
|
if (it.characterName != null) {
|
||||||
|
"[캐릭터 이미지 구매] ${it.characterName}"
|
||||||
|
} else {
|
||||||
|
"[캐릭터 이미지 구매]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CanUsage.CHAT_QUOTA_PURCHASE -> "캐릭터 톡 이용권 구매"
|
CanUsage.CHAT_QUOTA_PURCHASE -> "캐릭터 톡 이용권 구매"
|
||||||
CanUsage.CHAT_ROOM_RESET -> "캐릭터 톡 초기화"
|
CanUsage.CHAT_ROOM_RESET -> "캐릭터 톡 초기화"
|
||||||
}
|
}
|
||||||
|
|
||||||
val createdAt = it.createdAt!!
|
val createdAt = it.createdAt
|
||||||
.atZone(ZoneId.of("UTC"))
|
.atZone(ZoneId.of("UTC"))
|
||||||
.withZoneSameInstant(ZoneId.of(timezone))
|
.withZoneSameInstant(zoneId)
|
||||||
|
|
||||||
GetCanUseStatusResponseItem(
|
GetCanUseStatusResponseItem(
|
||||||
title = title,
|
title = title,
|
||||||
@@ -141,6 +144,12 @@ class CanService(
|
|||||||
timezone: String,
|
timezone: String,
|
||||||
container: String
|
container: String
|
||||||
): List<GetCanChargeStatusResponseItem> {
|
): List<GetCanChargeStatusResponseItem> {
|
||||||
|
val zoneId = try {
|
||||||
|
ZoneId.of(timezone)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ZoneId.of("UTC")
|
||||||
|
}
|
||||||
|
|
||||||
return repository.getCanChargeStatus(member, pageable, container)
|
return repository.getCanChargeStatus(member, pageable, container)
|
||||||
.map {
|
.map {
|
||||||
val canTitle = it.title ?: ""
|
val canTitle = it.title ?: ""
|
||||||
@@ -170,9 +179,9 @@ class CanService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val createdAt = it.createdAt!!
|
val createdAt = (it.createdAt ?: it.updatedAt!!)
|
||||||
.atZone(ZoneId.of("UTC"))
|
.atZone(ZoneId.of("UTC"))
|
||||||
.withZoneSameInstant(ZoneId.of(timezone))
|
.withZoneSameInstant(zoneId)
|
||||||
|
|
||||||
GetCanChargeStatusResponseItem(
|
GetCanChargeStatusResponseItem(
|
||||||
canTitle = canTitle,
|
canTitle = canTitle,
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package kr.co.vividnext.sodalive.can
|
||||||
|
|
||||||
|
import com.querydsl.core.annotations.QueryProjection
|
||||||
|
import kr.co.vividnext.sodalive.can.use.CanUsage
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
data class UseCanQueryDto @QueryProjection constructor(
|
||||||
|
val canUsage: CanUsage,
|
||||||
|
val can: Int,
|
||||||
|
val rewardCan: Int,
|
||||||
|
val createdAt: LocalDateTime,
|
||||||
|
val roomMemberNickname: String?,
|
||||||
|
val roomTitle: String?,
|
||||||
|
val audioContentMemberNickname: String?,
|
||||||
|
val audioContentTitle: String?,
|
||||||
|
val communityPostMemberNickname: String?,
|
||||||
|
val auditionTitle: String?,
|
||||||
|
val characterName: String?,
|
||||||
|
val recipientCreatorNickname: String?
|
||||||
|
)
|
||||||
165
src/test/kotlin/kr/co/vividnext/sodalive/can/CanServiceTest.kt
Normal file
165
src/test/kotlin/kr/co/vividnext/sodalive/can/CanServiceTest.kt
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
package kr.co.vividnext.sodalive.can
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.can.use.CanUsage
|
||||||
|
import kr.co.vividnext.sodalive.common.CountryContext
|
||||||
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.mockito.Mockito.mock
|
||||||
|
import org.mockito.Mockito.`when`
|
||||||
|
import org.springframework.data.domain.PageRequest
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
class CanServiceTest {
|
||||||
|
private lateinit var repository: CanRepository
|
||||||
|
private lateinit var countryContext: CountryContext
|
||||||
|
private lateinit var service: CanService
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setUp() {
|
||||||
|
repository = mock(CanRepository::class.java)
|
||||||
|
countryContext = mock(CountryContext::class.java)
|
||||||
|
service = CanService(repository, countryContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("AOS 컨테이너에 대해 캔 사용 내역이 올바르게 필터링 및 맵핑되는지 확인한다")
|
||||||
|
fun `should filter can use status correctly for aos`() {
|
||||||
|
// given
|
||||||
|
val member = Member(nickname = "user1", password = "password")
|
||||||
|
member.id = 1L
|
||||||
|
val pageable = PageRequest.of(0, 10)
|
||||||
|
|
||||||
|
val useCanDto1 = createUseCanDto(CanUsage.HEART, 10, 0, "nick1", null)
|
||||||
|
val useCanDto2 = createUseCanDto(CanUsage.DONATION, 0, 5, "nick2", null)
|
||||||
|
|
||||||
|
`when`(repository.getCanUseStatus(member, pageable, "aos")).thenReturn(listOf(useCanDto1, useCanDto2))
|
||||||
|
|
||||||
|
// when
|
||||||
|
val result = service.getCanUseStatus(member, pageable, "Asia/Seoul", "aos")
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(2, result.size)
|
||||||
|
assertEquals("[라이브 후원] nick1", result[0].title)
|
||||||
|
assertEquals(10, result[0].can)
|
||||||
|
assertEquals("[라이브 후원] nick2", result[1].title)
|
||||||
|
assertEquals(5, result[1].can)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("iOS 컨테이너에 대해 캔 사용 내역이 올바르게 필터링 및 맵핑되는지 확인한다")
|
||||||
|
fun `should filter can use status correctly for ios`() {
|
||||||
|
// given
|
||||||
|
val member = Member(nickname = "user1", password = "password")
|
||||||
|
member.id = 1L
|
||||||
|
val pageable = PageRequest.of(0, 10)
|
||||||
|
|
||||||
|
val useCanDto1 = createUseCanDto(CanUsage.HEART, 10, 0, "nick1", null)
|
||||||
|
val useCanDto2 = createUseCanDto(CanUsage.DONATION, 10, 0, "nick2", null)
|
||||||
|
|
||||||
|
`when`(repository.getCanUseStatus(member, pageable, "ios")).thenReturn(listOf(useCanDto1, useCanDto2))
|
||||||
|
|
||||||
|
// when
|
||||||
|
val result = service.getCanUseStatus(member, pageable, "Asia/Seoul", "ios")
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(2, result.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("조회 결과가 없을 때 빈 리스트를 반환하는지 확인한다")
|
||||||
|
fun `should return empty list when no status exists`() {
|
||||||
|
// given
|
||||||
|
val member = Member(nickname = "user1", password = "password")
|
||||||
|
member.id = 1L
|
||||||
|
val pageable = PageRequest.of(0, 10)
|
||||||
|
|
||||||
|
`when`(repository.getCanUseStatus(member, pageable, "aos")).thenReturn(emptyList())
|
||||||
|
|
||||||
|
// when
|
||||||
|
val result = service.getCanUseStatus(member, pageable, "Asia/Seoul", "aos")
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(0, result.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("유효하지 않은 타임존 입력 시 UTC를 기본으로 사용한다")
|
||||||
|
fun `should use UTC when timezone is invalid`() {
|
||||||
|
// given
|
||||||
|
val member = Member(nickname = "user1", password = "password")
|
||||||
|
member.id = 1L
|
||||||
|
val pageable = PageRequest.of(0, 10)
|
||||||
|
val useCanDto = createUseCanDto(CanUsage.HEART, 10, 0)
|
||||||
|
|
||||||
|
`when`(repository.getCanUseStatus(member, pageable, "aos")).thenReturn(listOf(useCanDto))
|
||||||
|
|
||||||
|
// when
|
||||||
|
val result = service.getCanUseStatus(member, pageable, "Invalid/Timezone", "aos")
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals(1, result.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("다양한 CanUsage 및 null 필드에 대해 타이틀이 올바르게 포맷팅되는지 확인한다")
|
||||||
|
fun `should handle various can usage and nullable fields correctly`() {
|
||||||
|
// given
|
||||||
|
val member = Member(nickname = "user1", password = "password")
|
||||||
|
member.id = 1L
|
||||||
|
val pageable = PageRequest.of(0, 10)
|
||||||
|
|
||||||
|
val dtos = listOf(
|
||||||
|
createUseCanDto(CanUsage.HEART, 10, 0, roomMemberNickname = null, audioContentMemberNickname = null),
|
||||||
|
createUseCanDto(CanUsage.CHANNEL_DONATION, 10, 0, recipientCreatorNickname = null),
|
||||||
|
createUseCanDto(CanUsage.LIVE, 10, 0, roomMemberNickname = "creator1"),
|
||||||
|
createUseCanDto(CanUsage.LIVE, 10, 0),
|
||||||
|
createUseCanDto(CanUsage.CHANGE_NICKNAME, 10, 0),
|
||||||
|
createUseCanDto(CanUsage.CHAT_QUOTA_PURCHASE, 10, 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
`when`(repository.getCanUseStatus(member, pageable, "aos")).thenReturn(dtos)
|
||||||
|
|
||||||
|
// when
|
||||||
|
val result = service.getCanUseStatus(member, pageable, "Asia/Seoul", "aos")
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertEquals("[후원]", result[0].title)
|
||||||
|
assertEquals("[채널 후원]", result[1].title)
|
||||||
|
assertEquals("[라이브] creator1", result[2].title)
|
||||||
|
assertEquals("[라이브]", result[3].title)
|
||||||
|
assertEquals("닉네임 변경", result[4].title)
|
||||||
|
assertEquals("캐릭터 톡 이용권 구매", result[5].title)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createUseCanDto(
|
||||||
|
usage: CanUsage,
|
||||||
|
can: Int,
|
||||||
|
rewardCan: Int,
|
||||||
|
roomMemberNickname: String? = null,
|
||||||
|
recipientCreatorNickname: String? = null,
|
||||||
|
roomTitle: String? = null,
|
||||||
|
audioContentMemberNickname: String? = null,
|
||||||
|
audioContentTitle: String? = null,
|
||||||
|
communityPostMemberNickname: String? = null,
|
||||||
|
auditionTitle: String? = null,
|
||||||
|
characterName: String? = null
|
||||||
|
): UseCanQueryDto {
|
||||||
|
return UseCanQueryDto(
|
||||||
|
canUsage = usage,
|
||||||
|
can = can,
|
||||||
|
rewardCan = rewardCan,
|
||||||
|
createdAt = LocalDateTime.now(),
|
||||||
|
roomMemberNickname = roomMemberNickname,
|
||||||
|
roomTitle = roomTitle,
|
||||||
|
audioContentMemberNickname = audioContentMemberNickname,
|
||||||
|
audioContentTitle = audioContentTitle,
|
||||||
|
communityPostMemberNickname = communityPostMemberNickname,
|
||||||
|
auditionTitle = auditionTitle,
|
||||||
|
characterName = characterName,
|
||||||
|
recipientCreatorNickname = recipientCreatorNickname
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user