관리자 - 라이브 정산 API 추가
This commit is contained in:
		| @@ -0,0 +1,19 @@ | ||||
| package kr.co.vividnext.sodalive.admin.calculate | ||||
|  | ||||
| import kr.co.vividnext.sodalive.common.ApiResponse | ||||
| 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 AdminCalculateController(private val service: AdminCalculateService) { | ||||
|     @GetMapping("/live") | ||||
|     fun getCalculateLive( | ||||
|         @RequestParam startDateStr: String, | ||||
|         @RequestParam endDateStr: String | ||||
|     ) = ApiResponse.ok(service.getCalculateLive(startDateStr, endDateStr)) | ||||
| } | ||||
| @@ -0,0 +1,53 @@ | ||||
| package kr.co.vividnext.sodalive.admin.calculate | ||||
|  | ||||
| import com.querydsl.core.types.dsl.Expressions | ||||
| import com.querydsl.jpa.impl.JPAQueryFactory | ||||
| 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.live.room.QLiveRoom.liveRoom | ||||
| import kr.co.vividnext.sodalive.member.QMember.member | ||||
| import org.springframework.stereotype.Repository | ||||
| import java.time.LocalDateTime | ||||
|  | ||||
| @Repository | ||||
| class AdminCalculateQueryRepository(private val queryFactory: JPAQueryFactory) { | ||||
|     fun getCalculateLive(startDate: LocalDateTime, endDate: LocalDateTime): List<GetCalculateLiveQueryData> { | ||||
|         val formattedDate = Expressions.stringTemplate( | ||||
|             "DATE_FORMAT({0}, {1})", | ||||
|             Expressions.dateTimeTemplate( | ||||
|                 LocalDateTime::class.java, | ||||
|                 "CONVERT_TZ({0},{1},{2})", | ||||
|                 liveRoom.beginDateTime, | ||||
|                 "UTC", | ||||
|                 "Asia/Seoul" | ||||
|             ), | ||||
|             "%Y-%m-%d" | ||||
|         ) | ||||
|  | ||||
|         return queryFactory | ||||
|             .select( | ||||
|                 QGetCalculateLiveQueryData( | ||||
|                     member.email, | ||||
|                     member.nickname, | ||||
|                     formattedDate, | ||||
|                     liveRoom.title, | ||||
|                     liveRoom.price, | ||||
|                     useCan.canUsage, | ||||
|                     useCanCalculate.can.sum() | ||||
|                 ) | ||||
|             ) | ||||
|             .from(useCanCalculate) | ||||
|             .innerJoin(useCanCalculate.useCan, useCan) | ||||
|             .innerJoin(useCan.room, liveRoom) | ||||
|             .innerJoin(liveRoom.member, member) | ||||
|             .where( | ||||
|                 useCanCalculate.status.eq(UseCanCalculateStatus.RECEIVED) | ||||
|                     .and(liveRoom.beginDateTime.goe(startDate)) | ||||
|                     .and(liveRoom.beginDateTime.loe(endDate)) | ||||
|             ) | ||||
|             .groupBy(liveRoom.id, useCan.canUsage) | ||||
|             .orderBy(member.nickname.desc(), formattedDate.desc()) | ||||
|             .fetch() | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,66 @@ | ||||
| package kr.co.vividnext.sodalive.admin.calculate | ||||
|  | ||||
| import kr.co.vividnext.sodalive.can.use.CanUsage | ||||
| import org.springframework.stereotype.Service | ||||
| import java.time.LocalDate | ||||
| import java.time.ZoneId | ||||
| import java.time.format.DateTimeFormatter | ||||
| import kotlin.math.roundToInt | ||||
|  | ||||
| @Service | ||||
| class AdminCalculateService(private val repository: AdminCalculateQueryRepository) { | ||||
|     fun getCalculateLive(startDateStr: String, endDateStr: String): List<GetCalculateLiveResponse> { | ||||
|         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() | ||||
|  | ||||
|         return repository | ||||
|             .getCalculateLive(startDate, endDate) | ||||
|             .asSequence() | ||||
|             .map { | ||||
|                 val canUsageStr = if (it.canUsage == CanUsage.LIVE) { | ||||
|                     "유료방 참여" | ||||
|                 } else { | ||||
|                     "후원" | ||||
|                 } | ||||
|  | ||||
|                 // 원화 = totalCoin * 100 ( 캔 1개 = 100원 ) | ||||
|                 val totalKrw = it.totalAmount * 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 | ||||
|  | ||||
|                 GetCalculateLiveResponse( | ||||
|                     email = it.email, | ||||
|                     nickname = it.nickname, | ||||
|                     date = it.date, | ||||
|                     title = it.title, | ||||
|                     entranceFee = it.entranceFee, | ||||
|                     coinUsageStr = canUsageStr, | ||||
|                     totalAmount = it.totalAmount, | ||||
|                     totalKrw = totalKrw, | ||||
|                     paymentFee = paymentFee.roundToInt(), | ||||
|                     settlementAmount = settlementAmount.roundToInt(), | ||||
|                     tax = tax.roundToInt(), | ||||
|                     depositAmount = depositAmount.roundToInt() | ||||
|                 ) | ||||
|             } | ||||
|             .toList() | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,17 @@ | ||||
| package kr.co.vividnext.sodalive.admin.calculate | ||||
|  | ||||
| import com.querydsl.core.annotations.QueryProjection | ||||
| import kr.co.vividnext.sodalive.can.use.CanUsage | ||||
|  | ||||
| data class GetCalculateLiveQueryData @QueryProjection constructor( | ||||
|     val email: String, | ||||
|     val nickname: String, | ||||
|     val date: String, | ||||
|     val title: String, | ||||
|     // 유료방 입장 금액 | ||||
|     val entranceFee: Int, | ||||
|     // 코인 사용 구분 | ||||
|     val canUsage: CanUsage, | ||||
|     // 합계 | ||||
|     val totalAmount: Int | ||||
| ) | ||||
| @@ -0,0 +1,24 @@ | ||||
| package kr.co.vividnext.sodalive.admin.calculate | ||||
|  | ||||
| data class GetCalculateLiveResponse( | ||||
|     val email: String, | ||||
|     val nickname: String, | ||||
|     val date: String, | ||||
|     val title: String, | ||||
|     // 유료방 입장 금액 | ||||
|     val entranceFee: Int, | ||||
|     // 코인 사용 구분 | ||||
|     val coinUsageStr: String, | ||||
|     // 합계 | ||||
|     val totalAmount: Int, | ||||
|     // 원화 | ||||
|     val totalKrw: Int, | ||||
|     // 결제수수료 | ||||
|     val paymentFee: Int, | ||||
|     // 정산금액 | ||||
|     val settlementAmount: Int, | ||||
|     // 원천세(세금 3.3%) | ||||
|     val tax: Int, | ||||
|     // 입금액 | ||||
|     val depositAmount: Int | ||||
| ) | ||||
		Reference in New Issue
	
	Block a user