관리자 - 탐색 메뉴 API 추가
This commit is contained in:
parent
14220ff6dc
commit
f7cdf40976
|
@ -0,0 +1,39 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.explorer
|
||||||
|
|
||||||
|
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.RestController
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/admin/explorer")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
class AdminExplorerController(private val service: AdminExplorerService) {
|
||||||
|
@PostMapping
|
||||||
|
fun createExplorerSection(@RequestBody request: CreateExplorerSectionRequest): ApiResponse<Any> {
|
||||||
|
service.createExplorerSection(request)
|
||||||
|
return ApiResponse.ok(null, "등록되었습니다.")
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
fun updateExplorerSection(@RequestBody request: UpdateExplorerSectionRequest) = ApiResponse.ok(
|
||||||
|
service.updateExplorerSection(request),
|
||||||
|
"수정되었습니다."
|
||||||
|
)
|
||||||
|
|
||||||
|
@PutMapping("/orders")
|
||||||
|
fun updateExplorerSectionOrders(
|
||||||
|
@RequestBody request: UpdateExplorerSectionOrdersRequest
|
||||||
|
) = ApiResponse.ok(
|
||||||
|
service.updateExplorerSectionOrders(request.firstOrders, request.ids),
|
||||||
|
"수정되었습니다."
|
||||||
|
)
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
fun getExplorerSections(pageable: Pageable) = ApiResponse.ok(service.getExplorerSections(pageable))
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.explorer
|
||||||
|
|
||||||
|
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||||
|
import kr.co.vividnext.sodalive.explorer.section.ExplorerSection
|
||||||
|
import kr.co.vividnext.sodalive.explorer.section.QExplorerSection.explorerSection
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
interface AdminExplorerSectionRepository : JpaRepository<ExplorerSection, Long>, AdminExplorerSectionQueryRepository
|
||||||
|
|
||||||
|
interface AdminExplorerSectionQueryRepository {
|
||||||
|
fun findByTitle(title: String): ExplorerSection?
|
||||||
|
fun findAllWithPaging(offset: Long, limit: Long): List<ExplorerSection>
|
||||||
|
fun totalCount(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
class AdminExplorerSectionQueryRepositoryImpl(
|
||||||
|
private val queryFactory: JPAQueryFactory
|
||||||
|
) : AdminExplorerSectionQueryRepository {
|
||||||
|
override fun findByTitle(title: String): ExplorerSection? {
|
||||||
|
return queryFactory
|
||||||
|
.selectFrom(explorerSection)
|
||||||
|
.where(explorerSection.title.eq(title))
|
||||||
|
.fetchFirst()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findAllWithPaging(offset: Long, limit: Long): List<ExplorerSection> {
|
||||||
|
return queryFactory
|
||||||
|
.selectFrom(explorerSection)
|
||||||
|
.offset(offset)
|
||||||
|
.limit(limit)
|
||||||
|
.orderBy(explorerSection.orders.asc())
|
||||||
|
.fetch()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun totalCount(): Int {
|
||||||
|
return queryFactory
|
||||||
|
.selectFrom(explorerSection)
|
||||||
|
.fetch()
|
||||||
|
.size
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.explorer
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
|
import kr.co.vividnext.sodalive.explorer.section.ExplorerSection
|
||||||
|
import kr.co.vividnext.sodalive.explorer.section.ExplorerSectionCreatorTag
|
||||||
|
import kr.co.vividnext.sodalive.member.tag.MemberTagRepository
|
||||||
|
import org.springframework.data.domain.Pageable
|
||||||
|
import org.springframework.data.repository.findByIdOrNull
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
import org.springframework.transaction.annotation.Transactional
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Transactional(readOnly = true)
|
||||||
|
class AdminExplorerService(
|
||||||
|
private val repository: AdminExplorerSectionRepository,
|
||||||
|
private val memberTagRepository: MemberTagRepository
|
||||||
|
) {
|
||||||
|
@Transactional
|
||||||
|
fun createExplorerSection(request: CreateExplorerSectionRequest): Long {
|
||||||
|
if (request.title.isBlank()) throw SodaException("제목을 입력하세요.")
|
||||||
|
|
||||||
|
val findExplorerSection = repository.findByTitle(request.title)
|
||||||
|
if (findExplorerSection != null) throw SodaException("동일한 제목이 있습니다.")
|
||||||
|
|
||||||
|
val explorerSection = ExplorerSection(title = request.title, isAdult = request.isAdult)
|
||||||
|
explorerSection.coloredTitle = request.coloredTitle
|
||||||
|
explorerSection.color = request.color
|
||||||
|
|
||||||
|
val tags = mutableListOf<ExplorerSectionCreatorTag>()
|
||||||
|
request.tagList.forEach {
|
||||||
|
val findTag = memberTagRepository.findByTag(it)
|
||||||
|
if (findTag != null) {
|
||||||
|
val tag = ExplorerSectionCreatorTag()
|
||||||
|
tag.explorerSection = explorerSection
|
||||||
|
tag.tag = findTag
|
||||||
|
tags.add(tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tags.size <= 0) throw SodaException("관심사를 선택하세요.")
|
||||||
|
explorerSection.tags = tags
|
||||||
|
|
||||||
|
return repository.save(explorerSection).id!!
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
fun updateExplorerSection(request: UpdateExplorerSectionRequest) {
|
||||||
|
if (
|
||||||
|
request.title == null &&
|
||||||
|
request.isAdult == null &&
|
||||||
|
request.tagList == null &&
|
||||||
|
request.color == null &&
|
||||||
|
request.coloredTitle == null &&
|
||||||
|
request.isActive == null
|
||||||
|
) {
|
||||||
|
throw SodaException("변경사항이 없습니다.")
|
||||||
|
}
|
||||||
|
|
||||||
|
val explorerSection = repository.findByIdOrNull(request.id)
|
||||||
|
?: throw SodaException("해당하는 섹션이 없습니다.")
|
||||||
|
|
||||||
|
if (request.title != null) {
|
||||||
|
if (request.title.isBlank()) throw SodaException("올바른 제목을 입력하세요.")
|
||||||
|
explorerSection.title = request.title
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.isActive != null) {
|
||||||
|
explorerSection.isActive = request.isActive
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.isAdult != null) {
|
||||||
|
explorerSection.isAdult = request.isAdult
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.color != null) {
|
||||||
|
explorerSection.color = request.color
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.coloredTitle != null) {
|
||||||
|
explorerSection.coloredTitle = request.coloredTitle
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.tagList != null) {
|
||||||
|
val requestTagList = request.tagList.toMutableList()
|
||||||
|
val tags = explorerSection.tags.filter {
|
||||||
|
requestTagList.contains(it.tag!!.tag)
|
||||||
|
requestTagList.remove(it.tag!!.tag)
|
||||||
|
}.toMutableList()
|
||||||
|
|
||||||
|
requestTagList.forEach {
|
||||||
|
val findTag = memberTagRepository.findByTag(it)
|
||||||
|
if (findTag != null) {
|
||||||
|
val tag = ExplorerSectionCreatorTag()
|
||||||
|
tag.explorerSection = explorerSection
|
||||||
|
tag.tag = findTag
|
||||||
|
tags.add(tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tags.size <= 0) throw SodaException("관심사를 입력하세요.")
|
||||||
|
if (tags != explorerSection.tags) {
|
||||||
|
explorerSection.tags.clear()
|
||||||
|
explorerSection.tags.addAll(tags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
fun updateExplorerSectionOrders(firstOrders: Int, ids: List<Long>) {
|
||||||
|
for (index in ids.indices) {
|
||||||
|
val explorerSection = repository.findByIdOrNull(ids[index])
|
||||||
|
|
||||||
|
if (explorerSection != null) {
|
||||||
|
explorerSection.orders = firstOrders + index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getExplorerSections(pageable: Pageable): GetAdminExplorerSectionResponse {
|
||||||
|
val totalCount = repository.totalCount()
|
||||||
|
val explorerSectionItemList = repository
|
||||||
|
.findAllWithPaging(pageable.offset, pageable.pageSize.toLong())
|
||||||
|
.map {
|
||||||
|
GetAdminExplorerSectionResponseItem(
|
||||||
|
id = it.id!!,
|
||||||
|
title = it.title,
|
||||||
|
coloredTitle = it.coloredTitle ?: "",
|
||||||
|
color = it.color ?: "",
|
||||||
|
isAdult = it.isAdult,
|
||||||
|
isActive = it.isActive,
|
||||||
|
tags = it.tags
|
||||||
|
.asSequence()
|
||||||
|
.filter { explorerSectionTag -> explorerSectionTag.tag!!.isActive }
|
||||||
|
.map { explorerSectionTag -> explorerSectionTag.tag!!.tag }
|
||||||
|
.toList()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetAdminExplorerSectionResponse(
|
||||||
|
totalCount = totalCount,
|
||||||
|
explorerSectionItemList = explorerSectionItemList
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.explorer
|
||||||
|
|
||||||
|
data class CreateExplorerSectionRequest(
|
||||||
|
val title: String,
|
||||||
|
val isAdult: Boolean,
|
||||||
|
val tagList: List<String>,
|
||||||
|
val coloredTitle: String? = null,
|
||||||
|
val color: String? = null
|
||||||
|
)
|
|
@ -0,0 +1,16 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.explorer
|
||||||
|
|
||||||
|
data class GetAdminExplorerSectionResponse(
|
||||||
|
val totalCount: Int,
|
||||||
|
val explorerSectionItemList: List<GetAdminExplorerSectionResponseItem>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class GetAdminExplorerSectionResponseItem(
|
||||||
|
val id: Long,
|
||||||
|
val title: String,
|
||||||
|
val coloredTitle: String,
|
||||||
|
val color: String,
|
||||||
|
val isAdult: Boolean,
|
||||||
|
val isActive: Boolean,
|
||||||
|
val tags: List<String>
|
||||||
|
)
|
|
@ -0,0 +1,6 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.explorer
|
||||||
|
|
||||||
|
data class UpdateExplorerSectionOrdersRequest(
|
||||||
|
val firstOrders: Int,
|
||||||
|
val ids: List<Long>
|
||||||
|
)
|
|
@ -0,0 +1,11 @@
|
||||||
|
package kr.co.vividnext.sodalive.admin.explorer
|
||||||
|
|
||||||
|
data class UpdateExplorerSectionRequest(
|
||||||
|
val id: Long,
|
||||||
|
val title: String? = null,
|
||||||
|
val isAdult: Boolean? = null,
|
||||||
|
val tagList: List<String>? = null,
|
||||||
|
val coloredTitle: String? = null,
|
||||||
|
val color: String? = null,
|
||||||
|
val isActive: Boolean? = null
|
||||||
|
)
|
|
@ -5,7 +5,9 @@ import kr.co.vividnext.sodalive.member.tag.QCreatorTag.creatorTag
|
||||||
import org.springframework.beans.factory.annotation.Value
|
import org.springframework.beans.factory.annotation.Value
|
||||||
import org.springframework.data.jpa.repository.JpaRepository
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
|
|
||||||
interface MemberTagRepository : JpaRepository<CreatorTag, Long>, MemberTagQueryRepository
|
interface MemberTagRepository : JpaRepository<CreatorTag, Long>, MemberTagQueryRepository {
|
||||||
|
fun findByTag(tag: String): CreatorTag?
|
||||||
|
}
|
||||||
|
|
||||||
interface MemberTagQueryRepository {
|
interface MemberTagQueryRepository {
|
||||||
fun getTags(): List<GetMemberTagResponse>
|
fun getTags(): List<GetMemberTagResponse>
|
||||||
|
|
Loading…
Reference in New Issue