From 35f66e7e41b3b2955632815873f4a741a3147b9f Mon Sep 17 00:00:00 2001
From: Klaus <klaus@vividnext.co.kr>
Date: Tue, 14 Nov 2023 20:50:54 +0900
Subject: [PATCH] =?UTF-8?q?=ED=81=AC=EB=A6=AC=EC=97=90=EC=9D=B4=ED=84=B0?=
 =?UTF-8?q?=20=EA=B4=80=EB=A6=AC=EC=9E=90=20-=20=EC=9D=BC=EC=9E=90?=
 =?UTF-8?q?=EB=B3=84=20=EC=BD=98=ED=85=90=EC=B8=A0=20=ED=9B=84=EC=9B=90=20?=
 =?UTF-8?q?=EC=A0=95=EC=82=B0=20API=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../CreatorAdminCalculateController.kt        | 19 ++++++
 .../CreatorAdminCalculateQueryRepository.kt   | 62 +++++++++++++++++++
 .../calculate/CreatorAdminCalculateService.kt | 59 ++++++++++++++++++
 ...CreatorCalculateContentDonationResponse.kt |  9 +++
 4 files changed, 149 insertions(+)
 create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/GetCreatorCalculateContentDonationResponse.kt

diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateController.kt
index 409c472..50235ff 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateController.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateController.kt
@@ -53,4 +53,23 @@ class CreatorAdminCalculateController(private val service: CreatorAdminCalculate
 
         ApiResponse.ok(service.getCumulativeSalesByContent(member.id!!, pageable.offset, pageable.pageSize.toLong()))
     }
+
+    @GetMapping("/content-donation-list")
+    fun getCalculateContentDonationList(
+        @RequestParam startDateStr: String,
+        @RequestParam endDateStr: String,
+        @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
+        pageable: Pageable
+    ) = run {
+        if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
+        ApiResponse.ok(
+            service.getCalculateContentDonationList(
+                startDateStr,
+                endDateStr,
+                member.id!!,
+                pageable.offset,
+                pageable.pageSize.toLong()
+            )
+        )
+    }
 }
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 8616741..c3c22c7 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
@@ -4,12 +4,15 @@ import com.querydsl.core.types.dsl.DateTimePath
 import com.querydsl.core.types.dsl.Expressions
 import com.querydsl.core.types.dsl.StringTemplate
 import com.querydsl.jpa.impl.JPAQueryFactory
+import kr.co.vividnext.sodalive.admin.calculate.GetCalculateContentDonationQueryData
 import kr.co.vividnext.sodalive.admin.calculate.GetCalculateContentQueryData
 import kr.co.vividnext.sodalive.admin.calculate.GetCalculateLiveQueryData
 import kr.co.vividnext.sodalive.admin.calculate.GetCumulativeSalesByContentQueryData
+import kr.co.vividnext.sodalive.admin.calculate.QGetCalculateContentDonationQueryData
 import kr.co.vividnext.sodalive.admin.calculate.QGetCalculateContentQueryData
 import kr.co.vividnext.sodalive.admin.calculate.QGetCalculateLiveQueryData
 import kr.co.vividnext.sodalive.admin.calculate.QGetCumulativeSalesByContentQueryData
+import kr.co.vividnext.sodalive.can.use.CanUsage
 import kr.co.vividnext.sodalive.can.use.QUseCan.useCan
 import kr.co.vividnext.sodalive.can.use.QUseCanCalculate.useCanCalculate
 import kr.co.vividnext.sodalive.can.use.UseCanCalculateStatus
@@ -184,4 +187,63 @@ class CreatorAdminCalculateQueryRepository(private val queryFactory: JPAQueryFac
             .orderBy(member.id.desc(), audioContent.id.desc())
             .fetch()
     }
+
+    fun getCalculateContentDonationListTotalCount(
+        startDate: LocalDateTime,
+        endDate: LocalDateTime,
+        memberId: Long
+    ): Int {
+        val donationFormattedDate = getFormattedDate(useCan.createdAt)
+        return queryFactory
+            .select(audioContent.id)
+            .from(useCan)
+            .innerJoin(useCan.audioContent, audioContent)
+            .innerJoin(audioContent.member, member)
+            .where(
+                useCan.isRefund.isFalse
+                    .and(useCan.canUsage.eq(CanUsage.DONATION))
+                    .and(useCan.createdAt.goe(startDate))
+                    .and(useCan.createdAt.loe(endDate))
+                    .and(audioContent.member.id.eq(memberId))
+            )
+            .groupBy(donationFormattedDate, audioContent.id)
+            .fetch()
+            .size
+    }
+
+    fun getCalculateContentDonationList(
+        startDate: LocalDateTime,
+        endDate: LocalDateTime,
+        memberId: Long,
+        offset: Long,
+        limit: Long
+    ): List<GetCalculateContentDonationQueryData> {
+        val donationFormattedDate = getFormattedDate(useCan.createdAt)
+        return queryFactory
+            .select(
+                QGetCalculateContentDonationQueryData(
+                    member.nickname,
+                    audioContent.title,
+                    getFormattedDate(audioContent.createdAt),
+                    donationFormattedDate,
+                    useCan.id.count(),
+                    useCan.can.add(useCan.rewardCan).sum()
+                )
+            )
+            .from(useCan)
+            .innerJoin(useCan.audioContent, audioContent)
+            .innerJoin(audioContent.member, member)
+            .where(
+                useCan.isRefund.isFalse
+                    .and(useCan.canUsage.eq(CanUsage.DONATION))
+                    .and(useCan.createdAt.goe(startDate))
+                    .and(useCan.createdAt.loe(endDate))
+                    .and(audioContent.member.id.eq(memberId))
+            )
+            .groupBy(donationFormattedDate, audioContent.id)
+            .offset(offset)
+            .limit(limit)
+            .orderBy(member.id.asc(), donationFormattedDate.desc())
+            .fetch()
+    }
 }
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateService.kt
index 4cec361..6d2a5ed 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateService.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/CreatorAdminCalculateService.kt
@@ -1,6 +1,7 @@
 package kr.co.vividnext.sodalive.creator.admin.calculate
 
 import kr.co.vividnext.sodalive.admin.calculate.CumulativeSalesByContentItem
+import kr.co.vividnext.sodalive.admin.calculate.GetCalculateContentDonationResponse
 import kr.co.vividnext.sodalive.admin.calculate.GetCalculateContentResponse
 import kr.co.vividnext.sodalive.admin.calculate.GetCalculateLiveResponse
 import kr.co.vividnext.sodalive.admin.calculate.GetCumulativeSalesByContentResponse
@@ -205,4 +206,62 @@ class CreatorAdminCalculateService(private val repository: CreatorAdminCalculate
 
         return GetCumulativeSalesByContentResponse(totalCount, items)
     }
+
+    @Transactional(readOnly = true)
+    fun getCalculateContentDonationList(
+        startDateStr: String,
+        endDateStr: String,
+        memberId: Long,
+        offset: Long,
+        limit: Long
+    ): GetCreatorCalculateContentDonationResponse {
+        val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
+        val startDate = LocalDate.parse(startDateStr, dateTimeFormatter).atTime(0, 0, 0)
+            .atZone(ZoneId.of("Asia/Seoul"))
+            .withZoneSameInstant(ZoneId.of("UTC"))
+            .toLocalDateTime()
+
+        val endDate = LocalDate.parse(endDateStr, dateTimeFormatter).atTime(23, 59, 59)
+            .atZone(ZoneId.of("Asia/Seoul"))
+            .withZoneSameInstant(ZoneId.of("UTC"))
+            .toLocalDateTime()
+
+        val totalCount = repository.getCalculateContentDonationListTotalCount(startDate, endDate, memberId)
+        val items = repository
+            .getCalculateContentDonationList(startDate, endDate, memberId, offset, limit)
+            .asSequence()
+            .map {
+                // 원화 = totalCoin * 100 ( 캔 1개 = 100원 )
+                val totalKrw = it.totalCan * 100
+
+                // 결제수수료 : 6.6%
+                val paymentFee = totalKrw * 0.066f
+
+                // 정산금액 = (원화 - 결제수수료) 의 70%
+                val settlementAmount = (totalKrw.toFloat() - paymentFee) * 0.7
+
+                // 원천세 = 정산금액의 3.3%
+                val tax = settlementAmount * 0.033
+
+                // 입금액
+                val depositAmount = settlementAmount - tax
+
+                GetCalculateContentDonationResponse(
+                    nickname = it.nickname,
+                    title = it.title,
+                    registrationDate = it.registrationDate,
+                    donationDate = it.donationDate,
+                    numberOfDonation = it.numberOfDonation.toInt(),
+                    totalCan = it.totalCan,
+                    totalKrw = totalKrw,
+                    paymentFee = paymentFee.roundToInt(),
+                    settlementAmount = settlementAmount.roundToInt(),
+                    tax = tax.roundToInt(),
+                    depositAmount = depositAmount.roundToInt()
+                )
+            }
+            .toList()
+
+        return GetCreatorCalculateContentDonationResponse(totalCount, items)
+    }
 }
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/GetCreatorCalculateContentDonationResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/GetCreatorCalculateContentDonationResponse.kt
new file mode 100644
index 0000000..bde83a9
--- /dev/null
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/calculate/GetCreatorCalculateContentDonationResponse.kt
@@ -0,0 +1,9 @@
+package kr.co.vividnext.sodalive.creator.admin.calculate
+
+import com.fasterxml.jackson.annotation.JsonProperty
+import kr.co.vividnext.sodalive.admin.calculate.GetCalculateContentDonationResponse
+
+data class GetCreatorCalculateContentDonationResponse(
+    @JsonProperty("totalCount") val totalCount: Int,
+    @JsonProperty("items") val items: List<GetCalculateContentDonationResponse>
+)