diff --git a/docs/20260415_에이전트정산기본비율7퍼센트변경.md b/docs/20260415_에이전트정산기본비율7퍼센트변경.md new file mode 100644 index 00000000..a2a44e2d --- /dev/null +++ b/docs/20260415_에이전트정산기본비율7퍼센트변경.md @@ -0,0 +1,18 @@ +# 에이전트 정산 기본 비율 7퍼센트 변경 계획 + +- [x] `AgentCalculateQueryRepository`의 agent settlement fallback 10 적용 지점을 확인하고 7로 변경한다. +- [x] Kotlin 응답 계산 모델의 agent settlement fallback 10 상수를 7로 변경해 DB 집계와 계산 로직을 일치시킨다. +- [x] 기본 fallback 10을 전제한 관련 테스트 기대값을 7 기준으로 수정한다. +- [x] 관련 테스트와 진단을 실행하고 결과를 문서 하단 검증 기록에 누적한다. + +## 검증 기록 + +- 1차 구현 + - 무엇을: 에이전트 정산 비율 미설정 시 적용되는 기본 fallback 값을 `10%`에서 `7%`로 변경했다. `AgentCalculateQueryRepository`의 native SQL `COALESCE(asr.settlement_ratio, ...)`와 Kotlin 계산 모델 두 곳의 `DEFAULT_AGENT_SETTLEMENT_RATIO`를 함께 조정하고, 관련 테스트 기대값을 7% 기준으로 갱신했다. + - 왜: 현재 에이전트 정산 기본 비율 정책이 10%가 아니라 7%여야 하므로, DB 집계 결과와 Kotlin 응답 계산 결과가 동일한 기본값을 사용하도록 맞춰야 한다. + - 어떻게: + - `./gradlew test --tests kr.co.vividnext.sodalive.partner.agent.calculate.AgentCalculateServiceTest --tests kr.co.vividnext.sodalive.partner.agent.calculate.AgentCalculateQueryRepositoryTest` → 실패. 7% 기준으로 먼저 바꾼 테스트가 기존 10% fallback 구현 때문에 깨지는 것을 확인했다. + - `./gradlew test --tests kr.co.vividnext.sodalive.partner.agent.calculate.AgentCalculateServiceTest --tests kr.co.vividnext.sodalive.partner.agent.calculate.AgentCalculateQueryRepositoryTest --tests kr.co.vividnext.sodalive.admin.partner.agent.read.AdminAgentReadCurrentMonthListSummaryTest` → 성공. + - `./gradlew ktlintCheck` → 성공. + - `./gradlew build` → 성공. + - `src/main/kotlin`에서 `COALESCE(asr.settlement_ratio, 10)` 및 `DEFAULT_AGENT_SETTLEMENT_RATIO = 10` 검색 → 미검출. diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateQueryRepository.kt index ba9d4316..710af214 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateQueryRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateQueryRepository.kt @@ -435,7 +435,7 @@ class AgentCalculateQueryRepository( SELECT COUNT(DISTINCT uc.id) AS count_value, SUM(ucc.can) AS total_can, - COALESCE(asr.settlement_ratio, 10) AS agent_settlement_ratio + COALESCE(asr.settlement_ratio, 7) AS agent_settlement_ratio FROM use_can_calculate ucc INNER JOIN use_can uc ON ucc.use_can_id = uc.id INNER JOIN member m ON m.id = ucc.recipient_creator_id @@ -451,7 +451,7 @@ class AgentCalculateQueryRepository( AND ucc.status = 'RECEIVED' AND uc.created_at >= :startDate AND uc.created_at <= :endDate - GROUP BY acr.id, asr.id, COALESCE(asr.settlement_ratio, 10) + GROUP BY acr.id, asr.id, COALESCE(asr.settlement_ratio, 7) ) grouped """.trimIndent() ) @@ -812,7 +812,7 @@ class AgentCalculateQueryRepository( COUNT(uc.id) AS count_value, SUM(uc.can + uc.reward_can) AS total_can, COALESCE(csr.live_settlement_ratio, 70) AS settlement_ratio, - COALESCE(asr.settlement_ratio, 10) AS agent_settlement_ratio + COALESCE(asr.settlement_ratio, 7) AS agent_settlement_ratio FROM use_can uc INNER JOIN live_room lr ON uc.room_id = lr.id INNER JOIN member m ON lr.member_id = m.id @@ -828,7 +828,7 @@ class AgentCalculateQueryRepository( WHERE uc.is_refund = FALSE AND uc.created_at >= :startDate AND uc.created_at <= :endDate - GROUP BY acr.id, asr.id, COALESCE(csr.live_settlement_ratio, 70), COALESCE(asr.settlement_ratio, 10) + GROUP BY acr.id, asr.id, COALESCE(csr.live_settlement_ratio, 70), COALESCE(asr.settlement_ratio, 7) """.trimIndent() private fun buildContentSettlementTotalSubQuery() = """ @@ -836,7 +836,7 @@ class AgentCalculateQueryRepository( COUNT(o.id) AS count_value, SUM(o.can) AS total_can, COALESCE(COALESCE(c.settlement_ratio, csr.content_settlement_ratio), 70) AS settlement_ratio, - COALESCE(asr.settlement_ratio, 10) AS agent_settlement_ratio + COALESCE(asr.settlement_ratio, 7) AS agent_settlement_ratio FROM orders o INNER JOIN content c ON o.content_id = c.id INNER JOIN member m ON c.member_id = m.id @@ -857,7 +857,7 @@ class AgentCalculateQueryRepository( asr.id, COALESCE(c.settlement_ratio, csr.content_settlement_ratio), COALESCE(COALESCE(c.settlement_ratio, csr.content_settlement_ratio), 70), - COALESCE(asr.settlement_ratio, 10) + COALESCE(asr.settlement_ratio, 7) """.trimIndent() private fun buildCommunitySettlementTotalSubQuery() = """ @@ -865,7 +865,7 @@ class AgentCalculateQueryRepository( COUNT(uc.id) AS count_value, SUM(uc.can + uc.reward_can) AS total_can, COALESCE(csr.community_settlement_ratio, 70) AS settlement_ratio, - COALESCE(asr.settlement_ratio, 10) AS agent_settlement_ratio + COALESCE(asr.settlement_ratio, 7) AS agent_settlement_ratio FROM use_can uc INNER JOIN creator_community cc ON uc.creator_community_id = cc.id INNER JOIN member m ON cc.member_id = m.id @@ -882,7 +882,7 @@ class AgentCalculateQueryRepository( AND uc.can_usage = 'PAID_COMMUNITY_POST' AND uc.created_at >= :startDate AND uc.created_at <= :endDate - GROUP BY acr.id, asr.id, COALESCE(csr.community_settlement_ratio, 70), COALESCE(asr.settlement_ratio, 10) + GROUP BY acr.id, asr.id, COALESCE(csr.community_settlement_ratio, 70), COALESCE(asr.settlement_ratio, 7) """.trimIndent() private fun buildContentDonationSettlementTotalSubQuery() = """ @@ -890,7 +890,7 @@ class AgentCalculateQueryRepository( COUNT(uc.id) AS count_value, SUM(uc.can + uc.reward_can) AS total_can, 70 AS settlement_ratio, - COALESCE(asr.settlement_ratio, 10) AS agent_settlement_ratio + COALESCE(asr.settlement_ratio, 7) AS agent_settlement_ratio FROM use_can uc INNER JOIN content c ON uc.content_id = c.id INNER JOIN member m ON c.member_id = m.id @@ -905,7 +905,7 @@ class AgentCalculateQueryRepository( AND uc.can_usage = 'DONATION' AND uc.created_at >= :startDate AND uc.created_at <= :endDate - GROUP BY acr.id, asr.id, COALESCE(asr.settlement_ratio, 10) + GROUP BY acr.id, asr.id, COALESCE(asr.settlement_ratio, 7) """.trimIndent() private fun Any?.toIntValue(): Int { diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/GetAgentChannelDonationSettlementByCreatorResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/GetAgentChannelDonationSettlementByCreatorResponse.kt index 53fde8e5..a42c4c19 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/GetAgentChannelDonationSettlementByCreatorResponse.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/GetAgentChannelDonationSettlementByCreatorResponse.kt @@ -64,7 +64,7 @@ data class GetAgentChannelDonationSettlementByCreatorQueryData @QueryProjection } companion object { - private const val DEFAULT_AGENT_SETTLEMENT_RATIO = 10 + private const val DEFAULT_AGENT_SETTLEMENT_RATIO = 7 } } 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 e90fc1d2..777f4cea 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 @@ -46,7 +46,7 @@ data class GetAgentCreatorSettlementSummaryQueryData @QueryProjection constructo private val TAX_RATE = BigDecimal("0.033") private val PERCENT_DIVISOR = BigDecimal("100") private const val DEFAULT_SETTLEMENT_RATIO = 70 - private const val DEFAULT_AGENT_SETTLEMENT_RATIO = 10 + private const val DEFAULT_AGENT_SETTLEMENT_RATIO = 7 private fun calculateAgentSettlementAmount(settlementAmount: Int, agentSettlementRatio: Int): Int { return BigDecimal(settlementAmount) diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateQueryRepositoryTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateQueryRepositoryTest.kt index 1637ff6a..d6ec2fea 100644 --- a/src/test/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateQueryRepositoryTest.kt +++ b/src/test/kotlin/kr/co/vividnext/sodalive/partner/agent/calculate/AgentCalculateQueryRepositoryTest.kt @@ -380,6 +380,54 @@ class AgentCalculateQueryRepositoryTest @Autowired constructor( assertEquals(kotlinTotal, dbTotal) } + @Test + @DisplayName("에이전트 비율 이력이 없으면 콘텐츠 후원 응답은 7퍼센트 기본값으로 agent 정산금을 계산한다") + fun shouldApplySevenPercentDefaultAgentSettlementRatioToContentDonationWhenAgentRatioHistoryDoesNotExist() { + val agent = saveMember("agent-default-content-donation", MemberRole.AGENT) + val creator = saveMember("creator-default-content-donation", MemberRole.CREATOR) + val buyer = saveMember("buyer-default-content-donation", MemberRole.USER) + + saveRelation(agent, creator) + + val donationContent = saveAudioContent(creator, "content-default-agent-ratio", price = 0, settlementRatio = null) + saveContentDonationUseCan(buyer, donationContent, 20, LocalDateTime.of(2026, 2, 20, 10, 0, 0)) + + val response = service.getCalculateContentDonationByCreator("2026-02-20", "2026-02-20", agent.id!!, 0, 10) + + assertGenericSettlementResponse( + response, + expectedCount = 1, + expectedTotalCan = 20, + expectedAgentSettlementAmount = calculateGenericAgentSettlementAmount( + totalCan = 20, + settlementRatio = 70, + agentSettlementRatio = 7 + ) + ) + } + + @Test + @DisplayName("에이전트 비율 이력이 없으면 채널후원 응답은 7퍼센트 기본값으로 agent 정산금을 계산한다") + fun shouldApplySevenPercentDefaultAgentSettlementRatioToChannelDonationWhenAgentRatioHistoryDoesNotExist() { + val agent = saveMember("agent-default-channel-donation", MemberRole.AGENT) + val creator = saveMember("creator-default-channel-donation", MemberRole.CREATOR) + val sender = saveMember("sender-default-channel-donation", MemberRole.USER) + + saveRelation(agent, creator) + + val channelDonation = saveChannelDonationUseCan(sender, 50, LocalDateTime.of(2026, 2, 20, 10, 0, 0)) + saveUseCanCalculate(channelDonation, creator.id!!, 50, PaymentGateway.PG) + + val response = service.getChannelDonationByCreator("2026-02-20", "2026-02-20", agent.id!!, 0, 10) + + assertChannelDonationSettlementResponse( + response, + expectedCount = 1, + expectedTotalCan = 50, + expectedAgentSettlementAmount = calculateChannelAgentSettlementAmount(totalCan = 50, agentSettlementRatio = 7) + ) + } + @Test @DisplayName("페이지 대상 creator가 없으면 모든 카테고리 조회는 빈 rows를 반환한다") fun shouldReturnEmptyRowsWhenPagedCreatorSelectionIsEmptyAcrossAllCategories() { 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 2bd0bdba..80b6c430 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 @@ -358,7 +358,7 @@ class AgentCalculateServiceTest { } @Test - @DisplayName("에이전트 비율 이력이 없으면 일반 정산 응답은 10퍼센트 기본값으로 agent 정산금을 계산한다") + @DisplayName("에이전트 비율 이력이 없으면 일반 정산 응답은 7퍼센트 기본값으로 agent 정산금을 계산한다") fun shouldApplyDefaultAgentSettlementRatioWhenAgentRatioHistoryDoesNotExist() { val queryData = listOf( GetAgentCreatorSettlementSummaryQueryData( @@ -393,7 +393,7 @@ class AgentCalculateServiceTest { settlementAmount = 1_308, tax = 43, depositAmount = 1_265, - agentSettlementAmount = 131 + agentSettlementAmount = 92 ) ) Mockito.`when`( @@ -416,8 +416,8 @@ class AgentCalculateServiceTest { assertEquals(1, response.totalCount) assertEquals(1_308, response.total.settlementAmount) - assertEquals(131, response.total.agentSettlementAmount) - assertEquals(131, response.items[0].agentSettlementAmount) + assertEquals(92, response.total.agentSettlementAmount) + assertEquals(92, response.items[0].agentSettlementAmount) } @Test @@ -493,7 +493,7 @@ class AgentCalculateServiceTest { } @Test - @DisplayName("에이전트 비율 이력이 없으면 채널후원 응답은 10퍼센트 기본값으로 agent 정산금을 계산한다") + @DisplayName("에이전트 비율 이력이 없으면 채널후원 응답은 7퍼센트 기본값으로 agent 정산금을 계산한다") fun shouldApplyDefaultAgentSettlementRatioToChannelDonationWhenAgentRatioHistoryDoesNotExist() { val queryData = listOf( GetAgentChannelDonationSettlementByCreatorQueryData( @@ -527,7 +527,7 @@ class AgentCalculateServiceTest { settlementAmount = 3_970, withholdingTax = 131, depositAmount = 3_839, - agentSettlementAmount = 397 + agentSettlementAmount = 278 ) ) Mockito.`when`( @@ -550,8 +550,8 @@ class AgentCalculateServiceTest { assertEquals(1, response.totalCount) assertEquals(3_970, response.total.settlementAmount) - assertEquals(397, response.total.agentSettlementAmount) - assertEquals(397, response.items[0].agentSettlementAmount) + assertEquals(278, response.total.agentSettlementAmount) + assertEquals(278, response.items[0].agentSettlementAmount) } @Test