관리자 - 추천 라이브 크리에이터 API
This commit is contained in:
parent
14b25bdfc3
commit
34590347a6
|
@ -1,15 +1,58 @@
|
|||
package kr.co.vividnext.sodalive.admin.live
|
||||
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.PostMapping
|
||||
import org.springframework.web.bind.annotation.PutMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RequestParam
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import org.springframework.web.multipart.MultipartFile
|
||||
|
||||
@RestController
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@RequestMapping("/admin/live")
|
||||
class AdminLiveController(private val service: AdminLiveService) {
|
||||
@GetMapping
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
fun getOnAirLive() = ApiResponse.ok(data = service.getLiveList())
|
||||
|
||||
@GetMapping("/recommend-creator")
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
fun getRecommendCreatorBanner(pageable: Pageable) = ApiResponse.ok(service.getRecommendCreator(pageable))
|
||||
|
||||
@PostMapping("/recommend-creator")
|
||||
fun createRecommendCreatorBanner(
|
||||
@RequestParam("image") image: MultipartFile,
|
||||
@RequestParam("creator_id") creatorId: Long,
|
||||
@RequestParam("start_date") startDate: String,
|
||||
@RequestParam("end_date") endDate: String,
|
||||
@RequestParam("is_adult") isAdult: Boolean
|
||||
) = ApiResponse.ok(
|
||||
service.createRecommendCreatorBanner(image, creatorId, startDate, endDate, isAdult),
|
||||
"등록되었습니다."
|
||||
)
|
||||
|
||||
@PutMapping("/recommend-creator")
|
||||
fun updateRecommendCreatorBanner(
|
||||
@RequestParam("recommend_creator_banner_id") recommendCreatorBannerId: Long,
|
||||
@RequestParam("image", required = false) image: MultipartFile?,
|
||||
@RequestParam("creator_id", required = false) creatorId: Long?,
|
||||
@RequestParam("start_date", required = false) startDate: String?,
|
||||
@RequestParam("end_date", required = false) endDate: String?,
|
||||
@RequestParam("is_adult", required = false) isAdult: Boolean?
|
||||
) = ApiResponse.ok(
|
||||
service.updateRecommendCreatorBanner(recommendCreatorBannerId, image, creatorId, startDate, endDate, isAdult),
|
||||
"수정되었습니다."
|
||||
)
|
||||
|
||||
@PutMapping("/recommend-creator/orders")
|
||||
fun updateRecommendCreatorBannerOrders(
|
||||
@RequestBody request: UpdateAdminRecommendCreatorBannerOrdersRequest
|
||||
) = ApiResponse.ok(
|
||||
service.updateRecommendCreatorBannerOrders(request.firstOrders, request.ids),
|
||||
"수정되었습니다."
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package kr.co.vividnext.sodalive.admin.live
|
||||
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||
import kr.co.vividnext.sodalive.live.recommend.QRecommendLiveCreatorBanner.recommendLiveCreatorBanner
|
||||
import kr.co.vividnext.sodalive.live.recommend.RecommendLiveCreatorBanner
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoom
|
||||
import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom
|
||||
import kr.co.vividnext.sodalive.member.QMember.member
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
|
@ -16,4 +19,21 @@ class AdminLiveRoomQueryRepository(private val queryFactory: JPAQueryFactory) {
|
|||
.orderBy(liveRoom.channelName.desc(), liveRoom.beginDateTime.asc())
|
||||
.fetch()
|
||||
}
|
||||
|
||||
fun getRecommendCreatorTotalCount(): Int {
|
||||
return queryFactory
|
||||
.select(recommendLiveCreatorBanner.id)
|
||||
.from(recommendLiveCreatorBanner)
|
||||
.fetch()
|
||||
.size
|
||||
}
|
||||
|
||||
fun getRecommendCreatorList(pageable: Pageable): List<RecommendLiveCreatorBanner> {
|
||||
return queryFactory
|
||||
.selectFrom(recommendLiveCreatorBanner)
|
||||
.offset(pageable.offset)
|
||||
.limit(pageable.pageSize.toLong())
|
||||
.orderBy(recommendLiveCreatorBanner.orders.asc(), recommendLiveCreatorBanner.id.desc())
|
||||
.fetch()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,31 @@
|
|||
package kr.co.vividnext.sodalive.admin.live
|
||||
|
||||
import com.amazonaws.services.s3.model.ObjectMetadata
|
||||
import kr.co.vividnext.sodalive.aws.s3.S3Uploader
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.live.recommend.RecommendLiveCreatorBanner
|
||||
import kr.co.vividnext.sodalive.live.recommend.RecommendLiveCreatorBannerRepository
|
||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||
import kr.co.vividnext.sodalive.utils.generateFileName
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.data.domain.Pageable
|
||||
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.LocalDateTime
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
@Service
|
||||
class AdminLiveService(
|
||||
private val recommendCreatorBannerRepository: RecommendLiveCreatorBannerRepository,
|
||||
private val repository: AdminLiveRoomQueryRepository,
|
||||
private val memberRepository: MemberRepository,
|
||||
private val s3Uploader: S3Uploader,
|
||||
|
||||
@Value("\${cloud.aws.s3.bucket}")
|
||||
private val bucket: String,
|
||||
@Value("\${cloud.aws.cloud-front.host}")
|
||||
private val coverImageHost: String
|
||||
) {
|
||||
|
@ -34,4 +53,188 @@ class AdminLiveService(
|
|||
.toList()
|
||||
)
|
||||
}
|
||||
|
||||
fun getRecommendCreator(pageable: Pageable): GetAdminRecommendCreatorResponse {
|
||||
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
|
||||
|
||||
val totalCount = repository.getRecommendCreatorTotalCount()
|
||||
|
||||
val recommendCreatorList = repository
|
||||
.getRecommendCreatorList(pageable)
|
||||
.asSequence()
|
||||
.map {
|
||||
GetAdminRecommendCreatorResponseItem(
|
||||
it.id!!,
|
||||
"$coverImageHost/${it.image}",
|
||||
it.creator!!.id!!,
|
||||
it.creator!!.nickname,
|
||||
it.startDate
|
||||
.atZone(ZoneId.of("UTC"))
|
||||
.withZoneSameInstant(ZoneId.of("Asia/Seoul"))
|
||||
.toLocalDateTime()
|
||||
.format(dateTimeFormatter),
|
||||
it.endDate
|
||||
.atZone(ZoneId.of("UTC"))
|
||||
.withZoneSameInstant(ZoneId.of("Asia/Seoul"))
|
||||
.toLocalDateTime()
|
||||
.format(dateTimeFormatter),
|
||||
it.isAdult
|
||||
)
|
||||
}
|
||||
.toList()
|
||||
|
||||
return GetAdminRecommendCreatorResponse(
|
||||
totalCount = totalCount,
|
||||
recommendCreatorList = recommendCreatorList
|
||||
)
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun createRecommendCreatorBanner(
|
||||
image: MultipartFile,
|
||||
creatorId: Long,
|
||||
startDateString: String,
|
||||
endDateString: String,
|
||||
isAdult: Boolean
|
||||
): Long {
|
||||
if (creatorId < 1) throw SodaException("올바른 크리에이터를 선택해 주세요.")
|
||||
|
||||
val creator = memberRepository.findCreatorByIdOrNull(memberId = creatorId)
|
||||
?: throw SodaException("올바른 크리에이터를 선택해 주세요.")
|
||||
|
||||
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 nowDate = LocalDateTime.now()
|
||||
.atZone(ZoneId.of("Asia/Seoul"))
|
||||
.withZoneSameInstant(ZoneId.of("UTC"))
|
||||
.toLocalDateTime()
|
||||
|
||||
if (startDate < nowDate) throw SodaException("노출 시작일은 현재시간 이후로 설정하셔야 합니다.")
|
||||
|
||||
val endDate = LocalDateTime.parse(endDateString, dateTimeFormatter)
|
||||
.atZone(ZoneId.of("Asia/Seoul"))
|
||||
.withZoneSameInstant(ZoneId.of("UTC"))
|
||||
.toLocalDateTime()
|
||||
|
||||
if (endDate < nowDate) throw SodaException("노출 종료일은 현재시간 이후로 설정하셔야 합니다.")
|
||||
if (endDate <= startDate) throw SodaException("노출 시작일은 노출 종료일 이전으로 설정하셔야 합니다.")
|
||||
|
||||
val recommendCreatorBanner = RecommendLiveCreatorBanner(
|
||||
startDate = startDate,
|
||||
endDate = endDate,
|
||||
isAdult = isAdult
|
||||
)
|
||||
recommendCreatorBanner.creator = creator
|
||||
recommendCreatorBannerRepository.save(recommendCreatorBanner)
|
||||
|
||||
val metadata = ObjectMetadata()
|
||||
metadata.contentLength = image.size
|
||||
val imagePath = s3Uploader.upload(
|
||||
inputStream = image.inputStream,
|
||||
bucket = bucket,
|
||||
filePath = "recommend_creator_banner/${recommendCreatorBanner.id}/${generateFileName()}",
|
||||
metadata = metadata
|
||||
)
|
||||
|
||||
recommendCreatorBanner.image = imagePath
|
||||
|
||||
return recommendCreatorBanner.id!!
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun updateRecommendCreatorBanner(
|
||||
recommendCreatorBannerId: Long,
|
||||
image: MultipartFile?,
|
||||
creatorId: Long?,
|
||||
startDateString: String?,
|
||||
endDateString: String?,
|
||||
isAdult: Boolean?
|
||||
) {
|
||||
val recommendCreatorBanner = recommendCreatorBannerRepository.findByIdOrNull(recommendCreatorBannerId)
|
||||
?: throw SodaException("해당하는 추천라이브가 없습니다. 다시 확인해 주세요.")
|
||||
|
||||
if (creatorId != null) {
|
||||
if (creatorId < 1) throw SodaException("올바른 크리에이터를 선택해 주세요.")
|
||||
|
||||
val creator = memberRepository.findCreatorByIdOrNull(memberId = creatorId)
|
||||
?: throw SodaException("올바른 크리에이터를 선택해 주세요.")
|
||||
|
||||
recommendCreatorBanner.creator = creator
|
||||
}
|
||||
|
||||
if (image != null) {
|
||||
val metadata = ObjectMetadata()
|
||||
metadata.contentLength = image.size
|
||||
val imagePath = s3Uploader.upload(
|
||||
inputStream = image.inputStream,
|
||||
bucket = bucket,
|
||||
filePath = "recommend_creator_banner/${recommendCreatorBanner.id}/${generateFileName()}",
|
||||
metadata = metadata
|
||||
)
|
||||
|
||||
recommendCreatorBanner.image = imagePath
|
||||
}
|
||||
|
||||
if (startDateString != null) {
|
||||
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 = if (endDateString != null) {
|
||||
LocalDateTime.parse(endDateString, dateTimeFormatter)
|
||||
.atZone(ZoneId.of("Asia/Seoul"))
|
||||
.withZoneSameInstant(ZoneId.of("UTC"))
|
||||
.toLocalDateTime()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
if (endDate != null) {
|
||||
if (endDate <= startDate) {
|
||||
throw SodaException("노출 시작일은 노출 종료일 이전으로 설정하셔야 합니다.")
|
||||
}
|
||||
|
||||
recommendCreatorBanner.endDate = endDate
|
||||
} else {
|
||||
if (recommendCreatorBanner.endDate <= startDate) {
|
||||
throw SodaException("노출 시작일은 노출 종료일 이전으로 설정하셔야 합니다.")
|
||||
}
|
||||
}
|
||||
|
||||
recommendCreatorBanner.startDate = startDate
|
||||
} else if (endDateString != null) {
|
||||
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
|
||||
val endDate = LocalDateTime.parse(endDateString, dateTimeFormatter)
|
||||
.atZone(ZoneId.of("Asia/Seoul"))
|
||||
.withZoneSameInstant(ZoneId.of("UTC"))
|
||||
.toLocalDateTime()
|
||||
|
||||
if (endDate <= recommendCreatorBanner.startDate) {
|
||||
throw SodaException("노출 종료일은 노출 시작일 이후로 설정하셔야 합니다.")
|
||||
}
|
||||
|
||||
recommendCreatorBanner.endDate = endDate
|
||||
}
|
||||
|
||||
if (isAdult != null) {
|
||||
recommendCreatorBanner.isAdult = isAdult
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun updateRecommendCreatorBannerOrders(firstOrders: Int, ids: List<Long>) {
|
||||
for (index in ids.indices) {
|
||||
val recommendCreatorBanner = recommendCreatorBannerRepository.findByIdOrNull(id = ids[index])
|
||||
|
||||
if (recommendCreatorBanner != null) {
|
||||
recommendCreatorBanner.orders = firstOrders + index
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package kr.co.vividnext.sodalive.admin.live
|
||||
|
||||
data class GetAdminRecommendCreatorResponse(
|
||||
val totalCount: Int,
|
||||
val recommendCreatorList: List<GetAdminRecommendCreatorResponseItem>
|
||||
)
|
||||
|
||||
data class GetAdminRecommendCreatorResponseItem(
|
||||
val id: Long,
|
||||
val image: String,
|
||||
val creatorId: Long,
|
||||
val creatorNickname: String,
|
||||
val startDate: String,
|
||||
val endDate: String,
|
||||
val isAdult: Boolean
|
||||
)
|
|
@ -0,0 +1,6 @@
|
|||
package kr.co.vividnext.sodalive.admin.live
|
||||
|
||||
data class UpdateAdminRecommendCreatorBannerOrdersRequest(
|
||||
val firstOrders: Int,
|
||||
val ids: List<Long>
|
||||
)
|
|
@ -11,8 +11,6 @@ import javax.persistence.ManyToOne
|
|||
|
||||
@Entity
|
||||
data class RecommendLiveCreatorBanner(
|
||||
@Column(nullable = false)
|
||||
var image: String,
|
||||
@Column(nullable = false)
|
||||
var startDate: LocalDateTime,
|
||||
@Column(nullable = false)
|
||||
|
@ -20,7 +18,9 @@ data class RecommendLiveCreatorBanner(
|
|||
@Column(nullable = false)
|
||||
var isAdult: Boolean = false,
|
||||
@Column(nullable = false)
|
||||
var orders: Int = 1
|
||||
var orders: Int = 1,
|
||||
@Column(nullable = true)
|
||||
var image: String? = null
|
||||
) : BaseEntity() {
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "creator_id", nullable = false)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package kr.co.vividnext.sodalive.live.recommend
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
interface RecommendLiveCreatorBannerRepository : JpaRepository<RecommendLiveCreatorBanner, Long>
|
|
@ -14,6 +14,7 @@ interface MemberRepository : JpaRepository<Member, Long>, MemberQueryRepository
|
|||
interface MemberQueryRepository {
|
||||
fun findByPushToken(pushToken: String): List<Member>
|
||||
fun findByNicknameAndOtherCondition(nickname: String, memberId: Long): List<Member>
|
||||
fun findCreatorByIdOrNull(memberId: Long): Member?
|
||||
}
|
||||
|
||||
@Repository
|
||||
|
@ -36,4 +37,14 @@ class MemberQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : Mem
|
|||
)
|
||||
.fetch()
|
||||
}
|
||||
|
||||
override fun findCreatorByIdOrNull(memberId: Long): Member? {
|
||||
return queryFactory
|
||||
.selectFrom(member)
|
||||
.where(
|
||||
member.id.eq(memberId)
|
||||
.and(member.role.eq(MemberRole.CREATOR))
|
||||
)
|
||||
.fetchFirst()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue