Merge pull request 'test' (#348) from test into main

Reviewed-on: #348
This commit is contained in:
2025-10-10 19:19:47 +00:00
6 changed files with 53 additions and 33 deletions

View File

@@ -21,6 +21,7 @@ class AdminChargeStatusController(private val service: AdminChargeStatusService)
@GetMapping("/detail") @GetMapping("/detail")
fun getChargeStatusDetail( fun getChargeStatusDetail(
@RequestParam startDateStr: String, @RequestParam startDateStr: String,
@RequestParam paymentGateway: PaymentGateway @RequestParam paymentGateway: PaymentGateway,
) = ApiResponse.ok(service.getChargeStatusDetail(startDateStr, paymentGateway)) @RequestParam(value = "currency", required = false) currency: String? = null
) = ApiResponse.ok(service.getChargeStatusDetail(startDateStr, paymentGateway, currency))
} }

View File

@@ -1,5 +1,6 @@
package kr.co.vividnext.sodalive.admin.charge package kr.co.vividnext.sodalive.admin.charge
import com.querydsl.core.BooleanBuilder
import com.querydsl.core.types.dsl.Expressions import com.querydsl.core.types.dsl.Expressions
import com.querydsl.jpa.impl.JPAQueryFactory import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.can.QCan.can1 import kr.co.vividnext.sodalive.can.QCan.can1
@@ -26,6 +27,7 @@ class AdminChargeStatusQueryRepository(private val queryFactory: JPAQueryFactory
), ),
"%Y-%m-%d" "%Y-%m-%d"
) )
val currency = Expressions.stringTemplate("substring({0}, length({0}) - 2, 3)", payment.locale)
return queryFactory return queryFactory
.select( .select(
@@ -33,7 +35,8 @@ class AdminChargeStatusQueryRepository(private val queryFactory: JPAQueryFactory
formattedDate, formattedDate,
payment.price.sum(), payment.price.sum(),
payment.id.count(), payment.id.count(),
payment.paymentGateway payment.paymentGateway,
currency
) )
) )
.from(payment) .from(payment)
@@ -45,7 +48,7 @@ class AdminChargeStatusQueryRepository(private val queryFactory: JPAQueryFactory
.and(charge.status.eq(ChargeStatus.CHARGE)) .and(charge.status.eq(ChargeStatus.CHARGE))
.and(payment.status.eq(PaymentStatus.COMPLETE)) .and(payment.status.eq(PaymentStatus.COMPLETE))
) )
.groupBy(formattedDate, payment.paymentGateway) .groupBy(formattedDate, payment.paymentGateway, currency)
.orderBy(formattedDate.desc()) .orderBy(formattedDate.desc())
.fetch() .fetch()
} }
@@ -53,7 +56,8 @@ class AdminChargeStatusQueryRepository(private val queryFactory: JPAQueryFactory
fun getChargeStatusDetail( fun getChargeStatusDetail(
startDate: LocalDateTime, startDate: LocalDateTime,
endDate: LocalDateTime, endDate: LocalDateTime,
paymentGateway: PaymentGateway paymentGateway: PaymentGateway,
currency: String? = null
): List<GetChargeStatusDetailQueryDto> { ): List<GetChargeStatusDetailQueryDto> {
val formattedDate = Expressions.stringTemplate( val formattedDate = Expressions.stringTemplate(
"DATE_FORMAT({0}, {1})", "DATE_FORMAT({0}, {1})",
@@ -66,6 +70,17 @@ class AdminChargeStatusQueryRepository(private val queryFactory: JPAQueryFactory
), ),
"%Y-%m-%d %H:%i:%s" "%Y-%m-%d %H:%i:%s"
) )
val currencyExpr = Expressions.stringTemplate("substring({0}, length({0}) - 2, 3)", payment.locale)
val whereBuilder = BooleanBuilder()
whereBuilder.and(charge.createdAt.goe(startDate))
.and(charge.createdAt.loe(endDate))
.and(charge.status.eq(ChargeStatus.CHARGE))
.and(payment.status.eq(PaymentStatus.COMPLETE))
.and(payment.paymentGateway.eq(paymentGateway))
if (currency != null) {
whereBuilder.and(currencyExpr.eq(currency))
}
return queryFactory return queryFactory
.select( .select(
@@ -74,7 +89,7 @@ class AdminChargeStatusQueryRepository(private val queryFactory: JPAQueryFactory
member.nickname, member.nickname,
payment.method.coalesce(""), payment.method.coalesce(""),
payment.price, payment.price,
payment.locale.coalesce(""), currencyExpr.coalesce(""),
formattedDate formattedDate
) )
) )
@@ -82,13 +97,7 @@ class AdminChargeStatusQueryRepository(private val queryFactory: JPAQueryFactory
.innerJoin(charge.member, member) .innerJoin(charge.member, member)
.innerJoin(charge.payment, payment) .innerJoin(charge.payment, payment)
.leftJoin(charge.can, can1) .leftJoin(charge.can, can1)
.where( .where(whereBuilder)
charge.createdAt.goe(startDate)
.and(charge.createdAt.loe(endDate))
.and(charge.status.eq(ChargeStatus.CHARGE))
.and(payment.status.eq(PaymentStatus.COMPLETE))
.and(payment.paymentGateway.eq(paymentGateway))
)
.orderBy(formattedDate.desc()) .orderBy(formattedDate.desc())
.fetch() .fetch()
} }

View File

@@ -20,42 +20,48 @@ class AdminChargeStatusService(val repository: AdminChargeStatusQueryRepository)
.withZoneSameInstant(ZoneId.of("UTC")) .withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime() .toLocalDateTime()
var totalChargeAmount = 0.toBigDecimal() val totalsByCurrency = mutableMapOf<String, Pair<java.math.BigDecimal, Long>>()
var totalChargeCount = 0L
val chargeStatusList = repository.getChargeStatus(startDate, endDate) val chargeStatusList = repository.getChargeStatus(startDate, endDate)
.map { .map {
val chargeAmount = it.amount val chargeAmount = it.amount
val chargeCount = it.chargeCount val chargeCount = it.chargeCount
val currency = it.currency
totalChargeAmount += chargeAmount val prev = totalsByCurrency[currency] ?: (0.toBigDecimal() to 0L)
totalChargeCount += chargeCount totalsByCurrency[currency] = (prev.first + chargeAmount) to (prev.second + chargeCount)
GetChargeStatusResponse( GetChargeStatusResponse(
date = it.date, date = it.date,
chargeAmount = chargeAmount, chargeAmount = chargeAmount,
chargeCount = chargeCount, chargeCount = chargeCount,
pg = it.paymentGateWay.name pg = it.paymentGateWay.name,
currency = currency
) )
} }
.toMutableList() .toMutableList()
chargeStatusList.add( val summaryRows = totalsByCurrency.entries
0, .sortedBy { it.key }
GetChargeStatusResponse( .map { (currency, total) ->
date = "합계", GetChargeStatusResponse(
chargeAmount = totalChargeAmount, date = "합계",
chargeCount = totalChargeCount, chargeAmount = total.first,
pg = "" chargeCount = total.second,
) pg = "",
) currency = currency
)
}
chargeStatusList.addAll(0, summaryRows)
return chargeStatusList.toList() return chargeStatusList.toList()
} }
fun getChargeStatusDetail( fun getChargeStatusDetail(
startDateStr: String, startDateStr: String,
paymentGateway: PaymentGateway paymentGateway: PaymentGateway,
currency: String? = null
): List<GetChargeStatusDetailResponse> { ): List<GetChargeStatusDetailResponse> {
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
val startDate = LocalDate.parse(startDateStr, dateTimeFormatter).atTime(0, 0, 0) val startDate = LocalDate.parse(startDateStr, dateTimeFormatter).atTime(0, 0, 0)
@@ -68,13 +74,13 @@ class AdminChargeStatusService(val repository: AdminChargeStatusQueryRepository)
.withZoneSameInstant(ZoneId.of("UTC")) .withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime() .toLocalDateTime()
return repository.getChargeStatusDetail(startDate, endDate, paymentGateway) return repository.getChargeStatusDetail(startDate, endDate, paymentGateway, currency)
.map { .map {
GetChargeStatusDetailResponse( GetChargeStatusDetailResponse(
memberId = it.memberId, memberId = it.memberId,
nickname = it.nickname, nickname = it.nickname,
method = it.method, method = it.method,
amount = it.amount.toInt(), amount = it.amount,
locale = it.locale, locale = it.locale,
datetime = it.datetime datetime = it.datetime
) )

View File

@@ -1,10 +1,12 @@
package kr.co.vividnext.sodalive.admin.charge package kr.co.vividnext.sodalive.admin.charge
import java.math.BigDecimal
data class GetChargeStatusDetailResponse( data class GetChargeStatusDetailResponse(
val memberId: Long, val memberId: Long,
val nickname: String, val nickname: String,
val method: String, val method: String,
val amount: Int, val amount: BigDecimal,
val locale: String, val locale: String,
val datetime: String val datetime: String
) )

View File

@@ -8,5 +8,6 @@ data class GetChargeStatusQueryDto @QueryProjection constructor(
val date: String, val date: String,
val amount: BigDecimal, val amount: BigDecimal,
val chargeCount: Long, val chargeCount: Long,
val paymentGateWay: PaymentGateway val paymentGateWay: PaymentGateway,
val currency: String
) )

View File

@@ -6,5 +6,6 @@ data class GetChargeStatusResponse(
val date: String, val date: String,
val chargeAmount: BigDecimal, val chargeAmount: BigDecimal,
val chargeCount: Long, val chargeCount: Long,
val pg: String val pg: String,
val currency: String
) )