쿠폰 번호 다운로드 API 추가
This commit is contained in:
parent
d20f51ceac
commit
f45e07c879
|
@ -59,6 +59,8 @@ dependencies {
|
||||||
// firebase admin sdk
|
// firebase admin sdk
|
||||||
implementation("com.google.firebase:firebase-admin:9.2.0")
|
implementation("com.google.firebase:firebase-admin:9.2.0")
|
||||||
|
|
||||||
|
implementation("org.apache.poi:poi-ooxml:5.2.3")
|
||||||
|
|
||||||
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||||
runtimeOnly("com.h2database:h2")
|
runtimeOnly("com.h2database:h2")
|
||||||
runtimeOnly("com.mysql:mysql-connector-j")
|
runtimeOnly("com.mysql:mysql-connector-j")
|
||||||
|
|
|
@ -4,6 +4,9 @@ import kr.co.vividnext.sodalive.common.ApiResponse
|
||||||
import kr.co.vividnext.sodalive.common.SodaException
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
import kr.co.vividnext.sodalive.member.Member
|
||||||
import org.springframework.data.domain.Pageable
|
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.security.access.prepost.PreAuthorize
|
||||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
@ -55,4 +58,20 @@ class CanCouponController(private val service: CanCouponService) {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/number-list/download")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
fun downloadCouponNumberList(
|
||||||
|
@RequestParam couponId: Long,
|
||||||
|
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||||
|
) = run {
|
||||||
|
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
||||||
|
|
||||||
|
val fileName = "쿠폰번호리스트.xlsx"
|
||||||
|
val response = service.downloadCouponNumberList(couponId)
|
||||||
|
ResponseEntity.ok()
|
||||||
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attatchment;filename=$fileName")
|
||||||
|
.contentType(MediaType.parseMediaType("application/vnd.ms-excel"))
|
||||||
|
.body(response)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@ interface CanCouponQueryRepository {
|
||||||
fun getCouponList(offset: Long, limit: Long): List<CanCoupon>
|
fun getCouponList(offset: Long, limit: Long): List<CanCoupon>
|
||||||
fun getCouponNumberTotalCount(couponId: Long): Int
|
fun getCouponNumberTotalCount(couponId: Long): Int
|
||||||
fun getCouponNumberList(couponId: Long, offset: Long, limit: Long): List<GetCouponNumberListItemResponse>
|
fun getCouponNumberList(couponId: Long, offset: Long, limit: Long): List<GetCouponNumberListItemResponse>
|
||||||
|
|
||||||
|
fun getAllCouponNumberList(couponId: Long): List<GetCouponNumberListItemResponse>
|
||||||
}
|
}
|
||||||
|
|
||||||
class CanCouponQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : CanCouponQueryRepository {
|
class CanCouponQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : CanCouponQueryRepository {
|
||||||
|
@ -57,4 +59,19 @@ class CanCouponQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) :
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.fetch()
|
.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getAllCouponNumberList(couponId: Long): List<GetCouponNumberListItemResponse> {
|
||||||
|
return queryFactory
|
||||||
|
.select(
|
||||||
|
QGetCouponNumberListItemResponse(
|
||||||
|
canCouponNumber.id,
|
||||||
|
canCouponNumber.couponNumber,
|
||||||
|
canCouponNumber.member.isNotNull
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.from(canCouponNumber)
|
||||||
|
.where(canCouponNumber.canCoupon.id.eq(couponId))
|
||||||
|
.orderBy(canCouponNumber.id.asc())
|
||||||
|
.fetch()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,13 @@ package kr.co.vividnext.sodalive.can.coupon
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper
|
import com.fasterxml.jackson.databind.ObjectMapper
|
||||||
import kr.co.vividnext.sodalive.aws.sqs.SqsEvent
|
import kr.co.vividnext.sodalive.aws.sqs.SqsEvent
|
||||||
import kr.co.vividnext.sodalive.aws.sqs.SqsEventType
|
import kr.co.vividnext.sodalive.aws.sqs.SqsEventType
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook
|
||||||
import org.springframework.context.ApplicationEventPublisher
|
import org.springframework.context.ApplicationEventPublisher
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
import java.io.ByteArrayInputStream
|
||||||
|
import java.io.ByteArrayOutputStream
|
||||||
|
import java.io.IOException
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
@ -48,4 +53,45 @@ class CanCouponService(
|
||||||
val items = repository.getCouponNumberList(couponId = couponId, offset = offset, limit = limit)
|
val items = repository.getCouponNumberList(couponId = couponId, offset = offset, limit = limit)
|
||||||
return GetCouponNumberListResponse(totalCount, items)
|
return GetCouponNumberListResponse(totalCount, items)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun downloadCouponNumberList(couponId: Long): ByteArrayInputStream {
|
||||||
|
val header = listOf("순번", "쿠폰번호", "사용여부")
|
||||||
|
val byteArrayOutputStream = ByteArrayOutputStream()
|
||||||
|
val couponNumberList = repository.getAllCouponNumberList(couponId)
|
||||||
|
|
||||||
|
val workbook = XSSFWorkbook()
|
||||||
|
try {
|
||||||
|
val sheet = workbook.createSheet()
|
||||||
|
val row = sheet.createRow(0)
|
||||||
|
header.forEachIndexed { index, string ->
|
||||||
|
val cell = row.createCell(index)
|
||||||
|
cell.setCellValue(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
couponNumberList.forEachIndexed { index, item ->
|
||||||
|
val couponNumberRow = sheet.createRow(index + 1)
|
||||||
|
couponNumberRow.createCell(0).setCellValue(item.couponNumberId.toString())
|
||||||
|
couponNumberRow.createCell(1).setCellValue(insertHyphens(item.couponNumber))
|
||||||
|
couponNumberRow.createCell(2).setCellValue(
|
||||||
|
if (item.isUsed) {
|
||||||
|
"O"
|
||||||
|
} else {
|
||||||
|
"X"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
workbook.write(byteArrayOutputStream)
|
||||||
|
return ByteArrayInputStream(byteArrayOutputStream.toByteArray())
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw SodaException("다운로드를 하지 못했습니다.\n다시 시도해 주세요.")
|
||||||
|
} finally {
|
||||||
|
workbook.close()
|
||||||
|
byteArrayOutputStream.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun insertHyphens(input: String): String {
|
||||||
|
return input.chunked(4).joinToString("-")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue