feat(series-banner): 시리즈 배너를 언어별로 등록하고 노출한다

This commit is contained in:
2026-04-02 16:59:31 +09:00
parent d3b1f4bcd4
commit 3c32559c5d
10 changed files with 371 additions and 8 deletions

View File

@@ -6,6 +6,7 @@ import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.content.series.ContentSeriesService
import kr.co.vividnext.sodalive.content.series.main.banner.ContentSeriesBannerService
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesPublishedDaysOfWeek
import kr.co.vividnext.sodalive.i18n.LangContext
import kr.co.vividnext.sodalive.member.Member
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
import org.springframework.beans.factory.annotation.Value
@@ -21,6 +22,7 @@ import org.springframework.web.bind.annotation.RestController
class SeriesMainController(
private val contentSeriesService: ContentSeriesService,
private val bannerService: ContentSeriesBannerService,
private val langContext: LangContext,
private val memberContentPreferenceService: MemberContentPreferenceService,
@Value("\${cloud.aws.cloud-front.host}")
@@ -33,7 +35,7 @@ class SeriesMainController(
if (member == null) throw SodaException(messageKey = "common.error.bad_credentials")
val preference = resolvePreference(member)
val banners = bannerService.getActiveBanners(PageRequest.of(0, 10))
val banners = bannerService.getDisplayBanners(PageRequest.of(0, 10), langContext.lang)
.content
.map {
SeriesBannerResponse.from(it, imageHost)

View File

@@ -2,6 +2,7 @@ package kr.co.vividnext.sodalive.content.series.main.banner
import kr.co.vividnext.sodalive.admin.content.series.AdminContentSeriesRepository
import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.i18n.Lang
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
@@ -16,22 +17,28 @@ class ContentSeriesBannerService(
return bannerRepository.findByIsActiveTrueOrderBySortOrderAsc(pageable)
}
fun getDisplayBanners(pageable: Pageable, lang: Lang): Page<SeriesBanner> {
return bannerRepository.findByIsActiveTrueAndLangOrderBySortOrderAsc(lang, pageable)
}
fun getBannerById(bannerId: Long): SeriesBanner {
return bannerRepository.findById(bannerId)
.orElseThrow { SodaException(messageKey = "series.banner.error.not_found") }
}
@Transactional
fun registerBanner(seriesId: Long, imagePath: String): SeriesBanner {
fun registerBanner(seriesId: Long, imagePath: String, lang: Lang? = null): SeriesBanner {
val series = seriesRepository.findByIdAndActiveTrue(seriesId)
?: throw SodaException(messageKey = "series.banner.error.series_not_found")
val finalSortOrder = (bannerRepository.findMaxSortOrder() ?: 0) + 1
val finalLang = lang ?: Lang.KO
val banner = SeriesBanner(
imagePath = imagePath,
series = series,
sortOrder = finalSortOrder
sortOrder = finalSortOrder,
lang = finalLang
)
return bannerRepository.save(banner)
}

View File

@@ -2,7 +2,11 @@ package kr.co.vividnext.sodalive.content.series.main.banner
import kr.co.vividnext.sodalive.common.BaseEntity
import kr.co.vividnext.sodalive.creator.admin.content.series.Series
import kr.co.vividnext.sodalive.i18n.Lang
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.EnumType
import javax.persistence.Enumerated
import javax.persistence.FetchType
import javax.persistence.JoinColumn
import javax.persistence.ManyToOne
@@ -25,6 +29,10 @@ class SeriesBanner(
// 정렬 순서 (낮을수록 먼저 표시)
var sortOrder: Int = 0,
@Column(nullable = false)
@Enumerated(EnumType.STRING)
var lang: Lang = Lang.KO,
// 활성화 여부 (소프트 삭제용)
var isActive: Boolean = true
) : BaseEntity()

View File

@@ -1,5 +1,6 @@
package kr.co.vividnext.sodalive.content.series.main.banner
import kr.co.vividnext.sodalive.i18n.Lang
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
@@ -10,6 +11,8 @@ import org.springframework.stereotype.Repository
interface SeriesBannerRepository : JpaRepository<SeriesBanner, Long> {
fun findByIsActiveTrueOrderBySortOrderAsc(pageable: Pageable): Page<SeriesBanner>
fun findByIsActiveTrueAndLangOrderBySortOrderAsc(lang: Lang, pageable: Pageable): Page<SeriesBanner>
@Query("SELECT MAX(b.sortOrder) FROM SeriesBanner b WHERE b.isActive = true")
fun findMaxSortOrder(): Int?
}