Compare commits

..

7 Commits

Author SHA1 Message Date
klaus dcbe57806c Merge pull request 'test' (#322) from test into main
Reviewed-on: #322
2025-06-02 12:41:46 +00:00
Klaus fd1b17e356 fix: 크리에이터 관리자 콘텐츠 수정 - 태그 수정 기능
- 이미 있는 태그는 다시 추가되지 않도록 추가
2025-06-02 21:33:00 +09:00
Klaus 28427a873a fix: 크리에이터 관리자 콘텐츠 수정 - 태그 수정 기능
- 이미 있는 태그는 다시 추가되지 않도록 추가
2025-06-02 21:20:47 +09:00
Klaus 5bdb101b52 fix: 크리에이터 관리자 콘텐츠 수정 - 태그 수정 기능
- 빈 칸인 경우 #으로 추가되는 버그 수정
2025-06-02 20:53:06 +09:00
Klaus 97b2b38f8e fix: 크리에이터 관리자, 관리자 콘텐츠 리스트
- isActive = True 태그만 조회되도록 수정
2025-06-02 20:25:54 +09:00
Klaus 2268f4a3fc fix: 크리에이터 관리자 콘텐츠 수정 - 태그 수정 기능
- 빈 칸인 경우 #으로 추가되는 버그 수정
2025-06-02 20:21:50 +09:00
Klaus 9eff828249 feat: 크리에이터 관리자 콘텐츠 수정
- 태그 수정 기능 추가
2025-06-02 20:10:13 +09:00
4 changed files with 74 additions and 0 deletions

View File

@ -140,6 +140,7 @@ class AdminAudioContentQueryRepositoryImpl(
audioContent.duration.isNotNull audioContent.duration.isNotNull
.and(audioContent.member.isNotNull) .and(audioContent.member.isNotNull)
.and(audioContentHashTag.audioContent.id.eq(audioContentId)) .and(audioContentHashTag.audioContent.id.eq(audioContentId))
.and(audioContentHashTag.isActive.isTrue)
) )
.fetch() .fetch()
} }

View File

@ -6,6 +6,7 @@ import com.querydsl.core.types.dsl.StringTemplate
import com.querydsl.jpa.impl.JPAQueryFactory import com.querydsl.jpa.impl.JPAQueryFactory
import kr.co.vividnext.sodalive.content.AudioContent import kr.co.vividnext.sodalive.content.AudioContent
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
import kr.co.vividnext.sodalive.content.hashtag.AudioContentHashTag
import kr.co.vividnext.sodalive.content.hashtag.QAudioContentHashTag.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.hashtag.QHashTag.hashTag
import kr.co.vividnext.sodalive.content.theme.QAudioContentTheme.audioContentTheme import kr.co.vividnext.sodalive.content.theme.QAudioContentTheme.audioContentTheme
@ -27,6 +28,10 @@ interface CreatorAdminAudioContentQueryRepository {
fun getHashTagList(audioContentId: Long): List<String> fun getHashTagList(audioContentId: Long): List<String>
fun getAudioContent(memberId: Long, audioContentId: Long): AudioContent? fun getAudioContent(memberId: Long, audioContentId: Long): AudioContent?
fun findContentHashTagByContentIdAndIsActive(contentId: Long, isActive: Boolean): List<AudioContentHashTag>
fun findContentIdAndHashTagId(contentId: Long, hashTagId: Int): AudioContentHashTag?
} }
class CreatorAdminAudioContentQueryRepositoryImpl( class CreatorAdminAudioContentQueryRepositoryImpl(
@ -111,6 +116,7 @@ class CreatorAdminAudioContentQueryRepositoryImpl(
audioContent.duration.isNotNull audioContent.duration.isNotNull
.and(audioContent.member.isNotNull) .and(audioContent.member.isNotNull)
.and(audioContentHashTag.audioContent.id.eq(audioContentId)) .and(audioContentHashTag.audioContent.id.eq(audioContentId))
.and(audioContentHashTag.isActive.isTrue)
) )
.fetch() .fetch()
} }
@ -127,6 +133,33 @@ class CreatorAdminAudioContentQueryRepositoryImpl(
.fetchFirst() .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()
}
private fun formattedDateExpression( private fun formattedDateExpression(
dateTime: DateTimePath<LocalDateTime>, dateTime: DateTimePath<LocalDateTime>,
format: String = "%Y-%m-%d" format: String = "%Y-%m-%d"

View File

@ -7,6 +7,9 @@ import kr.co.vividnext.sodalive.aws.s3.S3Uploader
import kr.co.vividnext.sodalive.common.SodaException import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.content.ContentPriceChangeLog import kr.co.vividnext.sodalive.content.ContentPriceChangeLog
import kr.co.vividnext.sodalive.content.ContentPriceChangeLogRepository import kr.co.vividnext.sodalive.content.ContentPriceChangeLogRepository
import kr.co.vividnext.sodalive.content.hashtag.AudioContentHashTag
import kr.co.vividnext.sodalive.content.hashtag.HashTag
import kr.co.vividnext.sodalive.content.hashtag.HashTagRepository
import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.member.Member
import kr.co.vividnext.sodalive.utils.generateFileName import kr.co.vividnext.sodalive.utils.generateFileName
import org.springframework.beans.factory.annotation.Value import org.springframework.beans.factory.annotation.Value
@ -18,6 +21,7 @@ import org.springframework.web.multipart.MultipartFile
@Service @Service
class CreatorAdminContentService( class CreatorAdminContentService(
private val repository: CreatorAdminContentRepository, private val repository: CreatorAdminContentRepository,
private val hashTagRepository: HashTagRepository,
private val contentPriceChangeLogRepository: ContentPriceChangeLogRepository, private val contentPriceChangeLogRepository: ContentPriceChangeLogRepository,
private val audioContentCloudFront: AudioContentCloudFront, private val audioContentCloudFront: AudioContentCloudFront,
private val objectMapper: ObjectMapper, private val objectMapper: ObjectMapper,
@ -156,5 +160,40 @@ class CreatorAdminContentService(
audioContent.price = request.price audioContent.price = request.price
} }
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.id, 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.id, hashTag.id!!)
?: AudioContentHashTag()
audioContentHashTag.audioContent = audioContent
audioContentHashTag.hashTag = hashTag
audioContentHashTag.isActive = true
audioContentHashTag
}
audioContent.audioContentHashTags.addAll(newAudioContentHashTagList)
}
} }
} }

View File

@ -4,6 +4,7 @@ data class UpdateCreatorAdminContentRequest(
val id: Long, val id: Long,
val title: String?, val title: String?,
val detail: String?, val detail: String?,
val tags: String?,
val price: Int?, val price: Int?,
val isAdult: Boolean?, val isAdult: Boolean?,
val isActive: Boolean?, val isActive: Boolean?,