feat(original): 원작 도메인 추가, 관리자 CRUD/연결 API, 소프트 삭제, 서비스 계층 정비
- 원작 엔티티/레포지토리/관리자 API 구축(이미지 S3 업로드 포함) - 캐릭터-원작 연관관계 및 관리자에서 배정/해제 API 제공 - 소프트 삭제(`isDeleted`) 도입 및 조회/수정/배정 로직에서 삭제 항목 필터링 - 컨트롤러-레포지토리 직접 접근 제거, `AdminOriginalWorkService`로 DB 접근 캡슐화 - 캐릭터 등록/수정에서 `originalWorkId` 지원 및 외부 API 업데이트 조건 분리
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package kr.co.vividnext.sodalive.chat.character
|
||||
|
||||
import kr.co.vividnext.sodalive.chat.original.OriginalWork
|
||||
import kr.co.vividnext.sodalive.common.BaseEntity
|
||||
import javax.persistence.CascadeType
|
||||
import javax.persistence.Column
|
||||
@@ -7,6 +8,8 @@ import javax.persistence.Entity
|
||||
import javax.persistence.EnumType
|
||||
import javax.persistence.Enumerated
|
||||
import javax.persistence.FetchType
|
||||
import javax.persistence.JoinColumn
|
||||
import javax.persistence.ManyToOne
|
||||
import javax.persistence.OneToMany
|
||||
|
||||
@Entity
|
||||
@@ -44,14 +47,19 @@ class ChatCharacter(
|
||||
@Column(columnDefinition = "TEXT")
|
||||
var appearance: String? = null,
|
||||
|
||||
// 원작 (optional)
|
||||
// 원작명/원작링크 (사용하지 않음 - 하위 호환을 위해 필드만 유지)
|
||||
@Column(nullable = true)
|
||||
var originalTitle: String? = null,
|
||||
|
||||
// 원작 링크 (optional)
|
||||
// 원작 링크 (사용하지 않음 - 하위 호환을 위해 필드만 유지)
|
||||
@Column(nullable = true)
|
||||
var originalLink: String? = null,
|
||||
|
||||
// 연관 원작 (한 캐릭터는 하나의 원작에만 속함)
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "original_work_id")
|
||||
var originalWork: OriginalWork? = null,
|
||||
|
||||
// 캐릭터 유형
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package kr.co.vividnext.sodalive.chat.original
|
||||
|
||||
import kr.co.vividnext.sodalive.common.BaseEntity
|
||||
import javax.persistence.Column
|
||||
import javax.persistence.Entity
|
||||
|
||||
/**
|
||||
* 원작(오리지널 작품) 엔티티
|
||||
* - 캐릭터를 원작별로 묶기 위한 기준 엔티티
|
||||
* - 각 필드는 운영에서 관리자가 입력/수정한다.
|
||||
*/
|
||||
@Entity
|
||||
class OriginalWork(
|
||||
/** 원작 제목 */
|
||||
@Column(nullable = false)
|
||||
var title: String,
|
||||
|
||||
/** 콘텐츠 타입 (예: 웹소설, 웹툰 등) */
|
||||
@Column(nullable = false)
|
||||
var contentType: String,
|
||||
|
||||
/** 카테고리/장르 (예: 로맨스, 판타지 등) */
|
||||
@Column(nullable = false)
|
||||
var category: String,
|
||||
|
||||
/** 19금 여부 */
|
||||
@Column(nullable = false)
|
||||
var isAdult: Boolean = false,
|
||||
|
||||
/** 작품 소개 */
|
||||
@Column(columnDefinition = "TEXT")
|
||||
var description: String = "",
|
||||
|
||||
/** 원작 링크 */
|
||||
@Column(nullable = true)
|
||||
var originalLink: String? = null
|
||||
) : BaseEntity() {
|
||||
/** 원작 대표 이미지 S3 경로 */
|
||||
var imagePath: String? = null
|
||||
|
||||
/** 소프트 삭제 여부 (true면 삭제된 것으로 간주) */
|
||||
var isDeleted: Boolean = false
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package kr.co.vividnext.sodalive.chat.original
|
||||
|
||||
import org.springframework.data.domain.Page
|
||||
import org.springframework.data.domain.Pageable
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.stereotype.Repository
|
||||
import java.util.Optional
|
||||
|
||||
@Repository
|
||||
interface OriginalWorkRepository : JpaRepository<OriginalWork, Long> {
|
||||
fun findByTitleAndIsDeletedFalse(title: String): OriginalWork?
|
||||
fun findByIdAndIsDeletedFalse(id: Long): Optional<OriginalWork>
|
||||
fun findByIsDeletedFalse(pageable: Pageable): Page<OriginalWork>
|
||||
}
|
||||
Reference in New Issue
Block a user