fix(calculate): 관리자 정산 엑셀 다운로드를 스트리밍 방식으로 전환한다
This commit is contained in:
@@ -2,11 +2,17 @@ package kr.co.vividnext.sodalive.admin.calculate
|
||||
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.http.ResponseEntity
|
||||
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
|
||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
@RestController
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@@ -18,12 +24,30 @@ class AdminCalculateController(private val service: AdminCalculateService) {
|
||||
@RequestParam endDateStr: String
|
||||
) = ApiResponse.ok(service.getCalculateLive(startDateStr, endDateStr))
|
||||
|
||||
@GetMapping("/live/excel")
|
||||
fun downloadCalculateLiveExcel(
|
||||
@RequestParam startDateStr: String,
|
||||
@RequestParam endDateStr: String
|
||||
): ResponseEntity<StreamingResponseBody> = createExcelResponse(
|
||||
fileName = "live.xlsx",
|
||||
response = service.downloadCalculateLiveExcel(startDateStr, endDateStr)
|
||||
)
|
||||
|
||||
@GetMapping("/content-list")
|
||||
fun getCalculateContentList(
|
||||
@RequestParam startDateStr: String,
|
||||
@RequestParam endDateStr: String
|
||||
) = ApiResponse.ok(service.getCalculateContentList(startDateStr, endDateStr))
|
||||
|
||||
@GetMapping("/content-list/excel")
|
||||
fun downloadCalculateContentListExcel(
|
||||
@RequestParam startDateStr: String,
|
||||
@RequestParam endDateStr: String
|
||||
): ResponseEntity<StreamingResponseBody> = createExcelResponse(
|
||||
fileName = "content-list.xlsx",
|
||||
response = service.downloadCalculateContentListExcel(startDateStr, endDateStr)
|
||||
)
|
||||
|
||||
@GetMapping("/cumulative-sales-by-content")
|
||||
fun getCumulativeSalesByContent(pageable: Pageable) = ApiResponse.ok(
|
||||
service.getCumulativeSalesByContent(pageable.offset, pageable.pageSize.toLong())
|
||||
@@ -35,6 +59,15 @@ class AdminCalculateController(private val service: AdminCalculateService) {
|
||||
@RequestParam endDateStr: String
|
||||
) = ApiResponse.ok(service.getCalculateContentDonationList(startDateStr, endDateStr))
|
||||
|
||||
@GetMapping("/content-donation-list/excel")
|
||||
fun downloadCalculateContentDonationListExcel(
|
||||
@RequestParam startDateStr: String,
|
||||
@RequestParam endDateStr: String
|
||||
): ResponseEntity<StreamingResponseBody> = createExcelResponse(
|
||||
fileName = "content-donation-list.xlsx",
|
||||
response = service.downloadCalculateContentDonationListExcel(startDateStr, endDateStr)
|
||||
)
|
||||
|
||||
@GetMapping("/community-post")
|
||||
fun getCalculateCommunityPost(
|
||||
@RequestParam startDateStr: String,
|
||||
@@ -49,6 +82,15 @@ class AdminCalculateController(private val service: AdminCalculateService) {
|
||||
)
|
||||
)
|
||||
|
||||
@GetMapping("/community-post/excel")
|
||||
fun downloadCalculateCommunityPostExcel(
|
||||
@RequestParam startDateStr: String,
|
||||
@RequestParam endDateStr: String
|
||||
): ResponseEntity<StreamingResponseBody> = createExcelResponse(
|
||||
fileName = "community-post.xlsx",
|
||||
response = service.downloadCalculateCommunityPostExcel(startDateStr, endDateStr)
|
||||
)
|
||||
|
||||
@GetMapping("/live-by-creator")
|
||||
fun getCalculateLiveByCreator(
|
||||
@RequestParam startDateStr: String,
|
||||
@@ -63,6 +105,15 @@ class AdminCalculateController(private val service: AdminCalculateService) {
|
||||
)
|
||||
)
|
||||
|
||||
@GetMapping("/live-by-creator/excel")
|
||||
fun downloadCalculateLiveByCreatorExcel(
|
||||
@RequestParam startDateStr: String,
|
||||
@RequestParam endDateStr: String
|
||||
): ResponseEntity<StreamingResponseBody> = createExcelResponse(
|
||||
fileName = "live-by-creator.xlsx",
|
||||
response = service.downloadCalculateLiveByCreatorExcel(startDateStr, endDateStr)
|
||||
)
|
||||
|
||||
@GetMapping("/content-by-creator")
|
||||
fun getCalculateContentByCreator(
|
||||
@RequestParam startDateStr: String,
|
||||
@@ -77,6 +128,15 @@ class AdminCalculateController(private val service: AdminCalculateService) {
|
||||
)
|
||||
)
|
||||
|
||||
@GetMapping("/content-by-creator/excel")
|
||||
fun downloadCalculateContentByCreatorExcel(
|
||||
@RequestParam startDateStr: String,
|
||||
@RequestParam endDateStr: String
|
||||
): ResponseEntity<StreamingResponseBody> = createExcelResponse(
|
||||
fileName = "content-by-creator.xlsx",
|
||||
response = service.downloadCalculateContentByCreatorExcel(startDateStr, endDateStr)
|
||||
)
|
||||
|
||||
@GetMapping("/community-by-creator")
|
||||
fun getCalculateCommunityByCreator(
|
||||
@RequestParam startDateStr: String,
|
||||
@@ -90,4 +150,28 @@ class AdminCalculateController(private val service: AdminCalculateService) {
|
||||
pageable.pageSize.toLong()
|
||||
)
|
||||
)
|
||||
|
||||
@GetMapping("/community-by-creator/excel")
|
||||
fun downloadCalculateCommunityByCreatorExcel(
|
||||
@RequestParam startDateStr: String,
|
||||
@RequestParam endDateStr: String
|
||||
): ResponseEntity<StreamingResponseBody> = createExcelResponse(
|
||||
fileName = "community-by-creator.xlsx",
|
||||
response = service.downloadCalculateCommunityByCreatorExcel(startDateStr, endDateStr)
|
||||
)
|
||||
|
||||
private fun createExcelResponse(
|
||||
fileName: String,
|
||||
response: StreamingResponseBody
|
||||
): ResponseEntity<StreamingResponseBody> {
|
||||
val encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replace("+", "%20")
|
||||
val headers = HttpHeaders().apply {
|
||||
add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''$encodedFileName")
|
||||
}
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.headers(headers)
|
||||
.contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
|
||||
.body(response)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,13 @@ package kr.co.vividnext.sodalive.admin.calculate
|
||||
|
||||
import kr.co.vividnext.sodalive.creator.admin.calculate.GetCreatorCalculateCommunityPostResponse
|
||||
import kr.co.vividnext.sodalive.extensions.convertLocalDateTime
|
||||
import org.apache.poi.ss.usermodel.Sheet
|
||||
import org.apache.poi.xssf.streaming.SXSSFWorkbook
|
||||
import org.springframework.cache.annotation.Cacheable
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Service
|
||||
class AdminCalculateService(private val repository: AdminCalculateQueryRepository) {
|
||||
@@ -139,4 +143,286 @@ class AdminCalculateService(private val repository: AdminCalculateQueryRepositor
|
||||
|
||||
GetCalculateByCreatorResponse(totalCount, items)
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun downloadCalculateLiveExcel(startDateStr: String, endDateStr: String): StreamingResponseBody {
|
||||
val (startDate, endDate) = toDateRange(startDateStr, endDateStr)
|
||||
val items = repository
|
||||
.getCalculateLive(startDate, endDate)
|
||||
.map { it.toGetCalculateLiveResponse() }
|
||||
|
||||
return createExcelStream(
|
||||
sheetName = "라이브 정산",
|
||||
headers = listOf(
|
||||
"이메일",
|
||||
"닉네임",
|
||||
"날짜",
|
||||
"라이브 제목",
|
||||
"입장료(캔)",
|
||||
"사용구분",
|
||||
"참여인원",
|
||||
"총 캔",
|
||||
"원화",
|
||||
"결제수수료",
|
||||
"정산금액",
|
||||
"원천세",
|
||||
"입금액"
|
||||
)
|
||||
) { sheet ->
|
||||
items.forEachIndexed { index, item ->
|
||||
val row = sheet.createRow(index + 1)
|
||||
row.createCell(0).setCellValue(item.email)
|
||||
row.createCell(1).setCellValue(item.nickname)
|
||||
row.createCell(2).setCellValue(item.date)
|
||||
row.createCell(3).setCellValue(item.title)
|
||||
row.createCell(4).setCellValue(item.entranceFee.toDouble())
|
||||
row.createCell(5).setCellValue(item.canUsageStr)
|
||||
row.createCell(6).setCellValue(item.numberOfPeople.toDouble())
|
||||
row.createCell(7).setCellValue(item.totalAmount.toDouble())
|
||||
row.createCell(8).setCellValue(item.totalKrw.toDouble())
|
||||
row.createCell(9).setCellValue(item.paymentFee.toDouble())
|
||||
row.createCell(10).setCellValue(item.settlementAmount.toDouble())
|
||||
row.createCell(11).setCellValue(item.tax.toDouble())
|
||||
row.createCell(12).setCellValue(item.depositAmount.toDouble())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun downloadCalculateContentListExcel(startDateStr: String, endDateStr: String): StreamingResponseBody {
|
||||
val (startDate, endDate) = toDateRange(startDateStr, endDateStr)
|
||||
val items = repository
|
||||
.getCalculateContentList(startDate, endDate)
|
||||
.map { it.toGetCalculateContentResponse() }
|
||||
|
||||
return createExcelStream(
|
||||
sheetName = "콘텐츠 정산",
|
||||
headers = listOf(
|
||||
"크리에이터",
|
||||
"콘텐츠 제목",
|
||||
"등록일",
|
||||
"판매일",
|
||||
"구분",
|
||||
"가격(캔)",
|
||||
"인원",
|
||||
"총 캔",
|
||||
"원화",
|
||||
"결제수수료",
|
||||
"정산금액",
|
||||
"원천세",
|
||||
"입금액"
|
||||
)
|
||||
) { sheet ->
|
||||
items.forEachIndexed { index, item ->
|
||||
val row = sheet.createRow(index + 1)
|
||||
row.createCell(0).setCellValue(item.nickname)
|
||||
row.createCell(1).setCellValue(item.title)
|
||||
row.createCell(2).setCellValue(item.registrationDate)
|
||||
row.createCell(3).setCellValue(item.saleDate)
|
||||
row.createCell(4).setCellValue(item.orderType)
|
||||
row.createCell(5).setCellValue(item.orderPrice.toDouble())
|
||||
row.createCell(6).setCellValue(item.numberOfPeople.toDouble())
|
||||
row.createCell(7).setCellValue(item.totalCan.toDouble())
|
||||
row.createCell(8).setCellValue(item.totalKrw.toDouble())
|
||||
row.createCell(9).setCellValue(item.paymentFee.toDouble())
|
||||
row.createCell(10).setCellValue(item.settlementAmount.toDouble())
|
||||
row.createCell(11).setCellValue(item.tax.toDouble())
|
||||
row.createCell(12).setCellValue(item.depositAmount.toDouble())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun downloadCalculateContentDonationListExcel(startDateStr: String, endDateStr: String): StreamingResponseBody {
|
||||
val (startDate, endDate) = toDateRange(startDateStr, endDateStr)
|
||||
val items = repository
|
||||
.getCalculateContentDonationList(startDate, endDate)
|
||||
.map { it.toGetCalculateContentDonationResponse() }
|
||||
|
||||
return createExcelStream(
|
||||
sheetName = "콘텐츠 후원 정산",
|
||||
headers = listOf(
|
||||
"크리에이터",
|
||||
"콘텐츠 제목",
|
||||
"유무료",
|
||||
"등록일",
|
||||
"후원일",
|
||||
"후원건수",
|
||||
"총 캔",
|
||||
"원화",
|
||||
"결제수수료",
|
||||
"정산금액",
|
||||
"원천세",
|
||||
"입금액"
|
||||
)
|
||||
) { sheet ->
|
||||
items.forEachIndexed { index, item ->
|
||||
val row = sheet.createRow(index + 1)
|
||||
row.createCell(0).setCellValue(item.nickname)
|
||||
row.createCell(1).setCellValue(item.title)
|
||||
row.createCell(2).setCellValue(item.paidOrFree)
|
||||
row.createCell(3).setCellValue(item.registrationDate)
|
||||
row.createCell(4).setCellValue(item.donationDate)
|
||||
row.createCell(5).setCellValue(item.numberOfDonation.toDouble())
|
||||
row.createCell(6).setCellValue(item.totalCan.toDouble())
|
||||
row.createCell(7).setCellValue(item.totalKrw.toDouble())
|
||||
row.createCell(8).setCellValue(item.paymentFee.toDouble())
|
||||
row.createCell(9).setCellValue(item.settlementAmount.toDouble())
|
||||
row.createCell(10).setCellValue(item.tax.toDouble())
|
||||
row.createCell(11).setCellValue(item.depositAmount.toDouble())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun downloadCalculateCommunityPostExcel(startDateStr: String, endDateStr: String): StreamingResponseBody {
|
||||
val (startDate, endDate) = toDateRange(startDateStr, endDateStr)
|
||||
val totalCount = repository.getCalculateCommunityPostTotalCount(startDate, endDate)
|
||||
val items = if (totalCount == 0) {
|
||||
emptyList()
|
||||
} else {
|
||||
repository
|
||||
.getCalculateCommunityPostList(startDate, endDate, 0L, totalCount.toLong())
|
||||
.map { it.toGetCalculateCommunityPostResponse() }
|
||||
}
|
||||
|
||||
return createExcelStream(
|
||||
sheetName = "커뮤니티 정산",
|
||||
headers = listOf(
|
||||
"크리에이터",
|
||||
"게시글",
|
||||
"날짜",
|
||||
"가격(캔)",
|
||||
"구매건수",
|
||||
"총 캔",
|
||||
"원화",
|
||||
"결제수수료",
|
||||
"정산금액",
|
||||
"원천세",
|
||||
"입금액"
|
||||
)
|
||||
) { sheet ->
|
||||
items.forEachIndexed { index, item ->
|
||||
val row = sheet.createRow(index + 1)
|
||||
row.createCell(0).setCellValue(item.nickname)
|
||||
row.createCell(1).setCellValue(item.title)
|
||||
row.createCell(2).setCellValue(item.date)
|
||||
row.createCell(3).setCellValue(item.can.toDouble())
|
||||
row.createCell(4).setCellValue(item.numberOfPurchase.toDouble())
|
||||
row.createCell(5).setCellValue(item.totalCan.toDouble())
|
||||
row.createCell(6).setCellValue(item.totalKrw.toDouble())
|
||||
row.createCell(7).setCellValue(item.paymentFee.toDouble())
|
||||
row.createCell(8).setCellValue(item.settlementAmount.toDouble())
|
||||
row.createCell(9).setCellValue(item.tax.toDouble())
|
||||
row.createCell(10).setCellValue(item.depositAmount.toDouble())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun downloadCalculateLiveByCreatorExcel(startDateStr: String, endDateStr: String): StreamingResponseBody {
|
||||
val (startDate, endDate) = toDateRange(startDateStr, endDateStr)
|
||||
val totalCount = repository.getCalculateLiveByCreatorTotalCount(startDate, endDate)
|
||||
val items = if (totalCount == 0) {
|
||||
emptyList()
|
||||
} else {
|
||||
repository
|
||||
.getCalculateLiveByCreator(startDate, endDate, 0L, totalCount.toLong())
|
||||
.map { it.toGetCalculateByCreator() }
|
||||
}
|
||||
|
||||
return createCalculateByCreatorExcel("크리에이터별 라이브 정산", items)
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun downloadCalculateContentByCreatorExcel(startDateStr: String, endDateStr: String): StreamingResponseBody {
|
||||
val (startDate, endDate) = toDateRange(startDateStr, endDateStr)
|
||||
val totalCount = repository.getCalculateContentByCreatorTotalCount(startDate, endDate)
|
||||
val items = if (totalCount == 0) {
|
||||
emptyList()
|
||||
} else {
|
||||
repository
|
||||
.getCalculateContentByCreator(startDate, endDate, 0L, totalCount.toLong())
|
||||
.map { it.toGetCalculateByCreator() }
|
||||
}
|
||||
|
||||
return createCalculateByCreatorExcel("크리에이터별 콘텐츠 정산", items)
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun downloadCalculateCommunityByCreatorExcel(startDateStr: String, endDateStr: String): StreamingResponseBody {
|
||||
val (startDate, endDate) = toDateRange(startDateStr, endDateStr)
|
||||
val totalCount = repository.getCalculateCommunityByCreatorTotalCount(startDate, endDate)
|
||||
val items = if (totalCount == 0) {
|
||||
emptyList()
|
||||
} else {
|
||||
repository
|
||||
.getCalculateCommunityByCreator(startDate, endDate, 0L, totalCount.toLong())
|
||||
.map { it.toGetCalculateByCreator() }
|
||||
}
|
||||
|
||||
return createCalculateByCreatorExcel("크리에이터별 커뮤니티 정산", items)
|
||||
}
|
||||
|
||||
private fun createCalculateByCreatorExcel(
|
||||
sheetName: String,
|
||||
items: List<GetCalculateByCreatorItem>
|
||||
): StreamingResponseBody {
|
||||
return createExcelStream(
|
||||
sheetName = sheetName,
|
||||
headers = listOf(
|
||||
"이메일",
|
||||
"닉네임",
|
||||
"총 캔",
|
||||
"원화",
|
||||
"결제수수료",
|
||||
"정산금액",
|
||||
"원천세",
|
||||
"입금액"
|
||||
)
|
||||
) { sheet ->
|
||||
items.forEachIndexed { index, item ->
|
||||
val row = sheet.createRow(index + 1)
|
||||
row.createCell(0).setCellValue(item.email)
|
||||
row.createCell(1).setCellValue(item.nickname)
|
||||
row.createCell(2).setCellValue(item.totalCan.toDouble())
|
||||
row.createCell(3).setCellValue(item.totalKrw.toDouble())
|
||||
row.createCell(4).setCellValue(item.paymentFee.toDouble())
|
||||
row.createCell(5).setCellValue(item.settlementAmount.toDouble())
|
||||
row.createCell(6).setCellValue(item.tax.toDouble())
|
||||
row.createCell(7).setCellValue(item.depositAmount.toDouble())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createExcelStream(
|
||||
sheetName: String,
|
||||
headers: List<String>,
|
||||
writeRows: (Sheet) -> Unit
|
||||
): StreamingResponseBody {
|
||||
return StreamingResponseBody { outputStream ->
|
||||
val workbook = SXSSFWorkbook(100)
|
||||
try {
|
||||
val sheet = workbook.createSheet(sheetName)
|
||||
val headerRow = sheet.createRow(0)
|
||||
headers.forEachIndexed { index, value ->
|
||||
headerRow.createCell(index).setCellValue(value)
|
||||
}
|
||||
|
||||
writeRows(sheet)
|
||||
workbook.write(outputStream)
|
||||
outputStream.flush()
|
||||
} finally {
|
||||
workbook.dispose()
|
||||
workbook.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun toDateRange(startDateStr: String, endDateStr: String): Pair<LocalDateTime, LocalDateTime> {
|
||||
val startDate = startDateStr.convertLocalDateTime()
|
||||
val endDate = endDateStr.convertLocalDateTime(hour = 23, minute = 59, second = 59)
|
||||
|
||||
return startDate to endDate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package kr.co.vividnext.sodalive.admin.calculate.channelDonation
|
||||
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import org.springframework.core.io.InputStreamResource
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.http.HttpHeaders
|
||||
import org.springframework.http.MediaType
|
||||
@@ -11,6 +10,7 @@ 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
|
||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
@@ -34,6 +34,15 @@ class AdminChannelDonationCalculateController(
|
||||
)
|
||||
)
|
||||
|
||||
@GetMapping("/channel-donation-by-date/excel")
|
||||
fun downloadChannelDonationByDateExcel(
|
||||
@RequestParam startDateStr: String,
|
||||
@RequestParam endDateStr: String
|
||||
): ResponseEntity<StreamingResponseBody> = createExcelResponse(
|
||||
fileName = "channel-donation-by-date.xlsx",
|
||||
response = service.downloadChannelDonationByDateExcel(startDateStr, endDateStr)
|
||||
)
|
||||
|
||||
@GetMapping("/channel-donation-by-creator")
|
||||
fun getChannelDonationByCreator(
|
||||
@RequestParam startDateStr: String,
|
||||
@@ -52,23 +61,23 @@ class AdminChannelDonationCalculateController(
|
||||
fun downloadChannelDonationByCreatorExcel(
|
||||
@RequestParam startDateStr: String,
|
||||
@RequestParam endDateStr: String
|
||||
): ResponseEntity<InputStreamResource> {
|
||||
val encodedFileName = URLEncoder.encode(
|
||||
"channel-donation-by-creator.xlsx",
|
||||
StandardCharsets.UTF_8.toString()
|
||||
).replace("+", "%20")
|
||||
): ResponseEntity<StreamingResponseBody> = createExcelResponse(
|
||||
fileName = "channel-donation-by-creator.xlsx",
|
||||
response = service.downloadChannelDonationByCreatorExcel(startDateStr, endDateStr)
|
||||
)
|
||||
|
||||
private fun createExcelResponse(
|
||||
fileName: String,
|
||||
response: StreamingResponseBody
|
||||
): ResponseEntity<StreamingResponseBody> {
|
||||
val encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString()).replace("+", "%20")
|
||||
val headers = HttpHeaders().apply {
|
||||
add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''$encodedFileName")
|
||||
}
|
||||
|
||||
val response = service.downloadChannelDonationByCreatorExcel(
|
||||
startDateStr = startDateStr,
|
||||
endDateStr = endDateStr
|
||||
)
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.headers(headers)
|
||||
.contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
|
||||
.body(InputStreamResource(response))
|
||||
.body(response)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package kr.co.vividnext.sodalive.admin.calculate.channelDonation
|
||||
|
||||
import kr.co.vividnext.sodalive.extensions.convertLocalDateTime
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook
|
||||
import org.apache.poi.ss.usermodel.Sheet
|
||||
import org.apache.poi.xssf.streaming.SXSSFWorkbook
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Service
|
||||
class AdminChannelDonationCalculateService(
|
||||
@@ -50,17 +51,21 @@ class AdminChannelDonationCalculateService(
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun downloadChannelDonationByCreatorExcel(startDateStr: String, endDateStr: String): ByteArrayInputStream {
|
||||
val startDate = startDateStr.convertLocalDateTime()
|
||||
val endDate = endDateStr.convertLocalDateTime(hour = 23, minute = 59, second = 59)
|
||||
val items = repository
|
||||
.getChannelDonationByCreatorForExcel(startDate, endDate)
|
||||
.map { it.toResponseItem() }
|
||||
val byteArrayOutputStream = ByteArrayOutputStream()
|
||||
fun downloadChannelDonationByDateExcel(startDateStr: String, endDateStr: String): StreamingResponseBody {
|
||||
val (startDate, endDate) = toDateRange(startDateStr, endDateStr)
|
||||
val totalCount = repository.getChannelDonationByDateTotalCount(startDate, endDate)
|
||||
val items = if (totalCount == 0) {
|
||||
emptyList()
|
||||
} else {
|
||||
repository
|
||||
.getChannelDonationByDate(startDate, endDate, 0L, totalCount.toLong())
|
||||
.map { it.toResponseItem() }
|
||||
}
|
||||
|
||||
XSSFWorkbook().use { workbook ->
|
||||
val sheet = workbook.createSheet("크리에이터별 채널후원 정산")
|
||||
val header = listOf(
|
||||
return createExcelStream(
|
||||
sheetName = "채널후원 정산",
|
||||
headers = listOf(
|
||||
"날짜",
|
||||
"크리에이터",
|
||||
"건수",
|
||||
"총 받은 캔 수",
|
||||
@@ -70,11 +75,42 @@ class AdminChannelDonationCalculateService(
|
||||
"원천세",
|
||||
"입금액"
|
||||
)
|
||||
val headerRow = sheet.createRow(0)
|
||||
header.forEachIndexed { index, value ->
|
||||
headerRow.createCell(index).setCellValue(value)
|
||||
) { sheet ->
|
||||
items.forEachIndexed { index, item ->
|
||||
val row = sheet.createRow(index + 1)
|
||||
row.createCell(0).setCellValue(item.date)
|
||||
row.createCell(1).setCellValue(item.creator)
|
||||
row.createCell(2).setCellValue(item.count.toDouble())
|
||||
row.createCell(3).setCellValue(item.totalCan.toDouble())
|
||||
row.createCell(4).setCellValue(item.krw.toDouble())
|
||||
row.createCell(5).setCellValue(item.fee.toDouble())
|
||||
row.createCell(6).setCellValue(item.settlementAmount.toDouble())
|
||||
row.createCell(7).setCellValue(item.withholdingTax.toDouble())
|
||||
row.createCell(8).setCellValue(item.depositAmount.toDouble())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun downloadChannelDonationByCreatorExcel(startDateStr: String, endDateStr: String): StreamingResponseBody {
|
||||
val (startDate, endDate) = toDateRange(startDateStr, endDateStr)
|
||||
val items = repository
|
||||
.getChannelDonationByCreatorForExcel(startDate, endDate)
|
||||
.map { it.toResponseItem() }
|
||||
|
||||
return createExcelStream(
|
||||
sheetName = "크리에이터별 채널후원 정산",
|
||||
headers = listOf(
|
||||
"크리에이터",
|
||||
"건수",
|
||||
"총 받은 캔 수",
|
||||
"원화",
|
||||
"수수료",
|
||||
"정산금액",
|
||||
"원천세",
|
||||
"입금액"
|
||||
)
|
||||
) { sheet ->
|
||||
items.forEachIndexed { index, item ->
|
||||
val row = sheet.createRow(index + 1)
|
||||
row.createCell(0).setCellValue(item.creator)
|
||||
@@ -86,10 +122,37 @@ class AdminChannelDonationCalculateService(
|
||||
row.createCell(6).setCellValue(item.withholdingTax.toDouble())
|
||||
row.createCell(7).setCellValue(item.depositAmount.toDouble())
|
||||
}
|
||||
|
||||
workbook.write(byteArrayOutputStream)
|
||||
}
|
||||
}
|
||||
|
||||
return ByteArrayInputStream(byteArrayOutputStream.toByteArray())
|
||||
private fun createExcelStream(
|
||||
sheetName: String,
|
||||
headers: List<String>,
|
||||
writeRows: (Sheet) -> Unit
|
||||
): StreamingResponseBody {
|
||||
return StreamingResponseBody { outputStream ->
|
||||
val workbook = SXSSFWorkbook(100)
|
||||
try {
|
||||
val sheet = workbook.createSheet(sheetName)
|
||||
val headerRow = sheet.createRow(0)
|
||||
headers.forEachIndexed { index, value ->
|
||||
headerRow.createCell(index).setCellValue(value)
|
||||
}
|
||||
|
||||
writeRows(sheet)
|
||||
workbook.write(outputStream)
|
||||
outputStream.flush()
|
||||
} finally {
|
||||
workbook.dispose()
|
||||
workbook.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun toDateRange(startDateStr: String, endDateStr: String): Pair<LocalDateTime, LocalDateTime> {
|
||||
val startDate = startDateStr.convertLocalDateTime()
|
||||
val endDate = endDateStr.convertLocalDateTime(hour = 23, minute = 59, second = 59)
|
||||
|
||||
return startDate to endDate
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user