fix(calculate): 관리자 정산 크리에이터 식별자를 보정한다
This commit is contained in:
@@ -391,7 +391,7 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) {
|
||||
return queryFactory
|
||||
.select(
|
||||
QGetCalculateByCreatorQueryData(
|
||||
member.email,
|
||||
member.id,
|
||||
member.nickname,
|
||||
useCan.can.add(useCan.rewardCan).sum(),
|
||||
creatorSettlementRatio.liveSettlementRatio
|
||||
@@ -447,7 +447,7 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) {
|
||||
return queryFactory
|
||||
.select(
|
||||
QGetCalculateByCreatorQueryData(
|
||||
member.email,
|
||||
member.id,
|
||||
member.nickname,
|
||||
order.can.sum(),
|
||||
creatorSettlementRatio.contentSettlementRatio
|
||||
@@ -504,7 +504,7 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) {
|
||||
return queryFactory
|
||||
.select(
|
||||
QGetCalculateByCreatorQueryData(
|
||||
member.email,
|
||||
member.id,
|
||||
member.nickname,
|
||||
useCan.can.add(useCan.rewardCan).sum(),
|
||||
creatorSettlementRatio.communitySettlementRatio
|
||||
|
||||
@@ -474,7 +474,7 @@ class AdminCalculateService(
|
||||
return createExcelStream(
|
||||
sheetName = sheetName,
|
||||
headers = listOf(
|
||||
"이메일",
|
||||
"크리에이터 번호",
|
||||
"닉네임",
|
||||
"총 캔",
|
||||
"원화",
|
||||
@@ -486,7 +486,7 @@ class AdminCalculateService(
|
||||
) { sheet ->
|
||||
items.forEachIndexed { index, item ->
|
||||
val row = sheet.createRow(index + 1)
|
||||
row.createCell(0).setCellValue(item.email)
|
||||
row.createCell(0).setCellValue(item.creatorId.toDouble())
|
||||
row.createCell(1).setCellValue(item.nickname)
|
||||
row.createCell(2).setCellValue(item.totalCan.toDouble())
|
||||
row.createCell(3).setCellValue(item.totalKrw.toDouble())
|
||||
|
||||
@@ -3,7 +3,7 @@ package kr.co.vividnext.sodalive.admin.calculate
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
|
||||
data class GetCalculateByCreatorItem(
|
||||
@JsonProperty("email") val email: String,
|
||||
@JsonProperty("creatorId") val creatorId: Long,
|
||||
@JsonProperty("nickname") val nickname: String,
|
||||
@JsonProperty("totalCan") val totalCan: Int,
|
||||
@JsonProperty("totalKrw") val totalKrw: Int,
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.math.BigDecimal
|
||||
import java.math.RoundingMode
|
||||
|
||||
data class GetCalculateByCreatorQueryData @QueryProjection constructor(
|
||||
val email: String,
|
||||
val creatorId: Long,
|
||||
val nickname: String,
|
||||
val totalCan: Int,
|
||||
val settlementRatio: Int?
|
||||
@@ -31,7 +31,7 @@ data class GetCalculateByCreatorQueryData @QueryProjection constructor(
|
||||
val depositAmount = settlementAmount.subtract(tax)
|
||||
|
||||
return GetCalculateByCreatorItem(
|
||||
email = email,
|
||||
creatorId = creatorId,
|
||||
nickname = nickname,
|
||||
totalCan = totalCan,
|
||||
totalKrw = totalKrw.toInt(),
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
package kr.co.vividnext.sodalive.admin.calculate
|
||||
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||
import kr.co.vividnext.sodalive.can.use.CanUsage
|
||||
import kr.co.vividnext.sodalive.can.use.UseCan
|
||||
import kr.co.vividnext.sodalive.can.use.UseCanRepository
|
||||
import kr.co.vividnext.sodalive.configs.QueryDslConfig
|
||||
import kr.co.vividnext.sodalive.content.AudioContent
|
||||
import kr.co.vividnext.sodalive.content.AudioContentRepository
|
||||
import kr.co.vividnext.sodalive.content.order.Order
|
||||
import kr.co.vividnext.sodalive.content.order.OrderRepository
|
||||
import kr.co.vividnext.sodalive.content.order.OrderType
|
||||
import kr.co.vividnext.sodalive.content.theme.AudioContentTheme
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.CreatorCommunity
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.CreatorCommunityRepository
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoom
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoomRepository
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||
import kr.co.vividnext.sodalive.member.MemberRole
|
||||
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.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
|
||||
import org.springframework.context.annotation.Import
|
||||
import java.time.LocalDateTime
|
||||
import javax.persistence.EntityManager
|
||||
|
||||
@DataJpaTest(
|
||||
properties = [
|
||||
"spring.cache.type=none",
|
||||
"spring.jpa.database-platform=kr.co.vividnext.sodalive.support.H2MySqlFunctionDialect"
|
||||
]
|
||||
)
|
||||
@Import(QueryDslConfig::class)
|
||||
class AdminCalculateQueryRepositoryTest @Autowired constructor(
|
||||
private val queryFactory: JPAQueryFactory,
|
||||
private val memberRepository: MemberRepository,
|
||||
private val liveRoomRepository: LiveRoomRepository,
|
||||
private val audioContentRepository: AudioContentRepository,
|
||||
private val orderRepository: OrderRepository,
|
||||
private val creatorCommunityRepository: CreatorCommunityRepository,
|
||||
private val useCanRepository: UseCanRepository,
|
||||
private val entityManager: EntityManager
|
||||
) {
|
||||
private lateinit var repository: AdminCalculateQueryRepository
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
repository = AdminCalculateQueryRepository(queryFactory)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("이메일이 없는 크리에이터도 크리에이터별 정산에서 번호로 조회한다")
|
||||
fun shouldReturnCreatorIdForByCreatorRowsWhenCreatorEmailIsNull() {
|
||||
// given
|
||||
val creator = saveMember(email = null, nickname = "creator", role = MemberRole.CREATOR)
|
||||
val buyer = saveMember(email = "buyer@test.com", nickname = "buyer", role = MemberRole.USER)
|
||||
val createdAt = LocalDateTime.of(2026, 8, 4, 12, 0, 0)
|
||||
|
||||
val room = saveLiveRoom(creator)
|
||||
saveUseCan(buyer, CanUsage.LIVE, 10, createdAt) { this.room = room }
|
||||
|
||||
val content = saveAudioContent(creator)
|
||||
saveOrder(buyer, creator, content, createdAt)
|
||||
|
||||
val post = saveCommunityPost(creator)
|
||||
saveUseCan(buyer, CanUsage.PAID_COMMUNITY_POST, 30, createdAt) { communityPost = post }
|
||||
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val startDate = LocalDateTime.of(2026, 8, 4, 0, 0, 0)
|
||||
val endDate = LocalDateTime.of(2026, 8, 4, 23, 59, 59)
|
||||
|
||||
// when
|
||||
val liveRows = repository.getCalculateLiveByCreator(startDate, endDate, offset = 0, limit = 10)
|
||||
val contentRows = repository.getCalculateContentByCreator(startDate, endDate, offset = 0, limit = 10)
|
||||
val communityRows = repository.getCalculateCommunityByCreator(startDate, endDate, offset = 0, limit = 10)
|
||||
|
||||
// then
|
||||
assertEquals(listOf(creator.id), liveRows.map { it.creatorId })
|
||||
assertEquals(listOf(creator.id), contentRows.map { it.creatorId })
|
||||
assertEquals(listOf(creator.id), communityRows.map { it.creatorId })
|
||||
}
|
||||
|
||||
private fun saveMember(email: String?, nickname: String, role: MemberRole): Member {
|
||||
return memberRepository.saveAndFlush(
|
||||
Member(
|
||||
email = email,
|
||||
password = "password",
|
||||
nickname = nickname,
|
||||
role = role
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun saveLiveRoom(creator: Member): LiveRoom {
|
||||
val room = LiveRoom(
|
||||
title = "live-room",
|
||||
notice = "notice",
|
||||
beginDateTime = LocalDateTime.of(2026, 8, 4, 8, 0, 0),
|
||||
numberOfPeople = 1,
|
||||
isAdult = false,
|
||||
price = 10
|
||||
)
|
||||
room.member = creator
|
||||
return liveRoomRepository.saveAndFlush(room)
|
||||
}
|
||||
|
||||
private fun saveAudioContent(creator: Member): AudioContent {
|
||||
val theme = AudioContentTheme(theme = "theme", image = "theme.png")
|
||||
entityManager.persist(theme)
|
||||
|
||||
val content = AudioContent(
|
||||
title = "content",
|
||||
detail = "detail",
|
||||
languageCode = "ko",
|
||||
price = 20
|
||||
)
|
||||
content.theme = theme
|
||||
content.member = creator
|
||||
content.isActive = true
|
||||
return audioContentRepository.saveAndFlush(content)
|
||||
}
|
||||
|
||||
private fun saveOrder(buyer: Member, creator: Member, content: AudioContent, createdAt: LocalDateTime) {
|
||||
val order = Order(type = OrderType.KEEP)
|
||||
order.member = buyer
|
||||
order.creator = creator
|
||||
order.audioContent = content
|
||||
val saved = orderRepository.saveAndFlush(order)
|
||||
updateCreatedAt("Order", saved.id!!, createdAt)
|
||||
}
|
||||
|
||||
private fun saveCommunityPost(creator: Member): CreatorCommunity {
|
||||
val post = CreatorCommunity(
|
||||
content = "community-content",
|
||||
price = 30,
|
||||
isCommentAvailable = true,
|
||||
isAdult = false
|
||||
)
|
||||
post.member = creator
|
||||
return creatorCommunityRepository.saveAndFlush(post)
|
||||
}
|
||||
|
||||
private fun saveUseCan(
|
||||
member: Member,
|
||||
usage: CanUsage,
|
||||
can: Int,
|
||||
createdAt: LocalDateTime,
|
||||
configure: UseCan.() -> Unit
|
||||
) {
|
||||
val useCan = UseCan(canUsage = usage, can = can, rewardCan = 0)
|
||||
useCan.member = member
|
||||
useCan.configure()
|
||||
val saved = useCanRepository.saveAndFlush(useCan)
|
||||
updateCreatedAt("UseCan", saved.id!!, createdAt)
|
||||
}
|
||||
|
||||
private fun updateCreatedAt(entityName: String, id: Long, createdAt: LocalDateTime) {
|
||||
entityManager.createQuery("update $entityName e set e.createdAt = :createdAt where e.id = :id")
|
||||
.setParameter("createdAt", createdAt)
|
||||
.setParameter("id", id)
|
||||
.executeUpdate()
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,13 @@ import kr.co.vividnext.sodalive.can.use.UseCanCalculate
|
||||
import kr.co.vividnext.sodalive.can.use.UseCanCalculateRepository
|
||||
import kr.co.vividnext.sodalive.can.use.UseCanCalculateStatus
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.extensions.convertLocalDateTime
|
||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
import kr.co.vividnext.sodalive.i18n.SodaMessageSource
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoom
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoomRepository
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
@@ -24,6 +26,8 @@ import org.mockito.Mockito.atLeastOnce
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.`when`
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.util.Optional
|
||||
|
||||
class AdminCalculateServiceTest {
|
||||
@@ -45,6 +49,35 @@ class AdminCalculateServiceTest {
|
||||
langContext
|
||||
)
|
||||
|
||||
@Test
|
||||
@DisplayName("크리에이터별 정산 엑셀은 이메일 대신 크리에이터 번호를 출력한다")
|
||||
fun shouldWriteCreatorIdInsteadOfEmailToCreatorSettlementExcel() {
|
||||
// given
|
||||
val startDate = "2026-08-04".convertLocalDateTime()
|
||||
val endDate = "2026-08-04".convertLocalDateTime(hour = 23, minute = 59, second = 59)
|
||||
val queryData = GetCalculateByCreatorQueryData(
|
||||
creatorId = 42L,
|
||||
nickname = "creator",
|
||||
totalCan = 100,
|
||||
settlementRatio = 70
|
||||
)
|
||||
|
||||
`when`(repository.getCalculateLiveByCreatorTotalCount(startDate, endDate)).thenReturn(1)
|
||||
`when`(repository.getCalculateLiveByCreator(startDate, endDate, 0L, 1L)).thenReturn(listOf(queryData))
|
||||
|
||||
// when
|
||||
val output = ByteArrayOutputStream()
|
||||
adminCalculateService.downloadCalculateLiveByCreatorExcel("2026-08-04", "2026-08-04").writeTo(output)
|
||||
|
||||
// then
|
||||
XSSFWorkbook(ByteArrayInputStream(output.toByteArray())).use { workbook ->
|
||||
val sheet = workbook.getSheetAt(0)
|
||||
assertEquals("크리에이터 번호", sheet.getRow(0).getCell(0).stringCellValue)
|
||||
assertEquals(42.0, sheet.getRow(1).getCell(0).numericCellValue)
|
||||
assertEquals("닉네임", sheet.getRow(0).getCell(1).stringCellValue)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("라이브 환불 성공 테스트")
|
||||
fun shouldRefundLiveSuccessfully() {
|
||||
|
||||
Reference in New Issue
Block a user