From 97e95b51ab6692b60cddd3bc312d521244620e2a Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 22 Sep 2025 13:36:36 +0900 Subject: [PATCH] =?UTF-8?q?feat(calculate-ratio):=20=EC=A0=95=EC=82=B0=20?= =?UTF-8?q?=EB=B9=84=EC=9C=A8=20=EC=88=98=EC=A0=95/=EC=82=AD=EC=A0=9C(?= =?UTF-8?q?=EC=86=8C=ED=94=84=ED=8A=B8=20=EC=82=AD=EC=A0=9C)=EC=99=80=20?= =?UTF-8?q?=EC=97=85=EC=84=9C=ED=8A=B8,=20=EC=BF=BC=EB=A6=AC=20=EB=B3=B4?= =?UTF-8?q?=EA=B0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - deletedAt 기반 소프트 삭제 도입 및 restore/updateValues 추가 - 생성 시 기존(삭제 포함) 레코드 복구 후 값 갱신(업서트) - /admin/calculate/ratio/update, /delete 엔드포인트 추가 - 정산 쿼리 조인에 deletedAt.isNull 적용하여 삭제 데이터 배제 - 목록/카운트 조회에서도 삭제 데이터 제외 --- .../AdminCalculateQueryRepository.kt | 50 +++++++++++++++---- .../calculate/ratio/CreatorSettlementRatio.kt | 26 ++++++++-- .../ratio/CreatorSettlementRatioController.kt | 10 ++++ .../ratio/CreatorSettlementRatioRepository.kt | 6 ++- .../ratio/CreatorSettlementRatioService.kt | 44 +++++++++++++++- .../CreatorAdminCalculateQueryRepository.kt | 20 ++++++-- 6 files changed, 135 insertions(+), 21 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/AdminCalculateQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/AdminCalculateQueryRepository.kt index e7b6e54..390d75a 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/AdminCalculateQueryRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/AdminCalculateQueryRepository.kt @@ -39,7 +39,10 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { .innerJoin(useCan.room, liveRoom) .innerJoin(liveRoom.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( useCan.isRefund.isFalse .and(useCan.createdAt.goe(startDate)) @@ -75,7 +78,10 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { .innerJoin(order.audioContent, audioContent) .innerJoin(audioContent.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( order.createdAt.goe(startDate) .and(order.createdAt.loe(endDate)) @@ -142,7 +148,10 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { .innerJoin(order.audioContent, audioContent) .innerJoin(audioContent.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where(order.isActive.isTrue) .groupBy( member.id, @@ -230,7 +239,10 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { .innerJoin(useCan.communityPost, creatorCommunity) .innerJoin(creatorCommunity.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( useCan.isRefund.isFalse .and(useCan.canUsage.eq(CanUsage.PAID_COMMUNITY_POST)) @@ -251,7 +263,10 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { .innerJoin(useCan.room, liveRoom) .innerJoin(liveRoom.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( useCan.isRefund.isFalse .and(useCan.createdAt.goe(startDate)) @@ -281,7 +296,10 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { .innerJoin(useCan.room, liveRoom) .innerJoin(liveRoom.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( useCan.isRefund.isFalse .and(useCan.createdAt.goe(startDate)) @@ -301,7 +319,10 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { .innerJoin(order.audioContent, audioContent) .innerJoin(audioContent.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( order.createdAt.goe(startDate) .and(order.createdAt.loe(endDate)) @@ -331,7 +352,10 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { .innerJoin(order.audioContent, audioContent) .innerJoin(audioContent.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( order.createdAt.goe(startDate) .and(order.createdAt.loe(endDate)) @@ -351,7 +375,10 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { .innerJoin(useCan.communityPost, creatorCommunity) .innerJoin(creatorCommunity.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( useCan.isRefund.isFalse .and(useCan.canUsage.eq(CanUsage.PAID_COMMUNITY_POST)) @@ -382,7 +409,10 @@ class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { .innerJoin(useCan.communityPost, creatorCommunity) .innerJoin(creatorCommunity.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( useCan.isRefund.isFalse .and(useCan.canUsage.eq(CanUsage.PAID_COMMUNITY_POST)) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatio.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatio.kt index 33ce414..ade5326 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatio.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatio.kt @@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.admin.calculate.ratio import kr.co.vividnext.sodalive.common.BaseEntity import kr.co.vividnext.sodalive.member.Member +import java.time.LocalDateTime import javax.persistence.Entity import javax.persistence.FetchType import javax.persistence.JoinColumn @@ -9,12 +10,29 @@ import javax.persistence.OneToOne @Entity data class CreatorSettlementRatio( - val subsidy: Int, - val liveSettlementRatio: Int, - val contentSettlementRatio: Int, - val communitySettlementRatio: Int + var subsidy: Int, + var liveSettlementRatio: Int, + var contentSettlementRatio: Int, + var communitySettlementRatio: Int ) : BaseEntity() { @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id", nullable = false) var member: Member? = null + + var deletedAt: LocalDateTime? = null + + fun softDelete() { + this.deletedAt = LocalDateTime.now() + } + + fun restore() { + this.deletedAt = null + } + + fun updateValues(subsidy: Int, live: Int, content: Int, community: Int) { + this.subsidy = subsidy + this.liveSettlementRatio = live + this.contentSettlementRatio = content + this.communitySettlementRatio = community + } } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatioController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatioController.kt index 10cd41e..089733d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatioController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatioController.kt @@ -27,4 +27,14 @@ class CreatorSettlementRatioController(private val service: CreatorSettlementRat limit = pageable.pageSize.toLong() ) ) + + @PostMapping("/update") + fun updateCreatorSettlementRatio( + @RequestBody request: CreateCreatorSettlementRatioRequest + ) = ApiResponse.ok(service.updateCreatorSettlementRatio(request)) + + @PostMapping("/delete") + fun deleteCreatorSettlementRatio( + @RequestBody memberId: Long + ) = ApiResponse.ok(service.deleteCreatorSettlementRatio(memberId)) } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatioRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatioRepository.kt index e788f53..177887c 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatioRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatioRepository.kt @@ -7,7 +7,9 @@ import org.springframework.data.jpa.repository.JpaRepository interface CreatorSettlementRatioRepository : JpaRepository, - CreatorSettlementRatioQueryRepository + CreatorSettlementRatioQueryRepository { + fun findByMemberId(memberId: Long): CreatorSettlementRatio? +} interface CreatorSettlementRatioQueryRepository { fun getCreatorSettlementRatio(offset: Long, limit: Long): List @@ -30,6 +32,7 @@ class CreatorSettlementRatioQueryRepositoryImpl( ) .from(creatorSettlementRatio) .innerJoin(creatorSettlementRatio.member, member) + .where(creatorSettlementRatio.deletedAt.isNull) .orderBy(creatorSettlementRatio.id.asc()) .offset(offset) .limit(limit) @@ -40,6 +43,7 @@ class CreatorSettlementRatioQueryRepositoryImpl( return queryFactory .select(creatorSettlementRatio.id) .from(creatorSettlementRatio) + .where(creatorSettlementRatio.deletedAt.isNull) .fetch() .size } diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatioService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatioService.kt index 140fb4a..d114f8c 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatioService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/calculate/ratio/CreatorSettlementRatioService.kt @@ -14,8 +14,6 @@ class CreatorSettlementRatioService( ) { @Transactional fun createCreatorSettlementRatio(request: CreateCreatorSettlementRatioRequest) { - val creatorSettlementRatio = request.toEntity() - val creator = memberRepository.findByIdOrNull(request.memberId) ?: throw SodaException("잘못된 크리에이터 입니다.") @@ -23,10 +21,52 @@ class CreatorSettlementRatioService( throw SodaException("잘못된 크리에이터 입니다.") } + val existing = repository.findByMemberId(request.memberId) + if (existing != null) { + // revive if soft-deleted, then update values + existing.restore() + existing.updateValues( + request.subsidy, + request.liveSettlementRatio, + request.contentSettlementRatio, + request.communitySettlementRatio + ) + repository.save(existing) + return + } + + val creatorSettlementRatio = request.toEntity() creatorSettlementRatio.member = creator repository.save(creatorSettlementRatio) } + @Transactional + fun updateCreatorSettlementRatio(request: CreateCreatorSettlementRatioRequest) { + val creator = memberRepository.findByIdOrNull(request.memberId) + ?: throw SodaException("잘못된 크리에이터 입니다.") + if (creator.role != MemberRole.CREATOR) { + throw SodaException("잘못된 크리에이터 입니다.") + } + val existing = repository.findByMemberId(request.memberId) + ?: throw SodaException("해당 크리에이터의 정산 비율 설정이 없습니다.") + existing.restore() + existing.updateValues( + request.subsidy, + request.liveSettlementRatio, + request.contentSettlementRatio, + request.communitySettlementRatio + ) + repository.save(existing) + } + + @Transactional + fun deleteCreatorSettlementRatio(memberId: Long) { + val existing = repository.findByMemberId(memberId) + ?: throw SodaException("해당 크리에이터의 정산 비율 설정이 없습니다.") + existing.softDelete() + repository.save(existing) + } + @Transactional(readOnly = true) fun getCreatorSettlementRatio(offset: Long, limit: Long): GetCreatorSettlementRatioResponse { val totalCount = repository.getCreatorSettlementRatioTotalCount() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateQueryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateQueryRepository.kt index f9b4289..d4267c4 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateQueryRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateQueryRepository.kt @@ -53,7 +53,10 @@ class CreatorAdminCalculateQueryRepository(private val queryFactory: JPAQueryFac .innerJoin(useCan.room, liveRoom) .innerJoin(liveRoom.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( useCan.isRefund.isFalse .and(useCan.createdAt.goe(startDate)) @@ -119,7 +122,10 @@ class CreatorAdminCalculateQueryRepository(private val queryFactory: JPAQueryFac .innerJoin(order.audioContent, audioContent) .innerJoin(audioContent.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( order.createdAt.goe(startDate) .and(order.createdAt.loe(endDate)) @@ -196,7 +202,10 @@ class CreatorAdminCalculateQueryRepository(private val queryFactory: JPAQueryFac .innerJoin(order.audioContent, audioContent) .innerJoin(audioContent.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( audioContent.member.id.eq(memberId) .and(order.isActive.isTrue) @@ -318,7 +327,10 @@ class CreatorAdminCalculateQueryRepository(private val queryFactory: JPAQueryFac .innerJoin(useCan.communityPost, creatorCommunity) .innerJoin(creatorCommunity.member, member) .leftJoin(creatorSettlementRatio) - .on(member.id.eq(creatorSettlementRatio.member.id)) + .on( + member.id.eq(creatorSettlementRatio.member.id) + .and(creatorSettlementRatio.deletedAt.isNull) + ) .where( useCan.isRefund.isFalse .and(useCan.canUsage.eq(CanUsage.PAID_COMMUNITY_POST))