feat(channel-donation-calculate): 채널 후원 정산 조회 기능을 추가한다
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package kr.co.vividnext.sodalive.admin.calculate.channelDonation
|
||||
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RequestParam
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@RequestMapping("/admin/calculate")
|
||||
class AdminChannelDonationCalculateController(
|
||||
private val service: AdminChannelDonationCalculateService
|
||||
) {
|
||||
@GetMapping("/channel-donation-by-creator")
|
||||
fun getChannelDonationByCreator(
|
||||
@RequestParam startDateStr: String,
|
||||
@RequestParam endDateStr: String,
|
||||
pageable: Pageable
|
||||
) = ApiResponse.ok(
|
||||
service.getChannelDonationByCreator(
|
||||
startDateStr = startDateStr,
|
||||
endDateStr = endDateStr,
|
||||
offset = pageable.offset,
|
||||
limit = pageable.pageSize.toLong()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package kr.co.vividnext.sodalive.admin.calculate.channelDonation
|
||||
|
||||
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.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
|
||||
import kr.co.vividnext.sodalive.member.QMember.member
|
||||
import org.springframework.stereotype.Repository
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Repository
|
||||
class AdminChannelDonationCalculateQueryRepository(
|
||||
private val queryFactory: JPAQueryFactory
|
||||
) {
|
||||
fun getChannelDonationByCreatorTotalCount(startDate: LocalDateTime, endDate: LocalDateTime): Int {
|
||||
val formattedDate = getFormattedDate(useCan.createdAt)
|
||||
val distinctGroupKey = Expressions.stringTemplate(
|
||||
"CONCAT({0}, '-', {1})",
|
||||
formattedDate,
|
||||
member.id.stringValue()
|
||||
)
|
||||
|
||||
return queryFactory
|
||||
.select(distinctGroupKey.countDistinct())
|
||||
.from(useCanCalculate)
|
||||
.innerJoin(useCanCalculate.useCan, useCan)
|
||||
.innerJoin(member)
|
||||
.on(member.id.eq(useCanCalculate.recipientCreatorId))
|
||||
.where(baseWhereCondition(startDate, endDate))
|
||||
.fetchOne()
|
||||
?.toInt()
|
||||
?: 0
|
||||
}
|
||||
|
||||
fun getChannelDonationByCreator(
|
||||
startDate: LocalDateTime,
|
||||
endDate: LocalDateTime,
|
||||
offset: Long,
|
||||
limit: Long
|
||||
): List<GetAdminChannelDonationSettlementQueryData> {
|
||||
val formattedDate = getFormattedDate(useCan.createdAt)
|
||||
|
||||
return queryFactory
|
||||
.select(
|
||||
QGetAdminChannelDonationSettlementQueryData(
|
||||
formattedDate,
|
||||
member.nickname,
|
||||
useCan.id.countDistinct(),
|
||||
useCanCalculate.can.sum()
|
||||
)
|
||||
)
|
||||
.from(useCanCalculate)
|
||||
.innerJoin(useCanCalculate.useCan, useCan)
|
||||
.innerJoin(member)
|
||||
.on(member.id.eq(useCanCalculate.recipientCreatorId))
|
||||
.where(baseWhereCondition(startDate, endDate))
|
||||
.groupBy(formattedDate, member.id)
|
||||
.orderBy(formattedDate.desc(), member.id.desc())
|
||||
.offset(offset)
|
||||
.limit(limit)
|
||||
.fetch()
|
||||
}
|
||||
|
||||
private fun baseWhereCondition(
|
||||
startDate: LocalDateTime,
|
||||
endDate: LocalDateTime
|
||||
) = useCan.canUsage.eq(CanUsage.CHANNEL_DONATION)
|
||||
.and(useCan.isRefund.isFalse)
|
||||
.and(useCanCalculate.status.eq(UseCanCalculateStatus.RECEIVED))
|
||||
.and(useCan.createdAt.goe(startDate))
|
||||
.and(useCan.createdAt.loe(endDate))
|
||||
|
||||
private fun getFormattedDate(dateTimePath: DateTimePath<LocalDateTime>): StringTemplate {
|
||||
return Expressions.stringTemplate(
|
||||
"DATE_FORMAT({0}, {1})",
|
||||
Expressions.dateTimeTemplate(
|
||||
LocalDateTime::class.java,
|
||||
"CONVERT_TZ({0},{1},{2})",
|
||||
dateTimePath,
|
||||
"UTC",
|
||||
"Asia/Seoul"
|
||||
),
|
||||
"%Y-%m-%d"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package kr.co.vividnext.sodalive.admin.calculate.channelDonation
|
||||
|
||||
import kr.co.vividnext.sodalive.extensions.convertLocalDateTime
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
|
||||
@Service
|
||||
class AdminChannelDonationCalculateService(
|
||||
private val repository: AdminChannelDonationCalculateQueryRepository
|
||||
) {
|
||||
@Transactional(readOnly = true)
|
||||
fun getChannelDonationByCreator(
|
||||
startDateStr: String,
|
||||
endDateStr: String,
|
||||
offset: Long,
|
||||
limit: Long
|
||||
): GetAdminChannelDonationSettlementResponse {
|
||||
val startDate = startDateStr.convertLocalDateTime()
|
||||
val endDate = endDateStr.convertLocalDateTime(hour = 23, minute = 59, second = 59)
|
||||
|
||||
val totalCount = repository.getChannelDonationByCreatorTotalCount(startDate, endDate)
|
||||
val items = repository
|
||||
.getChannelDonationByCreator(startDate, endDate, offset, limit)
|
||||
.map { it.toResponseItem() }
|
||||
|
||||
return GetAdminChannelDonationSettlementResponse(totalCount, items)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package kr.co.vividnext.sodalive.admin.calculate.channelDonation
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
|
||||
data class GetAdminChannelDonationSettlementItem(
|
||||
@JsonProperty("date") val date: String,
|
||||
@JsonProperty("creator") val creator: String,
|
||||
@JsonProperty("count") val count: Int,
|
||||
@JsonProperty("totalCan") val totalCan: Int,
|
||||
@JsonProperty("krw") val krw: Int,
|
||||
@JsonProperty("fee") val fee: Int,
|
||||
@JsonProperty("settlementAmount") val settlementAmount: Int,
|
||||
@JsonProperty("withholdingTax") val withholdingTax: Int,
|
||||
@JsonProperty("depositAmount") val depositAmount: Int
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
package kr.co.vividnext.sodalive.admin.calculate.channelDonation
|
||||
|
||||
import com.querydsl.core.annotations.QueryProjection
|
||||
import kr.co.vividnext.sodalive.calculate.channelDonation.ChannelDonationSettlementCalculator
|
||||
|
||||
data class GetAdminChannelDonationSettlementQueryData @QueryProjection constructor(
|
||||
val date: String,
|
||||
val creator: String,
|
||||
val count: Long,
|
||||
val totalCan: Int?
|
||||
) {
|
||||
fun toResponseItem(): GetAdminChannelDonationSettlementItem {
|
||||
val settlement = ChannelDonationSettlementCalculator.calculate(totalCan ?: 0)
|
||||
|
||||
return GetAdminChannelDonationSettlementItem(
|
||||
date = date,
|
||||
creator = creator,
|
||||
count = count.toInt(),
|
||||
totalCan = totalCan ?: 0,
|
||||
krw = settlement.krw,
|
||||
fee = settlement.fee,
|
||||
settlementAmount = settlement.settlementAmount,
|
||||
withholdingTax = settlement.withholdingTax,
|
||||
depositAmount = settlement.depositAmount
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package kr.co.vividnext.sodalive.admin.calculate.channelDonation
|
||||
|
||||
data class GetAdminChannelDonationSettlementResponse(
|
||||
val totalCount: Int,
|
||||
val items: List<GetAdminChannelDonationSettlementItem>
|
||||
)
|
||||
Reference in New Issue
Block a user