feat(agent-settlement): 에이전트 정산 스냅샷 관리 기능을 추가한다
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
package kr.co.vividnext.sodalive.admin.partner.agent.settlement
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.FinalizeAgentSettlementSnapshotRequest
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize
|
||||||
|
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
@RequestMapping("/admin/partner/agent/settlement")
|
||||||
|
class AdminAgentSettlementSnapshotController(private val service: AdminAgentSettlementSnapshotService) {
|
||||||
|
@PostMapping("/finalize")
|
||||||
|
fun finalizeSettlement(
|
||||||
|
@RequestBody request: FinalizeAgentSettlementSnapshotRequest,
|
||||||
|
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||||
|
) = run {
|
||||||
|
val admin = member ?: throw SodaException(messageKey = "common.error.bad_credentials")
|
||||||
|
ApiResponse.ok(service.finalizeSnapshots(request, admin.id!!))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,293 @@
|
|||||||
|
package kr.co.vividnext.sodalive.admin.partner.agent.settlement
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberRole
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.calculate.AgentCalculateQueryRepository
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.calculate.GetAgentChannelDonationSettlementByCreatorItem
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.calculate.GetAgentChannelDonationSettlementByCreatorQueryData
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.calculate.GetAgentCreatorSettlementSummaryQueryData
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.calculate.GetAgentSettlementByCreatorItem
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.calculate.toMergedResponseItems
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.AgentSettlementSnapshot
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.AgentSettlementSnapshotRepository
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.AgentSettlementSnapshotSourceDetail
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.AgentSettlementSnapshotSourceDetailRepository
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.AgentSettlementSnapshotType
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.FinalizeAgentSettlementSnapshotRequest
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.FinalizeAgentSettlementSnapshotResponse
|
||||||
|
import org.springframework.data.repository.findByIdOrNull
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
import org.springframework.transaction.annotation.Transactional
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
@Service
|
||||||
|
class AdminAgentSettlementSnapshotService(
|
||||||
|
private val snapshotRepository: AgentSettlementSnapshotRepository,
|
||||||
|
private val sourceDetailRepository: AgentSettlementSnapshotSourceDetailRepository,
|
||||||
|
private val calculateRepository: AgentCalculateQueryRepository,
|
||||||
|
private val memberRepository: MemberRepository
|
||||||
|
) {
|
||||||
|
private data class SourceDetailDraft(
|
||||||
|
val creatorId: Long,
|
||||||
|
val assignmentId: Long?,
|
||||||
|
val agentSettlementRatioId: Long?,
|
||||||
|
val appliedAgentSettlementRatio: Int?,
|
||||||
|
val count: Int,
|
||||||
|
val totalCan: Int,
|
||||||
|
val krw: Int,
|
||||||
|
val fee: Int,
|
||||||
|
val settlementAmount: Int,
|
||||||
|
val tax: Int,
|
||||||
|
val depositAmount: Int,
|
||||||
|
val agentSettlementAmount: Int
|
||||||
|
)
|
||||||
|
|
||||||
|
private data class SnapshotFinalizeDraft(
|
||||||
|
val snapshots: List<AgentSettlementSnapshot>,
|
||||||
|
val sourceDetailsByCreatorId: Map<Long, List<SourceDetailDraft>>
|
||||||
|
)
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
fun finalizeSnapshots(
|
||||||
|
request: FinalizeAgentSettlementSnapshotRequest,
|
||||||
|
finalizedByMemberId: Long
|
||||||
|
): FinalizeAgentSettlementSnapshotResponse {
|
||||||
|
val (startDate, endDate) = request.toDateRange()
|
||||||
|
if (
|
||||||
|
snapshotRepository.existsByPeriodStartAndPeriodEndAndSettlementTypeAndAgentId(
|
||||||
|
periodStart = startDate,
|
||||||
|
periodEnd = endDate,
|
||||||
|
settlementType = request.settlementType,
|
||||||
|
agentId = request.agentId
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return FinalizeAgentSettlementSnapshotResponse(finalizedCount = 0, alreadyFinalized = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
val agent = getAgent(request.agentId)
|
||||||
|
val finalizedAt = LocalDateTime.now()
|
||||||
|
|
||||||
|
val draft = when (request.settlementType) {
|
||||||
|
AgentSettlementSnapshotType.LIVE -> buildGenericSnapshots(
|
||||||
|
request = request,
|
||||||
|
agent = agent,
|
||||||
|
finalizedAt = finalizedAt,
|
||||||
|
finalizedByMemberId = finalizedByMemberId,
|
||||||
|
rows = calculateRepository.getCalculateLiveByCreator(startDate, endDate, request.agentId)
|
||||||
|
)
|
||||||
|
|
||||||
|
AgentSettlementSnapshotType.CONTENT -> buildGenericSnapshots(
|
||||||
|
request = request,
|
||||||
|
agent = agent,
|
||||||
|
finalizedAt = finalizedAt,
|
||||||
|
finalizedByMemberId = finalizedByMemberId,
|
||||||
|
rows = calculateRepository.getCalculateContentByCreator(startDate, endDate, request.agentId)
|
||||||
|
)
|
||||||
|
|
||||||
|
AgentSettlementSnapshotType.COMMUNITY -> buildGenericSnapshots(
|
||||||
|
request = request,
|
||||||
|
agent = agent,
|
||||||
|
finalizedAt = finalizedAt,
|
||||||
|
finalizedByMemberId = finalizedByMemberId,
|
||||||
|
rows = calculateRepository.getCalculateCommunityByCreator(startDate, endDate, request.agentId)
|
||||||
|
)
|
||||||
|
|
||||||
|
AgentSettlementSnapshotType.CONTENT_DONATION -> buildGenericSnapshots(
|
||||||
|
request = request,
|
||||||
|
agent = agent,
|
||||||
|
finalizedAt = finalizedAt,
|
||||||
|
finalizedByMemberId = finalizedByMemberId,
|
||||||
|
rows = calculateRepository.getCalculateContentDonationByCreator(startDate, endDate, request.agentId)
|
||||||
|
)
|
||||||
|
|
||||||
|
AgentSettlementSnapshotType.CHANNEL_DONATION -> buildChannelSnapshots(
|
||||||
|
request = request,
|
||||||
|
agent = agent,
|
||||||
|
finalizedAt = finalizedAt,
|
||||||
|
finalizedByMemberId = finalizedByMemberId,
|
||||||
|
rows = calculateRepository.getChannelDonationByCreator(startDate, endDate, request.agentId)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (draft.snapshots.isNotEmpty()) {
|
||||||
|
snapshotRepository.saveAll(draft.snapshots)
|
||||||
|
sourceDetailRepository.saveAll(buildSourceDetails(draft))
|
||||||
|
}
|
||||||
|
|
||||||
|
return FinalizeAgentSettlementSnapshotResponse(finalizedCount = draft.snapshots.size, alreadyFinalized = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getAgent(agentId: Long): Member {
|
||||||
|
val agent = memberRepository.findByIdOrNull(agentId)
|
||||||
|
?: throw SodaException(messageKey = "partner.agent.ratio.agent_not_found")
|
||||||
|
if (agent.role != MemberRole.AGENT) {
|
||||||
|
throw SodaException(messageKey = "partner.agent.ratio.invalid_agent")
|
||||||
|
}
|
||||||
|
return agent
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildGenericSnapshots(
|
||||||
|
request: FinalizeAgentSettlementSnapshotRequest,
|
||||||
|
agent: Member,
|
||||||
|
finalizedAt: LocalDateTime,
|
||||||
|
finalizedByMemberId: Long,
|
||||||
|
rows: List<GetAgentCreatorSettlementSummaryQueryData>
|
||||||
|
): SnapshotFinalizeDraft {
|
||||||
|
val (startDate, endDate) = request.toDateRange()
|
||||||
|
val rowsByCreator = rows.groupBy { it.creatorId }
|
||||||
|
val snapshots = rowsByCreator.map { (creatorId, creatorRows) ->
|
||||||
|
val merged = creatorRows.toMergedResponseItems().single()
|
||||||
|
val singleSourceRow = creatorRows.singleOrNull()
|
||||||
|
|
||||||
|
AgentSettlementSnapshot(
|
||||||
|
periodStart = startDate,
|
||||||
|
periodEnd = endDate,
|
||||||
|
settlementType = request.settlementType,
|
||||||
|
agentId = agent.id!!,
|
||||||
|
agentNickname = agent.nickname,
|
||||||
|
creatorId = creatorId,
|
||||||
|
creatorNickname = merged.creatorNickname,
|
||||||
|
assignmentId = singleSourceRow?.assignmentId,
|
||||||
|
agentSettlementRatioId = singleSourceRow?.agentSettlementRatioId,
|
||||||
|
appliedAgentSettlementRatio = singleSourceRow?.agentSettlementRatio,
|
||||||
|
count = merged.count,
|
||||||
|
totalCan = merged.totalCan,
|
||||||
|
krw = merged.krw,
|
||||||
|
fee = merged.fee,
|
||||||
|
settlementAmount = merged.settlementAmount,
|
||||||
|
tax = merged.tax,
|
||||||
|
depositAmount = merged.depositAmount,
|
||||||
|
agentSettlementAmount = merged.agentSettlementAmount,
|
||||||
|
finalizedAt = finalizedAt,
|
||||||
|
finalizedByMemberId = finalizedByMemberId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return SnapshotFinalizeDraft(
|
||||||
|
snapshots = snapshots,
|
||||||
|
sourceDetailsByCreatorId = rowsByCreator.mapValues { (_, creatorRows) ->
|
||||||
|
creatorRows.map { row ->
|
||||||
|
row.toResponseItem().toSourceDetailDraft(
|
||||||
|
assignmentId = row.assignmentId,
|
||||||
|
agentSettlementRatioId = row.agentSettlementRatioId,
|
||||||
|
appliedAgentSettlementRatio = row.agentSettlementRatio
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildChannelSnapshots(
|
||||||
|
request: FinalizeAgentSettlementSnapshotRequest,
|
||||||
|
agent: Member,
|
||||||
|
finalizedAt: LocalDateTime,
|
||||||
|
finalizedByMemberId: Long,
|
||||||
|
rows: List<GetAgentChannelDonationSettlementByCreatorQueryData>
|
||||||
|
): SnapshotFinalizeDraft {
|
||||||
|
val (startDate, endDate) = request.toDateRange()
|
||||||
|
val rowsByCreator = rows.groupBy { it.creatorId }
|
||||||
|
val snapshots = rowsByCreator.map { (creatorId, creatorRows) ->
|
||||||
|
val merged = creatorRows.toMergedResponseItems().single()
|
||||||
|
val singleSourceRow = creatorRows.singleOrNull()
|
||||||
|
|
||||||
|
AgentSettlementSnapshot(
|
||||||
|
periodStart = startDate,
|
||||||
|
periodEnd = endDate,
|
||||||
|
settlementType = request.settlementType,
|
||||||
|
agentId = agent.id!!,
|
||||||
|
agentNickname = agent.nickname,
|
||||||
|
creatorId = creatorId,
|
||||||
|
creatorNickname = merged.creatorNickname,
|
||||||
|
assignmentId = singleSourceRow?.assignmentId,
|
||||||
|
agentSettlementRatioId = singleSourceRow?.agentSettlementRatioId,
|
||||||
|
appliedAgentSettlementRatio = singleSourceRow?.agentSettlementRatio,
|
||||||
|
count = merged.count,
|
||||||
|
totalCan = merged.totalCan,
|
||||||
|
krw = merged.krw,
|
||||||
|
fee = merged.fee,
|
||||||
|
settlementAmount = merged.settlementAmount,
|
||||||
|
tax = merged.withholdingTax,
|
||||||
|
depositAmount = merged.depositAmount,
|
||||||
|
agentSettlementAmount = merged.agentSettlementAmount,
|
||||||
|
finalizedAt = finalizedAt,
|
||||||
|
finalizedByMemberId = finalizedByMemberId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return SnapshotFinalizeDraft(
|
||||||
|
snapshots = snapshots,
|
||||||
|
sourceDetailsByCreatorId = rowsByCreator.mapValues { (_, creatorRows) ->
|
||||||
|
creatorRows.map { row ->
|
||||||
|
row.toResponseItem().toSourceDetailDraft(
|
||||||
|
assignmentId = row.assignmentId,
|
||||||
|
agentSettlementRatioId = row.agentSettlementRatioId,
|
||||||
|
appliedAgentSettlementRatio = row.agentSettlementRatio
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildSourceDetails(draft: SnapshotFinalizeDraft): List<AgentSettlementSnapshotSourceDetail> {
|
||||||
|
val snapshotsByCreatorId = draft.snapshots.associateBy { it.creatorId }
|
||||||
|
return draft.sourceDetailsByCreatorId.flatMap { (creatorId, sourceDetails) ->
|
||||||
|
val snapshot = snapshotsByCreatorId.getValue(creatorId)
|
||||||
|
sourceDetails.map { detail ->
|
||||||
|
AgentSettlementSnapshotSourceDetail(
|
||||||
|
snapshot = snapshot,
|
||||||
|
assignmentId = detail.assignmentId,
|
||||||
|
agentSettlementRatioId = detail.agentSettlementRatioId,
|
||||||
|
appliedAgentSettlementRatio = detail.appliedAgentSettlementRatio,
|
||||||
|
count = detail.count,
|
||||||
|
totalCan = detail.totalCan,
|
||||||
|
krw = detail.krw,
|
||||||
|
fee = detail.fee,
|
||||||
|
settlementAmount = detail.settlementAmount,
|
||||||
|
tax = detail.tax,
|
||||||
|
depositAmount = detail.depositAmount,
|
||||||
|
agentSettlementAmount = detail.agentSettlementAmount
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun GetAgentSettlementByCreatorItem.toSourceDetailDraft(
|
||||||
|
assignmentId: Long?,
|
||||||
|
agentSettlementRatioId: Long?,
|
||||||
|
appliedAgentSettlementRatio: Int?
|
||||||
|
) = SourceDetailDraft(
|
||||||
|
creatorId = creatorId,
|
||||||
|
assignmentId = assignmentId,
|
||||||
|
agentSettlementRatioId = agentSettlementRatioId,
|
||||||
|
appliedAgentSettlementRatio = appliedAgentSettlementRatio,
|
||||||
|
count = count,
|
||||||
|
totalCan = totalCan,
|
||||||
|
krw = krw,
|
||||||
|
fee = fee,
|
||||||
|
settlementAmount = settlementAmount,
|
||||||
|
tax = tax,
|
||||||
|
depositAmount = depositAmount,
|
||||||
|
agentSettlementAmount = agentSettlementAmount
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun GetAgentChannelDonationSettlementByCreatorItem.toSourceDetailDraft(
|
||||||
|
assignmentId: Long?,
|
||||||
|
agentSettlementRatioId: Long?,
|
||||||
|
appliedAgentSettlementRatio: Int?
|
||||||
|
) = SourceDetailDraft(
|
||||||
|
creatorId = creatorId,
|
||||||
|
assignmentId = assignmentId,
|
||||||
|
agentSettlementRatioId = agentSettlementRatioId,
|
||||||
|
appliedAgentSettlementRatio = appliedAgentSettlementRatio,
|
||||||
|
count = count,
|
||||||
|
totalCan = totalCan,
|
||||||
|
krw = krw,
|
||||||
|
fee = fee,
|
||||||
|
settlementAmount = settlementAmount,
|
||||||
|
tax = withholdingTax,
|
||||||
|
depositAmount = depositAmount,
|
||||||
|
agentSettlementAmount = agentSettlementAmount
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package kr.co.vividnext.sodalive.partner.agent.settlement.snapshot
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.BaseEntity
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import javax.persistence.Column
|
||||||
|
import javax.persistence.Entity
|
||||||
|
import javax.persistence.EnumType
|
||||||
|
import javax.persistence.Enumerated
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
class AgentSettlementSnapshot(
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var periodStart: LocalDateTime,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var periodEnd: LocalDateTime,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
var settlementType: AgentSettlementSnapshotType,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var agentId: Long,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var agentNickname: String,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var creatorId: Long,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var creatorNickname: String,
|
||||||
|
|
||||||
|
@Column(nullable = true, updatable = false)
|
||||||
|
var assignmentId: Long? = null,
|
||||||
|
|
||||||
|
@Column(nullable = true, updatable = false)
|
||||||
|
var agentSettlementRatioId: Long? = null,
|
||||||
|
|
||||||
|
@Column(nullable = true, updatable = false)
|
||||||
|
var appliedAgentSettlementRatio: Int? = null,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var count: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var totalCan: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var krw: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var fee: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var settlementAmount: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var tax: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var depositAmount: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var agentSettlementAmount: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var finalizedAt: LocalDateTime,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var finalizedByMemberId: Long
|
||||||
|
) : BaseEntity()
|
||||||
|
|
||||||
|
enum class AgentSettlementSnapshotType {
|
||||||
|
LIVE,
|
||||||
|
CONTENT,
|
||||||
|
COMMUNITY,
|
||||||
|
CHANNEL_DONATION,
|
||||||
|
CONTENT_DONATION
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package kr.co.vividnext.sodalive.partner.agent.settlement.snapshot
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
interface AgentSettlementSnapshotRepository : JpaRepository<AgentSettlementSnapshot, Long> {
|
||||||
|
fun existsByPeriodStartAndPeriodEndAndSettlementTypeAndAgentId(
|
||||||
|
periodStart: LocalDateTime,
|
||||||
|
periodEnd: LocalDateTime,
|
||||||
|
settlementType: AgentSettlementSnapshotType,
|
||||||
|
agentId: Long
|
||||||
|
): Boolean
|
||||||
|
|
||||||
|
fun findAllByPeriodStartAndPeriodEndAndSettlementTypeAndAgentIdOrderByCreatorIdDesc(
|
||||||
|
periodStart: LocalDateTime,
|
||||||
|
periodEnd: LocalDateTime,
|
||||||
|
settlementType: AgentSettlementSnapshotType,
|
||||||
|
agentId: Long
|
||||||
|
): List<AgentSettlementSnapshot>
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package kr.co.vividnext.sodalive.partner.agent.settlement.snapshot
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.calculate.GetAgentChannelDonationSettlementByCreatorItem
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.calculate.GetAgentSettlementByCreatorItem
|
||||||
|
|
||||||
|
fun List<AgentSettlementSnapshot>.toSettlementByCreatorItems(): List<GetAgentSettlementByCreatorItem> {
|
||||||
|
return map {
|
||||||
|
GetAgentSettlementByCreatorItem(
|
||||||
|
creatorId = it.creatorId,
|
||||||
|
creatorNickname = it.creatorNickname,
|
||||||
|
count = it.count,
|
||||||
|
totalCan = it.totalCan,
|
||||||
|
krw = it.krw,
|
||||||
|
fee = it.fee,
|
||||||
|
settlementAmount = it.settlementAmount,
|
||||||
|
tax = it.tax,
|
||||||
|
depositAmount = it.depositAmount,
|
||||||
|
agentSettlementAmount = it.agentSettlementAmount
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun List<AgentSettlementSnapshot>.toChannelDonationSettlementByCreatorItems():
|
||||||
|
List<GetAgentChannelDonationSettlementByCreatorItem> {
|
||||||
|
return map {
|
||||||
|
GetAgentChannelDonationSettlementByCreatorItem(
|
||||||
|
creatorId = it.creatorId,
|
||||||
|
creatorNickname = it.creatorNickname,
|
||||||
|
count = it.count,
|
||||||
|
totalCan = it.totalCan,
|
||||||
|
krw = it.krw,
|
||||||
|
fee = it.fee,
|
||||||
|
settlementAmount = it.settlementAmount,
|
||||||
|
withholdingTax = it.tax,
|
||||||
|
depositAmount = it.depositAmount,
|
||||||
|
agentSettlementAmount = it.agentSettlementAmount
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package kr.co.vividnext.sodalive.partner.agent.settlement.snapshot
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.BaseEntity
|
||||||
|
import javax.persistence.Column
|
||||||
|
import javax.persistence.Entity
|
||||||
|
import javax.persistence.FetchType
|
||||||
|
import javax.persistence.JoinColumn
|
||||||
|
import javax.persistence.ManyToOne
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
class AgentSettlementSnapshotSourceDetail(
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "snapshot_id", nullable = false)
|
||||||
|
var snapshot: AgentSettlementSnapshot,
|
||||||
|
|
||||||
|
@Column(nullable = true, updatable = false)
|
||||||
|
var assignmentId: Long? = null,
|
||||||
|
|
||||||
|
@Column(nullable = true, updatable = false)
|
||||||
|
var agentSettlementRatioId: Long? = null,
|
||||||
|
|
||||||
|
@Column(nullable = true, updatable = false)
|
||||||
|
var appliedAgentSettlementRatio: Int? = null,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var count: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var totalCan: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var krw: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var fee: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var settlementAmount: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var tax: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var depositAmount: Int,
|
||||||
|
|
||||||
|
@Column(nullable = false, updatable = false)
|
||||||
|
var agentSettlementAmount: Int
|
||||||
|
) : BaseEntity()
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package kr.co.vividnext.sodalive.partner.agent.settlement.snapshot
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
|
|
||||||
|
interface AgentSettlementSnapshotSourceDetailRepository : JpaRepository<AgentSettlementSnapshotSourceDetail, Long>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package kr.co.vividnext.sodalive.partner.agent.settlement.snapshot
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.extensions.convertLocalDateTime
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
data class FinalizeAgentSettlementSnapshotRequest(
|
||||||
|
val agentId: Long,
|
||||||
|
val settlementType: AgentSettlementSnapshotType,
|
||||||
|
val startDateStr: String,
|
||||||
|
val endDateStr: String
|
||||||
|
) {
|
||||||
|
fun toDateRange(): Pair<LocalDateTime, LocalDateTime> {
|
||||||
|
val startDate = startDateStr.convertLocalDateTime()
|
||||||
|
val endDate = endDateStr.convertLocalDateTime(hour = 23, minute = 59, second = 59)
|
||||||
|
return startDate to endDate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class FinalizeAgentSettlementSnapshotResponse(
|
||||||
|
val finalizedCount: Int,
|
||||||
|
val alreadyFinalized: Boolean
|
||||||
|
)
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package kr.co.vividnext.sodalive.admin.partner.agent.settlement
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberRole
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.AgentSettlementSnapshotType
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.FinalizeAgentSettlementSnapshotRequest
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.FinalizeAgentSettlementSnapshotResponse
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Assertions.assertThrows
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.mockito.Mockito
|
||||||
|
|
||||||
|
class AdminAgentSettlementSnapshotControllerTest {
|
||||||
|
private lateinit var service: AdminAgentSettlementSnapshotService
|
||||||
|
private lateinit var controller: AdminAgentSettlementSnapshotController
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setup() {
|
||||||
|
service = Mockito.mock(AdminAgentSettlementSnapshotService::class.java)
|
||||||
|
controller = AdminAgentSettlementSnapshotController(service)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("인증 사용자 정보가 없으면 관리자 확정 정산 요청은 예외를 던진다")
|
||||||
|
fun shouldThrowWhenMemberIsNull() {
|
||||||
|
val request = FinalizeAgentSettlementSnapshotRequest(
|
||||||
|
agentId = 7L,
|
||||||
|
settlementType = AgentSettlementSnapshotType.LIVE,
|
||||||
|
startDateStr = "2026-02-20",
|
||||||
|
endDateStr = "2026-02-21"
|
||||||
|
)
|
||||||
|
|
||||||
|
val exception = assertThrows(SodaException::class.java) {
|
||||||
|
controller.finalizeSettlement(request = request, member = null)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("common.error.bad_credentials", exception.messageKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("관리자 컨트롤러는 확정 정산 요청과 인증 관리자 정보를 서비스로 전달한다")
|
||||||
|
fun shouldForwardFinalizeRequestToService() {
|
||||||
|
val request = FinalizeAgentSettlementSnapshotRequest(
|
||||||
|
agentId = 7L,
|
||||||
|
settlementType = AgentSettlementSnapshotType.LIVE,
|
||||||
|
startDateStr = "2026-02-20",
|
||||||
|
endDateStr = "2026-02-21"
|
||||||
|
)
|
||||||
|
val member = Member(password = "password", nickname = "admin", role = MemberRole.ADMIN)
|
||||||
|
member.id = 99L
|
||||||
|
val body = FinalizeAgentSettlementSnapshotResponse(
|
||||||
|
finalizedCount = 1,
|
||||||
|
alreadyFinalized = false
|
||||||
|
)
|
||||||
|
|
||||||
|
Mockito.`when`(service.finalizeSnapshots(request, 99L)).thenReturn(body)
|
||||||
|
|
||||||
|
val response = controller.finalizeSettlement(request = request, member = member)
|
||||||
|
|
||||||
|
assertEquals(true, response.success)
|
||||||
|
assertEquals(1, response.data!!.finalizedCount)
|
||||||
|
assertEquals(false, response.data!!.alreadyFinalized)
|
||||||
|
Mockito.verify(service).finalizeSnapshots(request, 99L)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,239 @@
|
|||||||
|
package kr.co.vividnext.sodalive.admin.partner.agent.settlement
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||||
|
import kr.co.vividnext.sodalive.member.MemberRole
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.calculate.AgentCalculateQueryRepository
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.calculate.GetAgentCreatorSettlementSummaryQueryData
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.AgentSettlementSnapshot
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.AgentSettlementSnapshotRepository
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.AgentSettlementSnapshotSourceDetail
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.AgentSettlementSnapshotSourceDetailRepository
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.AgentSettlementSnapshotType
|
||||||
|
import kr.co.vividnext.sodalive.partner.agent.settlement.snapshot.FinalizeAgentSettlementSnapshotRequest
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||||
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.mockito.ArgumentCaptor
|
||||||
|
import org.mockito.Mockito
|
||||||
|
import java.util.Optional
|
||||||
|
|
||||||
|
class AdminAgentSettlementSnapshotServiceTest {
|
||||||
|
private lateinit var snapshotRepository: AgentSettlementSnapshotRepository
|
||||||
|
private lateinit var sourceDetailRepository: AgentSettlementSnapshotSourceDetailRepository
|
||||||
|
private lateinit var calculateRepository: AgentCalculateQueryRepository
|
||||||
|
private lateinit var memberRepository: MemberRepository
|
||||||
|
private lateinit var service: AdminAgentSettlementSnapshotService
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
fun setup() {
|
||||||
|
snapshotRepository = Mockito.mock(AgentSettlementSnapshotRepository::class.java)
|
||||||
|
sourceDetailRepository = Mockito.mock(AgentSettlementSnapshotSourceDetailRepository::class.java)
|
||||||
|
calculateRepository = Mockito.mock(AgentCalculateQueryRepository::class.java)
|
||||||
|
memberRepository = Mockito.mock(MemberRepository::class.java)
|
||||||
|
service = AdminAgentSettlementSnapshotService(
|
||||||
|
snapshotRepository = snapshotRepository,
|
||||||
|
sourceDetailRepository = sourceDetailRepository,
|
||||||
|
calculateRepository = calculateRepository,
|
||||||
|
memberRepository = memberRepository
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("관리자는 live creator summary를 immutable 스냅샷으로 확정 저장한다")
|
||||||
|
fun shouldCreateImmutableSettlementSnapshots() {
|
||||||
|
val request = FinalizeAgentSettlementSnapshotRequest(
|
||||||
|
agentId = 7L,
|
||||||
|
settlementType = AgentSettlementSnapshotType.LIVE,
|
||||||
|
startDateStr = "2026-02-20",
|
||||||
|
endDateStr = "2026-02-21"
|
||||||
|
)
|
||||||
|
val agent = Member(password = "password", nickname = "agent-a", role = MemberRole.AGENT)
|
||||||
|
agent.id = 7L
|
||||||
|
val (startDate, endDate) = request.toDateRange()
|
||||||
|
|
||||||
|
Mockito.`when`(
|
||||||
|
snapshotRepository.existsByPeriodStartAndPeriodEndAndSettlementTypeAndAgentId(
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
AgentSettlementSnapshotType.LIVE,
|
||||||
|
7L
|
||||||
|
)
|
||||||
|
).thenReturn(false)
|
||||||
|
Mockito.`when`(memberRepository.findById(7L)).thenReturn(Optional.of(agent))
|
||||||
|
Mockito.`when`(calculateRepository.getCalculateLiveByCreator(startDate, endDate, 7L)).thenReturn(
|
||||||
|
listOf(
|
||||||
|
GetAgentCreatorSettlementSummaryQueryData(
|
||||||
|
creatorId = 21L,
|
||||||
|
creatorNickname = "creator-a",
|
||||||
|
assignmentId = 101L,
|
||||||
|
agentSettlementRatioId = 202L,
|
||||||
|
count = 2L,
|
||||||
|
totalCan = 100,
|
||||||
|
settlementRatio = 70,
|
||||||
|
agentSettlementRatio = 10
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val response = service.finalizeSnapshots(request, finalizedByMemberId = 99L)
|
||||||
|
|
||||||
|
assertEquals(1, response.finalizedCount)
|
||||||
|
assertEquals(false, response.alreadyFinalized)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val captor = ArgumentCaptor.forClass(List::class.java) as ArgumentCaptor<List<AgentSettlementSnapshot>>
|
||||||
|
Mockito.verify(snapshotRepository).saveAll(captor.capture())
|
||||||
|
|
||||||
|
val snapshot = captor.value.single()
|
||||||
|
assertEquals(startDate, snapshot.periodStart)
|
||||||
|
assertEquals(endDate, snapshot.periodEnd)
|
||||||
|
assertEquals(AgentSettlementSnapshotType.LIVE, snapshot.settlementType)
|
||||||
|
assertEquals(7L, snapshot.agentId)
|
||||||
|
assertEquals("agent-a", snapshot.agentNickname)
|
||||||
|
assertEquals(21L, snapshot.creatorId)
|
||||||
|
assertEquals("creator-a", snapshot.creatorNickname)
|
||||||
|
assertEquals(101L, snapshot.assignmentId)
|
||||||
|
assertEquals(202L, snapshot.agentSettlementRatioId)
|
||||||
|
assertEquals(10, snapshot.appliedAgentSettlementRatio)
|
||||||
|
assertEquals(2, snapshot.count)
|
||||||
|
assertEquals(100, snapshot.totalCan)
|
||||||
|
assertEquals(10_000, snapshot.krw)
|
||||||
|
assertEquals(660, snapshot.fee)
|
||||||
|
assertEquals(6_538, snapshot.settlementAmount)
|
||||||
|
assertEquals(216, snapshot.tax)
|
||||||
|
assertEquals(6_322, snapshot.depositAmount)
|
||||||
|
assertEquals(654, snapshot.agentSettlementAmount)
|
||||||
|
assertEquals(99L, snapshot.finalizedByMemberId)
|
||||||
|
assertNotNull(snapshot.finalizedAt)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val detailCaptor = ArgumentCaptor.forClass(List::class.java) as ArgumentCaptor<List<AgentSettlementSnapshotSourceDetail>>
|
||||||
|
Mockito.verify(sourceDetailRepository).saveAll(detailCaptor.capture())
|
||||||
|
val detail = detailCaptor.value.single()
|
||||||
|
assertEquals(101L, detail.assignmentId)
|
||||||
|
assertEquals(202L, detail.agentSettlementRatioId)
|
||||||
|
assertEquals(10, detail.appliedAgentSettlementRatio)
|
||||||
|
assertEquals(2, detail.count)
|
||||||
|
assertEquals(100, detail.totalCan)
|
||||||
|
assertEquals(10_000, detail.krw)
|
||||||
|
assertEquals(660, detail.fee)
|
||||||
|
assertEquals(6_538, detail.settlementAmount)
|
||||||
|
assertEquals(216, detail.tax)
|
||||||
|
assertEquals(6_322, detail.depositAmount)
|
||||||
|
assertEquals(654, detail.agentSettlementAmount)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("기간 중 source row가 여러 개면 summary FK는 비우고 source detail로 provenance를 남긴다")
|
||||||
|
fun shouldStoreMixedPeriodProvenanceInSourceDetails() {
|
||||||
|
val request = FinalizeAgentSettlementSnapshotRequest(
|
||||||
|
agentId = 7L,
|
||||||
|
settlementType = AgentSettlementSnapshotType.LIVE,
|
||||||
|
startDateStr = "2026-02-20",
|
||||||
|
endDateStr = "2026-02-21"
|
||||||
|
)
|
||||||
|
val agent = Member(password = "password", nickname = "agent-a", role = MemberRole.AGENT)
|
||||||
|
agent.id = 7L
|
||||||
|
val (startDate, endDate) = request.toDateRange()
|
||||||
|
|
||||||
|
Mockito.`when`(
|
||||||
|
snapshotRepository.existsByPeriodStartAndPeriodEndAndSettlementTypeAndAgentId(
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
AgentSettlementSnapshotType.LIVE,
|
||||||
|
7L
|
||||||
|
)
|
||||||
|
).thenReturn(false)
|
||||||
|
Mockito.`when`(memberRepository.findById(7L)).thenReturn(Optional.of(agent))
|
||||||
|
Mockito.`when`(calculateRepository.getCalculateLiveByCreator(startDate, endDate, 7L)).thenReturn(
|
||||||
|
listOf(
|
||||||
|
GetAgentCreatorSettlementSummaryQueryData(
|
||||||
|
creatorId = 21L,
|
||||||
|
creatorNickname = "creator-a",
|
||||||
|
assignmentId = 101L,
|
||||||
|
agentSettlementRatioId = 202L,
|
||||||
|
count = 1L,
|
||||||
|
totalCan = 40,
|
||||||
|
settlementRatio = 70,
|
||||||
|
agentSettlementRatio = 10
|
||||||
|
),
|
||||||
|
GetAgentCreatorSettlementSummaryQueryData(
|
||||||
|
creatorId = 21L,
|
||||||
|
creatorNickname = "creator-a",
|
||||||
|
assignmentId = 102L,
|
||||||
|
agentSettlementRatioId = 203L,
|
||||||
|
count = 1L,
|
||||||
|
totalCan = 60,
|
||||||
|
settlementRatio = 70,
|
||||||
|
agentSettlementRatio = 20
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val response = service.finalizeSnapshots(request, finalizedByMemberId = 99L)
|
||||||
|
|
||||||
|
assertEquals(1, response.finalizedCount)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val snapshotCaptor = ArgumentCaptor.forClass(List::class.java) as ArgumentCaptor<List<AgentSettlementSnapshot>>
|
||||||
|
Mockito.verify(snapshotRepository).saveAll(snapshotCaptor.capture())
|
||||||
|
val snapshot = snapshotCaptor.value.single()
|
||||||
|
assertEquals(null, snapshot.assignmentId)
|
||||||
|
assertEquals(null, snapshot.agentSettlementRatioId)
|
||||||
|
assertEquals(null, snapshot.appliedAgentSettlementRatio)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val detailCaptor = ArgumentCaptor.forClass(List::class.java) as ArgumentCaptor<List<AgentSettlementSnapshotSourceDetail>>
|
||||||
|
Mockito.verify(sourceDetailRepository).saveAll(detailCaptor.capture())
|
||||||
|
assertEquals(2, detailCaptor.value.size)
|
||||||
|
assertEquals(listOf(101L, 102L), detailCaptor.value.mapNotNull { it.assignmentId }.sorted())
|
||||||
|
assertEquals(listOf(202L, 203L), detailCaptor.value.mapNotNull { it.agentSettlementRatioId }.sorted())
|
||||||
|
assertEquals(snapshot.count, detailCaptor.value.sumOf { it.count })
|
||||||
|
assertEquals(snapshot.totalCan, detailCaptor.value.sumOf { it.totalCan })
|
||||||
|
assertEquals(snapshot.krw, detailCaptor.value.sumOf { it.krw })
|
||||||
|
assertEquals(snapshot.fee, detailCaptor.value.sumOf { it.fee })
|
||||||
|
assertEquals(snapshot.settlementAmount, detailCaptor.value.sumOf { it.settlementAmount })
|
||||||
|
assertEquals(snapshot.tax, detailCaptor.value.sumOf { it.tax })
|
||||||
|
assertEquals(snapshot.depositAmount, detailCaptor.value.sumOf { it.depositAmount })
|
||||||
|
assertEquals(snapshot.agentSettlementAmount, detailCaptor.value.sumOf { it.agentSettlementAmount })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("동일 기간과 타입이 이미 확정되었으면 스냅샷을 중복 저장하지 않는다")
|
||||||
|
fun shouldSkipSavingWhenSnapshotsAlreadyExist() {
|
||||||
|
val request = FinalizeAgentSettlementSnapshotRequest(
|
||||||
|
agentId = 7L,
|
||||||
|
settlementType = AgentSettlementSnapshotType.LIVE,
|
||||||
|
startDateStr = "2026-02-20",
|
||||||
|
endDateStr = "2026-02-21"
|
||||||
|
)
|
||||||
|
val (startDate, endDate) = request.toDateRange()
|
||||||
|
|
||||||
|
Mockito.`when`(
|
||||||
|
snapshotRepository.existsByPeriodStartAndPeriodEndAndSettlementTypeAndAgentId(
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
AgentSettlementSnapshotType.LIVE,
|
||||||
|
7L
|
||||||
|
)
|
||||||
|
).thenReturn(true)
|
||||||
|
|
||||||
|
val response = service.finalizeSnapshots(request, finalizedByMemberId = 99L)
|
||||||
|
|
||||||
|
assertEquals(0, response.finalizedCount)
|
||||||
|
assertEquals(true, response.alreadyFinalized)
|
||||||
|
Mockito.verify(snapshotRepository).existsByPeriodStartAndPeriodEndAndSettlementTypeAndAgentId(
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
AgentSettlementSnapshotType.LIVE,
|
||||||
|
7L
|
||||||
|
)
|
||||||
|
Mockito.verify(snapshotRepository, Mockito.never()).saveAll(Mockito.anyList())
|
||||||
|
Mockito.verifyNoInteractions(sourceDetailRepository)
|
||||||
|
Mockito.verifyNoInteractions(calculateRepository)
|
||||||
|
Mockito.verifyNoInteractions(memberRepository)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user