From 0b615695221df14530dbdecc37f65d60e5d88ccf Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 10 Apr 2026 13:51:28 +0900 Subject: [PATCH] =?UTF-8?q?fix(agent-calculate):=20=EC=A0=95=EC=82=B0=20?= =?UTF-8?q?=ED=95=A9=EA=B3=84=20=EA=B3=84=EC=82=B0=20=EA=B2=BD=EB=A1=9C?= =?UTF-8?q?=EC=99=80=20=ED=9A=8C=EA=B7=80=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EB=A5=BC=20=EB=B3=B4=EA=B0=95=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent/calculate/AgentCalculateService.kt | 1 - ...tAgentCreatorSettlementSummaryQueryData.kt | 27 +++ .../calculate/AgentCalculateServiceTest.kt | 163 ++++++++++++++++++ 3 files changed, 190 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateService.kt index 9e0712f4..b50d2ca4 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateService.kt @@ -199,7 +199,6 @@ class AgentCalculateService( val totalCount = totalCountLoader(startDate, endDate) val total = totalRowsLoader(startDate, endDate) - .toMergedResponseItems() .toResponseTotal() val items = pagedRowsLoader(startDate, endDate) .toMergedResponseItems() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/GetAgentCreatorSettlementSummaryQueryData.kt b/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/GetAgentCreatorSettlementSummaryQueryData.kt index 13b32e65..e90fc1d2 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/GetAgentCreatorSettlementSummaryQueryData.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/GetAgentCreatorSettlementSummaryQueryData.kt @@ -75,3 +75,30 @@ fun List.toMergedResponseItems(): Lis } } } + +fun List.toResponseTotal(): GetAgentSettlementByCreatorTotal { + return fold( + GetAgentSettlementByCreatorTotal( + count = 0, + totalCan = 0, + krw = 0, + fee = 0, + settlementAmount = 0, + tax = 0, + depositAmount = 0, + agentSettlementAmount = 0 + ) + ) { total, row -> + val item = row.toResponseItem() + total.copy( + count = total.count + item.count, + totalCan = total.totalCan + item.totalCan, + krw = total.krw + item.krw, + fee = total.fee + item.fee, + settlementAmount = total.settlementAmount + item.settlementAmount, + tax = total.tax + item.tax, + depositAmount = total.depositAmount + item.depositAmount, + agentSettlementAmount = total.agentSettlementAmount + item.agentSettlementAmount + ) + } +} diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateServiceTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateServiceTest.kt index 49529aa9..1cfdd74a 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateServiceTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateServiceTest.kt @@ -597,6 +597,169 @@ class AgentCalculateServiceTest { Mockito.verifyNoInteractions(repository) } + @Test + @DisplayName("에이전트 서비스는 generic 정산 결과가 없으면 total 0과 빈 items를 반환한다") + fun shouldReturnEmptyGenericSettlementResponseWhenNoRowsExist() { + val startDate = "2026-02-20".convertLocalDateTime() + val endDate = "2026-02-21".convertLocalDateTime(hour = 23, minute = 59, second = 59) + + Mockito.`when`(repository.getCalculateLiveByCreatorTotalCount(startDate, endDate, 7L)).thenReturn(0) + Mockito.`when`(repository.getCalculateLiveByCreator(startDate, endDate, 7L)).thenReturn(emptyList()) + Mockito.`when`(repository.getCalculateLiveByCreator(startDate, endDate, 7L, 0L, 20L)).thenReturn(emptyList()) + + val response = service.getCalculateLiveByCreator("2026-02-20", "2026-02-21", 7L, 0L, 20L) + + assertEquals(0, response.totalCount) + assertEquals(0, response.total.count) + assertEquals(0, response.total.totalCan) + assertEquals(0, response.total.krw) + assertEquals(0, response.total.fee) + assertEquals(0, response.total.settlementAmount) + assertEquals(0, response.total.tax) + assertEquals(0, response.total.depositAmount) + assertEquals(0, response.total.agentSettlementAmount) + assertEquals(emptyList(), response.items) + } + + @Test + @DisplayName("에이전트 서비스는 채널후원 결과가 없으면 total 0과 빈 items를 반환한다") + fun shouldReturnEmptyChannelDonationSettlementResponseWhenNoRowsExist() { + val startDate = "2026-02-20".convertLocalDateTime() + val endDate = "2026-02-21".convertLocalDateTime(hour = 23, minute = 59, second = 59) + + Mockito.`when`(repository.getChannelDonationByCreatorTotalCount(startDate, endDate, 7L)).thenReturn(0) + Mockito.`when`(repository.getChannelDonationByCreator(startDate, endDate, 7L)).thenReturn(emptyList()) + Mockito.`when`(repository.getChannelDonationByCreator(startDate, endDate, 7L, 0L, 20L)).thenReturn(emptyList()) + + val response = service.getChannelDonationByCreator("2026-02-20", "2026-02-21", 7L, 0L, 20L) + + assertEquals(0, response.totalCount) + assertEquals(0, response.total.count) + assertEquals(0, response.total.totalCan) + assertEquals(0, response.total.krw) + assertEquals(0, response.total.fee) + assertEquals(0, response.total.settlementAmount) + assertEquals(0, response.total.withholdingTax) + assertEquals(0, response.total.depositAmount) + assertEquals(0, response.total.agentSettlementAmount) + assertEquals(emptyList(), response.items) + } + + @Test + @DisplayName("에이전트 서비스는 finalized snapshot을 creatorId desc 순서로 페이지 조회한다") + fun shouldPageFinalizedSnapshotsByCreatorIdDesc() { + val startDate = "2026-02-20".convertLocalDateTime() + val endDate = "2026-02-21".convertLocalDateTime(hour = 23, minute = 59, second = 59) + + Mockito.`when`( + snapshotRepository.findAllByPeriodStartAndPeriodEndAndSettlementTypeAndAgentIdOrderByCreatorIdDesc( + startDate, + endDate, + AgentSettlementSnapshotType.LIVE, + 7L + ) + ).thenReturn( + listOf( + createSnapshot( + settlementType = AgentSettlementSnapshotType.LIVE, + count = 3, + totalCan = 300, + krw = 30_000, + fee = 1_980, + settlementAmount = 19_614, + tax = 647, + depositAmount = 18_967, + agentSettlementAmount = 1_961, + appliedAgentSettlementRatio = 10 + ).also { it.creatorId = 31L; it.creatorNickname = "creator-c" }, + createSnapshot( + settlementType = AgentSettlementSnapshotType.LIVE, + count = 2, + totalCan = 200, + krw = 20_000, + fee = 1_320, + settlementAmount = 13_076, + tax = 431, + depositAmount = 12_645, + agentSettlementAmount = 1_308, + appliedAgentSettlementRatio = 10 + ).also { it.creatorId = 21L; it.creatorNickname = "creator-b" }, + createSnapshot( + settlementType = AgentSettlementSnapshotType.LIVE, + count = 1, + totalCan = 100, + krw = 10_000, + fee = 660, + settlementAmount = 6_538, + tax = 216, + depositAmount = 6_322, + agentSettlementAmount = 654, + appliedAgentSettlementRatio = 10 + ).also { it.creatorId = 11L; it.creatorNickname = "creator-a" } + ) + ) + + val response = service.getCalculateLiveByCreator("2026-02-20", "2026-02-21", 7L, 1L, 1L) + + assertEquals(3, response.totalCount) + assertEquals(1, response.items.size) + assertEquals(21L, response.items[0].creatorId) + assertEquals("creator-b", response.items[0].creatorNickname) + Mockito.verifyNoInteractions(repository) + } + + @Test + @DisplayName("finalized 이후 live 데이터가 바뀌어도 동일 기간 응답은 snapshot 값을 유지한다") + fun shouldKeepUsingFinalizedSnapshotAfterLiveDataChanges() { + val startDate = "2026-02-20".convertLocalDateTime() + val endDate = "2026-02-21".convertLocalDateTime(hour = 23, minute = 59, second = 59) + + Mockito.`when`( + snapshotRepository.findAllByPeriodStartAndPeriodEndAndSettlementTypeAndAgentIdOrderByCreatorIdDesc( + startDate, + endDate, + AgentSettlementSnapshotType.LIVE, + 7L + ) + ).thenReturn( + listOf( + createSnapshot( + settlementType = AgentSettlementSnapshotType.LIVE, + count = 2, + totalCan = 100, + krw = 10_000, + fee = 660, + settlementAmount = 6_538, + tax = 216, + depositAmount = 6_322, + agentSettlementAmount = 654, + appliedAgentSettlementRatio = 10 + ) + ) + ) + Mockito.`when`(repository.getCalculateLiveByCreatorTotalCount(startDate, endDate, 7L)).thenReturn(99) + Mockito.`when`(repository.getCalculateLiveByCreator(startDate, endDate, 7L)).thenReturn( + listOf( + GetAgentCreatorSettlementSummaryQueryData( + creatorId = 88L, + creatorNickname = "changed-live", + count = 10L, + totalCan = 999, + settlementRatio = 50, + agentSettlementRatio = 30 + ) + ) + ) + + val response = service.getCalculateLiveByCreator("2026-02-20", "2026-02-21", 7L, 0L, 20L) + + assertEquals(1, response.totalCount) + assertEquals(21L, response.items[0].creatorId) + assertEquals(100, response.total.totalCan) + assertEquals(654, response.total.agentSettlementAmount) + Mockito.verifyNoInteractions(repository) + } + private fun createSnapshot( settlementType: AgentSettlementSnapshotType, count: Int,