diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/audio/domain/CreatorChannelAudioTab.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/audio/domain/CreatorChannelAudioTab.kt new file mode 100644 index 00000000..91062bd0 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/audio/domain/CreatorChannelAudioTab.kt @@ -0,0 +1,23 @@ +package kr.co.vividnext.sodalive.v2.creator.channel.audio.domain + +import kr.co.vividnext.sodalive.v2.common.domain.ContentSort +import kr.co.vividnext.sodalive.v2.creator.channel.common.domain.CreatorChannelAudioContent +import kr.co.vividnext.sodalive.v2.creator.channel.live.domain.CreatorChannelPage + +data class CreatorChannelAudioTab( + val audioContentCount: Int, + val paidAudioContentCount: Int, + val purchasedAudioContentCount: Int, + val purchasedAudioContentRate: Double, + val themes: List, + val audioContents: List, + val sort: ContentSort, + val themeId: Long?, + val page: CreatorChannelPage, + val hasNext: Boolean +) + +data class CreatorChannelAudioTheme( + val themeId: Long, + val themeName: String +) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/audio/port/out/CreatorChannelAudioQueryPort.kt b/src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/audio/port/out/CreatorChannelAudioQueryPort.kt new file mode 100644 index 00000000..26394421 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/audio/port/out/CreatorChannelAudioQueryPort.kt @@ -0,0 +1,75 @@ +package kr.co.vividnext.sodalive.v2.creator.channel.audio.port.out + +import kr.co.vividnext.sodalive.member.MemberRole +import kr.co.vividnext.sodalive.v2.common.domain.ContentSort +import java.time.LocalDateTime + +interface CreatorChannelAudioQueryPort { + fun findCreator(creatorId: Long, viewerId: Long?): CreatorChannelAudioCreatorRecord? + + fun existsBlockedBetween(viewerId: Long, creatorId: Long): Boolean + + fun findActiveThemeId(themeId: Long): Long? + + fun findAudioThemes(locale: String): List + + fun countAudioContents( + creatorId: Long, + themeId: Long?, + now: LocalDateTime, + canViewAdultContent: Boolean + ): Int + + fun countPaidAudioContents( + creatorId: Long, + themeId: Long?, + now: LocalDateTime, + canViewAdultContent: Boolean + ): Int + + fun countPurchasedAudioContents( + creatorId: Long, + viewerId: Long, + themeId: Long?, + now: LocalDateTime, + canViewAdultContent: Boolean + ): Int + + fun findAudioContents( + creatorId: Long, + viewerId: Long, + themeId: Long?, + now: LocalDateTime, + canViewAdultContent: Boolean, + sort: ContentSort, + locale: String, + offset: Long, + limit: Int + ): List +} + +data class CreatorChannelAudioCreatorRecord( + val creatorId: Long, + val role: MemberRole, + val nickname: String +) + +data class CreatorChannelAudioThemeRecord( + val themeId: Long, + val themeName: String +) + +data class CreatorChannelAudioContentRecord( + val audioContentId: Long, + val title: String, + val duration: String?, + val imagePath: String?, + val price: Int, + val isAdult: Boolean, + val isPointAvailable: Boolean, + val isFirstContent: Boolean, + val seriesName: String?, + val isOriginalSeries: Boolean?, + val isOwned: Boolean, + val isRented: Boolean +) diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/audio/application/CreatorChannelAudioQueryServiceTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/audio/application/CreatorChannelAudioQueryServiceTest.kt new file mode 100644 index 00000000..dcd54d26 --- /dev/null +++ b/src/test/kotlin/kr/co/vividnext/sodalive/v2/creator/channel/audio/application/CreatorChannelAudioQueryServiceTest.kt @@ -0,0 +1,123 @@ +package kr.co.vividnext.sodalive.v2.creator.channel.audio.application + +import kr.co.vividnext.sodalive.member.MemberRole +import kr.co.vividnext.sodalive.v2.common.domain.ContentSort +import kr.co.vividnext.sodalive.v2.creator.channel.audio.domain.CreatorChannelAudioTab +import kr.co.vividnext.sodalive.v2.creator.channel.audio.domain.CreatorChannelAudioTheme +import kr.co.vividnext.sodalive.v2.creator.channel.audio.port.out.CreatorChannelAudioContentRecord +import kr.co.vividnext.sodalive.v2.creator.channel.audio.port.out.CreatorChannelAudioCreatorRecord +import kr.co.vividnext.sodalive.v2.creator.channel.audio.port.out.CreatorChannelAudioQueryPort +import kr.co.vividnext.sodalive.v2.creator.channel.audio.port.out.CreatorChannelAudioThemeRecord +import kr.co.vividnext.sodalive.v2.creator.channel.common.domain.CreatorChannelAudioContent +import kr.co.vividnext.sodalive.v2.creator.channel.live.domain.CreatorChannelPage +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import java.time.LocalDateTime + +class CreatorChannelAudioQueryServiceTest { + @Test + @DisplayName("오디오 탭 domain model과 port 계약을 사용할 수 있다") + fun shouldUseAudioTabDomainModelAndPortContract() { + val page = CreatorChannelPage(page = 0, size = 20) + val tab = CreatorChannelAudioTab( + audioContentCount = 1, + paidAudioContentCount = 1, + purchasedAudioContentCount = 1, + purchasedAudioContentRate = 100.0, + themes = listOf(CreatorChannelAudioTheme(themeId = 10L, themeName = "theme")), + audioContents = listOf(audioContent()), + sort = ContentSort.LATEST, + themeId = 10L, + page = page, + hasNext = false + ) + val port = FakeCreatorChannelAudioQueryPort() + + assertEquals(1, tab.audioContentCount) + assertEquals(10L, tab.themes.first().themeId) + assertEquals(100L, tab.audioContents.first().audioContentId) + assertEquals(MemberRole.CREATOR, port.findCreator(creatorId = 1L, viewerId = 2L)?.role) + } + + private fun audioContent(): CreatorChannelAudioContent { + return CreatorChannelAudioContent( + audioContentId = 100L, + title = "audio", + duration = "00:01:00", + imageUrl = null, + price = 10, + isAdult = false, + isPointAvailable = true, + isFirstContent = true, + seriesName = null, + isOriginalSeries = null, + isOwned = true, + isRented = false + ) + } + + private class FakeCreatorChannelAudioQueryPort : CreatorChannelAudioQueryPort { + override fun findCreator(creatorId: Long, viewerId: Long?): CreatorChannelAudioCreatorRecord? { + return CreatorChannelAudioCreatorRecord( + creatorId = creatorId, + role = MemberRole.CREATOR, + nickname = "creator" + ) + } + + override fun existsBlockedBetween(viewerId: Long, creatorId: Long): Boolean { + return false + } + + override fun findActiveThemeId(themeId: Long): Long? { + return themeId + } + + override fun findAudioThemes(locale: String): List { + return listOf(CreatorChannelAudioThemeRecord(themeId = 10L, themeName = locale)) + } + + override fun countAudioContents( + creatorId: Long, + themeId: Long?, + now: LocalDateTime, + canViewAdultContent: Boolean + ): Int { + return 1 + } + + override fun countPaidAudioContents( + creatorId: Long, + themeId: Long?, + now: LocalDateTime, + canViewAdultContent: Boolean + ): Int { + return 1 + } + + override fun countPurchasedAudioContents( + creatorId: Long, + viewerId: Long, + themeId: Long?, + now: LocalDateTime, + canViewAdultContent: Boolean + ): Int { + return 1 + } + + override fun findAudioContents( + creatorId: Long, + viewerId: Long, + themeId: Long?, + now: LocalDateTime, + canViewAdultContent: Boolean, + sort: ContentSort, + locale: String, + offset: Long, + limit: Int + ): List { + return emptyList() + } + } +}