Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package site.billilge.api.backend.domain.payer.controller

import org.springframework.core.io.InputStreamResource
import org.springframework.http.ContentDisposition
import org.springframework.http.HttpHeaders
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import site.billilge.api.backend.domain.payer.dto.request.PayerDeleteRequest
Expand All @@ -9,6 +12,8 @@ import site.billilge.api.backend.domain.payer.service.PayerService
import site.billilge.api.backend.global.annotation.OnlyAdmin
import site.billilge.api.backend.global.dto.PageableCondition
import site.billilge.api.backend.global.dto.SearchCondition
import java.time.LocalDate
import java.time.format.DateTimeFormatter

@RestController
@RequestMapping("/admin/members/payers")
Expand All @@ -35,4 +40,20 @@ class AdminPayerController(
payerService.deletePayers(request)
return ResponseEntity.noContent().build()
}

@GetMapping("/excel")
fun createPayerExcel(): ResponseEntity<InputStreamResource> {
val excel = payerService.createPayerExcel()
val currentDate = LocalDate.now()
val dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd")
val headers = HttpHeaders().apply {
contentDisposition = ContentDisposition.builder("attachment")
.filename("kmusw_payers_${dateFormatter.format(currentDate)}.xlsx")
.build()
}

return ResponseEntity.ok()
.headers(headers)
.body(InputStreamResource((excel)))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ interface PayerRepository : JpaRepository<Payer, Long?> {

@Query("SELECT p FROM Payer p WHERE p.name LIKE CONCAT('%', :name, '%')")
fun findAllByNameContaining(@Param("name") name: String, pageable: Pageable): Page<Payer>

fun findAllByEnrollmentYear(enrollmentYear: String): List<Payer>
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@ import site.billilge.api.backend.domain.payer.entity.Payer
import site.billilge.api.backend.domain.payer.repository.PayerRepository
import site.billilge.api.backend.global.dto.PageableCondition
import site.billilge.api.backend.global.dto.SearchCondition
import site.billilge.api.backend.global.utils.ExcelGenerator
import site.billilge.api.backend.global.utils.ExcelRow
import java.io.ByteArrayInputStream
import java.time.Year

@Service
@Transactional(readOnly = true)
class PayerService(
private val payerRepository: PayerRepository,
private val memberRepository: MemberRepository

private val memberRepository: MemberRepository,

private val excelGenerator: ExcelGenerator
) {
fun isPayer(name: String, studentId: String): Boolean {
val enrollmentYear = studentId.substring(0, 4)
Expand Down Expand Up @@ -71,6 +78,7 @@ class PayerService(

@Transactional
fun addPayers(request: PayerRequest) {
val newPayers = mutableListOf<Payer>()
request.payers.forEach { payerItem ->
val name = payerItem.name
val studentId = payerItem.studentId
Expand All @@ -87,18 +95,19 @@ class PayerService(
this.registered = registered
}

payerRepository.save(payer)
newPayers.add(payer)
}

registeredMember?.isFeePaid = true
}

payerRepository.saveAll(newPayers)
}

@Transactional
fun deletePayers(request: PayerDeleteRequest) {
val payerStudentIds = payerRepository.findAllByIds(request.payerIds)
.mapNotNull { it.studentId }
.toList()

memberRepository.findAllByStudentIds(payerStudentIds)
.forEach { member ->
Expand All @@ -107,4 +116,21 @@ class PayerService(

payerRepository.deleteAllById(request.payerIds)
}

fun createPayerExcel(): ByteArrayInputStream {
val startYear = 2015
val currentYear = Year.now().value
val headerTitles = arrayOf("이름", "학번")
val sheetData = mutableMapOf<String, Pair<Array<String>, List<ExcelRow>>>()

for (year in startYear..currentYear) {
val yearText = "$year"
val payersByYearExcelRow = payerRepository.findAllByEnrollmentYear(yearText)
.map { payer -> ExcelRow(payer.name, payer.studentId ?: "${yearText}XXXX") }

sheetData.put(yearText, headerTitles to payersByYearExcelRow)
}

return excelGenerator.generateByMultipleSheets(sheetData)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package site.billilge.api.backend.global.config

import org.springframework.context.annotation.Configuration
import org.springframework.scheduling.annotation.EnableAsync

@EnableAsync
@Configuration
class AsyncConfig {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package site.billilge.api.backend.global.utils

import org.apache.poi.ss.usermodel.IndexedColors
import org.apache.poi.xssf.streaming.SXSSFSheet
import org.apache.poi.xssf.streaming.SXSSFWorkbook
import org.springframework.stereotype.Component
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream

private const val HEADER_ROW = 0

@Component
class ExcelGenerator {

fun generateByMultipleSheets(
sheetData: Map<String, Pair<Array<String>, List<ExcelRow>>>
): ByteArrayInputStream {
val workbook = SXSSFWorkbook()

sheetData.forEach { (sheetName, sheetContent) ->
val (headerTitles, rows) = sheetContent
val sheet = workbook.createSheet(sheetName)
styleHeaders(workbook, sheet, headerTitles)
fillData(sheet, rows, headerTitles.size)
}

val out = ByteArrayOutputStream()
workbook.write(out)
workbook.close()

return ByteArrayInputStream(out.toByteArray())
}

private fun styleHeaders(workbook: SXSSFWorkbook, sheet: SXSSFSheet, headerTitles: Array<String>) {
val headerFont = workbook.createFont()
headerFont.bold = true

val headerCellStyle = workbook.createCellStyle()
headerCellStyle.setFont(headerFont)
headerCellStyle.fillForegroundColor = IndexedColors.GREY_25_PERCENT.index
headerCellStyle.fillPattern = org.apache.poi.ss.usermodel.FillPatternType.SOLID_FOREGROUND

val headerRow = sheet.createRow(HEADER_ROW)
headerTitles.forEachIndexed { col, title ->
val cell = headerRow.createCell(col)
cell.setCellValue(title)
cell.cellStyle = headerCellStyle
}
}

private fun fillData(sheet: SXSSFSheet, rows: List<ExcelRow>, columnSize: Int) {
sheet.trackAllColumnsForAutoSizing()

rows.forEachIndexed { index, excelRow ->
val row = sheet.createRow(index + 1)
excelRow.data.forEachIndexed { propertyIndex, property ->
row.createCell(propertyIndex).setCellValue(property)
}
}

repeat(columnSize) { col -> sheet.autoSizeColumn(col) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package site.billilge.api.backend.global.utils

data class ExcelRow(
val data: List<String>
) {
constructor(vararg data: String) : this(data.toList())
}
Loading