From d2af7733b05f617f7f47f8fd1ffce498659ee0d0 Mon Sep 17 00:00:00 2001 From: stophwan Date: Wed, 7 Aug 2024 22:06:15 +0900 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20=EA=B8=B0=EC=83=81=EC=B2=AD=20API?= =?UTF-8?q?=20=ED=98=B8=EC=B6=9C=20client=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blooming/api/service/WeatherService.kt | 23 ++++++++++++++++++ .../user/oauth/KakaoIdTokenResolver.kt | 2 +- .../blooming/client/dto/WeatherItem.kt | 24 +++++++++++++++++++ .../blooming/client/dto/WeatherItems.kt | 5 ++++ .../client/{ => kakao}/KakaoOauthClient.kt | 2 +- .../client/weather/WeatherInfoClient.kt | 23 ++++++++++++++++++ 6 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/dnd11th/blooming/api/service/WeatherService.kt create mode 100644 src/main/kotlin/dnd11th/blooming/client/dto/WeatherItem.kt create mode 100644 src/main/kotlin/dnd11th/blooming/client/dto/WeatherItems.kt rename src/main/kotlin/dnd11th/blooming/client/{ => kakao}/KakaoOauthClient.kt (90%) create mode 100644 src/main/kotlin/dnd11th/blooming/client/weather/WeatherInfoClient.kt diff --git a/src/main/kotlin/dnd11th/blooming/api/service/WeatherService.kt b/src/main/kotlin/dnd11th/blooming/api/service/WeatherService.kt new file mode 100644 index 00000000..5282345c --- /dev/null +++ b/src/main/kotlin/dnd11th/blooming/api/service/WeatherService.kt @@ -0,0 +1,23 @@ +package dnd11th.blooming.api.service + +import dnd11th.blooming.client.dto.WeatherItems +import dnd11th.blooming.client.weather.WeatherInfoClient +import dnd11th.blooming.domain.repository.user.UserRepository +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +@Transactional(readOnly = true) +class WeatherService( + private val weatherInfoClient: WeatherInfoClient, + private val userRepository: UserRepository +) { + + fun createPlantMessageByWeather() { + var nx: Int = 55 + var ny: Int = 127 + //TODO 어느 시간대 어느 페이지 호추 할 것인지 DSL + val weatherItems: WeatherItems = weatherInfoClient.getWeatherInfo() + //TODO ITEM들을 MESSAGE로 변환하는 DSL + } +} diff --git a/src/main/kotlin/dnd11th/blooming/api/service/user/oauth/KakaoIdTokenResolver.kt b/src/main/kotlin/dnd11th/blooming/api/service/user/oauth/KakaoIdTokenResolver.kt index 2d2a3f36..3044c6a8 100644 --- a/src/main/kotlin/dnd11th/blooming/api/service/user/oauth/KakaoIdTokenResolver.kt +++ b/src/main/kotlin/dnd11th/blooming/api/service/user/oauth/KakaoIdTokenResolver.kt @@ -2,7 +2,7 @@ package dnd11th.blooming.api.service.user.oauth import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.readValue -import dnd11th.blooming.client.KakaoOauthClient +import dnd11th.blooming.client.kakao.KakaoOauthClient import dnd11th.blooming.client.dto.OidcPublicKeys import dnd11th.blooming.common.exception.ErrorType import dnd11th.blooming.common.exception.UnAuthorizedException diff --git a/src/main/kotlin/dnd11th/blooming/client/dto/WeatherItem.kt b/src/main/kotlin/dnd11th/blooming/client/dto/WeatherItem.kt new file mode 100644 index 00000000..b630b233 --- /dev/null +++ b/src/main/kotlin/dnd11th/blooming/client/dto/WeatherItem.kt @@ -0,0 +1,24 @@ +package dnd11th.blooming.client.dto + +import java.time.LocalDate + +data class WeatherItem( + val baseDate: LocalDate, + val baseTime: String, + val category: String, + val fcstDate: LocalDate, + val fcstTime: Int, + val fcstValue: Int, + val nx: Int, + val ny: Int +) +/** +"baseDate": "20240807", +"baseTime": "0200", +"category": "REH", +"fcstDate": "20240807", +"fcstTime": "1000", +"fcstValue": "80", +"nx": 55, +"ny": 127 + **/ diff --git a/src/main/kotlin/dnd11th/blooming/client/dto/WeatherItems.kt b/src/main/kotlin/dnd11th/blooming/client/dto/WeatherItems.kt new file mode 100644 index 00000000..6dc8c1c8 --- /dev/null +++ b/src/main/kotlin/dnd11th/blooming/client/dto/WeatherItems.kt @@ -0,0 +1,5 @@ +package dnd11th.blooming.client.dto + +data class WeatherItems ( + val items : List +) diff --git a/src/main/kotlin/dnd11th/blooming/client/KakaoOauthClient.kt b/src/main/kotlin/dnd11th/blooming/client/kakao/KakaoOauthClient.kt similarity index 90% rename from src/main/kotlin/dnd11th/blooming/client/KakaoOauthClient.kt rename to src/main/kotlin/dnd11th/blooming/client/kakao/KakaoOauthClient.kt index 7ebdf681..d7d13b7f 100644 --- a/src/main/kotlin/dnd11th/blooming/client/KakaoOauthClient.kt +++ b/src/main/kotlin/dnd11th/blooming/client/kakao/KakaoOauthClient.kt @@ -1,4 +1,4 @@ -package dnd11th.blooming.client +package dnd11th.blooming.client.kakao import dnd11th.blooming.client.dto.OidcPublicKeys import org.springframework.cloud.openfeign.FeignClient diff --git a/src/main/kotlin/dnd11th/blooming/client/weather/WeatherInfoClient.kt b/src/main/kotlin/dnd11th/blooming/client/weather/WeatherInfoClient.kt new file mode 100644 index 00000000..0b4a1e6f --- /dev/null +++ b/src/main/kotlin/dnd11th/blooming/client/weather/WeatherInfoClient.kt @@ -0,0 +1,23 @@ +package dnd11th.blooming.client.weather + +import dnd11th.blooming.client.dto.WeatherItems +import org.springframework.cloud.openfeign.FeignClient +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestParam + +@FeignClient( + name = "WeatherInfoClient", + url = "http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst", +) +interface WeatherInfoClient{ + + @GetMapping("/") + fun getWeatherInfo(@RequestParam serviceKey: String, + @RequestParam numberOfRows: Int, + @RequestParam pageNo: Int, + @RequestParam dataType: String = "JSON", + @RequestParam base_date: String, + @RequestParam base_time: String, + @RequestParam nx: Int, + @RequestParam ny: Int) : WeatherItems +} From 17757df1d45ef63f6f5ac87ea5710c3e9899dfea Mon Sep 17 00:00:00 2001 From: stophwan Date: Wed, 7 Aug 2024 22:06:33 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20User=20nx,=20ny=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/dnd11th/blooming/domain/entity/user/User.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/kotlin/dnd11th/blooming/domain/entity/user/User.kt b/src/main/kotlin/dnd11th/blooming/domain/entity/user/User.kt index 8989743e..31ab09e9 100644 --- a/src/main/kotlin/dnd11th/blooming/domain/entity/user/User.kt +++ b/src/main/kotlin/dnd11th/blooming/domain/entity/user/User.kt @@ -20,6 +20,10 @@ class User( val nickname: String = nickname + val nx: Int = 0 + + val ny: Int = 0 + companion object { fun create(claims: UserClaims): User { return User(claims.email, claims.nickname) From 999981e088d86edf93a7b680106421dc252eaa87 Mon Sep 17 00:00:00 2001 From: stophwan Date: Sun, 11 Aug 2024 13:29:28 +0900 Subject: [PATCH 3/9] =?UTF-8?q?refactor:=20Open=20API=20client,=20response?= =?UTF-8?q?=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blooming/client/dto/WeatherItem.kt | 24 ---------- .../blooming/client/dto/WeatherItems.kt | 5 -- .../blooming/client/dto/WeatherResponse.kt | 48 +++++++++++++++++++ .../client/weather/WeatherInfoClient.kt | 20 +++++--- .../common/exception/ClientCallException.kt | 4 ++ .../blooming/common/exception/ErrorType.kt | 8 +++- 6 files changed, 72 insertions(+), 37 deletions(-) delete mode 100644 src/main/kotlin/dnd11th/blooming/client/dto/WeatherItem.kt delete mode 100644 src/main/kotlin/dnd11th/blooming/client/dto/WeatherItems.kt create mode 100644 src/main/kotlin/dnd11th/blooming/client/dto/WeatherResponse.kt create mode 100644 src/main/kotlin/dnd11th/blooming/common/exception/ClientCallException.kt diff --git a/src/main/kotlin/dnd11th/blooming/client/dto/WeatherItem.kt b/src/main/kotlin/dnd11th/blooming/client/dto/WeatherItem.kt deleted file mode 100644 index b630b233..00000000 --- a/src/main/kotlin/dnd11th/blooming/client/dto/WeatherItem.kt +++ /dev/null @@ -1,24 +0,0 @@ -package dnd11th.blooming.client.dto - -import java.time.LocalDate - -data class WeatherItem( - val baseDate: LocalDate, - val baseTime: String, - val category: String, - val fcstDate: LocalDate, - val fcstTime: Int, - val fcstValue: Int, - val nx: Int, - val ny: Int -) -/** -"baseDate": "20240807", -"baseTime": "0200", -"category": "REH", -"fcstDate": "20240807", -"fcstTime": "1000", -"fcstValue": "80", -"nx": 55, -"ny": 127 - **/ diff --git a/src/main/kotlin/dnd11th/blooming/client/dto/WeatherItems.kt b/src/main/kotlin/dnd11th/blooming/client/dto/WeatherItems.kt deleted file mode 100644 index 6dc8c1c8..00000000 --- a/src/main/kotlin/dnd11th/blooming/client/dto/WeatherItems.kt +++ /dev/null @@ -1,5 +0,0 @@ -package dnd11th.blooming.client.dto - -data class WeatherItems ( - val items : List -) diff --git a/src/main/kotlin/dnd11th/blooming/client/dto/WeatherResponse.kt b/src/main/kotlin/dnd11th/blooming/client/dto/WeatherResponse.kt new file mode 100644 index 00000000..bab13531 --- /dev/null +++ b/src/main/kotlin/dnd11th/blooming/client/dto/WeatherResponse.kt @@ -0,0 +1,48 @@ +package dnd11th.blooming.client.dto + +import dnd11th.blooming.common.exception.ClientCallException +import dnd11th.blooming.common.exception.ErrorType + +data class WeatherResponse( + val response: ResponseData +) { + fun toWeatherItems(): List { + validate() + return response.body?.items?.item?:emptyList() + } + + private fun validate() { + if(response.header.resultCode != "00") { + throw ClientCallException(ErrorType.OPEN_API_CALL_EXCEPTION) + } + } +} + +data class ResponseData( + val header: HeaderData, + val body: BodyData? +) + +data class HeaderData( + val resultCode: String, + val resultMsg: String +) + +data class BodyData( + val items: Items +) + +data class Items( + val item: List +) + +data class WeatherItem( + val baseDate: String, + val baseTime: String, + val category: String, + val fcstDate: String, + val fcstTime: String, + val fcstValue: String, + val nx: Int, + val ny: Int +) diff --git a/src/main/kotlin/dnd11th/blooming/client/weather/WeatherInfoClient.kt b/src/main/kotlin/dnd11th/blooming/client/weather/WeatherInfoClient.kt index 0b4a1e6f..36a3e39c 100644 --- a/src/main/kotlin/dnd11th/blooming/client/weather/WeatherInfoClient.kt +++ b/src/main/kotlin/dnd11th/blooming/client/weather/WeatherInfoClient.kt @@ -1,6 +1,6 @@ package dnd11th.blooming.client.weather -import dnd11th.blooming.client.dto.WeatherItems +import dnd11th.blooming.client.dto.WeatherResponse import org.springframework.cloud.openfeign.FeignClient import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestParam @@ -10,14 +10,20 @@ import org.springframework.web.bind.annotation.RequestParam url = "http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst", ) interface WeatherInfoClient{ + companion object { + const val FIXED_PAGE_NUMBER = 1 + const val FIXED_NUMBER_OF_ROWS = 288 + const val FIXED_DATA_TYPE = "JSON" + const val FIXED_BASE_TIME = "0200" + } - @GetMapping("/") + @GetMapping fun getWeatherInfo(@RequestParam serviceKey: String, - @RequestParam numberOfRows: Int, - @RequestParam pageNo: Int, - @RequestParam dataType: String = "JSON", + @RequestParam pageNo: Int = FIXED_PAGE_NUMBER, + @RequestParam numOfRows: Int = FIXED_NUMBER_OF_ROWS, + @RequestParam dataType: String = FIXED_DATA_TYPE, @RequestParam base_date: String, - @RequestParam base_time: String, + @RequestParam base_time: String = FIXED_BASE_TIME, @RequestParam nx: Int, - @RequestParam ny: Int) : WeatherItems + @RequestParam ny: Int) : WeatherResponse } diff --git a/src/main/kotlin/dnd11th/blooming/common/exception/ClientCallException.kt b/src/main/kotlin/dnd11th/blooming/common/exception/ClientCallException.kt new file mode 100644 index 00000000..021a985b --- /dev/null +++ b/src/main/kotlin/dnd11th/blooming/common/exception/ClientCallException.kt @@ -0,0 +1,4 @@ +package dnd11th.blooming.common.exception + +class ClientCallException(errorType: ErrorType) : MyException(errorType) { +} diff --git a/src/main/kotlin/dnd11th/blooming/common/exception/ErrorType.kt b/src/main/kotlin/dnd11th/blooming/common/exception/ErrorType.kt index 95394aef..74b79144 100644 --- a/src/main/kotlin/dnd11th/blooming/common/exception/ErrorType.kt +++ b/src/main/kotlin/dnd11th/blooming/common/exception/ErrorType.kt @@ -8,8 +8,14 @@ enum class ErrorType(val status: HttpStatus, val message: String, val logLevel: NOT_FOUND_MYPLANT_ID(HttpStatus.NOT_FOUND, "존재하지 않는 내 식물입니다.", LogLevel.DEBUG), NOT_FOUND_LOCATION_ID(HttpStatus.NOT_FOUND, "존재하지 않는 위치입니다.", LogLevel.DEBUG), - // User + // Auth INVALID_JWT_TOKEN(HttpStatus.UNAUTHORIZED, "유효하지 않은 토큰입니다", LogLevel.DEBUG), INVALID_ID_TOKEN(HttpStatus.UNAUTHORIZED, "유효하지 않은 ID TOKEN입니다.", LogLevel.DEBUG), INVALID_OAUTH_PROVIDER(HttpStatus.BAD_REQUEST, "지원하지 않는 provider입니다", LogLevel.DEBUG), + + //User + USER_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않은 사용자입니다.", LogLevel.DEBUG), + + //OpenAPI + OPEN_API_CALL_EXCEPTION(HttpStatus.BAD_REQUEST, "OpenAPI 호출에 실패했습니다", LogLevel.WARN) } From 85f8352cd4c9eec3a509954f019d6cf01bafb221 Mon Sep 17 00:00:00 2001 From: stophwan Date: Sun, 11 Aug 2024 13:29:57 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20WeatherMessage=20Enum=20class=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blooming/api/service/weather/WeatherMessage.kt | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherMessage.kt diff --git a/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherMessage.kt b/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherMessage.kt new file mode 100644 index 00000000..a78b2291 --- /dev/null +++ b/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherMessage.kt @@ -0,0 +1,8 @@ +package dnd11th.blooming.api.service.weather + +enum class WeatherMessage(val title: String, val message: List) { + HUMIDITY("과습주의보", mutableListOf("과습이에요", "과습입니다.")), + DRY("건조주의보", mutableListOf("건조에요", "건조입니다")), + COLD("한파주의보", mutableListOf("한파입니다", "한파에요")), + HOT("더위주의보", mutableListOf("덥습니다", "더워요")), +} From 82175b794ef0db9f5c91341d67b512d0e05ef8f2 Mon Sep 17 00:00:00 2001 From: stophwan Date: Sun, 11 Aug 2024 13:30:58 +0900 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20=EB=8B=B9=EC=9D=BC=20=EB=82=A0?= =?UTF-8?q?=EC=94=A8=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EB=B0=98=ED=99=98=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../weather/WeatherMessageController.kt | 23 ++++ .../api/dto/weather/WeatherMessageResponse.kt | 19 ++++ .../blooming/api/service/WeatherService.kt | 23 ---- .../api/service/weather/WeatherService.kt | 105 ++++++++++++++++++ src/main/resources/application.yml | 3 + 5 files changed, 150 insertions(+), 23 deletions(-) create mode 100644 src/main/kotlin/dnd11th/blooming/api/controller/weather/WeatherMessageController.kt create mode 100644 src/main/kotlin/dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt delete mode 100644 src/main/kotlin/dnd11th/blooming/api/service/WeatherService.kt create mode 100644 src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt diff --git a/src/main/kotlin/dnd11th/blooming/api/controller/weather/WeatherMessageController.kt b/src/main/kotlin/dnd11th/blooming/api/controller/weather/WeatherMessageController.kt new file mode 100644 index 00000000..128c4312 --- /dev/null +++ b/src/main/kotlin/dnd11th/blooming/api/controller/weather/WeatherMessageController.kt @@ -0,0 +1,23 @@ +package dnd11th.blooming.api.controller.weather + +import dnd11th.blooming.api.dto.weather.WeatherMessageResponse +import dnd11th.blooming.api.service.weather.WeatherMessage +import dnd11th.blooming.api.service.weather.WeatherService +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController +import java.time.LocalDateTime + +@RestController +@RequestMapping("/api/v1/weather-message") +class WeatherMessageController( + private val weatherService: WeatherService +) { + + @GetMapping + fun getWeatherMessage() : List { + val weatherMessages: List = + weatherService.createPlantMessageByWeather(LocalDateTime.now()) + return weatherMessages.map { weatherMessage -> WeatherMessageResponse.from(weatherMessage) } + } +} diff --git a/src/main/kotlin/dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt b/src/main/kotlin/dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt new file mode 100644 index 00000000..d065198c --- /dev/null +++ b/src/main/kotlin/dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt @@ -0,0 +1,19 @@ +package dnd11th.blooming.api.dto.weather + +import dnd11th.blooming.api.service.weather.WeatherMessage + +data class WeatherMessageResponse( + val status: String, + val title: String, + val message: List +) { + companion object { + fun from(weatherMessages: WeatherMessage) : WeatherMessageResponse{ + return WeatherMessageResponse( + status = weatherMessages.name, + title = weatherMessages.title, + message = weatherMessages.message + ) + } + } +} diff --git a/src/main/kotlin/dnd11th/blooming/api/service/WeatherService.kt b/src/main/kotlin/dnd11th/blooming/api/service/WeatherService.kt deleted file mode 100644 index 5282345c..00000000 --- a/src/main/kotlin/dnd11th/blooming/api/service/WeatherService.kt +++ /dev/null @@ -1,23 +0,0 @@ -package dnd11th.blooming.api.service - -import dnd11th.blooming.client.dto.WeatherItems -import dnd11th.blooming.client.weather.WeatherInfoClient -import dnd11th.blooming.domain.repository.user.UserRepository -import org.springframework.stereotype.Service -import org.springframework.transaction.annotation.Transactional - -@Service -@Transactional(readOnly = true) -class WeatherService( - private val weatherInfoClient: WeatherInfoClient, - private val userRepository: UserRepository -) { - - fun createPlantMessageByWeather() { - var nx: Int = 55 - var ny: Int = 127 - //TODO 어느 시간대 어느 페이지 호추 할 것인지 DSL - val weatherItems: WeatherItems = weatherInfoClient.getWeatherInfo() - //TODO ITEM들을 MESSAGE로 변환하는 DSL - } -} diff --git a/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt b/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt new file mode 100644 index 00000000..47f95695 --- /dev/null +++ b/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt @@ -0,0 +1,105 @@ +package dnd11th.blooming.api.service.weather + +import dnd11th.blooming.client.dto.WeatherItem +import dnd11th.blooming.client.weather.WeatherInfoClient +import dnd11th.blooming.common.exception.ErrorType +import dnd11th.blooming.common.exception.NotFoundException +import dnd11th.blooming.domain.entity.user.User +import dnd11th.blooming.domain.repository.user.UserRepository +import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.format.DateTimeFormatter + +@Service +@Transactional(readOnly = true) +class WeatherService( + @Value("\${weather.serviceKey}") + private val serviceKey: String, + private val weatherInfoClient: WeatherInfoClient, + private val userRepository: UserRepository +) { + + companion object { + private const val HUMIDITY_KEY = "REH" + private const val TEMPERATURE_KEY = "TMP" + private const val MAX_HUMIDITY = 100 + private const val MIN_HUMIDITY = 0 + private const val MAX_TEMPERATURE = 40 + private const val MIN_TEMPERATURE = -20 + private const val HIGH_HUMIDITY_THRESHOLD = 80 + private const val LOW_HUMIDITY_THRESHOLD = 20 + private const val LOW_TEMPERATURE_THRESHOLD = 5 + private const val HIGH_TEMPERATURE_THRESHOLD = 30 + } + + fun createPlantMessageByWeather(now: LocalDateTime) : List { + val user: User = userRepository.findById(1L).orElseThrow { throw NotFoundException(ErrorType.USER_NOT_FOUND) } + + val weatherItems: List = weatherInfoClient.getWeatherInfo( + serviceKey = serviceKey, + base_date = getBaseDate(now), + nx = user.nx, + ny = user.ny + ).toWeatherItems() + + return determineWeatherMessages(weatherItems) + } + + /** + * 과습 -> 그날 습도가 80 이상 넘어가는 날 있으면 HUMIDITY + * 건조 -> 그날 습도가 20 이하 내려가는 시간 있으면 DRY + * 한파 -> 최저 온도가 5도 이하로 내려가면 COLD + * 더위 -> 최고 온도가 30도 이상 올라가는 날 있으면 HOT + */ + private fun determineWeatherMessages(items: List): List { + var maxHumidity = MIN_HUMIDITY + var minHumidity = MAX_HUMIDITY + var maxTemperature = MIN_TEMPERATURE + var minTemperature = MAX_TEMPERATURE + + items.forEach { item -> + when (item.category) { + HUMIDITY_KEY -> { + val humidity = item.fcstValue.toInt() + maxHumidity = maxOf(maxHumidity, humidity) + minHumidity = minOf(minHumidity, humidity) + } + TEMPERATURE_KEY -> { + val temperature = item.fcstValue.toInt() + maxTemperature = maxOf(maxTemperature, temperature) + minTemperature = minOf(minTemperature, temperature) + } + } + } + + return mutableListOf().apply { + if (maxHumidity >= HIGH_HUMIDITY_THRESHOLD) add(WeatherMessage.HUMIDITY) + if (minHumidity <= LOW_HUMIDITY_THRESHOLD) add(WeatherMessage.DRY) + if (minTemperature <= LOW_TEMPERATURE_THRESHOLD) add(WeatherMessage.COLD) + if (maxTemperature >= HIGH_TEMPERATURE_THRESHOLD) add(WeatherMessage.HOT) + } + } + + /** + * 현재 시간이 2시 10분을 지났다면, 현재 날짜를 반환합니다. + * 그렇지 않다면, 어제 날짜를 반환합니다. + */ + private fun getBaseDate(now: LocalDateTime) : String { + val baseTime = LocalTime.of(2, 20) + return if (now.toLocalTime().isAfter(baseTime)) { + formatDate(now.toLocalDate()) + } else { + formatDate(now.toLocalDate().minusDays(1)) + } + } + + private fun formatDate(date: LocalDate): String{ + val formatter = DateTimeFormatter.ofPattern("yyyyMMdd") + return date.format(formatter) + } + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index cbde8a76..49aa58c9 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -30,3 +30,6 @@ auth: iss: https://kauth.kakao.com aud: ${KAKAO_CLIENT_ID} nonce: coffeecoffeecoffeecoffeecoffeecoffeecoffeevcoffeecoffeecoffeecoffeecoffeecoffee + +weather: + serviceKey: ${OPEN_API_SERVICE_KEY} From e89dd0161602f8ace1d3cddf2253a748318ecde2 Mon Sep 17 00:00:00 2001 From: stophwan Date: Sun, 11 Aug 2024 14:16:41 +0900 Subject: [PATCH 6/9] style: ktlint formant --- .../weather/WeatherMessageController.kt | 5 ++-- .../api/dto/weather/WeatherMessageResponse.kt | 6 ++--- .../user/oauth/KakaoIdTokenResolver.kt | 2 +- .../api/service/weather/WeatherService.kt | 23 +++++++++---------- .../blooming/client/dto/WeatherResponse.kt | 16 ++++++------- .../client/weather/WeatherInfoClient.kt | 20 ++++++++-------- .../common/exception/ClientCallException.kt | 3 +-- .../blooming/common/exception/ErrorType.kt | 6 ++--- 8 files changed, 40 insertions(+), 41 deletions(-) diff --git a/src/main/kotlin/dnd11th/blooming/api/controller/weather/WeatherMessageController.kt b/src/main/kotlin/dnd11th/blooming/api/controller/weather/WeatherMessageController.kt index 128c4312..eb8202b8 100644 --- a/src/main/kotlin/dnd11th/blooming/api/controller/weather/WeatherMessageController.kt +++ b/src/main/kotlin/dnd11th/blooming/api/controller/weather/WeatherMessageController.kt @@ -11,11 +11,10 @@ import java.time.LocalDateTime @RestController @RequestMapping("/api/v1/weather-message") class WeatherMessageController( - private val weatherService: WeatherService + private val weatherService: WeatherService, ) { - @GetMapping - fun getWeatherMessage() : List { + fun getWeatherMessage(): List { val weatherMessages: List = weatherService.createPlantMessageByWeather(LocalDateTime.now()) return weatherMessages.map { weatherMessage -> WeatherMessageResponse.from(weatherMessage) } diff --git a/src/main/kotlin/dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt b/src/main/kotlin/dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt index d065198c..40e933cf 100644 --- a/src/main/kotlin/dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt +++ b/src/main/kotlin/dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt @@ -5,14 +5,14 @@ import dnd11th.blooming.api.service.weather.WeatherMessage data class WeatherMessageResponse( val status: String, val title: String, - val message: List + val message: List, ) { companion object { - fun from(weatherMessages: WeatherMessage) : WeatherMessageResponse{ + fun from(weatherMessages: WeatherMessage): WeatherMessageResponse { return WeatherMessageResponse( status = weatherMessages.name, title = weatherMessages.title, - message = weatherMessages.message + message = weatherMessages.message, ) } } diff --git a/src/main/kotlin/dnd11th/blooming/api/service/user/oauth/KakaoIdTokenResolver.kt b/src/main/kotlin/dnd11th/blooming/api/service/user/oauth/KakaoIdTokenResolver.kt index 3044c6a8..f332ee79 100644 --- a/src/main/kotlin/dnd11th/blooming/api/service/user/oauth/KakaoIdTokenResolver.kt +++ b/src/main/kotlin/dnd11th/blooming/api/service/user/oauth/KakaoIdTokenResolver.kt @@ -2,8 +2,8 @@ package dnd11th.blooming.api.service.user.oauth import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.readValue -import dnd11th.blooming.client.kakao.KakaoOauthClient import dnd11th.blooming.client.dto.OidcPublicKeys +import dnd11th.blooming.client.kakao.KakaoOauthClient import dnd11th.blooming.common.exception.ErrorType import dnd11th.blooming.common.exception.UnAuthorizedException import dnd11th.blooming.domain.entity.user.OidcUser diff --git a/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt b/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt index 47f95695..6a0256fc 100644 --- a/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt +++ b/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt @@ -20,9 +20,8 @@ class WeatherService( @Value("\${weather.serviceKey}") private val serviceKey: String, private val weatherInfoClient: WeatherInfoClient, - private val userRepository: UserRepository + private val userRepository: UserRepository, ) { - companion object { private const val HUMIDITY_KEY = "REH" private const val TEMPERATURE_KEY = "TMP" @@ -36,15 +35,16 @@ class WeatherService( private const val HIGH_TEMPERATURE_THRESHOLD = 30 } - fun createPlantMessageByWeather(now: LocalDateTime) : List { + fun createPlantMessageByWeather(now: LocalDateTime): List { val user: User = userRepository.findById(1L).orElseThrow { throw NotFoundException(ErrorType.USER_NOT_FOUND) } - val weatherItems: List = weatherInfoClient.getWeatherInfo( - serviceKey = serviceKey, - base_date = getBaseDate(now), - nx = user.nx, - ny = user.ny - ).toWeatherItems() + val weatherItems: List = + weatherInfoClient.getWeatherInfo( + serviceKey = serviceKey, + base_date = getBaseDate(now), + nx = user.nx, + ny = user.ny, + ).toWeatherItems() return determineWeatherMessages(weatherItems) } @@ -88,7 +88,7 @@ class WeatherService( * 현재 시간이 2시 10분을 지났다면, 현재 날짜를 반환합니다. * 그렇지 않다면, 어제 날짜를 반환합니다. */ - private fun getBaseDate(now: LocalDateTime) : String { + private fun getBaseDate(now: LocalDateTime): String { val baseTime = LocalTime.of(2, 20) return if (now.toLocalTime().isAfter(baseTime)) { formatDate(now.toLocalDate()) @@ -97,9 +97,8 @@ class WeatherService( } } - private fun formatDate(date: LocalDate): String{ + private fun formatDate(date: LocalDate): String { val formatter = DateTimeFormatter.ofPattern("yyyyMMdd") return date.format(formatter) } - } diff --git a/src/main/kotlin/dnd11th/blooming/client/dto/WeatherResponse.kt b/src/main/kotlin/dnd11th/blooming/client/dto/WeatherResponse.kt index bab13531..5b8b2c86 100644 --- a/src/main/kotlin/dnd11th/blooming/client/dto/WeatherResponse.kt +++ b/src/main/kotlin/dnd11th/blooming/client/dto/WeatherResponse.kt @@ -4,15 +4,15 @@ import dnd11th.blooming.common.exception.ClientCallException import dnd11th.blooming.common.exception.ErrorType data class WeatherResponse( - val response: ResponseData + val response: ResponseData, ) { fun toWeatherItems(): List { validate() - return response.body?.items?.item?:emptyList() + return response.body?.items?.item ?: emptyList() } private fun validate() { - if(response.header.resultCode != "00") { + if (response.header.resultCode != "00") { throw ClientCallException(ErrorType.OPEN_API_CALL_EXCEPTION) } } @@ -20,20 +20,20 @@ data class WeatherResponse( data class ResponseData( val header: HeaderData, - val body: BodyData? + val body: BodyData?, ) data class HeaderData( val resultCode: String, - val resultMsg: String + val resultMsg: String, ) data class BodyData( - val items: Items + val items: Items, ) data class Items( - val item: List + val item: List, ) data class WeatherItem( @@ -44,5 +44,5 @@ data class WeatherItem( val fcstTime: String, val fcstValue: String, val nx: Int, - val ny: Int + val ny: Int, ) diff --git a/src/main/kotlin/dnd11th/blooming/client/weather/WeatherInfoClient.kt b/src/main/kotlin/dnd11th/blooming/client/weather/WeatherInfoClient.kt index 36a3e39c..c17846d6 100644 --- a/src/main/kotlin/dnd11th/blooming/client/weather/WeatherInfoClient.kt +++ b/src/main/kotlin/dnd11th/blooming/client/weather/WeatherInfoClient.kt @@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.RequestParam name = "WeatherInfoClient", url = "http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst", ) -interface WeatherInfoClient{ +interface WeatherInfoClient { companion object { const val FIXED_PAGE_NUMBER = 1 const val FIXED_NUMBER_OF_ROWS = 288 @@ -18,12 +18,14 @@ interface WeatherInfoClient{ } @GetMapping - fun getWeatherInfo(@RequestParam serviceKey: String, - @RequestParam pageNo: Int = FIXED_PAGE_NUMBER, - @RequestParam numOfRows: Int = FIXED_NUMBER_OF_ROWS, - @RequestParam dataType: String = FIXED_DATA_TYPE, - @RequestParam base_date: String, - @RequestParam base_time: String = FIXED_BASE_TIME, - @RequestParam nx: Int, - @RequestParam ny: Int) : WeatherResponse + fun getWeatherInfo( + @RequestParam serviceKey: String, + @RequestParam pageNo: Int = FIXED_PAGE_NUMBER, + @RequestParam numOfRows: Int = FIXED_NUMBER_OF_ROWS, + @RequestParam dataType: String = FIXED_DATA_TYPE, + @RequestParam base_date: String, + @RequestParam base_time: String = FIXED_BASE_TIME, + @RequestParam nx: Int, + @RequestParam ny: Int, + ): WeatherResponse } diff --git a/src/main/kotlin/dnd11th/blooming/common/exception/ClientCallException.kt b/src/main/kotlin/dnd11th/blooming/common/exception/ClientCallException.kt index 021a985b..bf2d68cb 100644 --- a/src/main/kotlin/dnd11th/blooming/common/exception/ClientCallException.kt +++ b/src/main/kotlin/dnd11th/blooming/common/exception/ClientCallException.kt @@ -1,4 +1,3 @@ package dnd11th.blooming.common.exception -class ClientCallException(errorType: ErrorType) : MyException(errorType) { -} +class ClientCallException(errorType: ErrorType) : MyException(errorType) diff --git a/src/main/kotlin/dnd11th/blooming/common/exception/ErrorType.kt b/src/main/kotlin/dnd11th/blooming/common/exception/ErrorType.kt index 74b79144..b965f3ba 100644 --- a/src/main/kotlin/dnd11th/blooming/common/exception/ErrorType.kt +++ b/src/main/kotlin/dnd11th/blooming/common/exception/ErrorType.kt @@ -13,9 +13,9 @@ enum class ErrorType(val status: HttpStatus, val message: String, val logLevel: INVALID_ID_TOKEN(HttpStatus.UNAUTHORIZED, "유효하지 않은 ID TOKEN입니다.", LogLevel.DEBUG), INVALID_OAUTH_PROVIDER(HttpStatus.BAD_REQUEST, "지원하지 않는 provider입니다", LogLevel.DEBUG), - //User + // User USER_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않은 사용자입니다.", LogLevel.DEBUG), - //OpenAPI - OPEN_API_CALL_EXCEPTION(HttpStatus.BAD_REQUEST, "OpenAPI 호출에 실패했습니다", LogLevel.WARN) + // OpenAPI + OPEN_API_CALL_EXCEPTION(HttpStatus.BAD_REQUEST, "OpenAPI 호출에 실패했습니다", LogLevel.WARN), } From 998fb5b200daae03253b2678bc5ed8312e791ea6 Mon Sep 17 00:00:00 2001 From: stophwan Date: Sun, 11 Aug 2024 14:21:48 +0900 Subject: [PATCH 7/9] =?UTF-8?q?test:=20test.yml=20serviceKey=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt | 2 +- .../dnd11th/blooming/api/service/weather/WeatherService.kt | 2 +- src/test/resources/application-test.yml | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt b/src/main/kotlin/dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt index 40e933cf..b9b5e986 100644 --- a/src/main/kotlin/dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt +++ b/src/main/kotlin/dnd11th/blooming/api/dto/weather/WeatherMessageResponse.kt @@ -8,7 +8,7 @@ data class WeatherMessageResponse( val message: List, ) { companion object { - fun from(weatherMessages: WeatherMessage): WeatherMessageResponse { + fun from(weatherMessages: WeatherMessage): WeatherMessageResponse { return WeatherMessageResponse( status = weatherMessages.name, title = weatherMessages.title, diff --git a/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt b/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt index 6a0256fc..1ef1effa 100644 --- a/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt +++ b/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt @@ -97,7 +97,7 @@ class WeatherService( } } - private fun formatDate(date: LocalDate): String { + private fun formatDate(date: LocalDate): String { val formatter = DateTimeFormatter.ofPattern("yyyyMMdd") return date.format(formatter) } diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index e7bdab24..0cff3dc4 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -16,3 +16,6 @@ spring: properties: hibernate.format_sql: true dialect: org.hibernate.dialect.H2Dialect + +weather: + serviceKey: "serviceKey" From 03006ecc02e374f72e03cf8d5c076ac2e0c68466 Mon Sep 17 00:00:00 2001 From: stophwan Date: Sun, 11 Aug 2024 15:00:08 +0900 Subject: [PATCH 8/9] =?UTF-8?q?refactor:=20WeatherMessage=20message?= =?UTF-8?q?=EB=A5=BC=20mutableList=20->=20List=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blooming/api/service/weather/WeatherMessage.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherMessage.kt b/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherMessage.kt index a78b2291..78af1f20 100644 --- a/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherMessage.kt +++ b/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherMessage.kt @@ -1,8 +1,8 @@ package dnd11th.blooming.api.service.weather enum class WeatherMessage(val title: String, val message: List) { - HUMIDITY("과습주의보", mutableListOf("과습이에요", "과습입니다.")), - DRY("건조주의보", mutableListOf("건조에요", "건조입니다")), - COLD("한파주의보", mutableListOf("한파입니다", "한파에요")), - HOT("더위주의보", mutableListOf("덥습니다", "더워요")), + HUMIDITY("과습주의보", listOf("과습이에요", "과습입니다.")), + DRY("건조주의보", listOf("건조에요", "건조입니다")), + COLD("한파주의보", listOf("한파입니다", "한파에요")), + HOT("더위주의보", listOf("덥습니다", "더워요")), } From 0c00fead95b46ad23ba3ba8fb49e6b721ff62ca0 Mon Sep 17 00:00:00 2001 From: stophwan Date: Sun, 11 Aug 2024 16:20:02 +0900 Subject: [PATCH 9/9] =?UTF-8?q?refactor:=20=EB=82=A0=EC=94=A8=EB=B3=84=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EC=A1=B0=ED=9A=8C=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blooming/api/controller/weather/WeatherMessageController.kt | 2 +- .../dnd11th/blooming/api/service/weather/WeatherService.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/dnd11th/blooming/api/controller/weather/WeatherMessageController.kt b/src/main/kotlin/dnd11th/blooming/api/controller/weather/WeatherMessageController.kt index eb8202b8..ae074660 100644 --- a/src/main/kotlin/dnd11th/blooming/api/controller/weather/WeatherMessageController.kt +++ b/src/main/kotlin/dnd11th/blooming/api/controller/weather/WeatherMessageController.kt @@ -16,7 +16,7 @@ class WeatherMessageController( @GetMapping fun getWeatherMessage(): List { val weatherMessages: List = - weatherService.createPlantMessageByWeather(LocalDateTime.now()) + weatherService.createWeatherMessage(LocalDateTime.now()) return weatherMessages.map { weatherMessage -> WeatherMessageResponse.from(weatherMessage) } } } diff --git a/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt b/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt index 1ef1effa..124ea4da 100644 --- a/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt +++ b/src/main/kotlin/dnd11th/blooming/api/service/weather/WeatherService.kt @@ -35,7 +35,7 @@ class WeatherService( private const val HIGH_TEMPERATURE_THRESHOLD = 30 } - fun createPlantMessageByWeather(now: LocalDateTime): List { + fun createWeatherMessage(now: LocalDateTime): List { val user: User = userRepository.findById(1L).orElseThrow { throw NotFoundException(ErrorType.USER_NOT_FOUND) } val weatherItems: List =