feat(channel-donation-calculate): 채널 후원 정산 조회 기능을 추가한다
This commit is contained in:
+68
@@ -0,0 +1,68 @@
|
||||
package kr.co.vividnext.sodalive.admin.calculate.channelDonation
|
||||
|
||||
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
|
||||
import org.springframework.data.domain.PageRequest
|
||||
|
||||
class AdminChannelDonationCalculateControllerTest {
|
||||
private lateinit var service: AdminChannelDonationCalculateService
|
||||
private lateinit var controller: AdminChannelDonationCalculateController
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
service = Mockito.mock(AdminChannelDonationCalculateService::class.java)
|
||||
controller = AdminChannelDonationCalculateController(service)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("관리자 컨트롤러는 날짜/페이지 파라미터를 서비스로 전달한다")
|
||||
fun shouldForwardDateRangeAndPageableToService() {
|
||||
val response = GetAdminChannelDonationSettlementResponse(
|
||||
totalCount = 1,
|
||||
items = listOf(
|
||||
GetAdminChannelDonationSettlementItem(
|
||||
date = "2026-02-26",
|
||||
creator = "creator-a",
|
||||
count = 2,
|
||||
totalCan = 20,
|
||||
krw = 2000,
|
||||
fee = 132,
|
||||
settlementAmount = 1588,
|
||||
withholdingTax = 52,
|
||||
depositAmount = 1536
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Mockito.`when`(
|
||||
service.getChannelDonationByCreator(
|
||||
startDateStr = "2026-02-20",
|
||||
endDateStr = "2026-02-21",
|
||||
offset = 15L,
|
||||
limit = 15L
|
||||
)
|
||||
).thenReturn(response)
|
||||
|
||||
val apiResponse = controller.getChannelDonationByCreator(
|
||||
startDateStr = "2026-02-20",
|
||||
endDateStr = "2026-02-21",
|
||||
pageable = PageRequest.of(1, 15)
|
||||
)
|
||||
|
||||
assertEquals(true, apiResponse.success)
|
||||
assertEquals(1, apiResponse.data!!.totalCount)
|
||||
assertEquals("creator-a", apiResponse.data!!.items[0].creator)
|
||||
assertEquals(2, apiResponse.data!!.items[0].count)
|
||||
assertEquals(20, apiResponse.data!!.items[0].totalCan)
|
||||
|
||||
Mockito.verify(service).getChannelDonationByCreator(
|
||||
startDateStr = "2026-02-20",
|
||||
endDateStr = "2026-02-21",
|
||||
offset = 15L,
|
||||
limit = 15L
|
||||
)
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
package kr.co.vividnext.sodalive.admin.calculate.channelDonation
|
||||
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||
import kr.co.vividnext.sodalive.can.payment.PaymentGateway
|
||||
import kr.co.vividnext.sodalive.can.use.CanUsage
|
||||
import kr.co.vividnext.sodalive.can.use.UseCan
|
||||
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.can.use.UseCanRepository
|
||||
import kr.co.vividnext.sodalive.configs.QueryDslConfig
|
||||
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.jpa.database-platform=kr.co.vividnext.sodalive.support.H2MySqlFunctionDialect"])
|
||||
@Import(QueryDslConfig::class)
|
||||
class AdminChannelDonationCalculateQueryRepositoryTest @Autowired constructor(
|
||||
private val queryFactory: JPAQueryFactory,
|
||||
private val memberRepository: MemberRepository,
|
||||
private val useCanRepository: UseCanRepository,
|
||||
private val useCanCalculateRepository: UseCanCalculateRepository,
|
||||
private val entityManager: EntityManager
|
||||
) {
|
||||
private lateinit var repository: AdminChannelDonationCalculateQueryRepository
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
registerMysqlDateFunctions()
|
||||
repository = AdminChannelDonationCalculateQueryRepository(queryFactory)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("동일 후원의 분할 정산 레코드는 건수를 중복 집계하지 않는다")
|
||||
fun shouldCountDistinctUseCanWhenDonationIsSplitAcrossCalculations() {
|
||||
val creator = saveMember(nickname = "creator-admin", role = MemberRole.CREATOR)
|
||||
val sender = saveMember(nickname = "sender-admin", role = MemberRole.USER)
|
||||
val useCan = saveUseCan(member = sender, can = 50, rewardCan = 0)
|
||||
|
||||
saveUseCanCalculate(
|
||||
useCan = useCan,
|
||||
recipientCreatorId = creator.id!!,
|
||||
can = 20,
|
||||
paymentGateway = PaymentGateway.PG
|
||||
)
|
||||
saveUseCanCalculate(
|
||||
useCan = useCan,
|
||||
recipientCreatorId = creator.id!!,
|
||||
can = 30,
|
||||
paymentGateway = PaymentGateway.GOOGLE_IAP
|
||||
)
|
||||
updateUseCanCreatedAt(useCan.id!!, LocalDateTime.of(2026, 2, 20, 12, 0, 0))
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val startDate = LocalDateTime.of(2026, 2, 20, 0, 0, 0)
|
||||
val endDate = LocalDateTime.of(2026, 2, 20, 23, 59, 59)
|
||||
|
||||
val totalCount = repository.getChannelDonationByCreatorTotalCount(startDate, endDate)
|
||||
val items = repository.getChannelDonationByCreator(startDate, endDate, offset = 0, limit = 20)
|
||||
|
||||
assertEquals(1, totalCount)
|
||||
assertEquals(1, items.size)
|
||||
assertEquals("2026-02-20", items[0].date)
|
||||
assertEquals("creator-admin", items[0].creator)
|
||||
assertEquals(1L, items[0].count)
|
||||
assertEquals(50, items[0].totalCan)
|
||||
}
|
||||
|
||||
private fun saveMember(nickname: String, role: MemberRole): Member {
|
||||
return memberRepository.saveAndFlush(
|
||||
Member(
|
||||
email = "$nickname@test.com",
|
||||
password = "password",
|
||||
nickname = nickname,
|
||||
role = role
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun saveUseCan(member: Member, can: Int, rewardCan: Int): UseCan {
|
||||
val useCan = UseCan(
|
||||
canUsage = CanUsage.CHANNEL_DONATION,
|
||||
can = can,
|
||||
rewardCan = rewardCan
|
||||
)
|
||||
useCan.member = member
|
||||
return useCanRepository.saveAndFlush(useCan)
|
||||
}
|
||||
|
||||
private fun saveUseCanCalculate(useCan: UseCan, recipientCreatorId: Long, can: Int, paymentGateway: PaymentGateway) {
|
||||
val useCanCalculate = UseCanCalculate(
|
||||
can = can,
|
||||
paymentGateway = paymentGateway,
|
||||
status = UseCanCalculateStatus.RECEIVED
|
||||
)
|
||||
useCanCalculate.useCan = useCan
|
||||
useCanCalculate.recipientCreatorId = recipientCreatorId
|
||||
useCanCalculateRepository.saveAndFlush(useCanCalculate)
|
||||
}
|
||||
|
||||
private fun updateUseCanCreatedAt(useCanId: Long, createdAt: LocalDateTime) {
|
||||
entityManager.createQuery("update UseCan u set u.createdAt = :createdAt where u.id = :id")
|
||||
.setParameter("createdAt", createdAt)
|
||||
.setParameter("id", useCanId)
|
||||
.executeUpdate()
|
||||
}
|
||||
|
||||
private fun registerMysqlDateFunctions() {
|
||||
entityManager.createNativeQuery(
|
||||
"CREATE ALIAS IF NOT EXISTS DATE_FORMAT FOR 'kr.co.vividnext.sodalive.support.H2MysqlDateFunctions.dateFormat'"
|
||||
).executeUpdate()
|
||||
entityManager.createNativeQuery(
|
||||
"CREATE ALIAS IF NOT EXISTS CONVERT_TZ FOR 'kr.co.vividnext.sodalive.support.H2MysqlDateFunctions.convertTz'"
|
||||
).executeUpdate()
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
package kr.co.vividnext.sodalive.admin.calculate.channelDonation
|
||||
|
||||
import kr.co.vividnext.sodalive.extensions.convertLocalDateTime
|
||||
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
|
||||
|
||||
class AdminChannelDonationCalculateServiceTest {
|
||||
private lateinit var repository: AdminChannelDonationCalculateQueryRepository
|
||||
private lateinit var service: AdminChannelDonationCalculateService
|
||||
|
||||
@BeforeEach
|
||||
fun setup() {
|
||||
repository = Mockito.mock(AdminChannelDonationCalculateQueryRepository::class.java)
|
||||
service = AdminChannelDonationCalculateService(repository)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("관리자 정산 조회는 날짜 범위를 변환하고 크리에이터 그룹 응답을 반환한다")
|
||||
fun shouldConvertDateRangeAndReturnCreatorGroupedItems() {
|
||||
val queryData = GetAdminChannelDonationSettlementQueryData(
|
||||
date = "2026-02-26",
|
||||
creator = "creator-a",
|
||||
count = 3L,
|
||||
totalCan = 100
|
||||
)
|
||||
|
||||
Mockito.`when`(
|
||||
repository.getChannelDonationByCreatorTotalCount(
|
||||
"2026-02-20".convertLocalDateTime(),
|
||||
"2026-02-21".convertLocalDateTime(hour = 23, minute = 59, second = 59)
|
||||
)
|
||||
).thenReturn(1)
|
||||
Mockito.`when`(
|
||||
repository.getChannelDonationByCreator(
|
||||
"2026-02-20".convertLocalDateTime(),
|
||||
"2026-02-21".convertLocalDateTime(hour = 23, minute = 59, second = 59),
|
||||
0L,
|
||||
20L
|
||||
)
|
||||
).thenReturn(listOf(queryData))
|
||||
|
||||
val result = service.getChannelDonationByCreator(
|
||||
startDateStr = "2026-02-20",
|
||||
endDateStr = "2026-02-21",
|
||||
offset = 0,
|
||||
limit = 20
|
||||
)
|
||||
|
||||
assertEquals(1, result.totalCount)
|
||||
assertEquals(1, result.items.size)
|
||||
assertEquals("2026-02-26", result.items[0].date)
|
||||
assertEquals("creator-a", result.items[0].creator)
|
||||
assertEquals(3, result.items[0].count)
|
||||
assertEquals(100, result.items[0].totalCan)
|
||||
assertEquals(10_000, result.items[0].krw)
|
||||
assertEquals(660, result.items[0].fee)
|
||||
|
||||
Mockito.verify(repository).getChannelDonationByCreatorTotalCount(
|
||||
"2026-02-20".convertLocalDateTime(),
|
||||
"2026-02-21".convertLocalDateTime(hour = 23, minute = 59, second = 59)
|
||||
)
|
||||
Mockito.verify(repository).getChannelDonationByCreator(
|
||||
"2026-02-20".convertLocalDateTime(),
|
||||
"2026-02-21".convertLocalDateTime(hour = 23, minute = 59, second = 59),
|
||||
0L,
|
||||
20L
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user