관리자 - FAQ API
This commit is contained in:
parent
87a5ceee9c
commit
a983595bad
|
@ -0,0 +1,7 @@
|
||||||
|
package kr.co.vividnext.sodalive.faq
|
||||||
|
|
||||||
|
data class CreateFaqRequest(
|
||||||
|
val question: String,
|
||||||
|
val answer: String,
|
||||||
|
val category: String
|
||||||
|
)
|
|
@ -0,0 +1,22 @@
|
||||||
|
package kr.co.vividnext.sodalive.faq
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.BaseEntity
|
||||||
|
import javax.persistence.Column
|
||||||
|
import javax.persistence.Entity
|
||||||
|
import javax.persistence.FetchType
|
||||||
|
import javax.persistence.JoinColumn
|
||||||
|
import javax.persistence.ManyToOne
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
data class Faq(
|
||||||
|
@Column(nullable = false)
|
||||||
|
var question: String,
|
||||||
|
@Column(columnDefinition = "TEXT", nullable = false)
|
||||||
|
var answer: String,
|
||||||
|
var isActive: Boolean = true,
|
||||||
|
val orders: Int = 1
|
||||||
|
) : BaseEntity() {
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "category_id", nullable = false)
|
||||||
|
var category: FaqCategory? = null
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package kr.co.vividnext.sodalive.faq
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.BaseEntity
|
||||||
|
import javax.persistence.Column
|
||||||
|
import javax.persistence.Entity
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
data class FaqCategory(
|
||||||
|
@Column(nullable = false)
|
||||||
|
val category: String,
|
||||||
|
val isActive: Boolean = true,
|
||||||
|
val orders: Int = 1
|
||||||
|
) : BaseEntity()
|
|
@ -0,0 +1,7 @@
|
||||||
|
package kr.co.vividnext.sodalive.faq
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
interface FaqCategoryRepository : JpaRepository<FaqCategory, Long>
|
|
@ -0,0 +1,41 @@
|
||||||
|
package kr.co.vividnext.sodalive.faq
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize
|
||||||
|
import org.springframework.web.bind.annotation.DeleteMapping
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable
|
||||||
|
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
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/faq")
|
||||||
|
class FaqController(private val service: FaqService) {
|
||||||
|
@PostMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
fun createFaq(@RequestBody request: CreateFaqRequest) = ApiResponse.ok(
|
||||||
|
service.save(request),
|
||||||
|
"등록되었습니다."
|
||||||
|
)
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
fun modifyFaq(@RequestBody request: ModifyFaqRequest) = ApiResponse.ok(
|
||||||
|
service.modify(request),
|
||||||
|
"수정되었습니다."
|
||||||
|
)
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
|
fun deleteCoin(@PathVariable id: Long) = ApiResponse.ok(service.delete(id), "삭제되었습니다.")
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
fun getFaqList(@RequestParam("category") category: String) = ApiResponse.ok(service.getFaqList(category))
|
||||||
|
|
||||||
|
@GetMapping("/category")
|
||||||
|
fun getFaqCategoryList() = ApiResponse.ok(service.getCategoryList())
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package kr.co.vividnext.sodalive.faq
|
||||||
|
|
||||||
|
import com.querydsl.core.types.dsl.Expressions
|
||||||
|
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||||
|
import kr.co.vividnext.sodalive.faq.QFaq.faq
|
||||||
|
import kr.co.vividnext.sodalive.faq.QFaqCategory.faqCategory
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
interface FaqRepository : JpaRepository<Faq, Long>
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
class FaqQueryRepository(private val queryFactory: JPAQueryFactory) {
|
||||||
|
fun getCategory(category: String): FaqCategory? {
|
||||||
|
return queryFactory
|
||||||
|
.selectFrom(faqCategory)
|
||||||
|
.where(
|
||||||
|
faqCategory.isActive.isTrue
|
||||||
|
.and(faqCategory.category.eq(category))
|
||||||
|
)
|
||||||
|
.fetchFirst()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getCategoryList(): List<String> {
|
||||||
|
return queryFactory
|
||||||
|
.select(faqCategory.category)
|
||||||
|
.from(faqCategory)
|
||||||
|
.where(faqCategory.isActive.isTrue)
|
||||||
|
.orderBy(faqCategory.orders.desc())
|
||||||
|
.fetch()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFaqList(category: String): List<GetFaqResponseItem> {
|
||||||
|
return queryFactory
|
||||||
|
.select(
|
||||||
|
QGetFaqResponseItem(
|
||||||
|
faq.id,
|
||||||
|
Expressions.asString(category),
|
||||||
|
faq.question,
|
||||||
|
faq.answer
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.from(faq)
|
||||||
|
.innerJoin(faq.category, faqCategory)
|
||||||
|
.where(
|
||||||
|
faq.isActive.isTrue
|
||||||
|
.and(faqCategory.isActive.isTrue)
|
||||||
|
.and(faqCategory.category.eq(category))
|
||||||
|
)
|
||||||
|
.orderBy(faq.orders.desc())
|
||||||
|
.fetch()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFaq(id: Long): Faq? {
|
||||||
|
return queryFactory
|
||||||
|
.selectFrom(faq)
|
||||||
|
.where(
|
||||||
|
faq.isActive.isTrue
|
||||||
|
.and(faq.id.eq(id))
|
||||||
|
)
|
||||||
|
.fetchFirst()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package kr.co.vividnext.sodalive.faq
|
||||||
|
|
||||||
|
import kr.co.vividnext.sodalive.common.SodaException
|
||||||
|
import org.springframework.data.repository.findByIdOrNull
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
import org.springframework.transaction.annotation.Transactional
|
||||||
|
|
||||||
|
@Service
|
||||||
|
class FaqService(
|
||||||
|
private val repository: FaqRepository,
|
||||||
|
private val queryRepository: FaqQueryRepository
|
||||||
|
) {
|
||||||
|
@Transactional
|
||||||
|
fun save(request: CreateFaqRequest): Long {
|
||||||
|
if (request.question.isBlank()) throw SodaException("질문을 입력하세요.")
|
||||||
|
if (request.answer.isBlank()) throw SodaException("답변을 입력하세요.")
|
||||||
|
if (request.category.isBlank()) throw SodaException("카테고리를 선택하세요.")
|
||||||
|
|
||||||
|
val category = queryRepository.getCategory(request.category)
|
||||||
|
?: throw SodaException("잘못된 카테고리 입니다.")
|
||||||
|
|
||||||
|
val faq = Faq(request.question, request.answer)
|
||||||
|
faq.category = category
|
||||||
|
|
||||||
|
return repository.save(faq).id!!
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
fun modify(request: ModifyFaqRequest) {
|
||||||
|
val faq = queryRepository.getFaq(request.id)
|
||||||
|
?: throw SodaException("잘못된 요청입니다.")
|
||||||
|
|
||||||
|
if (request.question != null) {
|
||||||
|
if (request.question.isBlank()) throw SodaException("질문을 입력하세요.")
|
||||||
|
faq.question = request.question
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.answer != null) {
|
||||||
|
if (request.answer.isBlank()) throw SodaException("답변을 입력하세요.")
|
||||||
|
faq.answer = request.answer
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.category != null) {
|
||||||
|
if (request.category.isBlank()) throw SodaException("카테고리를 선택하세요.")
|
||||||
|
val category = queryRepository.getCategory(request.category) ?: throw SodaException("잘못된 카테고리 입니다.")
|
||||||
|
faq.category = category
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
fun delete(id: Long) {
|
||||||
|
if (id <= 0) throw SodaException("잘못된 요청입니다.")
|
||||||
|
val faq = repository.findByIdOrNull(id)
|
||||||
|
?: throw SodaException("잘못된 요청입니다.")
|
||||||
|
|
||||||
|
faq.isActive = false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFaqList(category: String) = queryRepository.getFaqList(category)
|
||||||
|
|
||||||
|
fun getCategoryList() = queryRepository.getCategoryList()
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package kr.co.vividnext.sodalive.faq
|
||||||
|
|
||||||
|
import com.querydsl.core.annotations.QueryProjection
|
||||||
|
|
||||||
|
data class GetFaqResponseItem @QueryProjection constructor(
|
||||||
|
val id: Long,
|
||||||
|
val category: String,
|
||||||
|
val question: String,
|
||||||
|
val answer: String
|
||||||
|
)
|
|
@ -0,0 +1,8 @@
|
||||||
|
package kr.co.vividnext.sodalive.faq
|
||||||
|
|
||||||
|
data class ModifyFaqRequest(
|
||||||
|
val id: Long,
|
||||||
|
val question: String? = null,
|
||||||
|
val answer: String? = null,
|
||||||
|
val category: String? = null
|
||||||
|
)
|
Loading…
Reference in New Issue