라이브 - 시작, 취소, 입장, 수정, 예약 API 추가
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
package kr.co.vividnext.sodalive.live.reservation
|
||||
|
||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
||||
import org.springframework.web.bind.annotation.PostMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/live/reservation")
|
||||
class LiveReservationController(private val service: LiveReservationService) {
|
||||
@PostMapping
|
||||
fun makeReservation(
|
||||
@RequestBody request: MakeLiveReservationRequest,
|
||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
||||
) = run {
|
||||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
||||
|
||||
ApiResponse.ok(service.makeReservation(request, member.id!!))
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
package kr.co.vividnext.sodalive.live.reservation
|
||||
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
||||
import kr.co.vividnext.sodalive.live.reservation.QLiveReservation.liveReservation
|
||||
import kr.co.vividnext.sodalive.live.room.QLiveRoom.liveRoom
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.QMember.member
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
interface LiveReservationRepository : JpaRepository<LiveReservation, Long>, LiveReservationQueryRepository
|
||||
|
||||
interface LiveReservationQueryRepository {
|
||||
fun getReservationList(roomId: Long): List<LiveReservation>
|
||||
|
||||
fun cancelReservation(roomId: Long)
|
||||
|
||||
fun getReservationBookerList(roomId: Long): List<Member>
|
||||
|
||||
fun isExistsReservation(roomId: Long, memberId: Long): Boolean
|
||||
}
|
||||
|
||||
@Repository
|
||||
class LiveReservationQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : LiveReservationQueryRepository {
|
||||
override fun getReservationList(roomId: Long): List<LiveReservation> {
|
||||
return queryFactory
|
||||
.selectFrom(liveReservation)
|
||||
.innerJoin(liveReservation.room, liveRoom)
|
||||
.where(
|
||||
liveRoom.id.eq(roomId)
|
||||
.and(liveReservation.isActive.isTrue)
|
||||
)
|
||||
.fetch()
|
||||
}
|
||||
|
||||
override fun cancelReservation(roomId: Long) {
|
||||
queryFactory
|
||||
.update(liveReservation)
|
||||
.set(liveReservation.isActive, false)
|
||||
.where(liveReservation.room.id.eq(roomId))
|
||||
.execute()
|
||||
}
|
||||
|
||||
override fun getReservationBookerList(roomId: Long): List<Member> {
|
||||
return queryFactory
|
||||
.select(member)
|
||||
.from(liveReservation)
|
||||
.innerJoin(liveReservation.member, member)
|
||||
.innerJoin(liveReservation.room, liveRoom)
|
||||
.where(
|
||||
liveRoom.id.eq(roomId)
|
||||
.and(liveReservation.isActive.isTrue)
|
||||
)
|
||||
.fetch()
|
||||
}
|
||||
|
||||
override fun isExistsReservation(roomId: Long, memberId: Long): Boolean {
|
||||
return queryFactory
|
||||
.selectFrom(liveReservation)
|
||||
.innerJoin(liveReservation.member, member)
|
||||
.innerJoin(liveReservation.room, liveRoom)
|
||||
.where(
|
||||
liveReservation.isActive.isTrue
|
||||
.and(liveReservation.room.id.eq(roomId))
|
||||
.and(liveReservation.member.id.eq(memberId))
|
||||
)
|
||||
.fetchFirst() != null
|
||||
}
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
package kr.co.vividnext.sodalive.live.reservation
|
||||
|
||||
import kr.co.vividnext.sodalive.can.payment.CanPaymentService
|
||||
import kr.co.vividnext.sodalive.can.use.CanUsage
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoomRepository
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoomType
|
||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||
import org.springframework.data.repository.findByIdOrNull
|
||||
import org.springframework.stereotype.Service
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
@Service
|
||||
class LiveReservationService(
|
||||
private val repository: LiveReservationRepository,
|
||||
private val liveRoomRepository: LiveRoomRepository,
|
||||
private val memberRepository: MemberRepository,
|
||||
private val canPaymentService: CanPaymentService
|
||||
) {
|
||||
fun makeReservation(request: MakeLiveReservationRequest, memberId: Long): MakeLiveReservationResponse {
|
||||
val room = liveRoomRepository.findByIdOrNull(id = request.roomId)
|
||||
?: throw SodaException(message = "잘못된 요청입니다.\n다시 시도해 주세요.")
|
||||
|
||||
val member = memberRepository.findByIdOrNull(id = memberId)
|
||||
?: throw SodaException(message = "로그인 정보를 확인해주세요.")
|
||||
|
||||
if (
|
||||
room.member!!.id!! != memberId &&
|
||||
room.type == LiveRoomType.PRIVATE &&
|
||||
(request.password == null || request.password != room.password)
|
||||
) {
|
||||
throw SodaException("비밀번호가 일치하지 않습니다.\n다시 확인 후 입력해주세요.")
|
||||
}
|
||||
|
||||
if (repository.isExistsReservation(roomId = request.roomId, memberId = memberId)) {
|
||||
throw SodaException("이미 예약한 라이브 입니다.")
|
||||
}
|
||||
|
||||
val haveCan = member.getChargeCan(request.container) + member.getRewardCan(request.container)
|
||||
if (haveCan < room.price) {
|
||||
throw SodaException("${room.price - haveCan}캔이 부족합니다. 충전 후 이용해 주세요.")
|
||||
}
|
||||
|
||||
if (room.price > 0) {
|
||||
canPaymentService.spendCan(
|
||||
memberId = member.id!!,
|
||||
needCan = room.price,
|
||||
canUsage = CanUsage.LIVE,
|
||||
liveRoom = room,
|
||||
container = request.container
|
||||
)
|
||||
}
|
||||
|
||||
val reservation = LiveReservation()
|
||||
reservation.room = room
|
||||
reservation.member = member
|
||||
repository.save(reservation)
|
||||
|
||||
val beginDateTime = room.beginDateTime
|
||||
.atZone(ZoneId.of("UTC"))
|
||||
.withZoneSameInstant(ZoneId.of(request.timezone))
|
||||
|
||||
return MakeLiveReservationResponse(
|
||||
reservationId = reservation.id!!,
|
||||
nickname = room.member!!.nickname,
|
||||
title = room.title,
|
||||
beginDateString = beginDateTime.format(DateTimeFormatter.ofPattern("yyyy년 M월 d일 (E), a hh:mm")),
|
||||
price = if (room.price > 0) {
|
||||
"${room.price} 캔"
|
||||
} else {
|
||||
"무료"
|
||||
},
|
||||
haveCan = haveCan,
|
||||
useCan = room.price,
|
||||
remainingCan = haveCan - room.price
|
||||
)
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
package kr.co.vividnext.sodalive.live.reservation
|
||||
|
||||
data class MakeLiveReservationRequest(
|
||||
val roomId: Long,
|
||||
val container: String,
|
||||
val timezone: String = "Asia/Seoul",
|
||||
val password: String? = null
|
||||
)
|
@@ -0,0 +1,12 @@
|
||||
package kr.co.vividnext.sodalive.live.reservation
|
||||
|
||||
data class MakeLiveReservationResponse(
|
||||
val reservationId: Long,
|
||||
val nickname: String,
|
||||
val title: String,
|
||||
val beginDateString: String,
|
||||
val price: String,
|
||||
val haveCan: Int,
|
||||
val useCan: Int,
|
||||
val remainingCan: Int
|
||||
)
|
Reference in New Issue
Block a user