Skip to content

Commit

Permalink
Merge pull request #261 from Nexters/feature/Boolti-235
Browse files Browse the repository at this point in the history
Feature/boolti 235 티켓 N매 구현
  • Loading branch information
mangbaam authored Jul 7, 2024
2 parents 382e3d7 + 359d60c commit cfb725f
Show file tree
Hide file tree
Showing 28 changed files with 1,142 additions and 529 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ package com.nexters.boolti.data.datasource

import com.nexters.boolti.data.network.api.TicketService
import com.nexters.boolti.data.network.response.TicketDetailDto
import com.nexters.boolti.domain.model.Ticket
import com.nexters.boolti.data.network.response.TicketGroupDto
import com.nexters.boolti.domain.model.LegacyTicket
import com.nexters.boolti.domain.model.TicketGroup
import retrofit2.Response
import javax.inject.Inject

internal class TicketDataSource @Inject constructor(
private val apiService: TicketService,
) {
suspend fun getTickets(): List<Ticket> = apiService.getTickets().map { it.toDomain() }
suspend fun getTicket(ticketId: String): Response<TicketDetailDto> = apiService.getTicket(ticketId)
suspend fun legacyGetTickets(): List<LegacyTicket> = apiService.legacyGetTickets().map { it.toDomain() }
suspend fun legacyGetTicket(ticketId: String): Response<TicketDetailDto> = apiService.legacyGetTicket(ticketId)
suspend fun getTickets(): List<TicketGroup> = apiService.getTickets().map { it.toDomain() }
suspend fun getTicket(reservationId: String): Response<TicketGroupDto> = apiService.getTicket(reservationId)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,26 @@ package com.nexters.boolti.data.network.api

import com.nexters.boolti.data.network.response.TicketDetailDto
import com.nexters.boolti.data.network.response.TicketDto
import com.nexters.boolti.data.network.response.TicketGroupDto
import com.nexters.boolti.data.network.response.TicketsDto
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path

internal interface TicketService {
@GET("/app/api/v1/tickets")
suspend fun getTickets(): List<TicketDto>
suspend fun legacyGetTickets(): List<TicketDto>

@GET("/app/api/v1/ticket/{ticketId}")
suspend fun getTicket(
suspend fun legacyGetTicket(
@Path("ticketId") ticketId: String,
): Response<TicketDetailDto>

@GET("/app/api/v1/reservation/tickets")
suspend fun getTickets(): List<TicketsDto>

@GET("/app/api/v1/ticket/reservation/{reservationId}")
suspend fun getTicket(
@Path("reservationId") reservationId: String,
): Response<TicketGroupDto>
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.nexters.boolti.data.network.response

import com.nexters.boolti.data.util.toLocalDateTime
import com.nexters.boolti.domain.model.Ticket
import com.nexters.boolti.domain.model.LegacyTicket
import kotlinx.serialization.Serializable
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
Expand All @@ -21,7 +21,7 @@ internal data class TicketDto(
val ticketCreatedAt: String,
val csTicketId: String,
) {
fun toDomain(): Ticket = Ticket(
fun toDomain(): LegacyTicket = LegacyTicket(
userId = userId,
ticketId = ticketId,
showName = showName,
Expand Down Expand Up @@ -61,7 +61,7 @@ data class TicketDetailDto(
val csReservationId: String = "",
val csTicketId: String = "",
) {
fun toDomain(): Ticket = Ticket(
fun toDomain(): LegacyTicket = LegacyTicket(
userId = userId,
showId = showId,
ticketId = ticketId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package com.nexters.boolti.data.network.response


import com.nexters.boolti.data.util.toLocalDateTime
import com.nexters.boolti.domain.model.TicketGroup
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.time.LocalDateTime

@Serializable
internal data class TicketsDto(
@SerialName("userId")
val userId: String? = null,
@SerialName("reservationId")
val reservationId: String? = null,
@SerialName("showName")
val showName: String? = null,
@SerialName("placeName")
val placeName: String? = null,
@SerialName("showDate")
val showDate: String? = null,
@SerialName("showImgPath")
val showImgPath: String? = null,
@SerialName("ticketType")
val ticketType: String? = null,
@SerialName("ticketName")
val ticketName: String? = null,
@SerialName("ticketCount")
val ticketCount: Int? = null,
) {
fun toDomain(): TicketGroup = TicketGroup(
userId = userId ?: "",
showId = "",
reservationId = reservationId ?: "",
showName = showName ?: "",
placeName = placeName ?: "",
streetAddress = "",
detailAddress = "",
showDate = showDate?.toLocalDateTime() ?: LocalDateTime.now(),
notice = "",
ticketNotice = "",
poster = showImgPath ?: "",
ticketType = TicketGroup.TicketType.convert(ticketType),
ticketName = ticketName ?: "",
hostName = "",
hostPhoneNumber = "",
tickets = List(ticketCount ?: 0) {
TicketGroup.Ticket(
ticketId = "",
entryCode = "",
usedAt = null,
ticketCreatedAt = LocalDateTime.MIN,
csTicketId = "",
showDate = LocalDateTime.MIN,
)
}
)
}

@Serializable
internal data class TicketGroupDto(
@SerialName("detailAddress")
val detailAddress: String? = null,
@SerialName("hostName")
val hostName: String? = null,
@SerialName("hostPhoneNumber")
val hostPhoneNumber: String? = null,
@SerialName("notice")
val notice: String? = null,
@SerialName("placeName")
val placeName: String? = null,
@SerialName("reservationId")
val reservationId: String? = null,
@SerialName("showDate")
val showDate: String? = null,
@SerialName("showId")
val showId: String? = null,
@SerialName("showImgPath")
val showImgPath: String? = null,
@SerialName("showName")
val showName: String? = null,
@SerialName("streetAddress")
val streetAddress: String? = null,
@SerialName("ticketName")
val ticketName: String? = null,
@SerialName("ticketNotice")
val ticketNotice: String? = null,
@SerialName("ticketType")
val ticketType: String? = null,
@SerialName("tickets")
val tickets: List<TicketDto>? = null,
@SerialName("userId")
val userId: String? = null,
) {
fun toDomain(): TicketGroup = TicketGroup(
userId = userId ?: "",
showId = showId ?: "",
reservationId = reservationId ?: "",
showName = showName ?: "",
placeName = placeName ?: "",
streetAddress = streetAddress ?: "",
detailAddress = detailAddress ?: "",
showDate = showDate?.toLocalDateTime() ?: LocalDateTime.MIN,
notice = notice ?: "",
ticketNotice = ticketNotice ?: "",
poster = showImgPath ?: "",
ticketType = TicketGroup.TicketType.convert(ticketType),
ticketName = ticketName ?: "",
hostName = hostName ?: "",
hostPhoneNumber = hostPhoneNumber ?: "",
tickets = tickets?.map {
it.toDomain(showDate = showDate?.toLocalDateTime() ?: LocalDateTime.MIN)
} ?: emptyList(),
)

@Serializable
data class TicketDto(
@SerialName("csTicketId")
val csTicketId: String? = null,
@SerialName("entryCode")
val entryCode: String? = null,
@SerialName("ticketCreatedAt")
val ticketCreatedAt: String? = null,
@SerialName("ticketId")
val ticketId: String? = null,
@SerialName("usedAt")
val usedAt: String? = null,
) {
fun toDomain(showDate: LocalDateTime): TicketGroup.Ticket = TicketGroup.Ticket(
ticketId = ticketId ?: "",
entryCode = entryCode ?: "",
usedAt = usedAt?.toLocalDateTime(),
ticketCreatedAt = ticketCreatedAt?.toLocalDateTime() ?: LocalDateTime.MIN,
csTicketId = csTicketId ?: "",
showDate = showDate,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import com.nexters.boolti.domain.exception.ManagerCodeErrorType
import com.nexters.boolti.domain.exception.ManagerCodeException
import com.nexters.boolti.domain.exception.TicketException
import com.nexters.boolti.domain.extension.errorType
import com.nexters.boolti.domain.model.Ticket
import com.nexters.boolti.domain.model.LegacyTicket
import com.nexters.boolti.domain.model.TicketGroup
import com.nexters.boolti.domain.repository.TicketRepository
import com.nexters.boolti.domain.request.ManagerCodeRequest
import kotlinx.coroutines.flow.Flow
Expand All @@ -17,12 +18,27 @@ internal class TicketRepositoryImpl @Inject constructor(
private val dataSource: TicketDataSource,
private val hostDataSource: HostDataSource,
) : TicketRepository {
override suspend fun getTicket(): Flow<List<Ticket>> = flow {
override suspend fun legacyGetTicket(): Flow<List<LegacyTicket>> = flow {
emit(dataSource.legacyGetTickets())
}

override suspend fun legacyGetTicket(ticketId: String): Flow<LegacyTicket> = flow {
val response = dataSource.legacyGetTicket(ticketId)
if (response.isSuccessful) {
response.body()?.toDomain()?.let { emit(it) }
} else {
when (response.code()) {
404 -> throw TicketException.TicketNotFound
}
}
}

override fun getTickets(): Flow<List<TicketGroup>> = flow {
emit(dataSource.getTickets())
}

override suspend fun getTicket(ticketId: String): Flow<Ticket> = flow {
val response = dataSource.getTicket(ticketId)
override fun getTicket(reservationId: String): Flow<TicketGroup> = flow {
val response = dataSource.getTicket(reservationId)
if (response.isSuccessful) {
response.body()?.toDomain()?.let { emit(it) }
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.nexters.boolti.domain.model

import java.time.LocalDateTime

/**
* @property userId
* @property showId
* @property ticketId
* @property reservationId
* @property salesTicketTypeId
* @property showName
* @property streetAddress
* @property detailAddress
* @property showDate
* @property poster
* @property isInviteTicket
* @property ticketName
* @property notice 공연 내용 (공연 상세에서 사용)
* @property ticketNotice 안내사항 for 주최자
* @property placeName
* @property entryCode QR 에 담길 정보
* @property usedAt
* @property hostName
* @property hostPhoneNumber
*/
data class LegacyTicket(
val userId: String = "",
val showId: String = "",
val ticketId: String = "",
val reservationId: String = "",
val salesTicketTypeId: String = "",
val showName: String = "",
val streetAddress: String = "",
val detailAddress: String = "",
val showDate: LocalDateTime = LocalDateTime.now(),
val poster: String = "",
val isInviteTicket: Boolean = false,
val ticketName: String = "",
val notice: String = "",
val ticketNotice: String = "",
val placeName: String = "",
val entryCode: String = "",
val usedAt: LocalDateTime? = null,
val hostName: String = "",
val hostPhoneNumber: String = "",
val csReservationId: String = "",
val csTicketId: String = "",
) {
val ticketState: TicketState
get() = run {
val now = LocalDateTime.now()
when {
usedAt != null && now > usedAt -> TicketState.Used
now.toLocalDate() > showDate.toLocalDate() -> TicketState.Finished
else -> TicketState.Ready
}
}
}

enum class TicketState {
Ready, Used, Finished
}
Loading

0 comments on commit cfb725f

Please sign in to comment.