generated from pricelees/issue-pr-template
refactor: schedule 관련 로직 및 테스트에 한국 시간 반영
This commit is contained in:
parent
6c2e63e35e
commit
844c8b6007
@ -1,6 +1,8 @@
|
|||||||
package com.sangdol.roomescape.schedule.business
|
package com.sangdol.roomescape.schedule.business
|
||||||
|
|
||||||
import com.sangdol.common.persistence.IDGenerator
|
import com.sangdol.common.persistence.IDGenerator
|
||||||
|
import com.sangdol.common.utils.KoreaDate
|
||||||
|
import com.sangdol.common.utils.KoreaTime
|
||||||
import com.sangdol.roomescape.admin.business.AdminService
|
import com.sangdol.roomescape.admin.business.AdminService
|
||||||
import com.sangdol.roomescape.common.types.AuditingInfo
|
import com.sangdol.roomescape.common.types.AuditingInfo
|
||||||
import com.sangdol.roomescape.common.types.Auditor
|
import com.sangdol.roomescape.common.types.Auditor
|
||||||
@ -44,7 +46,9 @@ class ScheduleService(
|
|||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
fun getStoreScheduleByDate(storeId: Long, date: LocalDate): ScheduleWithThemeListResponse {
|
fun getStoreScheduleByDate(storeId: Long, date: LocalDate): ScheduleWithThemeListResponse {
|
||||||
log.info { "[getStoreScheduleByDate] 매장 일정 조회: storeId=${storeId}, date=$date" }
|
log.info { "[getStoreScheduleByDate] 매장 일정 조회: storeId=${storeId}, date=$date" }
|
||||||
val currentDate = LocalDate.now()
|
|
||||||
|
val currentDate: LocalDate = KoreaDate.today()
|
||||||
|
val currentTime: LocalTime = KoreaTime.now()
|
||||||
|
|
||||||
if (date.isBefore(currentDate)) {
|
if (date.isBefore(currentDate)) {
|
||||||
log.warn { "[getStoreScheduleByDate] 이전 날짜 선택으로 인한 실패: date=${date}" }
|
log.warn { "[getStoreScheduleByDate] 이전 날짜 선택으로 인한 실패: date=${date}" }
|
||||||
@ -53,7 +57,7 @@ class ScheduleService(
|
|||||||
|
|
||||||
val schedules: List<ScheduleOverview> =
|
val schedules: List<ScheduleOverview> =
|
||||||
scheduleRepository.findStoreSchedulesWithThemeByDate(storeId, date)
|
scheduleRepository.findStoreSchedulesWithThemeByDate(storeId, date)
|
||||||
.filter { it.date.isAfter(date) || (it.date.isEqual(date) && it.time.isAfter(LocalTime.now())) }
|
.filter { it.time.isAfter(currentTime) }
|
||||||
|
|
||||||
return schedules.toResponse()
|
return schedules.toResponse()
|
||||||
.also {
|
.also {
|
||||||
@ -89,7 +93,7 @@ class ScheduleService(
|
|||||||
fun searchSchedules(storeId: Long, date: LocalDate?, themeId: Long?): AdminScheduleSummaryListResponse {
|
fun searchSchedules(storeId: Long, date: LocalDate?, themeId: Long?): AdminScheduleSummaryListResponse {
|
||||||
log.info { "[searchSchedules] 일정 검색 시작: storeId=$storeId, date=$date, themeId=$themeId" }
|
log.info { "[searchSchedules] 일정 검색 시작: storeId=$storeId, date=$date, themeId=$themeId" }
|
||||||
|
|
||||||
val searchDate = date ?: LocalDate.now()
|
val searchDate = date ?: KoreaDate.today()
|
||||||
|
|
||||||
val schedules: List<ScheduleOverview> =
|
val schedules: List<ScheduleOverview> =
|
||||||
scheduleRepository.findStoreSchedulesWithThemeByDate(storeId, searchDate)
|
scheduleRepository.findStoreSchedulesWithThemeByDate(storeId, searchDate)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.sangdol.roomescape.schedule.business
|
package com.sangdol.roomescape.schedule.business
|
||||||
|
|
||||||
|
import com.sangdol.common.utils.KoreaDateTime
|
||||||
import com.sangdol.roomescape.schedule.exception.ScheduleErrorCode
|
import com.sangdol.roomescape.schedule.exception.ScheduleErrorCode
|
||||||
import com.sangdol.roomescape.schedule.exception.ScheduleException
|
import com.sangdol.roomescape.schedule.exception.ScheduleException
|
||||||
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleEntity
|
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleEntity
|
||||||
@ -13,6 +14,7 @@ import org.springframework.stereotype.Component
|
|||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.LocalTime
|
import java.time.LocalTime
|
||||||
|
import java.time.temporal.ChronoUnit
|
||||||
|
|
||||||
private val log: KLogger = KotlinLogging.logger {}
|
private val log: KLogger = KotlinLogging.logger {}
|
||||||
|
|
||||||
@ -56,9 +58,10 @@ class ScheduleValidator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun validateNotInPast(date: LocalDate, time: LocalTime) {
|
private fun validateNotInPast(date: LocalDate, time: LocalTime) {
|
||||||
val dateTime = LocalDateTime.of(date, time)
|
val now = KoreaDateTime.now().truncatedTo(ChronoUnit.MINUTES)
|
||||||
|
val inputDateTime = LocalDateTime.of(date, time).truncatedTo(ChronoUnit.MINUTES)
|
||||||
|
|
||||||
if (dateTime.isBefore(LocalDateTime.now())) {
|
if (inputDateTime.isBefore(now)) {
|
||||||
log.info {
|
log.info {
|
||||||
"[ScheduleValidator.validateDateTime] 이전 시간 선택으로 인한 실패: date=${date} / time=${time}"
|
"[ScheduleValidator.validateDateTime] 이전 시간 선택으로 인한 실패: date=${date} / time=${time}"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
package com.sangdol.roomescape.schedule
|
package com.sangdol.roomescape.schedule
|
||||||
|
|
||||||
import com.sangdol.roomescape.common.types.Auditor
|
|
||||||
import com.sangdol.common.types.web.HttpStatus
|
import com.sangdol.common.types.web.HttpStatus
|
||||||
|
import com.sangdol.common.utils.KoreaDate
|
||||||
|
import com.sangdol.common.utils.KoreaDateTime
|
||||||
|
import com.sangdol.common.utils.KoreaTime
|
||||||
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminPermissionLevel
|
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminPermissionLevel
|
||||||
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminType
|
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminType
|
||||||
import com.sangdol.roomescape.auth.exception.AuthErrorCode
|
import com.sangdol.roomescape.auth.exception.AuthErrorCode
|
||||||
|
import com.sangdol.roomescape.common.types.Auditor
|
||||||
import com.sangdol.roomescape.schedule.exception.ScheduleErrorCode
|
import com.sangdol.roomescape.schedule.exception.ScheduleErrorCode
|
||||||
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleEntity
|
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleEntity
|
||||||
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleRepository
|
import com.sangdol.roomescape.schedule.infrastructure.persistence.ScheduleRepository
|
||||||
@ -54,7 +57,8 @@ class AdminScheduleApiTest(
|
|||||||
lateinit var token: String
|
lateinit var token: String
|
||||||
|
|
||||||
beforeTest {
|
beforeTest {
|
||||||
val today = LocalDate.now()
|
val now = KoreaDateTime.now()
|
||||||
|
val today = now.toLocalDate()
|
||||||
store = dummyInitializer.createStore()
|
store = dummyInitializer.createStore()
|
||||||
val admin = AdminFixture.createStoreAdmin(storeId = store.id)
|
val admin = AdminFixture.createStoreAdmin(storeId = store.id)
|
||||||
token = testAuthUtil.adminLogin(admin).second
|
token = testAuthUtil.adminLogin(admin).second
|
||||||
@ -66,21 +70,21 @@ class AdminScheduleApiTest(
|
|||||||
storeId = store.id,
|
storeId = store.id,
|
||||||
request = ScheduleFixture.createRequest.copy(
|
request = ScheduleFixture.createRequest.copy(
|
||||||
date = today,
|
date = today,
|
||||||
time = LocalTime.now().plusHours(2)
|
time = now.toLocalTime().plusHours(2)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
dummyInitializer.createSchedule(
|
dummyInitializer.createSchedule(
|
||||||
storeId = store.id,
|
storeId = store.id,
|
||||||
request = ScheduleFixture.createRequest.copy(
|
request = ScheduleFixture.createRequest.copy(
|
||||||
date = today,
|
date = today,
|
||||||
time = LocalTime.now().plusHours(1)
|
time = now.toLocalTime().plusHours(1)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
dummyInitializer.createSchedule(
|
dummyInitializer.createSchedule(
|
||||||
storeId = store.id,
|
storeId = store.id,
|
||||||
request = ScheduleFixture.createRequest.copy(
|
request = ScheduleFixture.createRequest.copy(
|
||||||
date = today.plusDays(1),
|
date = today.plusDays(1),
|
||||||
time = LocalTime.of(11, 0)
|
time = LocalTime.of(10, 0)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -95,7 +99,7 @@ class AdminScheduleApiTest(
|
|||||||
},
|
},
|
||||||
expect = {
|
expect = {
|
||||||
statusCode(HttpStatus.OK.value())
|
statusCode(HttpStatus.OK.value())
|
||||||
body("data.schedules.size()", equalTo(schedules.filter { it.date.isEqual(LocalDate.now()) }.size))
|
body("data.schedules.size()", equalTo(schedules.filter { it.date.isEqual(KoreaDate.today()) }.size))
|
||||||
assertProperties(
|
assertProperties(
|
||||||
props = setOf("id", "themeName", "startFrom", "endAt", "status"),
|
props = setOf("id", "themeName", "startFrom", "endAt", "status"),
|
||||||
propsNameIfList = "schedules"
|
propsNameIfList = "schedules"
|
||||||
@ -386,8 +390,9 @@ class AdminScheduleApiTest(
|
|||||||
|
|
||||||
test("과거 시간을 선택하면 실패한다.") {
|
test("과거 시간을 선택하면 실패한다.") {
|
||||||
val (admin, token) = testAuthUtil.defaultStoreAdminLogin()
|
val (admin, token) = testAuthUtil.defaultStoreAdminLogin()
|
||||||
val date = LocalDate.now()
|
val now = KoreaDateTime.now()
|
||||||
val time = LocalTime.now().minusMinutes(1)
|
val date = now.toLocalDate()
|
||||||
|
val time = now.toLocalTime().minusMinutes(1)
|
||||||
val theme = dummyInitializer.createTheme()
|
val theme = dummyInitializer.createTheme()
|
||||||
|
|
||||||
val request = ScheduleFixture.createRequest.copy(date = date, time = time, themeId = theme.id)
|
val request = ScheduleFixture.createRequest.copy(date = date, time = time, themeId = theme.id)
|
||||||
@ -490,7 +495,8 @@ class AdminScheduleApiTest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
context("정상 응답") {
|
context("정상 응답") {
|
||||||
test("시간만 변경한다.") {
|
context("시간만 변경한다.") {
|
||||||
|
test("성공") {
|
||||||
val (admin, token) = testAuthUtil.defaultStoreAdminLogin()
|
val (admin, token) = testAuthUtil.defaultStoreAdminLogin()
|
||||||
val schedule = initialize("수정을 위한 일정 생성") {
|
val schedule = initialize("수정을 위한 일정 생성") {
|
||||||
dummyInitializer.createSchedule()
|
dummyInitializer.createSchedule()
|
||||||
@ -516,6 +522,26 @@ class AdminScheduleApiTest(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("지난 시간을 선택하면 실패한다.") {
|
||||||
|
val (admin, token) = testAuthUtil.defaultStoreAdminLogin()
|
||||||
|
val schedule = initialize("수정을 위한 일정 생성") {
|
||||||
|
val request = ScheduleFixture.createRequest.copy(
|
||||||
|
date = KoreaDate.today(),
|
||||||
|
time = KoreaTime.now().plusHours(1)
|
||||||
|
)
|
||||||
|
dummyInitializer.createSchedule(request = request)
|
||||||
|
}
|
||||||
|
|
||||||
|
runExceptionTest(
|
||||||
|
token = token,
|
||||||
|
method = HttpMethod.PATCH,
|
||||||
|
endpoint = "/admin/schedules/${schedule.id}",
|
||||||
|
requestBody = ScheduleUpdateRequest(time = KoreaTime.now().minusMinutes(1)),
|
||||||
|
expectedErrorCode = ScheduleErrorCode.PAST_DATE_TIME
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
test("상태만 변경한다.") {
|
test("상태만 변경한다.") {
|
||||||
val (admin, token) = testAuthUtil.defaultStoreAdminLogin()
|
val (admin, token) = testAuthUtil.defaultStoreAdminLogin()
|
||||||
val schedule = initialize("수정을 위한 일정 생성") {
|
val schedule = initialize("수정을 위한 일정 생성") {
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package com.sangdol.roomescape.schedule
|
package com.sangdol.roomescape.schedule
|
||||||
|
|
||||||
import com.sangdol.common.types.web.HttpStatus
|
import com.sangdol.common.types.web.HttpStatus
|
||||||
|
import com.sangdol.common.utils.KoreaDate
|
||||||
|
import com.sangdol.common.utils.KoreaTime
|
||||||
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminPermissionLevel
|
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminPermissionLevel
|
||||||
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminType
|
import com.sangdol.roomescape.admin.infrastructure.persistence.AdminType
|
||||||
import com.sangdol.roomescape.auth.exception.AuthErrorCode
|
import com.sangdol.roomescape.auth.exception.AuthErrorCode
|
||||||
@ -13,16 +15,18 @@ import org.hamcrest.CoreMatchers.equalTo
|
|||||||
import org.springframework.data.repository.findByIdOrNull
|
import org.springframework.data.repository.findByIdOrNull
|
||||||
import org.springframework.http.HttpMethod
|
import org.springframework.http.HttpMethod
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.time.LocalTime
|
|
||||||
|
|
||||||
class ScheduleApiTest(
|
class ScheduleApiTest(
|
||||||
private val scheduleRepository: ScheduleRepository
|
private val scheduleRepository: ScheduleRepository
|
||||||
) : FunSpecSpringbootTest() {
|
) : FunSpecSpringbootTest() {
|
||||||
init {
|
init {
|
||||||
context("특정 매장 + 날짜의 일정 및 테마 정보를 조회한다.") {
|
context("특정 매장 + 날짜의 일정 및 테마 정보를 조회한다.") {
|
||||||
|
/**
|
||||||
|
* @throws 23시 57분 ~ 59분에 실행하면 실패함.
|
||||||
|
*/
|
||||||
test("날짜가 당일이면 현재 시간 이후의 정보만 조회된다.") {
|
test("날짜가 당일이면 현재 시간 이후의 정보만 조회된다.") {
|
||||||
val size = 3
|
val size = 3
|
||||||
val date = LocalDate.now()
|
val date = KoreaDate.today()
|
||||||
val store = dummyInitializer.createStore()
|
val store = dummyInitializer.createStore()
|
||||||
|
|
||||||
initialize("조회를 위한 오늘 날짜의 현재 시간 이후인 ${size}개의 일정, 현재 시간 이전인 1개의 일정 생성") {
|
initialize("조회를 위한 오늘 날짜의 현재 시간 이후인 ${size}개의 일정, 현재 시간 이전인 1개의 일정 생성") {
|
||||||
@ -31,7 +35,7 @@ class ScheduleApiTest(
|
|||||||
storeId = store.id,
|
storeId = store.id,
|
||||||
request = ScheduleFixture.createRequest.copy(
|
request = ScheduleFixture.createRequest.copy(
|
||||||
date = date,
|
date = date,
|
||||||
time = LocalTime.now().plusMinutes(i.toLong())
|
time = KoreaTime.now().plusMinutes(i.toLong())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -40,22 +44,18 @@ class ScheduleApiTest(
|
|||||||
storeId = store.id,
|
storeId = store.id,
|
||||||
request = ScheduleFixture.createRequest.copy(
|
request = ScheduleFixture.createRequest.copy(
|
||||||
date = date,
|
date = date,
|
||||||
time = LocalTime.now().minusMinutes(1)
|
time = KoreaTime.now().minusMinutes(1)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val expectedSize = scheduleRepository.findAll().takeIf { it.isNotEmpty() }
|
|
||||||
?.let { it.count { schedule -> schedule.date.isEqual(date) && schedule.time.isAfter(LocalTime.now()) } }
|
|
||||||
?: throw AssertionError("initialize 작업에서 레코드가 저장되지 않음.")
|
|
||||||
|
|
||||||
runTest(
|
runTest(
|
||||||
on = {
|
on = {
|
||||||
get("/stores/${store.id}/schedules?date=${date}")
|
get("/stores/${store.id}/schedules?date=${date}")
|
||||||
},
|
},
|
||||||
expect = {
|
expect = {
|
||||||
statusCode(HttpStatus.OK.value())
|
statusCode(HttpStatus.OK.value())
|
||||||
body("data.schedules.size()", equalTo(expectedSize))
|
body("data.schedules.size()", equalTo(size))
|
||||||
assertProperties(
|
assertProperties(
|
||||||
props = setOf("id", "startFrom", "endAt", "themeId", "themeName", "themeDifficulty", "status"),
|
props = setOf("id", "startFrom", "endAt", "themeId", "themeName", "themeDifficulty", "status"),
|
||||||
propsNameIfList = "schedules"
|
propsNameIfList = "schedules"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user