feat(recommend): 크리에이터 데뷔 판정 정책을 추가한다

This commit is contained in:
2026-05-30 17:45:06 +09:00
parent 07bbc75844
commit c5b92d250e
2 changed files with 90 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
package kr.co.vividnext.sodalive.v2.recommend.domain
import java.time.LocalDateTime
import java.time.temporal.ChronoUnit
class CreatorDebutPolicy {
fun resolveDebutAt(firstContentPublishedAt: LocalDateTime?, firstLiveAt: LocalDateTime?): LocalDateTime? {
return listOfNotNull(firstContentPublishedAt, firstLiveAt).minOrNull()
}
fun isNewCreator(debutAt: LocalDateTime?, now: LocalDateTime): Boolean {
if (debutAt == null) {
return false
}
val days = ChronoUnit.DAYS.between(debutAt.toLocalDate(), now.toLocalDate())
return days in 0..30
}
}

View File

@@ -0,0 +1,71 @@
package kr.co.vividnext.sodalive.v2.recommend.domain
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import java.time.LocalDateTime
class CreatorDebutPolicyTest {
private val policy = CreatorDebutPolicy()
@Test
@DisplayName("첫 공개 콘텐츠만 있으면 콘텐츠 공개일을 데뷔일로 선택한다")
fun shouldResolveDebutAtFromFirstContentOnly() {
val firstContentPublishedAt = LocalDateTime.of(2026, 5, 1, 10, 0)
val debutAt = policy.resolveDebutAt(firstContentPublishedAt, firstLiveAt = null)
assertEquals(firstContentPublishedAt, debutAt)
}
@Test
@DisplayName("첫 라이브만 있으면 라이브 일시를 데뷔일로 선택한다")
fun shouldResolveDebutAtFromFirstLiveOnly() {
val firstLiveAt = LocalDateTime.of(2026, 5, 2, 10, 0)
val debutAt = policy.resolveDebutAt(firstContentPublishedAt = null, firstLiveAt)
assertEquals(firstLiveAt, debutAt)
}
@Test
@DisplayName("첫 공개 콘텐츠와 첫 라이브가 모두 있으면 빠른 일시를 데뷔일로 선택한다")
fun shouldResolveEarliestDebutAtWhenBothExist() {
val firstContentPublishedAt = LocalDateTime.of(2026, 5, 3, 10, 0)
val firstLiveAt = LocalDateTime.of(2026, 5, 2, 10, 0)
val debutAt = policy.resolveDebutAt(firstContentPublishedAt, firstLiveAt)
assertEquals(firstLiveAt, debutAt)
}
@Test
@DisplayName("첫 공개 콘텐츠와 첫 라이브가 모두 없으면 데뷔일은 null이다")
fun shouldReturnNullWhenDebutSourcesDoNotExist() {
val debutAt = policy.resolveDebutAt(firstContentPublishedAt = null, firstLiveAt = null)
assertNull(debutAt)
}
@Test
@DisplayName("데뷔 후 30일 이내이면 신규 크리에이터로 판정한다")
fun shouldReturnTrueWhenCreatorIsWithinThirtyDaysFromDebut() {
val now = LocalDateTime.of(2026, 5, 30, 12, 0)
assertTrue(policy.isNewCreator(now.minusDays(0), now))
assertTrue(policy.isNewCreator(now.minusDays(30), now))
}
@Test
@DisplayName("데뷔 후 30일이 지났거나 데뷔일이 없으면 신규 크리에이터가 아니다")
fun shouldReturnFalseWhenCreatorIsNotWithinThirtyDaysFromDebut() {
val now = LocalDateTime.of(2026, 5, 30, 12, 0)
assertFalse(policy.isNewCreator(now.minusDays(31), now))
assertFalse(policy.isNewCreator(now.plusDays(1), now))
assertFalse(policy.isNewCreator(debutAt = null, now))
}
}