From 7055bb987227f00778ce30169dc3081c7255d887 Mon Sep 17 00:00:00 2001
From: Klaus <klaus@vividnext.co.kr>
Date: Wed, 4 Jun 2025 17:21:08 +0900
Subject: [PATCH] =?UTF-8?q?fix:=20=EC=95=B1=20=EC=BD=98=ED=85=90=EC=B8=A0?=
 =?UTF-8?q?=20=EC=88=98=EC=A0=95=20-=20=ED=83=9C=EA=B7=B8=20=EC=88=98?=
 =?UTF-8?q?=EC=A0=95,=20=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=82=AC=EC=9A=A9?=
 =?UTF-8?q?=EC=97=AC=EB=B6=80=20=EC=88=98=EC=A0=95=20=EA=B8=B0=EB=8A=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../content/AudioContentRepository.kt         | 34 ++++++++++++++++++
 .../sodalive/content/AudioContentService.kt   | 36 +++++++++++++++++++
 .../content/ModifyAudioContentRequest.kt      |  2 ++
 3 files changed, 72 insertions(+)

diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt
index c118124..7028673 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentRepository.kt
@@ -5,6 +5,9 @@ import com.querydsl.jpa.impl.JPAQueryFactory
 import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
 import kr.co.vividnext.sodalive.content.category.QCategoryContent.categoryContent
 import kr.co.vividnext.sodalive.content.comment.QAudioContentComment.audioContentComment
+import kr.co.vividnext.sodalive.content.hashtag.AudioContentHashTag
+import kr.co.vividnext.sodalive.content.hashtag.QAudioContentHashTag.audioContentHashTag
+import kr.co.vividnext.sodalive.content.hashtag.QHashTag.hashTag
 import kr.co.vividnext.sodalive.content.like.QAudioContentLike.audioContentLike
 import kr.co.vividnext.sodalive.content.main.ContentCreatorResponse
 import kr.co.vividnext.sodalive.content.main.GetAudioContentMainItem
@@ -169,6 +172,10 @@ interface AudioContentQueryRepository {
     fun findNextContent(seriesId: Long, title: String, isAdult: Boolean): OtherContentResponse?
 
     fun findSeriesIdByContentId(contentId: Long, isAdult: Boolean): Long?
+
+    fun findContentHashTagByContentIdAndIsActive(contentId: Long, isActive: Boolean): List<AudioContentHashTag>
+
+    fun findContentIdAndHashTagId(contentId: Long, hashTagId: Int): AudioContentHashTag?
 }
 
 @Repository
@@ -1240,4 +1247,31 @@ class AudioContentQueryRepositoryImpl(
             .limit(1)
             .fetchFirst()
     }
+
+    override fun findContentHashTagByContentIdAndIsActive(
+        contentId: Long,
+        isActive: Boolean
+    ): List<AudioContentHashTag> {
+        return queryFactory
+            .selectFrom(audioContentHashTag)
+            .innerJoin(audioContentHashTag.audioContent, audioContent)
+            .where(
+                audioContentHashTag.isActive.eq(isActive)
+                    .and(audioContent.id.eq(contentId))
+            )
+            .fetch()
+    }
+
+    override fun findContentIdAndHashTagId(contentId: Long, hashTagId: Int): AudioContentHashTag? {
+        return queryFactory
+            .selectFrom(audioContentHashTag)
+            .innerJoin(audioContentHashTag.audioContent, audioContent)
+            .innerJoin(audioContentHashTag.hashTag, hashTag)
+            .where(
+                audioContent.id.eq(contentId),
+                hashTag.id.eq(hashTagId)
+            )
+            .orderBy(audioContentHashTag.id.asc())
+            .fetchFirst()
+    }
 }
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt
index b9cb6a5..39c917d 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/AudioContentService.kt
@@ -104,6 +104,7 @@ class AudioContentService(
 
         if (request.title != null) audioContent.title = request.title
         if (request.detail != null) audioContent.detail = request.detail
+        if (request.isPointAvailable != null) audioContent.isPointAvailable = request.isPointAvailable
         audioContent.isCommentAvailable = request.isCommentAvailable
         audioContent.isAdult = request.isAdult
 
@@ -124,6 +125,41 @@ class AudioContentService(
 
             audioContent.coverImage = coverImagePath
         }
+
+        if (!request.tags.isNullOrBlank()) {
+            val normalizedTags = request.tags
+                .replace("#", " #")
+                .split(" ")
+                .map { it.trim() }
+                .filter { it.isNotBlank() }
+                .map { if (it.startsWith("#")) it else "#$it" }
+                .distinct()
+
+            val currentContentTags = repository.findContentHashTagByContentIdAndIsActive(request.contentId, true)
+            val currentTagMap = currentContentTags.associateBy { it.hashTag!!.tag }
+
+            val tagsToAdd = normalizedTags.subtract(currentTagMap.keys)
+            val tagsToDeactivate = currentTagMap.keys.subtract(normalizedTags.toSet())
+
+            tagsToDeactivate.forEach {
+                currentTagMap[it]?.let { cht -> cht.isActive = false }
+            }
+
+            val newAudioContentHashTagList = tagsToAdd.map { tag ->
+                val hashTag = hashTagRepository.findByTag(tag)
+                    ?: hashTagRepository.save(HashTag(tag))
+
+                val audioContentHashTag = repository.findContentIdAndHashTagId(request.contentId, hashTag.id!!)
+                    ?: AudioContentHashTag()
+                audioContentHashTag.audioContent = audioContent
+                audioContentHashTag.hashTag = hashTag
+                audioContentHashTag.isActive = true
+
+                audioContentHashTag
+            }
+
+            audioContent.audioContentHashTags.addAll(newAudioContentHashTagList)
+        }
     }
 
     @Transactional
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/content/ModifyAudioContentRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/content/ModifyAudioContentRequest.kt
index fc104f7..83ca0d1 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/content/ModifyAudioContentRequest.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/content/ModifyAudioContentRequest.kt
@@ -4,6 +4,8 @@ data class ModifyAudioContentRequest(
     val contentId: Long,
     val title: String?,
     val detail: String?,
+    val tags: String?,
     val isAdult: Boolean,
+    val isPointAvailable: Boolean?,
     val isCommentAvailable: Boolean
 )