Skip to content

Commit

Permalink
Merge pull request #20 from WoongyuChoi/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
WoongyuChoi authored Dec 5, 2024
2 parents 657f121 + 9421dd1 commit 17537c3
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 42 deletions.
4 changes: 2 additions & 2 deletions api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from .external import *
from .external import ExternalAPI

__all__ = [name for name in globals() if not name.startswith("_")]
__all__ = ["ExternalAPI"]
45 changes: 45 additions & 0 deletions api/data_processor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from handler.logger import get_logger

logger = get_logger(__name__)


class DataProcessor:
"""
외부 API에서 받은 데이터를 처리하는 클래스.
"""

@staticmethod
def process_exchange_rate_data(response_data):
if "StatisticSearch" not in response_data:
logger.error(f"ValueError: {str(response_data)}")

raw_rows = response_data.get("StatisticSearch", {}).get("row", [])
if not raw_rows:
return {"content": []}

processed_data = []
for row in raw_rows:
try:
value = float(row.get("DATA_VALUE", "0").replace(",", ""))
except ValueError:
value = 0

processed_data.append(
{
"value": value,
"item_code": row.get("ITEM_CODE1"),
"item_name": row.get("ITEM_NAME1"),
"time": row.get("TIME"),
"unit": (
row.get("UNIT_NAME").strip() if row.get("UNIT_NAME") else None
),
}
)

sorted_data = sorted(
processed_data,
key=lambda x: x["time"] if x["time"] else "",
reverse=False,
)

return {"content": sorted_data}
66 changes: 36 additions & 30 deletions api/external.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from dotenv import load_dotenv

from api.data_processor import DataProcessor
from decorators import default_params
from handler.logger import get_logger
from models import APIParams
Expand All @@ -13,33 +14,38 @@
load_dotenv()


def check_ecos():
try:
response = fetch_data("https://ecos.bok.or.kr/api/", return_json=False)
logger.info(f"Response: {response.status_code} {dict(response.headers)} ")
return response.status_code == 200
except ValueError as e:
logger.warning(f"ECOS API health check failed: {e}")
return False


@default_params
def fetch_exchange_rate(start_date, end_date, item_code=None):
"""
외부 API를 호출하여 주요국 통화의 대원화환율 데이터를 조회합니다.
:param start_date: 검색 시작일자 (YYYYMMDD), 기본값은 지난달의 첫날
:param end_date: 검색 종료일자 (YYYYMMDD), 기본값은 지난달의 마지막날
:param item_code: 통계항목코드1 (기본값: 0000001, 미국 달러)
:return: API 응답 데이터 (JSON)
"""

params = APIParams(
service_name="StatisticSearch",
table_code="731Y001",
start_date=start_date,
end_date=end_date,
item_code=item_code or "0000001",
)

url = generate_statistic_url(params)
return fetch_data(url)
class ExternalAPI:

@staticmethod
def check_ecos():
try:
response = fetch_data("https://ecos.bok.or.kr/api/", return_json=False)
logger.info(f"Response: {response.status_code} {dict(response.headers)} ")
return response.status_code == 200
except ValueError as e:
logger.warning(f"ECOS API health check failed: {e}")
return False

@staticmethod
@default_params
def fetch_exchange_rate(start_date, end_date, item_code=None):
"""
외부 API를 호출하여 주요국 통화의 대원화환율 데이터를 조회합니다.
:param start_date: 검색 시작일자 (YYYYMMDD), 기본값은 지난달의 첫날
:param end_date: 검색 종료일자 (YYYYMMDD), 기본값은 지난달의 마지막날
:param item_code: 통계항목코드1 (기본값: 0000001, 미국 달러)
:return: API 응답 데이터 (JSON)
"""

params = APIParams(
service_name="StatisticSearch",
table_code="731Y001",
start_date=start_date,
end_date=end_date,
item_code=item_code or "0000001",
)

url = generate_statistic_url(params)
response_data = fetch_data(url)

return DataProcessor.process_exchange_rate_data(response_data)
21 changes: 11 additions & 10 deletions api/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
from flask import Flask, jsonify, request
from flask_caching import Cache

from api import check_ecos, fetch_exchange_rate
from api import ExternalAPI
from config import Config
from handler.exception_handler import register_exception_handlers
from handler.logger import get_logger
from utils import get_request_params

app = Flask(__name__)
app.config.from_object(Config)
Expand All @@ -19,32 +20,32 @@

@app.route("/")
def health_check():
app.logger.info("Health check called.")
logger.info("Health check called.")
status = {
"status": "UP",
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"details": {"ecos_api": "UP" if check_ecos() else "DOWN"},
"details": {"ecos_api": "UP" if ExternalAPI.check_ecos() else "DOWN"},
}
return jsonify(status), 200


@app.route("/favicon.<ext>")
def favicon(ext):
app.logger.debug(f"Favicon request received with extension: {ext}")
logger.debug(f"Favicon request received with extension: {ext}")
return "", 204, {"Content-Type": "image/x-icon"}


@app.route("/api/exchange-rate", methods=["GET"])
@cache.cached(query_string=True)
def get_exchange_rate():
start_date = request.args.get("start_date")
end_date = request.args.get("end_date")
item_code = request.args.get("item_code")
params = get_request_params("start_date", "end_date", "item_code")

data = fetch_exchange_rate(
start_date=start_date, end_date=end_date, item_code=item_code
data = ExternalAPI.fetch_exchange_rate(
start_date=params["start_date"],
end_date=params["end_date"],
item_code=params["item_code"],
)
app.logger.info("Exchange rate data fetched successfully.")
logger.info("Exchange rate data fetched successfully.")
return jsonify(data), 200


Expand Down
2 changes: 2 additions & 0 deletions utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from .date_utils import get_first_day_of_last_month, get_last_day_of_last_month
from .fetch_utils import fetch_data, generate_statistic_url
from .request_utils import get_request_params

__all__ = [
"get_first_day_of_last_month",
"get_last_day_of_last_month",
"fetch_data",
"generate_statistic_url",
"get_request_params",
]
14 changes: 14 additions & 0 deletions utils/request_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from flask import request


def get_request_params(*keys, defaults=None):
"""
요청에서 여러 파라미터를 한 번에 추출.
:param keys: 추출할 파라미터 키들
:param defaults: 기본값 딕셔너리 (key-value 쌍)
:return: 추출된 파라미터 딕셔너리
"""
if defaults is None:
defaults = {}

return {key: request.args.get(key, defaults.get(key)) for key in keys}

0 comments on commit 17537c3

Please sign in to comment.