feat(recommend): 콘텐츠 조회 이력 서비스를 추가한다
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
package kr.co.vividnext.sodalive.v2.recommend.application
|
||||
|
||||
import kr.co.vividnext.sodalive.v2.recommend.port.out.CreatorContentViewHistoryPort
|
||||
import kr.co.vividnext.sodalive.v2.recommend.port.out.CreatorContentViewHistoryRecord
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Propagation
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@Service
|
||||
class CreatorContentViewHistoryService(
|
||||
private val port: CreatorContentViewHistoryPort
|
||||
) {
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
fun recordView(memberId: Long?, contentId: Long, viewedAt: LocalDateTime = LocalDateTime.now()) {
|
||||
if (memberId == null) return
|
||||
|
||||
val genreId = port.findGenreIdByContentId(contentId) ?: return
|
||||
port.save(
|
||||
CreatorContentViewHistoryRecord(
|
||||
memberId = memberId,
|
||||
contentId = contentId,
|
||||
genreId = genreId,
|
||||
viewedAt = viewedAt
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package kr.co.vividnext.sodalive.v2.recommend.application
|
||||
|
||||
import kr.co.vividnext.sodalive.v2.recommend.port.out.CreatorContentViewHistoryPort
|
||||
import kr.co.vividnext.sodalive.v2.recommend.port.out.CreatorContentViewHistoryRecord
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.time.LocalDateTime
|
||||
|
||||
class CreatorContentViewHistoryServiceTest {
|
||||
private val port = FakeCreatorContentViewHistoryPort()
|
||||
private val service = CreatorContentViewHistoryService(port)
|
||||
|
||||
@Test
|
||||
@DisplayName("인증 회원의 콘텐츠 상세 진입 시 memberId/contentId/genreId/viewedAt을 저장한다")
|
||||
fun shouldRecordAuthenticatedMemberContentViewWithGenreAndViewedAt() {
|
||||
val viewedAt = LocalDateTime.of(2026, 5, 31, 10, 0)
|
||||
port.genreIdByContentId[20L] = 30L
|
||||
|
||||
service.recordView(memberId = 10L, contentId = 20L, viewedAt = viewedAt)
|
||||
|
||||
assertEquals(
|
||||
listOf(
|
||||
CreatorContentViewHistoryRecord(
|
||||
memberId = 10L,
|
||||
contentId = 20L,
|
||||
genreId = 30L,
|
||||
viewedAt = viewedAt
|
||||
)
|
||||
),
|
||||
port.savedRecords
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("비회원 콘텐츠 상세 진입은 조회 이력을 저장하지 않는다")
|
||||
fun shouldNotRecordAnonymousContentView() {
|
||||
service.recordView(memberId = null, contentId = 20L)
|
||||
|
||||
assertTrue(port.savedRecords.isEmpty())
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("콘텐츠의 활성 장르를 찾지 못하면 조회 이력을 저장하지 않는다")
|
||||
fun shouldNotRecordWhenContentGenreDoesNotExist() {
|
||||
service.recordView(memberId = 10L, contentId = 20L)
|
||||
|
||||
assertTrue(port.savedRecords.isEmpty())
|
||||
}
|
||||
|
||||
private class FakeCreatorContentViewHistoryPort : CreatorContentViewHistoryPort {
|
||||
val genreIdByContentId = mutableMapOf<Long, Long>()
|
||||
val savedRecords = mutableListOf<CreatorContentViewHistoryRecord>()
|
||||
|
||||
override fun findGenreIdByContentId(contentId: Long): Long? {
|
||||
return genreIdByContentId[contentId]
|
||||
}
|
||||
|
||||
override fun save(record: CreatorContentViewHistoryRecord) {
|
||||
savedRecords.add(record)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user