From b5825459913633c23b1f68c102b1156ad7674cc7 Mon Sep 17 00:00:00 2001 From: klaus Date: Wed, 15 Jul 2026 21:26:37 +0900 Subject: [PATCH] =?UTF-8?q?feat(live):=20=EC=9E=85=EC=9E=A5=20=EC=A0=95?= =?UTF-8?q?=EC=B1=85=20=EB=AA=A8=EB=8D=B8=EC=9D=84=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../v2/live/action/LiveEntryDecision.kt | 11 +++ .../v2/live/action/LiveEntryPolicy.kt | 23 ++++++ .../v2/live/action/LiveEntryPolicyTest.kt | 78 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryDecision.kt create mode 100644 app/src/main/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryPolicy.kt create mode 100644 app/src/test/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryPolicyTest.kt diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryDecision.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryDecision.kt new file mode 100644 index 00000000..f89f1f9f --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryDecision.kt @@ -0,0 +1,11 @@ +package kr.co.vividnext.sodalive.v2.live.action + +sealed interface LiveEntryDecision { + data object ShowDetail : LiveEntryDecision + + data object Enter : LiveEntryDecision + + data class RequestPassword(val can: Int) : LiveEntryDecision + + data object RequestPayment : LiveEntryDecision +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryPolicy.kt b/app/src/main/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryPolicy.kt new file mode 100644 index 00000000..29058bee --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryPolicy.kt @@ -0,0 +1,23 @@ +package kr.co.vividnext.sodalive.v2.live.action + +data class LiveEntryContext( + val channelName: String?, + val managerId: Long, + val currentUserId: Long, + val price: Int, + val isPaid: Boolean, + val isPrivateRoom: Boolean +) + +object LiveEntryPolicy { + fun decide(context: LiveEntryContext): LiveEntryDecision = with(context) { + when { + channelName.isNullOrBlank() -> LiveEntryDecision.ShowDetail + managerId == currentUserId -> LiveEntryDecision.Enter + (price == 0 || isPaid) && isPrivateRoom -> LiveEntryDecision.RequestPassword(can = 0) + price == 0 || isPaid -> LiveEntryDecision.Enter + isPrivateRoom -> LiveEntryDecision.RequestPassword(can = price) + else -> LiveEntryDecision.RequestPayment + } + } +} diff --git a/app/src/test/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryPolicyTest.kt b/app/src/test/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryPolicyTest.kt new file mode 100644 index 00000000..88384162 --- /dev/null +++ b/app/src/test/java/kr/co/vividnext/sodalive/v2/live/action/LiveEntryPolicyTest.kt @@ -0,0 +1,78 @@ +package kr.co.vividnext.sodalive.v2.live.action + +import org.junit.Assert.assertEquals +import org.junit.Test + +class LiveEntryPolicyTest { + + @Test + fun `channel이 없으면 라이브 상세를 표시한다`() { + assertEquals(LiveEntryDecision.ShowDetail, decide(channelName = null)) + assertEquals(LiveEntryDecision.ShowDetail, decide(channelName = " ")) + } + + @Test + fun `channel이 없으면 본인 manager여도 라이브 상세를 우선 표시한다`() { + assertEquals( + LiveEntryDecision.ShowDetail, + decide(channelName = null, managerId = 7L, currentUserId = 7L) + ) + } + + @Test + fun `관리자는 가격과 비밀번호보다 우선해 바로 입장한다`() { + assertEquals( + LiveEntryDecision.Enter, + decide(managerId = 7L, currentUserId = 7L, price = 100, isPrivateRoom = true) + ) + } + + @Test + fun `무료 또는 결제 완료 공개방은 바로 입장한다`() { + assertEquals(LiveEntryDecision.Enter, decide(price = 0)) + assertEquals(LiveEntryDecision.Enter, decide(price = 100, isPaid = true)) + } + + @Test + fun `무료 또는 결제 완료 비밀번호방은 결제액 없이 비밀번호를 요청한다`() { + assertEquals( + LiveEntryDecision.RequestPassword(can = 0), + decide(price = 0, isPrivateRoom = true) + ) + assertEquals( + LiveEntryDecision.RequestPassword(can = 0), + decide(price = 100, isPaid = true, isPrivateRoom = true) + ) + } + + @Test + fun `미결제 유료 비밀번호방은 가격과 함께 비밀번호를 요청한다`() { + assertEquals( + LiveEntryDecision.RequestPassword(can = 100), + decide(price = 100, isPrivateRoom = true) + ) + } + + @Test + fun `미결제 유료 공개방은 결제를 요청한다`() { + assertEquals(LiveEntryDecision.RequestPayment, decide(price = 100)) + } + + private fun decide( + channelName: String? = "channel", + managerId: Long = 2L, + currentUserId: Long = 1L, + price: Int = 0, + isPaid: Boolean = false, + isPrivateRoom: Boolean = false + ): LiveEntryDecision = LiveEntryPolicy.decide( + LiveEntryContext( + channelName = channelName, + managerId = managerId, + currentUserId = currentUserId, + price = price, + isPaid = isPaid, + isPrivateRoom = isPrivateRoom + ) + ) +}