이벤트 배너, 충전 이벤트 - 기간 설정에 시간 추가 #285

Merged
klaus merged 5 commits from test into main 2025-03-14 03:40:08 +00:00
10 changed files with 76 additions and 75 deletions

View File

@ -2,10 +2,13 @@ package kr.co.vividnext.sodalive.admin.event.banner
import com.querydsl.core.types.dsl.DateTimePath
import com.querydsl.core.types.dsl.Expressions
import com.querydsl.core.types.dsl.StringExpression
import com.querydsl.core.types.dsl.StringPath
import com.querydsl.core.types.dsl.StringTemplate
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.event.Event
import kr.co.vividnext.sodalive.event.QEvent.event
import org.springframework.beans.factory.annotation.Value
import org.springframework.data.jpa.repository.JpaRepository
import java.time.LocalDateTime
@ -16,12 +19,13 @@ interface AdminEventBannerQueryRepository {
}
class AdminEventBannerQueryRepositoryImpl(
private val queryFactory: JPAQueryFactory
private val queryFactory: JPAQueryFactory,
@Value("\${cloud.aws.cloud-front.host}")
private val cloudFrontHost: String
) : AdminEventBannerQueryRepository {
override fun getEventList(): List<GetAdminEventResponse> {
val now = LocalDateTime.now()
val where = event.isActive.isTrue
.and(event.startDate.loe(now))
.and(event.endDate.goe(now))
return queryFactory
@ -29,9 +33,9 @@ class AdminEventBannerQueryRepositoryImpl(
QGetAdminEventResponse(
event.id,
event.title,
event.thumbnailImage,
event.detailImage,
event.popupImage,
getProcessedUrlExpression(event.thumbnailImage),
getProcessedUrlExpression(event.detailImage),
getProcessedUrlExpression(event.popupImage),
getFormattedDate(event.startDate),
getFormattedDate(event.endDate),
event.link,
@ -55,7 +59,14 @@ class AdminEventBannerQueryRepositoryImpl(
"UTC",
"Asia/Seoul"
),
"%Y-%m-%d"
"%Y-%m-%d %H:%i"
)
}
private fun getProcessedUrlExpression(path: StringPath): StringExpression {
return Expressions.stringTemplate(
"CASE WHEN {0} LIKE '$cloudFrontHost%' THEN {0} ELSE CONCAT('$cloudFrontHost/', {0}) END",
path
)
}
}

View File

@ -10,7 +10,7 @@ import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.web.multipart.MultipartFile
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
@ -20,9 +20,7 @@ class AdminEventBannerService(
private val s3Uploader: S3Uploader,
@Value("\${cloud.aws.s3.bucket}")
private val bucket: String,
@Value("\${cloud.aws.cloud-front.host}")
private val cloudFrontHost: String
private val bucket: String
) {
@Transactional
fun save(
@ -38,13 +36,13 @@ class AdminEventBannerService(
): Long {
if (detail == null && link.isNullOrBlank()) throw SodaException("상세이미지 혹은 링크를 등록하세요")
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
val startDate = LocalDate.parse(startDateString, dateTimeFormatter).atTime(0, 0)
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
val startDate = LocalDateTime.parse(startDateString, dateTimeFormatter)
.atZone(ZoneId.of("Asia/Seoul"))
.withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime()
val endDate = LocalDate.parse(endDateString, dateTimeFormatter).atTime(23, 59, 59)
val endDate = LocalDateTime.parse(endDateString, dateTimeFormatter).withSecond(59)
.atZone(ZoneId.of("Asia/Seoul"))
.withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime()
@ -174,16 +172,16 @@ class AdminEventBannerService(
event.isAdult = isAdult
}
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
if (startDateString != null) {
event.startDate = LocalDate.parse(startDateString, dateTimeFormatter).atTime(0, 0)
event.startDate = LocalDateTime.parse(startDateString, dateTimeFormatter)
.atZone(ZoneId.of("Asia/Seoul"))
.withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime()
}
if (endDateString != null) {
event.endDate = LocalDate.parse(endDateString, dateTimeFormatter).atTime(23, 59, 59)
event.endDate = LocalDateTime.parse(endDateString, dateTimeFormatter).withSecond(59)
.atZone(ZoneId.of("Asia/Seoul"))
.withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime()
@ -201,22 +199,5 @@ class AdminEventBannerService(
fun getEventList(): List<GetAdminEventResponse> {
return repository.getEventList()
.asSequence()
.map {
if (!it.thumbnailImageUrl.startsWith("https://")) {
it.thumbnailImageUrl = "$cloudFrontHost/${it.thumbnailImageUrl}"
}
if (it.detailImageUrl != null && !it.detailImageUrl!!.startsWith("https://")) {
it.detailImageUrl = "$cloudFrontHost/${it.detailImageUrl}"
}
if (it.popupImageUrl != null && !it.popupImageUrl!!.startsWith("https://")) {
it.popupImageUrl = "$cloudFrontHost/${it.popupImageUrl}"
}
it
}
.toList()
}
}

View File

@ -5,11 +5,11 @@ import com.querydsl.core.annotations.QueryProjection
data class GetAdminEventResponse @QueryProjection constructor(
val id: Long,
val title: String? = null,
var thumbnailImageUrl: String,
var detailImageUrl: String? = null,
var popupImageUrl: String? = null,
var startDate: String,
var endDate: String,
val thumbnailImageUrl: String,
val detailImageUrl: String? = null,
val popupImageUrl: String? = null,
val startDate: String,
val endDate: String,
val link: String? = null,
val isAdult: Boolean? = null,
val isPopup: Boolean

View File

@ -1,22 +1,51 @@
package kr.co.vividnext.sodalive.admin.event.charge
import com.querydsl.core.types.dsl.DateTimePath
import com.querydsl.core.types.dsl.Expressions
import com.querydsl.core.types.dsl.StringTemplate
import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.admin.event.charge.QChargeEvent.chargeEvent
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
import java.time.LocalDateTime
@Repository
interface AdminChargeEventRepository : JpaRepository<ChargeEvent, Long>, AdminChargeEventQueryRepository
interface AdminChargeEventQueryRepository {
fun getChargeEventList(): List<ChargeEvent>
fun getChargeEventList(): List<GetChargeEventListResponse>
}
class AdminChargeEventQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : AdminChargeEventQueryRepository {
override fun getChargeEventList(): List<ChargeEvent> {
override fun getChargeEventList(): List<GetChargeEventListResponse> {
return queryFactory
.selectFrom(chargeEvent)
.select(
QGetChargeEventListResponse(
chargeEvent.id,
chargeEvent.title,
getFormattedDate(chargeEvent.startDate),
getFormattedDate(chargeEvent.endDate),
chargeEvent.availableCount,
chargeEvent.addPercent.multiply(100).castToNum(Int::class.java),
chargeEvent.isActive
)
)
.from(chargeEvent)
.orderBy(chargeEvent.createdAt.desc())
.fetch()
}
private fun getFormattedDate(dateTimePath: DateTimePath<LocalDateTime>): StringTemplate {
return Expressions.stringTemplate(
"DATE_FORMAT({0}, {1})",
Expressions.dateTimeTemplate(
LocalDateTime::class.java,
"CONVERT_TZ({0},{1},{2})",
dateTimePath,
"UTC",
"Asia/Seoul"
),
"%Y-%m-%d %H:%i"
)
}
}

View File

@ -4,7 +4,7 @@ import kr.co.vividnext.sodalive.common.SodaException
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
@ -13,13 +13,13 @@ import java.time.format.DateTimeFormatter
class AdminChargeEventService(private val repository: AdminChargeEventRepository) {
@Transactional
fun createChargeEvent(request: CreateChargeEventRequest): Long {
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
val startDate = LocalDate.parse(request.startDateString, dateTimeFormatter).atTime(0, 0)
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
val startDate = LocalDateTime.parse(request.startDateString, dateTimeFormatter)
.atZone(ZoneId.of("Asia/Seoul"))
.withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime()
val endDate = LocalDate.parse(request.endDateString, dateTimeFormatter).atTime(23, 59, 59)
val endDate = LocalDateTime.parse(request.endDateString, dateTimeFormatter).withSecond(59)
.atZone(ZoneId.of("Asia/Seoul"))
.withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime()
@ -44,16 +44,16 @@ class AdminChargeEventService(private val repository: AdminChargeEventRepository
chargeEvent.title = request.title
}
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
if (request.startDateString != null) {
chargeEvent.startDate = LocalDate.parse(request.startDateString, dateTimeFormatter).atTime(0, 0)
chargeEvent.startDate = LocalDateTime.parse(request.startDateString, dateTimeFormatter)
.atZone(ZoneId.of("Asia/Seoul"))
.withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime()
}
if (request.endDateString != null) {
chargeEvent.endDate = LocalDate.parse(request.endDateString, dateTimeFormatter).atTime(23, 59, 59)
chargeEvent.endDate = LocalDateTime.parse(request.endDateString, dateTimeFormatter).withSecond(59)
.atZone(ZoneId.of("Asia/Seoul"))
.withZoneSameInstant(ZoneId.of("UTC"))
.toLocalDateTime()
@ -74,27 +74,5 @@ class AdminChargeEventService(private val repository: AdminChargeEventRepository
fun getChargeEventList(): List<GetChargeEventListResponse> {
return repository.getChargeEventList()
.map {
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
val startDate = it.startDate
.atZone(ZoneId.of("UTC"))
.withZoneSameInstant(ZoneId.of("Asia/Seoul"))
.format(dateTimeFormatter)
val endDate = it.endDate
.atZone(ZoneId.of("UTC"))
.withZoneSameInstant(ZoneId.of("Asia/Seoul"))
.format(dateTimeFormatter)
GetChargeEventListResponse(
id = it.id!!,
title = it.title,
startDate = startDate,
endDate = endDate,
availableCount = it.availableCount,
addPercent = (it.addPercent * 100).toInt(),
isActive = it.isActive
)
}
}
}

View File

@ -1,6 +1,8 @@
package kr.co.vividnext.sodalive.admin.event.charge
data class GetChargeEventListResponse(
import com.querydsl.core.annotations.QueryProjection
data class GetChargeEventListResponse @QueryProjection constructor(
val id: Long,
val title: String,
val startDate: String,

View File

@ -1,4 +1,4 @@
package kr.co.vividnext.sodalive.admin.marketing.statistics
package kr.co.vividnext.sodalive.admin.statistics.ad
import kr.co.vividnext.sodalive.common.ApiResponse
import org.springframework.data.domain.Pageable

View File

@ -1,4 +1,4 @@
package kr.co.vividnext.sodalive.admin.marketing.statistics
package kr.co.vividnext.sodalive.admin.statistics.ad
import com.querydsl.core.types.dsl.CaseBuilder
import com.querydsl.core.types.dsl.DateTimePath

View File

@ -1,4 +1,4 @@
package kr.co.vividnext.sodalive.admin.marketing.statistics
package kr.co.vividnext.sodalive.admin.statistics.ad
import kr.co.vividnext.sodalive.extensions.convertLocalDateTime
import org.springframework.stereotype.Service

View File

@ -1,4 +1,4 @@
package kr.co.vividnext.sodalive.admin.marketing.statistics
package kr.co.vividnext.sodalive.admin.statistics.ad
import com.querydsl.core.annotations.QueryProjection