test #426

Merged
klaus merged 415 commits from test into main 2026-06-27 00:35:30 +00:00
4 changed files with 59 additions and 1 deletions
Showing only changes of commit 5d1290e114 - Show all commits

View File

@@ -21,6 +21,8 @@ import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.QCreatorCommun
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment.QCreatorCommunityComment.creatorCommunityComment import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.comment.QCreatorCommunityComment.creatorCommunityComment
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.like.QCreatorCommunityLike.creatorCommunityLike import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.like.QCreatorCommunityLike.creatorCommunityLike
import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom
import kr.co.vividnext.sodalive.member.MemberKind
import kr.co.vividnext.sodalive.member.MemberRole
import kr.co.vividnext.sodalive.member.QMember import kr.co.vividnext.sodalive.member.QMember
import kr.co.vividnext.sodalive.member.QMember.member import kr.co.vividnext.sodalive.member.QMember.member
import kr.co.vividnext.sodalive.member.block.QBlockMember import kr.co.vividnext.sodalive.member.block.QBlockMember
@@ -688,12 +690,14 @@ class DefaultHomeRecommendationQueryRepository(
): List<HomeAiCharacterRecommendationRecord> { ): List<HomeAiCharacterRecommendationRecord> {
if (characterIds.isEmpty()) return emptyList() if (characterIds.isEmpty()) return emptyList()
val linkedOriginalWork = QOriginalWork("linkedOriginalWork") val linkedOriginalWork = QOriginalWork("linkedOriginalWork")
val creatorMember = QMember("creatorMember")
return queryFactory return queryFactory
.select( .select(
Projections.constructor( Projections.constructor(
HomeAiCharacterRecommendationRecord::class.java, HomeAiCharacterRecommendationRecord::class.java,
chatCharacter.id, chatCharacter.id,
creatorMember.id,
chatCharacter.name, chatCharacter.name,
chatCharacter.description, chatCharacter.description,
chatCharacter.imagePath, chatCharacter.imagePath,
@@ -702,6 +706,7 @@ class DefaultHomeRecommendationQueryRepository(
) )
) )
.from(chatCharacter) .from(chatCharacter)
.join(chatCharacter.creatorMember, creatorMember)
.leftJoin(chatCharacter.originalWork, linkedOriginalWork).on(linkedOriginalWork.isDeleted.isFalse) .leftJoin(chatCharacter.originalWork, linkedOriginalWork).on(linkedOriginalWork.isDeleted.isFalse)
.leftJoin(chatParticipant).on( .leftJoin(chatParticipant).on(
chatParticipant.character.id.eq(chatCharacter.id), chatParticipant.character.id.eq(chatCharacter.id),
@@ -712,9 +717,16 @@ class DefaultHomeRecommendationQueryRepository(
chatMessage.participant.id.eq(chatParticipant.id), chatMessage.participant.id.eq(chatParticipant.id),
chatMessage.isActive.isTrue chatMessage.isActive.isTrue
) )
.where(chatCharacter.isActive.isTrue, chatCharacter.id.`in`(characterIds)) .where(
chatCharacter.isActive.isTrue,
chatCharacter.id.`in`(characterIds),
creatorMember.isActive.isTrue,
creatorMember.role.eq(MemberRole.CREATOR),
creatorMember.memberKind.eq(MemberKind.AI_CHARACTER)
)
.groupBy( .groupBy(
chatCharacter.id, chatCharacter.id,
creatorMember.id,
chatCharacter.name, chatCharacter.name,
chatCharacter.description, chatCharacter.description,
chatCharacter.imagePath, chatCharacter.imagePath,

View File

@@ -121,6 +121,7 @@ data class HomeFirstAudioContentRecord(
data class HomeAiCharacterRecommendationRecord( data class HomeAiCharacterRecommendationRecord(
val characterId: Long, val characterId: Long,
val creatorId: Long,
val name: String, val name: String,
val description: String, val description: String,
val profileImage: String?, val profileImage: String?,

View File

@@ -1169,6 +1169,8 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
.associateBy { it.characterId } .associateBy { it.characterId }
assertEquals(setOf(characterWithWork.id, characterWithoutWork.id), details.keys) assertEquals(setOf(characterWithWork.id, characterWithoutWork.id), details.keys)
assertEquals(characterWithWork.creatorMember!!.id, details[characterWithWork.id]!!.creatorId)
assertEquals(characterWithoutWork.creatorMember!!.id, details[characterWithoutWork.id]!!.creatorId)
assertEquals("ai-detail-work", details[characterWithWork.id]!!.name) assertEquals("ai-detail-work", details[characterWithWork.id]!!.name)
assertEquals("description", details[characterWithWork.id]!!.description) assertEquals("description", details[characterWithWork.id]!!.description)
assertEquals(2L, details[characterWithWork.id]!!.totalChatCount) assertEquals(2L, details[characterWithWork.id]!!.totalChatCount)
@@ -1177,6 +1179,37 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
assertEquals(null, details[characterWithoutWork.id]!!.originalWorkTitle) assertEquals(null, details[characterWithoutWork.id]!!.originalWorkTitle)
} }
@Test
@DisplayName("AI 캐릭터 상세는 활성 AI 캐릭터 크리에이터 회원인 경우만 조회한다")
fun shouldFindAiCharacterRecommendationDetailsForActiveAiCreatorMembersOnly() {
val activeCharacter = saveCharacter("ai-detail-active-creator-member", isActive = true)
val missingCreatorCharacter = saveCharacter("ai-detail-missing-creator-member", isActive = true)
val inactiveCreatorCharacter = saveCharacter("ai-detail-inactive-creator-member", isActive = true).apply {
creatorMember!!.isActive = false
}
val userCreatorCharacter = saveCharacter("ai-detail-user-creator-member", isActive = true).apply {
creatorMember!!.role = MemberRole.USER
}
val humanCreatorCharacter = saveCharacter("ai-detail-human-creator-member", isActive = true).apply {
creatorMember!!.memberKind = MemberKind.HUMAN
}
detachCreatorMember(missingCreatorCharacter)
flushAndClear()
val details = repository.findAiCharacterRecommendationDetails(
listOf(
activeCharacter.id!!,
missingCreatorCharacter.id!!,
inactiveCreatorCharacter.id!!,
userCreatorCharacter.id!!,
humanCreatorCharacter.id!!
)
)
assertEquals(listOf(activeCharacter.id), details.map { it.characterId })
assertEquals(activeCharacter.creatorMember!!.id, details.single().creatorId)
}
@Test @Test
@DisplayName("AI 캐릭터 상세는 빈 id 목록이면 빈 배열을 반환한다") @DisplayName("AI 캐릭터 상세는 빈 id 목록이면 빈 배열을 반환한다")
fun shouldReturnEmptyAiCharacterRecommendationDetailsWhenIdsAreEmpty() { fun shouldReturnEmptyAiCharacterRecommendationDetailsWhenIdsAreEmpty() {
@@ -2107,4 +2140,13 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
entityManager.flush() entityManager.flush()
entityManager.clear() entityManager.clear()
} }
private fun detachCreatorMember(character: ChatCharacter) {
entityManager.flush()
entityManager.createNativeQuery("alter table chat_character alter column creator_member_id drop not null")
.executeUpdate()
entityManager.createNativeQuery("update chat_character set creator_member_id = null where id = :id")
.setParameter("id", character.id)
.executeUpdate()
}
} }

View File

@@ -143,6 +143,7 @@ class HomeRecommendationQueryServiceTest {
port.aiCharacterDetails = listOf( port.aiCharacterDetails = listOf(
HomeAiCharacterRecommendationRecord( HomeAiCharacterRecommendationRecord(
characterId = 1L, characterId = 1L,
creatorId = 101L,
name = "character-1", name = "character-1",
description = "description-1", description = "description-1",
profileImage = "profile/character-1.png", profileImage = "profile/character-1.png",
@@ -151,6 +152,7 @@ class HomeRecommendationQueryServiceTest {
), ),
HomeAiCharacterRecommendationRecord( HomeAiCharacterRecommendationRecord(
characterId = 2L, characterId = 2L,
creatorId = 102L,
name = "character-2", name = "character-2",
description = "description-2", description = "description-2",
profileImage = null, profileImage = null,
@@ -163,6 +165,7 @@ class HomeRecommendationQueryServiceTest {
assertEquals((1L..10L).toList(), port.aiCharacterDetailIds) assertEquals((1L..10L).toList(), port.aiCharacterDetailIds)
assertEquals(listOf(1L, 2L), characters.map { it.characterId }) assertEquals(listOf(1L, 2L), characters.map { it.characterId })
assertEquals(listOf(101L, 102L), characters.map { it.creatorId })
assertEquals("profile/character-1.png", characters.first().profileImage) assertEquals("profile/character-1.png", characters.first().profileImage)
assertEquals(null, characters.last().profileImage) assertEquals(null, characters.last().profileImage)
assertEquals("original-work", characters.first().originalWorkTitle) assertEquals("original-work", characters.first().originalWorkTitle)