Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge: (#149) 전체 지점 일정 조회 #151

Merged
merged 7 commits into from
Nov 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package team.comit.simtong.domain.schedule.dto

import java.time.LocalDate
import java.util.UUID

/**
*
* 모든 지점 일정 조회 정보를 전송하는 EntireSpotScheduleResponse
*
* @author Chokyunghyeon
* @date 2022/11/26
* @version 1.0.0
**/
data class EntireSpotScheduleResponse(
val schedules: List<SpotScheduleResponse>
)

/**
*
* 지점 일정 정보를 전송하는 SpotScheduleResponse
*
* @author Chokyunghyeon
* @date 2022/11/26
* @version 1.0.0
**/
data class SpotScheduleResponse(
val id: UUID,

val startAt: LocalDate,

val endAt: LocalDate,

val title: String,

val spot: SpotElement
) {
data class SpotElement(
val id: UUID,
val name: String
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package team.comit.simtong.domain.schedule.usecase

import team.comit.simtong.domain.schedule.dto.EntireSpotScheduleResponse
import team.comit.simtong.domain.schedule.dto.SpotScheduleResponse
import team.comit.simtong.domain.schedule.spi.QuerySchedulePort
import team.comit.simtong.global.annotation.ReadOnlyUseCase
import java.time.LocalDate

/**
*
* 모든 지점 일정 조회 요청을 담당하는 QuerySpotScheduleUseCase
*
* @author Chokyunghyeon
* @date 2022/11/26
* @version 1.0.0
**/
@ReadOnlyUseCase
class EntireSpotScheduleUseCase(
private val querySchedulePort: QuerySchedulePort
) {

fun execute(date: LocalDate): EntireSpotScheduleResponse {
val list = querySchedulePort.querySchedulesByDateContains(date)

val response = list.map {
SpotScheduleResponse(
id = it.id,
startAt = it.startAt,
endAt = it.endAt,
title = it.title,
spot = SpotScheduleResponse.SpotElement(
id = it.spotId,
name = it.spotName
)
)
}

return EntireSpotScheduleResponse(response)
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package team.comit.simtong.domain.spot.spi

import team.comit.simtong.domain.schedule.spi.ScheduleQuerySpotPort
import team.comit.simtong.domain.user.spi.UserQuerySpotPort

/**
Expand All @@ -10,4 +11,4 @@ import team.comit.simtong.domain.user.spi.UserQuerySpotPort
* @date 2022/09/18
* @version 1.0.0
**/
interface SpotPort : UserQuerySpotPort, QuerySpotPort
interface SpotPort : UserQuerySpotPort, QuerySpotPort, ScheduleQuerySpotPort
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ class DomainPropertiesInitialization {
DomainProperties.putAll(
mapOf(
Pair(DomainPropertiesPrefix.USER_DEFAULT_IMAGE, "test"),
Pair(DomainPropertiesPrefix.AUTHCODE_EXPIRED, "12345"),
Pair(DomainPropertiesPrefix.AUTHCODELIMIT_EXPIRED, "12345"),
Pair(DomainPropertiesPrefix.AUTHCODELIMIT_VERIFIED_EXPIRED, "12345"),
Pair(DomainPropertiesPrefix.AUTHCODE_EXP, "12345"),
Pair(DomainPropertiesPrefix.AUTHCODELIMIT_EXP, "12345"),
Pair(DomainPropertiesPrefix.AUTHCODELIMIT_VERIFIED_EXP, "12345"),
Pair(DomainPropertiesPrefix.AUTHCODELIMIT_MAX_ATTEMPT_COUNT, "12345")
)
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package team.comit.simtong.domain.schedule.usecase

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.kotlin.given
import org.springframework.boot.test.mock.mockito.MockBean
import org.springframework.test.context.junit.jupiter.SpringExtension
import team.comit.simtong.domain.schedule.dto.EntireSpotScheduleResponse
import team.comit.simtong.domain.schedule.dto.SpotScheduleResponse
import team.comit.simtong.domain.schedule.spi.QuerySchedulePort
import team.comit.simtong.domain.schedule.vo.SpotSchedule
import java.time.LocalDate
import java.util.UUID

@ExtendWith(SpringExtension::class)
class EntireSpotScheduleUseCaseTests {

@MockBean
private lateinit var querySchedulePort: QuerySchedulePort

private lateinit var entireSpotScheduleUseCase: EntireSpotScheduleUseCase

private val date: LocalDate = LocalDate.now()

private val uuid: UUID = UUID.randomUUID()

private val spotScheduleListStub = listOf(
SpotSchedule(
id = uuid,
spotId = uuid,
spotName = "test name",
title = "test title",
startAt = date,
endAt = date
)
)

private val responseStub: EntireSpotScheduleResponse by lazy {
EntireSpotScheduleResponse(
listOf(
SpotScheduleResponse(
id = uuid,
startAt = date,
endAt = date,
title = "test title",
spot = SpotScheduleResponse.SpotElement(
id = uuid,
name = "test name"
)
)
)
)
}

@BeforeEach
fun setUp() {
entireSpotScheduleUseCase = EntireSpotScheduleUseCase(querySchedulePort)
}

@Test
fun `전체 지점 일정 조회 성공`() {
// given
given(querySchedulePort.querySchedulesByDateContains(date))
.willReturn(spotScheduleListStub)

// when
val response = entireSpotScheduleUseCase.execute(date)

// then
assertEquals(response, responseStub)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ data class AuthCode @Default constructor(

companion object {
@JvmField
val EXPIRED = getProperty(DomainPropertiesPrefix.AUTHCODE_EXPIRED).toInt()
val EXPIRED = getProperty(DomainPropertiesPrefix.AUTHCODE_EXP).toInt()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ data class AuthCodeLimit @Default constructor(
val MAX_ATTEMPT_COUNT: Short = getProperty(DomainPropertiesPrefix.AUTHCODELIMIT_MAX_ATTEMPT_COUNT).toShort()

@JvmField
val EXPIRED: Int = getProperty(DomainPropertiesPrefix.AUTHCODELIMIT_EXPIRED).toInt()
val EXPIRED: Int = getProperty(DomainPropertiesPrefix.AUTHCODELIMIT_EXP).toInt()

@JvmField
val VERIFIED_EXPIRED: Int = getProperty(DomainPropertiesPrefix.AUTHCODELIMIT_VERIFIED_EXPIRED).toInt()
val VERIFIED_EXPIRED: Int = getProperty(DomainPropertiesPrefix.AUTHCODELIMIT_VERIFIED_EXP).toInt()

fun certified(email: String) = AuthCodeLimit(
key = email,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package team.comit.simtong.domain.schedule.spi

import team.comit.simtong.domain.schedule.model.Schedule
import team.comit.simtong.domain.schedule.vo.SpotSchedule
import java.time.LocalDate
import java.util.UUID

/**
Expand All @@ -15,4 +17,6 @@ interface QuerySchedulePort {

fun queryScheduleById(id: UUID): Schedule?

fun querySchedulesByDateContains(date: LocalDate): List<SpotSchedule>

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package team.comit.simtong.domain.schedule.spi

import team.comit.simtong.domain.spot.model.Spot
import java.util.UUID

/**
*
* Schedule Domain에서 Spot에 관한 Query를 요청하는 ScheduleQuerySpotPort
*
* @author Chokyunghyeon
* @date 2022/11/26
* @version 1.0.0
**/
interface ScheduleQuerySpotPort {

fun querySpotById(id: UUID) : Spot?

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package team.comit.simtong.domain.schedule.vo

import java.time.LocalDate
import java.util.UUID

/**
*
* Schedule과 Schedule의 Spot 정보를 가지는 SpotSchedule
*
* @author Chokyunghyeon
* @date 2022/11/26
* @version 1.0.0
**/
open class SpotSchedule(
val id: UUID,

val title: String,

val startAt: LocalDate,

val endAt: LocalDate,

val spotId: UUID,

val spotName: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ object DomainPropertiesPrefix {
const val USER_DEFAULT_IMAGE = "user.default-image"

// AuthCode
const val AUTHCODE_EXPIRED = "authcode.expired"
const val AUTHCODE_EXP = "authcode.exp"

// AuthCodeLimit
const val AUTHCODELIMIT_EXPIRED = "authcodelimit.expired"
const val AUTHCODELIMIT_VERIFIED_EXPIRED = "authcodelimit.verified-expired"
const val AUTHCODELIMIT_EXP = "authcodelimit.exp"
const val AUTHCODELIMIT_VERIFIED_EXP = "authcodelimit.verified-exp"
const val AUTHCODELIMIT_MAX_ATTEMPT_COUNT = "authcodelimit.max-attempt-count"

}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class SecurityConfig(
.antMatchers(HttpMethod.POST, "/files/list").permitAll()

// schedules
.antMatchers(HttpMethod.GET, "/schedules/spots").hasAnyRole(ROLE_ADMIN.role, ROLE_SUPER.role)
.antMatchers(HttpMethod.POST, "/schedules/spots/{spot-id}").hasAnyRole(ROLE_ADMIN.role, ROLE_SUPER.role)
.antMatchers(HttpMethod.PUT, "/schedules/spots/{schedule-id}").hasAnyRole(ROLE_ADMIN.role, ROLE_SUPER.role)
.antMatchers(HttpMethod.DELETE, "/schedules/spots/{schedule-id}").hasAnyRole(ROLE_ADMIN.role, ROLE_SUPER.role)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package team.comit.simtong.persistence.schedule

import com.querydsl.jpa.impl.JPAQueryFactory
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Component
import team.comit.simtong.domain.schedule.model.Schedule
import team.comit.simtong.domain.schedule.spi.SchedulePort
import team.comit.simtong.domain.schedule.vo.SpotSchedule
import team.comit.simtong.persistence.schedule.mapper.ScheduleMapper
import team.comit.simtong.persistence.schedule.vo.QSpotScheduleVo
import java.time.LocalDate
import java.util.UUID
import team.comit.simtong.persistence.schedule.entity.QScheduleJpaEntity.scheduleJpaEntity as schedule
import team.comit.simtong.persistence.spot.entity.QSpotJpaEntity.spotJpaEntity as spot

/**
*
Expand All @@ -18,7 +24,8 @@ import java.util.UUID
@Component
class SchedulePersistenceAdapter(
private val scheduleJpaRepository: ScheduleJpaRepository,
private val scheduleMapper: ScheduleMapper
private val scheduleMapper: ScheduleMapper,
private val queryFactory: JPAQueryFactory
) : SchedulePort {

override fun save(schedule: Schedule) = scheduleMapper.toDomain(
Expand All @@ -39,4 +46,29 @@ class SchedulePersistenceAdapter(
)
}

override fun querySchedulesByDateContains(date: LocalDate): List<SpotSchedule> {
val startDate = date.withDayOfMonth(1)
val endDate = date.withDayOfMonth(date.lengthOfMonth())

return queryFactory
.select(
QSpotScheduleVo(
schedule.id,
schedule.title,
schedule.startAt,
schedule.endAt,
spot.id,
spot.name
))
.from(schedule)
.join(spot)
.on(schedule.spot.eq(spot))
.where(
schedule.startAt.between(startDate, endDate)
.or(schedule.endAt.between(startDate, endDate))
)
.orderBy(schedule.startAt.asc())
.fetch()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package team.comit.simtong.persistence.schedule.vo

import com.querydsl.core.annotations.QueryProjection
import team.comit.simtong.domain.schedule.vo.SpotSchedule
import java.time.LocalDate
import java.util.UUID

/**
*
* Schedule과 Schedule의 Spot 정보를 가져오는 SpotScheduleVo
*
* @author Chokyunghyeon
* @date 2022/11/26
* @version 1.0.0
**/
class SpotScheduleVo @QueryProjection constructor(
id: UUID,
title: String,
startAt: LocalDate,
endAt: LocalDate,
spotId: UUID,
spotName: String
) : SpotSchedule(
id = id,
title = title,
startAt = startAt,
endAt = endAt,
spotId = spotId,
spotName = spotName
)
Loading