Compare commits
4 Commits
1a1f67cc1a
...
1649d0b36e
| Author | SHA1 | Date | |
|---|---|---|---|
| 1649d0b36e | |||
| 8c82acacef | |||
| c506f9c92b | |||
| 86c1be1d67 |
@@ -270,13 +270,15 @@ class HomeRecommendationFacade(
|
|||||||
creatorProfileImage = imageUrl(cloudFrontHost, creatorProfileImage),
|
creatorProfileImage = imageUrl(cloudFrontHost, creatorProfileImage),
|
||||||
title = title,
|
title = title,
|
||||||
coverImage = imageUrl(cloudFrontHost, coverImage),
|
coverImage = imageUrl(cloudFrontHost, coverImage),
|
||||||
releaseDate = releaseDate.toUtcIso()
|
releaseDate = releaseDate.toUtcIso(),
|
||||||
|
isPointAvailable = isPointAvailable
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun HomeAiCharacterRecommendationRecord.toItem() = HomeAiCharacterItem(
|
private fun HomeAiCharacterRecommendationRecord.toItem() = HomeAiCharacterItem(
|
||||||
characterId = characterId,
|
characterId = characterId,
|
||||||
name = name,
|
name = name,
|
||||||
description = description,
|
description = description,
|
||||||
|
profileImage = imageUrl(cloudFrontHost, profileImage),
|
||||||
totalChatCount = totalChatCount,
|
totalChatCount = totalChatCount,
|
||||||
originalWorkTitle = originalWorkTitle
|
originalWorkTitle = originalWorkTitle
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package kr.co.vividnext.sodalive.v2.api.home.dto
|
package kr.co.vividnext.sodalive.v2.api.home.dto
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.ZoneOffset
|
import java.time.ZoneOffset
|
||||||
|
|
||||||
@@ -66,13 +67,16 @@ data class HomeFirstAudioContentItem(
|
|||||||
val creatorProfileImage: String?,
|
val creatorProfileImage: String?,
|
||||||
val title: String,
|
val title: String,
|
||||||
val coverImage: String?,
|
val coverImage: String?,
|
||||||
val releaseDate: String
|
val releaseDate: String,
|
||||||
|
@JsonProperty("isPointAvailable")
|
||||||
|
val isPointAvailable: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
data class HomeAiCharacterItem(
|
data class HomeAiCharacterItem(
|
||||||
val characterId: Long,
|
val characterId: Long,
|
||||||
val name: String,
|
val name: String,
|
||||||
val description: String,
|
val description: String,
|
||||||
|
val profileImage: String?,
|
||||||
val totalChatCount: Long,
|
val totalChatCount: Long,
|
||||||
val originalWorkTitle: String?
|
val originalWorkTitle: String?
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -395,6 +395,7 @@ class DefaultHomeRecommendationQueryRepository(
|
|||||||
ac.cover_image as cover_image,
|
ac.cover_image as cover_image,
|
||||||
ac.release_date as release_date,
|
ac.release_date as release_date,
|
||||||
ac.is_active as is_active,
|
ac.is_active as is_active,
|
||||||
|
ac.is_point_available as is_point_available,
|
||||||
row_number() over (
|
row_number() over (
|
||||||
partition by ac.member_id
|
partition by ac.member_id
|
||||||
order by ac.created_at asc, ac.release_date asc, ac.id asc
|
order by ac.created_at asc, ac.release_date asc, ac.id asc
|
||||||
@@ -421,6 +422,7 @@ class DefaultHomeRecommendationQueryRepository(
|
|||||||
ec.title as title,
|
ec.title as title,
|
||||||
ec.cover_image as cover_image,
|
ec.cover_image as cover_image,
|
||||||
ec.release_date as release_date,
|
ec.release_date as release_date,
|
||||||
|
ec.is_point_available as is_point_available,
|
||||||
case
|
case
|
||||||
when ec.release_date >= :recency3Start then 100
|
when ec.release_date >= :recency3Start then 100
|
||||||
when ec.release_date >= :recency7Start then 80
|
when ec.release_date >= :recency7Start then 80
|
||||||
@@ -471,8 +473,9 @@ class DefaultHomeRecommendationQueryRepository(
|
|||||||
title = row[4] as String,
|
title = row[4] as String,
|
||||||
coverImage = row[5] as String?,
|
coverImage = row[5] as String?,
|
||||||
releaseDate = toLocalDateTime(row[6]),
|
releaseDate = toLocalDateTime(row[6]),
|
||||||
recencyScore = (row[7] as Number).toInt(),
|
isPointAvailable = row[7] as Boolean,
|
||||||
randomTieBreaker = (row[8] as Number).toDouble()
|
recencyScore = (row[8] as Number).toInt(),
|
||||||
|
randomTieBreaker = (row[9] as Number).toDouble()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -708,6 +711,7 @@ class DefaultHomeRecommendationQueryRepository(
|
|||||||
chatCharacter.id,
|
chatCharacter.id,
|
||||||
chatCharacter.name,
|
chatCharacter.name,
|
||||||
chatCharacter.description,
|
chatCharacter.description,
|
||||||
|
chatCharacter.imagePath,
|
||||||
chatMessage.id.count(),
|
chatMessage.id.count(),
|
||||||
linkedOriginalWork.title
|
linkedOriginalWork.title
|
||||||
)
|
)
|
||||||
@@ -724,7 +728,13 @@ class DefaultHomeRecommendationQueryRepository(
|
|||||||
chatMessage.isActive.isTrue
|
chatMessage.isActive.isTrue
|
||||||
)
|
)
|
||||||
.where(chatCharacter.isActive.isTrue, chatCharacter.id.`in`(characterIds))
|
.where(chatCharacter.isActive.isTrue, chatCharacter.id.`in`(characterIds))
|
||||||
.groupBy(chatCharacter.id, chatCharacter.name, chatCharacter.description, linkedOriginalWork.title)
|
.groupBy(
|
||||||
|
chatCharacter.id,
|
||||||
|
chatCharacter.name,
|
||||||
|
chatCharacter.description,
|
||||||
|
chatCharacter.imagePath,
|
||||||
|
linkedOriginalWork.title
|
||||||
|
)
|
||||||
.fetch()
|
.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ data class HomeFirstAudioContentRecord(
|
|||||||
val title: String,
|
val title: String,
|
||||||
val coverImage: String?,
|
val coverImage: String?,
|
||||||
val releaseDate: LocalDateTime,
|
val releaseDate: LocalDateTime,
|
||||||
|
val isPointAvailable: Boolean,
|
||||||
val recencyScore: Int,
|
val recencyScore: Int,
|
||||||
val randomTieBreaker: Double
|
val randomTieBreaker: Double
|
||||||
)
|
)
|
||||||
@@ -134,6 +135,7 @@ data class HomeAiCharacterRecommendationRecord(
|
|||||||
val characterId: Long,
|
val characterId: Long,
|
||||||
val name: String,
|
val name: String,
|
||||||
val description: String,
|
val description: String,
|
||||||
|
val profileImage: String?,
|
||||||
val totalChatCount: Long,
|
val totalChatCount: Long,
|
||||||
val originalWorkTitle: String?
|
val originalWorkTitle: String?
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package kr.co.vividnext.sodalive.v2.api.home.dto
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
import org.junit.jupiter.api.Assertions.assertFalse
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class HomeRecommendationResponseTest {
|
||||||
|
private val objectMapper = jacksonObjectMapper()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun shouldSerializeNewHomeRecommendationFields() {
|
||||||
|
val response = HomeRecommendationResponse(
|
||||||
|
lives = emptyList(),
|
||||||
|
banners = emptyList(),
|
||||||
|
recentlyActiveCreators = emptyList(),
|
||||||
|
recentDebutCreators = emptyList(),
|
||||||
|
firstAudioContents = listOf(
|
||||||
|
HomeFirstAudioContentItem(
|
||||||
|
contentId = 1L,
|
||||||
|
creatorId = 2L,
|
||||||
|
creatorNickname = "creator",
|
||||||
|
creatorProfileImage = "https://cdn.test/profile/creator.png",
|
||||||
|
title = "first audio",
|
||||||
|
coverImage = "https://cdn.test/cover/audio.png",
|
||||||
|
releaseDate = "2026-06-01T00:00:00Z",
|
||||||
|
isPointAvailable = true
|
||||||
|
)
|
||||||
|
),
|
||||||
|
aiCharacters = listOf(
|
||||||
|
HomeAiCharacterItem(
|
||||||
|
characterId = 3L,
|
||||||
|
name = "character",
|
||||||
|
description = "description",
|
||||||
|
profileImage = "https://cdn.test/profile/character.png",
|
||||||
|
totalChatCount = 4L,
|
||||||
|
originalWorkTitle = "original"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
genreCreators = emptyList(),
|
||||||
|
cheerCreators = emptyList(),
|
||||||
|
popularCommunities = emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
|
val json = objectMapper.readTree(objectMapper.writeValueAsString(response))
|
||||||
|
|
||||||
|
assertEquals(true, json["firstAudioContents"][0]["isPointAvailable"].asBoolean())
|
||||||
|
assertFalse(json["firstAudioContents"][0].has("pointAvailable"))
|
||||||
|
assertEquals("https://cdn.test/profile/character.png", json["aiCharacters"][0]["profileImage"].asText())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -154,6 +154,7 @@ class HomeRecommendationQueryServiceTest {
|
|||||||
characterId = 1L,
|
characterId = 1L,
|
||||||
name = "character-1",
|
name = "character-1",
|
||||||
description = "description-1",
|
description = "description-1",
|
||||||
|
profileImage = "profile/character-1.png",
|
||||||
totalChatCount = 3L,
|
totalChatCount = 3L,
|
||||||
originalWorkTitle = "original-work"
|
originalWorkTitle = "original-work"
|
||||||
),
|
),
|
||||||
@@ -161,6 +162,7 @@ class HomeRecommendationQueryServiceTest {
|
|||||||
characterId = 2L,
|
characterId = 2L,
|
||||||
name = "character-2",
|
name = "character-2",
|
||||||
description = "description-2",
|
description = "description-2",
|
||||||
|
profileImage = null,
|
||||||
totalChatCount = 0L,
|
totalChatCount = 0L,
|
||||||
originalWorkTitle = null
|
originalWorkTitle = null
|
||||||
)
|
)
|
||||||
@@ -170,6 +172,8 @@ 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("profile/character-1.png", characters.first().profileImage)
|
||||||
|
assertEquals(null, characters.last().profileImage)
|
||||||
assertEquals("original-work", characters.first().originalWorkTitle)
|
assertEquals("original-work", characters.first().originalWorkTitle)
|
||||||
assertEquals(null, characters.last().originalWorkTitle)
|
assertEquals(null, characters.last().originalWorkTitle)
|
||||||
}
|
}
|
||||||
@@ -488,6 +492,7 @@ class HomeRecommendationQueryServiceTest {
|
|||||||
title = "first-audio",
|
title = "first-audio",
|
||||||
coverImage = "first-audio.png",
|
coverImage = "first-audio.png",
|
||||||
releaseDate = LocalDateTime.of(2026, 5, 30, 10, 0),
|
releaseDate = LocalDateTime.of(2026, 5, 30, 10, 0),
|
||||||
|
isPointAvailable = true,
|
||||||
recencyScore = 100,
|
recencyScore = 100,
|
||||||
randomTieBreaker = 0.3
|
randomTieBreaker = 0.3
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user