test #162
@@ -1,41 +1,36 @@
 | 
				
			|||||||
package kr.co.vividnext.sodalive.live.room
 | 
					package kr.co.vividnext.sodalive.live.room
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.querydsl.core.types.OrderSpecifier
 | 
					 | 
				
			||||||
import com.querydsl.core.types.Predicate
 | 
					 | 
				
			||||||
import com.querydsl.core.types.Projections
 | 
					import com.querydsl.core.types.Projections
 | 
				
			||||||
import com.querydsl.core.types.dsl.CaseBuilder
 | 
					import com.querydsl.core.types.dsl.CaseBuilder
 | 
				
			||||||
import com.querydsl.core.types.dsl.Expressions
 | 
					 | 
				
			||||||
import com.querydsl.jpa.impl.JPAQueryFactory
 | 
					import com.querydsl.jpa.impl.JPAQueryFactory
 | 
				
			||||||
import kr.co.vividnext.sodalive.can.use.CanUsage
 | 
					import kr.co.vividnext.sodalive.can.use.CanUsage
 | 
				
			||||||
import kr.co.vividnext.sodalive.can.use.QUseCan.useCan
 | 
					import kr.co.vividnext.sodalive.can.use.QUseCan.useCan
 | 
				
			||||||
import kr.co.vividnext.sodalive.can.use.QUseCanCalculate.useCanCalculate
 | 
					import kr.co.vividnext.sodalive.can.use.QUseCanCalculate.useCanCalculate
 | 
				
			||||||
import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom
 | 
					import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.live.room.QQuarterLiveRankings.quarterLiveRankings
 | 
				
			||||||
import kr.co.vividnext.sodalive.live.room.donation.GetLiveRoomDonationItem
 | 
					import kr.co.vividnext.sodalive.live.room.donation.GetLiveRoomDonationItem
 | 
				
			||||||
import kr.co.vividnext.sodalive.live.room.donation.QGetLiveRoomDonationItem
 | 
					import kr.co.vividnext.sodalive.live.room.donation.QGetLiveRoomDonationItem
 | 
				
			||||||
import kr.co.vividnext.sodalive.member.Member
 | 
					 | 
				
			||||||
import kr.co.vividnext.sodalive.member.QMember
 | 
					 | 
				
			||||||
import kr.co.vividnext.sodalive.member.QMember.member
 | 
					import kr.co.vividnext.sodalive.member.QMember.member
 | 
				
			||||||
import org.springframework.data.domain.Pageable
 | 
					 | 
				
			||||||
import org.springframework.data.jpa.repository.JpaRepository
 | 
					import org.springframework.data.jpa.repository.JpaRepository
 | 
				
			||||||
import org.springframework.stereotype.Repository
 | 
					import org.springframework.stereotype.Repository
 | 
				
			||||||
import java.time.LocalDate
 | 
					 | 
				
			||||||
import java.time.LocalDateTime
 | 
					import java.time.LocalDateTime
 | 
				
			||||||
import java.time.ZoneId
 | 
					import java.time.ZoneId
 | 
				
			||||||
import java.time.format.DateTimeFormatter
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Repository
 | 
					@Repository
 | 
				
			||||||
interface LiveRoomRepository : JpaRepository<LiveRoom, Long>, LiveRoomQueryRepository
 | 
					interface LiveRoomRepository : JpaRepository<LiveRoom, Long>, LiveRoomQueryRepository
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface LiveRoomQueryRepository {
 | 
					interface LiveRoomQueryRepository {
 | 
				
			||||||
    fun getLiveRoomList(
 | 
					    fun getLiveRoomListNow(offset: Long, limit: Long, timezone: String, isAdult: Boolean): List<LiveRoom>
 | 
				
			||||||
        dateString: String?,
 | 
					
 | 
				
			||||||
        status: LiveRoomStatus,
 | 
					    fun getLiveRoomListReservationWithDate(
 | 
				
			||||||
        pageable: Pageable,
 | 
					        date: LocalDateTime,
 | 
				
			||||||
        member: Member,
 | 
					        offset: Long,
 | 
				
			||||||
        timezone: String,
 | 
					        limit: Long,
 | 
				
			||||||
        isAdult: Boolean
 | 
					        isAdult: Boolean
 | 
				
			||||||
    ): List<LiveRoom>
 | 
					    ): List<LiveRoom>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun getLiveRoomListReservationWithoutDate(timezone: String, memberId: Long, isAdult: Boolean): List<LiveRoom>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fun getLiveRoom(id: Long): LiveRoom?
 | 
					    fun getLiveRoom(id: Long): LiveRoom?
 | 
				
			||||||
    fun getLiveRoomAndAccountId(roomId: Long, memberId: Long): LiveRoom?
 | 
					    fun getLiveRoomAndAccountId(roomId: Long, memberId: Long): LiveRoom?
 | 
				
			||||||
    fun getRecentRoomInfo(memberId: Long, cloudFrontHost: String): GetRecentRoomInfoResponse?
 | 
					    fun getRecentRoomInfo(memberId: Long, cloudFrontHost: String): GetRecentRoomInfoResponse?
 | 
				
			||||||
@@ -45,35 +40,67 @@ interface LiveRoomQueryRepository {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LiveRoomQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : LiveRoomQueryRepository {
 | 
					class LiveRoomQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : LiveRoomQueryRepository {
 | 
				
			||||||
    override fun getLiveRoomList(
 | 
					    override fun getLiveRoomListNow(offset: Long, limit: Long, timezone: String, isAdult: Boolean): List<LiveRoom> {
 | 
				
			||||||
        dateString: String?,
 | 
					        var where = liveRoom.channelName.isNotNull
 | 
				
			||||||
        status: LiveRoomStatus,
 | 
					            .and(liveRoom.channelName.isNotEmpty)
 | 
				
			||||||
        pageable: Pageable,
 | 
					            .and(liveRoom.isActive.isTrue)
 | 
				
			||||||
        member: Member,
 | 
					            .and(liveRoom.member.isNotNull)
 | 
				
			||||||
        timezone: String,
 | 
					
 | 
				
			||||||
 | 
					        if (!isAdult) {
 | 
				
			||||||
 | 
					            where = where.and(liveRoom.isAdult.isFalse)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return queryFactory
 | 
				
			||||||
 | 
					            .selectFrom(liveRoom)
 | 
				
			||||||
 | 
					            .innerJoin(liveRoom.member, member)
 | 
				
			||||||
 | 
					            .leftJoin(quarterLiveRankings).on(liveRoom.id.eq(quarterLiveRankings.roomId))
 | 
				
			||||||
 | 
					            .where(where)
 | 
				
			||||||
 | 
					            .offset(offset)
 | 
				
			||||||
 | 
					            .limit(limit)
 | 
				
			||||||
 | 
					            .orderBy(
 | 
				
			||||||
 | 
					                quarterLiveRankings.totalCan.desc(),
 | 
				
			||||||
 | 
					                quarterLiveRankings.totalParticipants.desc(),
 | 
				
			||||||
 | 
					                liveRoom.beginDateTime.desc(),
 | 
				
			||||||
 | 
					                liveRoom.member.createdAt.desc()
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .fetch()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun getLiveRoomListReservationWithDate(
 | 
				
			||||||
 | 
					        date: LocalDateTime,
 | 
				
			||||||
 | 
					        offset: Long,
 | 
				
			||||||
 | 
					        limit: Long,
 | 
				
			||||||
        isAdult: Boolean
 | 
					        isAdult: Boolean
 | 
				
			||||||
    ): List<LiveRoom> {
 | 
					    ): List<LiveRoom> {
 | 
				
			||||||
        var where: Predicate
 | 
					        var where = liveRoom.beginDateTime.goe(date)
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (status == LiveRoomStatus.NOW) {
 | 
					 | 
				
			||||||
            where = liveRoom.channelName.isNotNull
 | 
					 | 
				
			||||||
                .and(liveRoom.channelName.isNotEmpty)
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            where = if (dateString != null) {
 | 
					 | 
				
			||||||
                val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
 | 
					 | 
				
			||||||
                val date = LocalDate.parse(dateString, dateTimeFormatter).atStartOfDay()
 | 
					 | 
				
			||||||
                    .atZone(ZoneId.of(timezone))
 | 
					 | 
				
			||||||
                    .withZoneSameInstant(ZoneId.of("UTC"))
 | 
					 | 
				
			||||||
                    .toLocalDateTime()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                liveRoom.beginDateTime.goe(date)
 | 
					 | 
				
			||||||
            .and(liveRoom.beginDateTime.lt(date.plusDays(1)))
 | 
					            .and(liveRoom.beginDateTime.lt(date.plusDays(1)))
 | 
				
			||||||
            .and(
 | 
					            .and(
 | 
				
			||||||
                liveRoom.channelName.isNull
 | 
					                liveRoom.channelName.isNull
 | 
				
			||||||
                    .or(liveRoom.channelName.isEmpty)
 | 
					                    .or(liveRoom.channelName.isEmpty)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            } else {
 | 
					            .and(liveRoom.isActive.isTrue)
 | 
				
			||||||
                liveRoom.beginDateTime.gt(
 | 
					            .and(liveRoom.member.isNotNull)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!isAdult) {
 | 
				
			||||||
 | 
					            where = where.and(liveRoom.isAdult.isFalse)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return queryFactory
 | 
				
			||||||
 | 
					            .selectFrom(liveRoom)
 | 
				
			||||||
 | 
					            .innerJoin(liveRoom.member, member)
 | 
				
			||||||
 | 
					            .where(where)
 | 
				
			||||||
 | 
					            .offset(offset)
 | 
				
			||||||
 | 
					            .limit(limit)
 | 
				
			||||||
 | 
					            .orderBy(liveRoom.beginDateTime.asc())
 | 
				
			||||||
 | 
					            .fetch()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun getLiveRoomListReservationWithoutDate(
 | 
				
			||||||
 | 
					        timezone: String,
 | 
				
			||||||
 | 
					        memberId: Long,
 | 
				
			||||||
 | 
					        isAdult: Boolean
 | 
				
			||||||
 | 
					    ): List<LiveRoom> {
 | 
				
			||||||
 | 
					        var where = liveRoom.beginDateTime.gt(
 | 
				
			||||||
            LocalDateTime.now()
 | 
					            LocalDateTime.now()
 | 
				
			||||||
                .atZone(ZoneId.of(timezone))
 | 
					                .atZone(ZoneId.of(timezone))
 | 
				
			||||||
                .withZoneSameInstant(ZoneId.of("UTC"))
 | 
					                .withZoneSameInstant(ZoneId.of("UTC"))
 | 
				
			||||||
@@ -83,29 +110,24 @@ class LiveRoomQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : L
 | 
				
			|||||||
                liveRoom.channelName.isNull
 | 
					                liveRoom.channelName.isNull
 | 
				
			||||||
                    .or(liveRoom.channelName.isEmpty)
 | 
					                    .or(liveRoom.channelName.isEmpty)
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            }
 | 
					            .and(liveRoom.isActive.isTrue)
 | 
				
			||||||
        }
 | 
					            .and(liveRoom.member.isNotNull)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!isAdult) {
 | 
					        if (!isAdult) {
 | 
				
			||||||
            where = where.and(liveRoom.isAdult.isFalse)
 | 
					            where = where.and(liveRoom.isAdult.isFalse)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        where = where.and(liveRoom.isActive.isTrue)
 | 
					 | 
				
			||||||
            .and(liveRoom.member.isNotNull)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return queryFactory
 | 
					        return queryFactory
 | 
				
			||||||
            .selectFrom(liveRoom)
 | 
					            .selectFrom(liveRoom)
 | 
				
			||||||
            .innerJoin(liveRoom.member, QMember.member)
 | 
					            .innerJoin(liveRoom.member, member)
 | 
				
			||||||
            .offset(pageable.offset)
 | 
					            .limit(10)
 | 
				
			||||||
            .limit(pageable.pageSize.toLong())
 | 
					 | 
				
			||||||
            .where(where)
 | 
					            .where(where)
 | 
				
			||||||
            .orderBy(
 | 
					            .orderBy(
 | 
				
			||||||
                *orderByFieldAccountId(
 | 
					                CaseBuilder()
 | 
				
			||||||
                    memberId = member.id!!,
 | 
					                    .`when`(member.id.eq(memberId)).then(1)
 | 
				
			||||||
                    status = status,
 | 
					                    .otherwise(2)
 | 
				
			||||||
                    offset = pageable.offset,
 | 
					                    .asc(),
 | 
				
			||||||
                    dateString = dateString
 | 
					                liveRoom.beginDateTime.asc()
 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            .fetch()
 | 
					            .fetch()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -201,25 +223,4 @@ class LiveRoomQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : L
 | 
				
			|||||||
            )
 | 
					            )
 | 
				
			||||||
            .fetch()
 | 
					            .fetch()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private fun orderByFieldAccountId(
 | 
					 | 
				
			||||||
        memberId: Long,
 | 
					 | 
				
			||||||
        status: LiveRoomStatus,
 | 
					 | 
				
			||||||
        offset: Long,
 | 
					 | 
				
			||||||
        dateString: String?
 | 
					 | 
				
			||||||
    ): Array<out OrderSpecifier<*>> {
 | 
					 | 
				
			||||||
        return if (status == LiveRoomStatus.NOW) {
 | 
					 | 
				
			||||||
            arrayOf(Expressions.numberTemplate(Double::class.java, "function('rand')").asc())
 | 
					 | 
				
			||||||
        } else if (status == LiveRoomStatus.RESERVATION && offset == 0L && dateString == null) {
 | 
					 | 
				
			||||||
            arrayOf(
 | 
					 | 
				
			||||||
                CaseBuilder()
 | 
					 | 
				
			||||||
                    .`when`(member.id.eq(memberId)).then(1)
 | 
					 | 
				
			||||||
                    .otherwise(2)
 | 
					 | 
				
			||||||
                    .asc(),
 | 
					 | 
				
			||||||
                liveRoom.beginDateTime.asc()
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            arrayOf(liveRoom.beginDateTime.asc())
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,6 +58,7 @@ import org.springframework.data.repository.findByIdOrNull
 | 
				
			|||||||
import org.springframework.stereotype.Service
 | 
					import org.springframework.stereotype.Service
 | 
				
			||||||
import org.springframework.transaction.annotation.Transactional
 | 
					import org.springframework.transaction.annotation.Transactional
 | 
				
			||||||
import org.springframework.web.multipart.MultipartFile
 | 
					import org.springframework.web.multipart.MultipartFile
 | 
				
			||||||
 | 
					import java.time.LocalDate
 | 
				
			||||||
import java.time.LocalDateTime
 | 
					import java.time.LocalDateTime
 | 
				
			||||||
import java.time.ZoneId
 | 
					import java.time.ZoneId
 | 
				
			||||||
import java.time.format.DateTimeFormatter
 | 
					import java.time.format.DateTimeFormatter
 | 
				
			||||||
@@ -115,16 +116,24 @@ class LiveRoomService(
 | 
				
			|||||||
        member: Member,
 | 
					        member: Member,
 | 
				
			||||||
        timezone: String
 | 
					        timezone: String
 | 
				
			||||||
    ): List<GetRoomListResponse> {
 | 
					    ): List<GetRoomListResponse> {
 | 
				
			||||||
        return repository
 | 
					        val roomList = if (status == LiveRoomStatus.NOW) {
 | 
				
			||||||
            .getLiveRoomList(
 | 
					            getLiveRoomListNow(pageable, timezone, isAdult = member.auth != null)
 | 
				
			||||||
                dateString = dateString,
 | 
					        } else if (dateString != null) {
 | 
				
			||||||
                status = status,
 | 
					            getLiveRoomListReservationWithDate(
 | 
				
			||||||
                pageable = pageable,
 | 
					                dateString,
 | 
				
			||||||
                member = member,
 | 
					                pageable,
 | 
				
			||||||
                timezone = timezone,
 | 
					                timezone,
 | 
				
			||||||
                isAdult = member.auth != null
 | 
					                isAdult = member.auth != null
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            .asSequence()
 | 
					        } else {
 | 
				
			||||||
 | 
					            getLiveRoomListReservationWithoutDate(
 | 
				
			||||||
 | 
					                timezone,
 | 
				
			||||||
 | 
					                memberId = member.id!!,
 | 
				
			||||||
 | 
					                isAdult = member.auth != null
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return roomList
 | 
				
			||||||
            .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.member!!.id!!) }
 | 
					            .filter { !blockMemberRepository.isBlocked(blockedMemberId = member.id!!, memberId = it.member!!.id!!) }
 | 
				
			||||||
            .map {
 | 
					            .map {
 | 
				
			||||||
                val roomInfo = roomInfoRepository.findByIdOrNull(it.id!!)
 | 
					                val roomInfo = roomInfoRepository.findByIdOrNull(it.id!!)
 | 
				
			||||||
@@ -174,7 +183,43 @@ class LiveRoomService(
 | 
				
			|||||||
                    isPrivateRoom = it.type == LiveRoomType.PRIVATE
 | 
					                    isPrivateRoom = it.type == LiveRoomType.PRIVATE
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            .toList()
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun getLiveRoomListNow(pageable: Pageable, timezone: String, isAdult: Boolean): List<LiveRoom> {
 | 
				
			||||||
 | 
					        return repository.getLiveRoomListNow(
 | 
				
			||||||
 | 
					            offset = pageable.offset,
 | 
				
			||||||
 | 
					            limit = pageable.pageSize.toLong(),
 | 
				
			||||||
 | 
					            timezone = timezone,
 | 
				
			||||||
 | 
					            isAdult = isAdult
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun getLiveRoomListReservationWithDate(
 | 
				
			||||||
 | 
					        dateString: String,
 | 
				
			||||||
 | 
					        pageable: Pageable,
 | 
				
			||||||
 | 
					        timezone: String,
 | 
				
			||||||
 | 
					        isAdult: Boolean
 | 
				
			||||||
 | 
					    ): List<LiveRoom> {
 | 
				
			||||||
 | 
					        val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
 | 
				
			||||||
 | 
					        val date = LocalDate.parse(dateString, dateTimeFormatter).atStartOfDay()
 | 
				
			||||||
 | 
					            .atZone(ZoneId.of(timezone))
 | 
				
			||||||
 | 
					            .withZoneSameInstant(ZoneId.of("UTC"))
 | 
				
			||||||
 | 
					            .toLocalDateTime()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return repository.getLiveRoomListReservationWithDate(
 | 
				
			||||||
 | 
					            date = date,
 | 
				
			||||||
 | 
					            offset = pageable.offset,
 | 
				
			||||||
 | 
					            limit = pageable.pageSize.toLong(),
 | 
				
			||||||
 | 
					            isAdult = isAdult
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun getLiveRoomListReservationWithoutDate(
 | 
				
			||||||
 | 
					        timezone: String,
 | 
				
			||||||
 | 
					        memberId: Long,
 | 
				
			||||||
 | 
					        isAdult: Boolean
 | 
				
			||||||
 | 
					    ): List<LiveRoom> {
 | 
				
			||||||
 | 
					        return repository.getLiveRoomListReservationWithoutDate(timezone, memberId, isAdult)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Transactional
 | 
					    @Transactional
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					package kr.co.vividnext.sodalive.live.room
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.persistence.Entity
 | 
				
			||||||
 | 
					import javax.persistence.GeneratedValue
 | 
				
			||||||
 | 
					import javax.persistence.GenerationType
 | 
				
			||||||
 | 
					import javax.persistence.Id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Entity
 | 
				
			||||||
 | 
					data class QuarterLiveRankings(
 | 
				
			||||||
 | 
					    @Id
 | 
				
			||||||
 | 
					    @GeneratedValue(strategy = GenerationType.IDENTITY)
 | 
				
			||||||
 | 
					    var id: Long? = null,
 | 
				
			||||||
 | 
					    val roomId: Long,
 | 
				
			||||||
 | 
					    val totalCan: Int,
 | 
				
			||||||
 | 
					    val totalParticipants: Int
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
		Reference in New Issue
	
	Block a user