diff --git a/src/main/kotlin/nexters/weski/batch/ResortBatchController.kt b/src/main/kotlin/nexters/weski/batch/ResortBatchController.kt index b55bb44..919801b 100644 --- a/src/main/kotlin/nexters/weski/batch/ResortBatchController.kt +++ b/src/main/kotlin/nexters/weski/batch/ResortBatchController.kt @@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RestController -@Tag(name = "스키장 개장일/폐장일 업데이트 API", description = "스키장 개장일/폐장일을 업데이트") +@Tag(name = "스키장 데이터 업데이트 API", description = "스키장 데이터를 업데이트") @RestController class ResortBatchController( private val resortService: SkiResortService diff --git a/src/main/kotlin/nexters/weski/batch/ResortStatusUpdateScheduler.kt b/src/main/kotlin/nexters/weski/batch/ResortStatusUpdateScheduler.kt index 9c606f9..6281aac 100644 --- a/src/main/kotlin/nexters/weski/batch/ResortStatusUpdateScheduler.kt +++ b/src/main/kotlin/nexters/weski/batch/ResortStatusUpdateScheduler.kt @@ -12,4 +12,9 @@ class ResortStatusUpdateScheduler( fun scheduleResortStatusUpdate() { skiResortService.updateSkiResortStatus() } + + @Scheduled(cron = "30 0 0 * * ?") + fun scheduleResortSlopeCountUpdate() { + skiResortService.updateSkiResortSlopeCount() + } } \ No newline at end of file diff --git a/src/main/kotlin/nexters/weski/batch/SlopeBatchController.kt b/src/main/kotlin/nexters/weski/batch/SlopeBatchController.kt new file mode 100644 index 0000000..f0e3231 --- /dev/null +++ b/src/main/kotlin/nexters/weski/batch/SlopeBatchController.kt @@ -0,0 +1,67 @@ +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 nexters.weski.slope.SlopeService +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 SlopeBatchController( + private val slopeService: SlopeService, + private val resortService: SkiResortService +) { + @Operation( + summary = "스키장 슬로프 운영 현황 업데이트 API", + description = """ + 스키장 id, 슬로프 이름, 주간/야간/심야/새벽/자정, 운영 여부를 파라미터로 전달해서 업데이트합니다. + resortId는 다음과 같습니다. + 1, 지산 리조트 + 2, 곤지암 스키장 + 3, 비발디파크 + 4, 엘리시안 강촌 + 5, 웰리힐리파크 + 6, 휘닉스파크 + 7, 하이원 스키장 + 8, 용평스키장 모나 + 9, 무주덕유산 + 10, 에덴벨리(양산) + 11, 오투리조트 + """ + ) + @PostMapping("/batch/slope-status") + fun updateSlopeStatus( + @RequestBody + @io.swagger.v3.oas.annotations.parameters.RequestBody( + description = "slopes 운영여부 업데이트 요청", + required = true, + content = [Content( + mediaType = "application/json", + schema = Schema(implementation = SlopeDateUpdateRequest::class) + )] + ) + request: SlopeDateUpdateRequest + ) { + slopeService.updateSlopeOpeningStatus( + resortId = request.resortId, + slopeName = request.slopeName, + timeType = request.timeType, + isOpen = request.isOpen + ) + } + + @Operation( + summary = "스키장 슬로프 count 업데이트", + description = "스키장의 슬로프 count가 업데이트됩니다." + ) + @PostMapping("/batch/resort-slope-count") + fun updateSlopeCount() { + resortService.updateSkiResortSlopeCount() + } + +} \ No newline at end of file diff --git a/src/main/kotlin/nexters/weski/batch/SlopeDateUpdateRequest.kt b/src/main/kotlin/nexters/weski/batch/SlopeDateUpdateRequest.kt new file mode 100644 index 0000000..843ffa9 --- /dev/null +++ b/src/main/kotlin/nexters/weski/batch/SlopeDateUpdateRequest.kt @@ -0,0 +1,30 @@ +package nexters.weski.batch + +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDate + +class SlopeDateUpdateRequest ( + @Schema( + description = "스키장 ID", + example = "1" + ) + val resortId: Long, + + @Schema( + description = "슬로프 이름", + example = "레몬1" + ) + val slopeName: String, + + @Schema( + description = "주간/야간/심야/새벽/자정 중 하나", + example = "주간" + ) + val timeType: String, + + @Schema( + description = "운영 여부(Y/N)", + example = "Y" + ) + val isOpen: String, +) diff --git a/src/main/kotlin/nexters/weski/ski_resort/SkiResortController.kt b/src/main/kotlin/nexters/weski/ski_resort/SkiResortController.kt index e46752c..1c658f5 100644 --- a/src/main/kotlin/nexters/weski/ski_resort/SkiResortController.kt +++ b/src/main/kotlin/nexters/weski/ski_resort/SkiResortController.kt @@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RestController -@Tag(name = "전체 스키장 정보 API", description = "전체 스키장 날씨 및 슬로프 정보 관련") +@Tag(name = "스키장 정보 API", description = "전체 스키장 날씨 및 슬로프 정보 관련") @RestController class SkiResortController( private val skiResortService: SkiResortService diff --git a/src/main/kotlin/nexters/weski/ski_resort/SkiResortService.kt b/src/main/kotlin/nexters/weski/ski_resort/SkiResortService.kt index f5f285a..ac24e68 100644 --- a/src/main/kotlin/nexters/weski/ski_resort/SkiResortService.kt +++ b/src/main/kotlin/nexters/weski/ski_resort/SkiResortService.kt @@ -1,6 +1,7 @@ package nexters.weski.ski_resort import nexters.weski.batch.DateType +import nexters.weski.slope.SlopeService import nexters.weski.weather.CurrentWeatherRepository import nexters.weski.weather.DailyWeatherRepository import org.springframework.stereotype.Service @@ -10,7 +11,8 @@ import java.time.LocalDate class SkiResortService( private val skiResortRepository: SkiResortRepository, private val currentWeatherRepository: CurrentWeatherRepository, - private val dailyWeatherRepository: DailyWeatherRepository + private val dailyWeatherRepository: DailyWeatherRepository, + private val slopeService: SlopeService ) { fun getAllSkiResortsAndWeather(): List { val skiResorts = skiResortRepository.findAllByOrderByOpeningDateAsc() @@ -63,4 +65,13 @@ class SkiResortService( } } + fun updateSkiResortSlopeCount() { + val skiResorts = skiResortRepository.findAll() + skiResorts.forEach { skiResort -> + val totalSlopeCount = slopeService.getTotalSlopeCount(skiResort.resortId) + val openingSlopeCount = slopeService.getOpeningSlopeCount(skiResort.resortId) + val updatedSkiResort = skiResort.copy(totalSlopes = totalSlopeCount, openSlopes = openingSlopeCount) + skiResortRepository.save(updatedSkiResort) + } + } } diff --git a/src/main/kotlin/nexters/weski/slope/Slope.kt b/src/main/kotlin/nexters/weski/slope/Slope.kt index a5a2399..b618be1 100644 --- a/src/main/kotlin/nexters/weski/slope/Slope.kt +++ b/src/main/kotlin/nexters/weski/slope/Slope.kt @@ -15,11 +15,11 @@ data class Slope( @Enumerated(EnumType.STRING) val difficulty: DifficultyLevel, - val isDayOperating: Boolean = false, - val isNightOperating: Boolean = false, - val isLateNightOperating: Boolean = false, - val isDawnOperating: Boolean = false, - val isMidnightOperating: Boolean = false, + var isDayOperating: Boolean = false, + var isNightOperating: Boolean = false, + var isLateNightOperating: Boolean = false, + var isDawnOperating: Boolean = false, + var isMidnightOperating: Boolean = false, @ManyToOne @JoinColumn(name = "resort_id") diff --git a/src/main/kotlin/nexters/weski/slope/SlopeRepository.kt b/src/main/kotlin/nexters/weski/slope/SlopeRepository.kt index 46fe5ce..8338078 100644 --- a/src/main/kotlin/nexters/weski/slope/SlopeRepository.kt +++ b/src/main/kotlin/nexters/weski/slope/SlopeRepository.kt @@ -1,7 +1,22 @@ package nexters.weski.slope import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query interface SlopeRepository : JpaRepository { fun findAllBySkiResortResortId(resortId: Long): List + fun countBySkiResortResortId(resortId: Long): Int + fun findBySkiResortResortIdAndName(resortId: Long, name: String): Slope? + + @Query(""" + SELECT COUNT(s) + FROM Slope s + WHERE s.skiResort.resortId = :resortId + AND (s.isDayOperating = true + OR s.isNightOperating = true + OR s.isLateNightOperating = true + OR s.isDawnOperating = true + OR s.isMidnightOperating = true) + """) + fun countOperatingSlopesByResortId(resortId: Long): Int } diff --git a/src/main/kotlin/nexters/weski/slope/SlopeService.kt b/src/main/kotlin/nexters/weski/slope/SlopeService.kt index cacc4cb..f9349e4 100644 --- a/src/main/kotlin/nexters/weski/slope/SlopeService.kt +++ b/src/main/kotlin/nexters/weski/slope/SlopeService.kt @@ -17,4 +17,31 @@ class SlopeService( return SlopeResponseDto.fromEntities(skiResort, slopes, webcams) } + fun getTotalSlopeCount(resortId: Long): Int { + return slopeRepository.countBySkiResortResortId(resortId) + } + + fun getOpeningSlopeCount(resortId: Long): Int { + return slopeRepository.countOperatingSlopesByResortId(resortId) + } + + fun updateSlopeOpeningStatus( + resortId: Long, + slopeName: String, + timeType: String, + isOpen: String + ) { + val slope = slopeRepository.findBySkiResortResortIdAndName(resortId, slopeName) + ?: throw Exception("Slope not found") + + when (timeType) { + "주간" -> slope.isDayOperating = isOpen == "Y" + "야간" -> slope.isNightOperating = isOpen == "Y" + "심야" -> slope.isLateNightOperating = isOpen == "Y" + "새벽" -> slope.isDawnOperating = isOpen == "Y" + "자정" -> slope.isMidnightOperating = isOpen == "Y" + else -> throw Exception("Invalid time type") + } + slopeRepository.save(slope) + } } \ No newline at end of file