From 34c08d434552a7d3133479eda6e88925fba5e3bb Mon Sep 17 00:00:00 2001 From: Klaus Date: Thu, 1 Feb 2024 19:37:15 +0900 Subject: [PATCH] =?UTF-8?q?=EC=BD=98=ED=85=90=EC=B8=A0=20=EC=B9=B4?= =?UTF-8?q?=ED=85=8C=EA=B3=A0=EB=A6=AC=20-=20=EB=93=B1=EB=A1=9D=20API=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/content/category/Category.kt | 18 +++++++++ .../content/category/CategoryContent.kt | 21 ++++++++++ .../category/CategoryContentRepository.kt | 23 +++++++++++ .../content/category/CategoryController.kt | 28 +++++++++++++ .../content/category/CategoryRepository.kt | 23 +++++++++++ .../content/category/CategoryService.kt | 40 +++++++++++++++++++ .../content/category/CreateCategoryRequest.kt | 6 +++ 7 files changed, 159 insertions(+) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/category/Category.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryContent.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryContentRepository.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryController.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryRepository.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryService.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/content/category/CreateCategoryRequest.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/category/Category.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/Category.kt new file mode 100644 index 0000000..4d576ae --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/Category.kt @@ -0,0 +1,18 @@ +package kr.co.vividnext.sodalive.content.category + +import kr.co.vividnext.sodalive.common.BaseEntity +import kr.co.vividnext.sodalive.member.Member +import javax.persistence.Entity +import javax.persistence.FetchType +import javax.persistence.JoinColumn +import javax.persistence.ManyToOne + +@Entity +data class Category( + val title: String, + var isActive: Boolean = true +) : BaseEntity() { + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", nullable = false) + var member: Member? = null +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryContent.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryContent.kt new file mode 100644 index 0000000..e48986d --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryContent.kt @@ -0,0 +1,21 @@ +package kr.co.vividnext.sodalive.content.category + +import kr.co.vividnext.sodalive.common.BaseEntity +import kr.co.vividnext.sodalive.content.AudioContent +import javax.persistence.Entity +import javax.persistence.FetchType +import javax.persistence.JoinColumn +import javax.persistence.ManyToOne + +@Entity +data class CategoryContent( + var isActive: Boolean = true +) : BaseEntity() { + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "content_id", nullable = false) + var content: AudioContent? = null + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "category_id", nullable = false) + var category: Category? = null +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryContentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryContentRepository.kt new file mode 100644 index 0000000..af49a35 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryContentRepository.kt @@ -0,0 +1,23 @@ +package kr.co.vividnext.sodalive.content.category + +import com.querydsl.jpa.impl.JPAQueryFactory +import kr.co.vividnext.sodalive.content.category.QCategoryContent.categoryContent +import org.springframework.data.jpa.repository.JpaRepository + +interface CategoryContentRepository : JpaRepository, CategoryContentQueryRepository + +interface CategoryContentQueryRepository { + fun findByContentIdAndCategoryId(contentId: Long, categoryId: Long): CategoryContent? +} + +class CategoryContentQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : CategoryContentQueryRepository { + override fun findByContentIdAndCategoryId(contentId: Long, categoryId: Long): CategoryContent? { + return queryFactory + .selectFrom(categoryContent) + .where( + categoryContent.content.id.eq(contentId) + .and(categoryContent.category.id.eq(categoryId)) + ) + .fetchFirst() + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryController.kt new file mode 100644 index 0000000..331944d --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryController.kt @@ -0,0 +1,28 @@ +package kr.co.vividnext.sodalive.content.category + +import kr.co.vividnext.sodalive.common.ApiResponse +import kr.co.vividnext.sodalive.common.SodaException +import kr.co.vividnext.sodalive.member.Member +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.security.core.annotation.AuthenticationPrincipal +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/category") +class CategoryController(private val service: CategoryService) { + @PostMapping + @PreAuthorize("hasRole('CREATOR')") + fun createCategory( + @RequestBody request: CreateCategoryRequest, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.createCategory(request = request, member = member) + ) + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryRepository.kt new file mode 100644 index 0000000..24bab28 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryRepository.kt @@ -0,0 +1,23 @@ +package kr.co.vividnext.sodalive.content.category + +import com.querydsl.jpa.impl.JPAQueryFactory +import kr.co.vividnext.sodalive.content.category.QCategory.category +import org.springframework.data.jpa.repository.JpaRepository + +interface CategoryRepository : JpaRepository, CategoryQueryRepository + +interface CategoryQueryRepository { + fun findByTitleAndMemberId(title: String, memberId: Long): Category? +} + +class CategoryQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : CategoryQueryRepository { + override fun findByTitleAndMemberId(title: String, memberId: Long): Category? { + return queryFactory + .selectFrom(category) + .where( + category.title.eq(title) + .and(category.member.id.eq(memberId)) + ) + .fetchFirst() + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryService.kt new file mode 100644 index 0000000..414e6b3 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CategoryService.kt @@ -0,0 +1,40 @@ +package kr.co.vividnext.sodalive.content.category + +import kr.co.vividnext.sodalive.content.AudioContentRepository +import kr.co.vividnext.sodalive.member.Member +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class CategoryService( + private val repository: CategoryRepository, + private val contentRepository: AudioContentRepository, + private val categoryContentRepository: CategoryContentRepository +) { + @Transactional + fun createCategory(request: CreateCategoryRequest, member: Member) { + val category = repository.findByTitleAndMemberId(title = request.title, memberId = member.id!!) + ?: repository.save( + Category(title = request.title).apply { + this.member = member + } + ) + category.isActive = true + + for (contentId in request.contentIdList) { + val content = contentRepository.findByIdAndActive(contentId = contentId) + ?: continue + + val categoryContent = categoryContentRepository.findByContentIdAndCategoryId( + contentId = contentId, + categoryId = category.id!! + ) ?: categoryContentRepository.save( + CategoryContent().apply { + this.content = content + this.category = category + } + ) + categoryContent.isActive = true + } + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CreateCategoryRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CreateCategoryRequest.kt new file mode 100644 index 0000000..7484b3c --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/category/CreateCategoryRequest.kt @@ -0,0 +1,6 @@ +package kr.co.vividnext.sodalive.content.category + +data class CreateCategoryRequest( + val title: String, + val contentIdList: List +)