Skip to content

Commit 42cbcc3

Browse files
committed
feat(#85): 학생회비 납부자 엑셀 다운로드 구현
1 parent a7446e3 commit 42cbcc3

File tree

6 files changed

+42
-56
lines changed

6 files changed

+42
-56
lines changed

src/main/kotlin/site/billilge/api/backend/domain/payer/controller/AdminPayerController.kt

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
package site.billilge.api.backend.domain.payer.controller
22

3+
import org.springframework.core.io.InputStreamResource
4+
import org.springframework.http.ContentDisposition
5+
import org.springframework.http.HttpHeaders
36
import org.springframework.http.ResponseEntity
47
import org.springframework.web.bind.annotation.*
58
import site.billilge.api.backend.domain.payer.dto.request.PayerDeleteRequest
69
import site.billilge.api.backend.domain.payer.dto.request.PayerRequest
7-
import site.billilge.api.backend.domain.payer.dto.response.PayerExcelFileResponse
810
import site.billilge.api.backend.domain.payer.dto.response.PayerFindAllResponse
911
import site.billilge.api.backend.domain.payer.service.PayerService
1012
import site.billilge.api.backend.global.annotation.OnlyAdmin
1113
import site.billilge.api.backend.global.dto.PageableCondition
1214
import site.billilge.api.backend.global.dto.SearchCondition
15+
import java.time.LocalDate
16+
import java.time.format.DateTimeFormatter
1317

1418
@RestController
1519
@RequestMapping("/admin/members/payers")
@@ -38,7 +42,18 @@ class AdminPayerController(
3842
}
3943

4044
@GetMapping("/excel")
41-
fun getExcelFileUrl(): ResponseEntity<PayerExcelFileResponse> {
42-
return ResponseEntity.ok(payerService.getExcelFileUrl());
45+
fun createPayerExcel(): ResponseEntity<InputStreamResource> {
46+
val excel = payerService.createPayerExcel()
47+
val currentDate = LocalDate.now()
48+
val dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd")
49+
val headers = HttpHeaders().apply {
50+
contentDisposition = ContentDisposition.builder("attachment")
51+
.filename("kmusw_payers_${dateFormatter.format(currentDate)}.xlsx")
52+
.build()
53+
}
54+
55+
return ResponseEntity.ok()
56+
.headers(headers)
57+
.body(InputStreamResource((excel)))
4358
}
4459
}

src/main/kotlin/site/billilge/api/backend/domain/payer/dto/response/PayerExcelFileResponse.kt

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/main/kotlin/site/billilge/api/backend/domain/payer/event/PayerEvents.kt

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/main/kotlin/site/billilge/api/backend/domain/payer/event/listener/PayerEventListener.kt

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/main/kotlin/site/billilge/api/backend/domain/payer/repository/PayerRepository.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@ interface PayerRepository : JpaRepository<Payer, Long?> {
1515

1616
@Query("SELECT p FROM Payer p WHERE p.name LIKE CONCAT('%', :name, '%')")
1717
fun findAllByNameContaining(@Param("name") name: String, pageable: Pageable): Page<Payer>
18+
19+
fun findAllByEnrollmentYear(enrollmentYear: String): List<Payer>
1820
}

src/main/kotlin/site/billilge/api/backend/domain/payer/service/PayerService.kt

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package site.billilge.api.backend.domain.payer.service
22

3-
import org.springframework.beans.factory.annotation.Value
4-
import org.springframework.context.ApplicationEventPublisher
53
import org.springframework.data.domain.PageRequest
64
import org.springframework.data.domain.Sort
75
import org.springframework.stereotype.Service
@@ -10,25 +8,25 @@ import site.billilge.api.backend.domain.member.entity.Member
108
import site.billilge.api.backend.domain.member.repository.MemberRepository
119
import site.billilge.api.backend.domain.payer.dto.request.PayerDeleteRequest
1210
import site.billilge.api.backend.domain.payer.dto.request.PayerRequest
13-
import site.billilge.api.backend.domain.payer.dto.response.PayerExcelFileResponse
1411
import site.billilge.api.backend.domain.payer.dto.response.PayerFindAllResponse
1512
import site.billilge.api.backend.domain.payer.dto.response.PayerSummary
1613
import site.billilge.api.backend.domain.payer.entity.Payer
17-
import site.billilge.api.backend.domain.payer.event.PayerAddEvent
18-
import site.billilge.api.backend.domain.payer.event.PayerDeleteEvent
1914
import site.billilge.api.backend.domain.payer.repository.PayerRepository
2015
import site.billilge.api.backend.global.dto.PageableCondition
2116
import site.billilge.api.backend.global.dto.SearchCondition
22-
import java.time.LocalDate
17+
import site.billilge.api.backend.global.utils.ExcelGenerator
18+
import site.billilge.api.backend.global.utils.ExcelRow
19+
import java.io.ByteArrayInputStream
20+
import java.time.Year
2321

2422
@Service
2523
@Transactional(readOnly = true)
2624
class PayerService(
27-
private val publisher: ApplicationEventPublisher,
2825
private val payerRepository: PayerRepository,
26+
2927
private val memberRepository: MemberRepository,
30-
@Value("\${cloud.aws.s3.base-url}")
31-
private val s3BaseUrl: String,
28+
29+
private val excelGenerator: ExcelGenerator
3230
) {
3331
fun isPayer(name: String, studentId: String): Boolean {
3432
val enrollmentYear = studentId.substring(0, 4)
@@ -104,28 +102,35 @@ class PayerService(
104102
}
105103

106104
payerRepository.saveAll(newPayers)
107-
108-
publisher.publishEvent(PayerAddEvent(newPayers.map { it.id }))
109105
}
110106

111107
@Transactional
112108
fun deletePayers(request: PayerDeleteRequest) {
113109
val payerStudentIds = payerRepository.findAllByIds(request.payerIds)
114110
.mapNotNull { it.studentId }
115-
.toList()
116111

117112
memberRepository.findAllByStudentIds(payerStudentIds)
118113
.forEach { member ->
119114
member.isFeePaid = false
120115
}
121116

122117
payerRepository.deleteAllById(request.payerIds)
123-
124-
publisher.publishEvent(PayerDeleteEvent(request.payerIds))
125118
}
126119

127-
fun getExcelFileUrl(): PayerExcelFileResponse {
128-
val currentYear = LocalDate.now().year
129-
return PayerExcelFileResponse(s3BaseUrl + "/payers/payer_${currentYear}.xlsx")
120+
fun createPayerExcel(): ByteArrayInputStream {
121+
val startYear = 2015
122+
val currentYear = Year.now().value
123+
val headerTitles = arrayOf("이름", "학번")
124+
val sheetData = mutableMapOf<String, Pair<Array<String>, List<ExcelRow>>>()
125+
126+
for (year in startYear..currentYear) {
127+
val yearText = "$year"
128+
val payersByYearExcelRow = payerRepository.findAllByEnrollmentYear(yearText)
129+
.map { payer -> ExcelRow(payer.name, payer.studentId ?: "${yearText}XXXX") }
130+
131+
sheetData.put(yearText, headerTitles to payersByYearExcelRow)
132+
}
133+
134+
return excelGenerator.generateByMultipleSheets(sheetData)
130135
}
131136
}

0 commit comments

Comments
 (0)