관리자 - 탐색 메뉴 API 추가

This commit is contained in:
Klaus 2023-08-07 18:20:00 +09:00
parent 14220ff6dc
commit f7cdf40976
8 changed files with 271 additions and 1 deletions

View File

@ -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))
}

View File

@ -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
}
}

View File

@ -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
)
}
}

View File

@ -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
)

View File

@ -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>
)

View File

@ -0,0 +1,6 @@
package kr.co.vividnext.sodalive.admin.explorer
data class UpdateExplorerSectionOrdersRequest(
val firstOrders: Int,
val ids: List<Long>
)

View File

@ -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
)

View File

@ -5,7 +5,9 @@ import kr.co.vividnext.sodalive.member.tag.QCreatorTag.creatorTag
import org.springframework.beans.factory.annotation.Value
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 {
fun getTags(): List<GetMemberTagResponse>