Skip to content

Commit

Permalink
Merge pull request #28 from Nexters/feature/27-update-resort-dates-an…
Browse files Browse the repository at this point in the history
…d-status

[#27] 스키장 개장일/폐장일 업데이트 API 추가 및 운영 상태 업데이트 Batch 추가 및 조회 필드 추가
  • Loading branch information
jun108059 authored Nov 18, 2024
2 parents 45da12b + 4dc9292 commit 60c1efa
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 7 deletions.
71 changes: 71 additions & 0 deletions src/main/kotlin/nexters/weski/batch/ResortBatchController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package nexters.weski.batch

import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.Content
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.tags.Tag
import nexters.weski.ski_resort.SkiResortService
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController


@Tag(name = "스키장 개장일/폐장일 업데이트 API", description = "스키장 개장일/폐장일을 업데이트")
@RestController
class ResortBatchController(
private val resortService: SkiResortService
) {
@Operation(
summary = "스키장 개장일/폐장일 업데이트 API",
description = """
스키장 개장일을 업데이트하면 해당 스키장의 개장일이 변경됩니다.
date : OPENING_DATE, CLOSING_DATE 중 하나를 선택합니다.
resortId는 다음과 같습니다.
1, 지산 리조트
2, 곤지암 스키장
3, 비발디파크
4, 엘리시안 강촌
5, 웰리힐리파크
6, 휘닉스파크
7, 하이원 스키장
8, 용평스키장 모나
9, 무주덕유산
10, 에덴벨리(양산)
11, 오투리조트
"""
)
@PostMapping("/batch/resort-date")
fun updateResortDate(
@RequestBody
@io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "스키장 개장일/폐장일 업데이트 요청",
required = true,
content = [Content(
mediaType = "application/json",
schema = Schema(implementation = ResortDateUpdateRequest::class)
)]
)
request: ResortDateUpdateRequest
) {
resortService.updateResortDate(
resortId = request.resortId,
dateType = request.dateType,
date = request.date
)
}

@Operation(
summary = "스키장 운영상태 업데이트",
description = """
스키장 운영상태를 업데이트하면 해당 스키장의 개장일과 폐장일을 기준으로 운영상태가 변경됩니다.
스키장 운영상태는 다음과 같습니다.
- 예정
- 운영중
- 운영종료
"""
)
@PostMapping("/batch/resort-status")
fun updateResortStatus() {
resortService.updateSkiResortStatus()
}
}
32 changes: 32 additions & 0 deletions src/main/kotlin/nexters/weski/batch/ResortDateUpdateRequest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package nexters.weski.batch

import io.swagger.v3.oas.annotations.media.Schema
import java.time.LocalDate

class ResortDateUpdateRequest (
@Schema(
description = "스키장 ID",
example = "1"
)
val resortId: Long,

@Schema(
description = "날짜 타입 (OPENING_DATE: 개장일, CLOSING_DATE: 폐장일)",
example = "OPENING_DATE"
)
val dateType: DateType,

@Schema(
description = "날짜 (yyyy-MM-dd 형식)",
example = "2024-11-30"
)
val date: LocalDate
)

enum class DateType {
@Schema(description = "개장일")
OPENING_DATE,

@Schema(description = "폐장일")
CLOSING_DATE
}
15 changes: 15 additions & 0 deletions src/main/kotlin/nexters/weski/batch/ResortStatusUpdateScheduler.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package nexters.weski.batch

import nexters.weski.ski_resort.SkiResortService
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component

@Component
class ResortStatusUpdateScheduler(
private val skiResortService: SkiResortService
) {
@Scheduled(cron = "15 0 0 * * ?")
fun scheduleResortStatusUpdate() {
skiResortService.updateSkiResortStatus()
}
}
17 changes: 17 additions & 0 deletions src/main/kotlin/nexters/weski/common/config/SwaggerConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package nexters.weski.common.config

import io.swagger.v3.oas.models.OpenAPI
import io.swagger.v3.oas.models.info.Info
import org.springdoc.core.models.GroupedOpenApi
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.filter.ForwardedHeaderFilter
Expand All @@ -24,6 +25,22 @@ class SwaggerConfig {
)
}

@Bean
fun userApi(): GroupedOpenApi {
return GroupedOpenApi.builder()
.group("API for WE-SKI Client")
.pathsToMatch("/api/**")
.build()
}

@Bean
fun productApi(): GroupedOpenApi {
return GroupedOpenApi.builder()
.group("BATCH for ADMIN")
.pathsToMatch("/batch/**")
.build()
}

@Bean
fun forwardedHeaderFilter(): ForwardedHeaderFilter {
return ForwardedHeaderFilter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ data class SkiResortResponseDto(
val resortId: Long,
val name: String,
val status: String,
val openingDate: String,
val closingDate: String,
val openSlopes: Int,
val currentWeather: SimpleCurrentWeatherDto,
val weeklyWeather: List<WeeklyWeatherDto>
Expand All @@ -25,6 +27,8 @@ data class SkiResortResponseDto(
resortId = skiResort.resortId,
name = skiResort.name,
status = skiResort.status.name,
openingDate = skiResort.openingDate?.toString() ?: "미정",
closingDate = skiResort.closingDate?.toString() ?: "미정",
openSlopes = skiResort.openSlopes,
currentWeather = currentWeather?.let {
SimpleCurrentWeatherDto(
Expand Down
34 changes: 34 additions & 0 deletions src/main/kotlin/nexters/weski/ski_resort/SkiResortService.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package nexters.weski.ski_resort

import nexters.weski.batch.DateType
import nexters.weski.weather.CurrentWeatherRepository
import nexters.weski.weather.DailyWeatherRepository
import org.springframework.stereotype.Service
import java.time.LocalDate

@Service
class SkiResortService(
Expand All @@ -19,4 +21,36 @@ class SkiResortService(
SkiResortResponseDto.fromEntity(skiResort, currentWeather, weeklyWeather)
}
}

fun updateResortDate(resortId: Long, dateType: DateType, date: LocalDate) {
val skiResort = skiResortRepository.findById(resortId)
.orElseThrow { IllegalArgumentException("해당 ID의 스키장이 존재하지 않습니다.") }

val updatedSkiResort = when (dateType) {
DateType.OPENING_DATE -> skiResort.copy(openingDate = date)
DateType.CLOSING_DATE -> skiResort.copy(closingDate = date)
}

skiResortRepository.save(updatedSkiResort)
}

fun updateSkiResortStatus() {
val skiResorts = skiResortRepository.findAll()
val today = LocalDate.now()

skiResorts.forEach { skiResort ->
val openingDate = skiResort.openingDate
val closingDate = skiResort.closingDate

val newStatus = when {
today.isBefore(openingDate) -> ResortStatus.예정
closingDate != null && today.isAfter(closingDate) -> ResortStatus.운영종료
else -> ResortStatus.운영중
}

val updatedSkiResort = skiResort.copy(status = newStatus)
skiResortRepository.save(updatedSkiResort)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ class SkiResortControllerTest @Autowired constructor(
)
// Given
val skiResorts = listOf(
SkiResortResponseDto(1, "스키장 A", ResortStatus.운영중.name, 3, currentWeather, weeklyWeather),
SkiResortResponseDto(2, "스키장 B", ResortStatus.운영중.name, 4, currentWeather, weeklyWeather),
SkiResortResponseDto(1, "스키장 A", ResortStatus.운영중.name, "미정", "미정", 3, currentWeather, weeklyWeather),
SkiResortResponseDto(2, "스키장 B", ResortStatus.운영중.name, "미정", "미정", 4, currentWeather, weeklyWeather),
)
every { skiResortService.getAllSkiResortsAndWeather() } returns skiResorts

Expand Down
30 changes: 27 additions & 3 deletions src/test/kotlin/nexters/weski/ski_resort/SkiResortServiceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,34 @@ class SkiResortServiceTest {
fun `getAllSkiResorts should return list of SkiResortDto`() {
// Given
val skiResorts = listOf(
SkiResort(1, "스키장 A", ResortStatus.운영중, null, null, 5, 10),
SkiResort(2, "스키장 B", ResortStatus.예정, null, null, 0, 8)
SkiResort(
resortId = 1,
name = "스키장 A",
status = ResortStatus.운영중,
openingDate = null,
closingDate = null,
openSlopes = 3,
totalSlopes = 8,
xCoordinate = "12.0",
yCoordinate = "34.0",
detailedAreaCode = "11D20201",
broadAreaCode = "11D20000"
),
SkiResort(
resortId = 2,
name = "스키장 B",
status = ResortStatus.운영중,
openingDate = null,
closingDate = null,
openSlopes = 3,
totalSlopes = 8,
xCoordinate = "12.0",
yCoordinate = "34.0",
detailedAreaCode = "11D20201",
broadAreaCode = "11D20000"
)
)
every { skiResortRepository.findAll() } returns skiResorts
every { skiResortRepository.findAllByOrderByOpeningDateAsc() } returns skiResorts
every { currentWeatherRepository.findBySkiResortResortId(any()) } returns null
every { dailyWeatherRepository.findAllBySkiResortResortId(any()) } returns emptyList()

Expand Down
14 changes: 13 additions & 1 deletion src/test/kotlin/nexters/weski/snow_maker/SnowMakerServiceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,19 @@ class SnowMakerServiceTest {
// Given
val resortId = 1L
val isPositive = true
val skiResort = SkiResort(resortId, "스키장 A", ResortStatus.운영중, null, null, 5, 10)
val skiResort = SkiResort(
resortId = 1,
name = "스키장 A",
status = ResortStatus.운영중,
openingDate = null,
closingDate = null,
openSlopes = 3,
totalSlopes = 8,
xCoordinate = "12.0",
yCoordinate = "34.0",
detailedAreaCode = "11D20201",
broadAreaCode = "11D20000"
)
val snowMakerVote = SnowMakerVote(
isPositive = isPositive,
skiResort = skiResort
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class WeatherServiceTest {
resortId, -5, -2, -8, -10, "눈이 내리고 있습니다.", "", skiResort
)
every { currentWeatherRepository.findBySkiResortResortId(resortId) } returns currentWeather
every { hourlyWeatherRepository.findAll() } returns listOf()
every { hourlyWeatherRepository.findBySkiResortResortId(resortId) } returns listOf()
every { dailyWeatherRepository.findAllBySkiResortResortId(resortId) } returns listOf()

// When
Expand Down

0 comments on commit 60c1efa

Please sign in to comment.