From 33c6cd2d5cf588bad370f317724acc28767affca Mon Sep 17 00:00:00 2001 From: thug0bin Date: Sat, 7 Mar 2026 17:07:25 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=B2=98=EB=B0=A9=EC=95=BD=ED=92=88=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EB=9F=89=20=ED=8E=98=EC=9D=B4=EC=A7=80=20-?= =?UTF-8?q?=20=EC=A3=BC=EB=AC=B8=EB=9F=89=20=EC=A7=80=EC=98=A4=EC=98=81+?= =?UTF-8?q?=EC=88=98=EC=9D=B8=20=ED=95=A9=EC=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GET /api/geoyoung/orders/summary-by-kd 추가 - admin_rx_usage.html: 두 도매상 병렬 조회 후 합산 표시 - 콘솔에 도매상별 주문량 로깅 --- backend/geoyoung_api.py | 100 ++++++++++++++++++++++++++ backend/templates/admin_rx_usage.html | 47 ++++++++++-- 2 files changed, 140 insertions(+), 7 deletions(-) diff --git a/backend/geoyoung_api.py b/backend/geoyoung_api.py index d0dccec..67e84c9 100644 --- a/backend/geoyoung_api.py +++ b/backend/geoyoung_api.py @@ -567,6 +567,106 @@ def api_geoyoung_order_detail(order_num): }), 500 +@geoyoung_bp.route('/orders/summary-by-kd', methods=['GET']) +def api_geoyoung_orders_by_kd(): + """ + 지오영 주문량 KD코드별 집계 API + + GET /api/geoyoung/orders/summary-by-kd?start_date=2026-03-01&end_date=2026-03-07 + + Returns: + { + "success": true, + "order_count": 4, + "by_kd_code": { + "670400830": { + "product_name": "레바미피드정", + "spec": "100T", + "boxes": 2, + "units": 200 + } + }, + "total_products": 15 + } + """ + import re + from datetime import datetime + + today = datetime.now().strftime("%Y-%m-%d") + start_date = request.args.get('start_date', today).strip() + end_date = request.args.get('end_date', today).strip() + + def parse_spec(spec: str) -> int: + """규격에서 수량 추출 (30T → 30, 100C → 100)""" + if not spec: + return 1 + match = re.search(r'(\d+)', spec) + return int(match.group(1)) if match else 1 + + try: + session = get_geo_session() + + # 주문 목록 조회 (items 포함) + orders_result = session.get_order_list(start_date, end_date) + + if not orders_result.get('success'): + return jsonify({ + 'success': False, + 'error': orders_result.get('error', 'ORDERS_FETCH_FAILED'), + 'by_kd_code': {}, + 'order_count': 0 + }) + + orders = orders_result.get('orders', []) + + # KD코드별 집계 + kd_summary = {} + + for order in orders: + # 지오영은 get_order_list에서 items도 같이 반환 + for item in order.get('items', []): + kd_code = item.get('kd_code', '') + if not kd_code: + continue + + product_name = item.get('product_name', '') + spec = item.get('spec', '') + quantity = item.get('quantity', 0) or item.get('order_qty', 0) + per_unit = parse_spec(spec) + total_units = quantity * per_unit + + if kd_code not in kd_summary: + kd_summary[kd_code] = { + 'product_name': product_name, + 'spec': spec, + 'boxes': 0, + 'units': 0 + } + + kd_summary[kd_code]['boxes'] += quantity + kd_summary[kd_code]['units'] += total_units + + logger.info(f"지오영 주문량 집계: {start_date}~{end_date}, {len(orders)}건 주문, {len(kd_summary)}개 품목") + + return jsonify({ + 'success': True, + 'order_count': len(orders), + 'period': {'start': start_date, 'end': end_date}, + 'by_kd_code': kd_summary, + 'total_products': len(kd_summary) + }) + + except Exception as e: + logger.error(f"지오영 주문량 집계 오류: {e}") + return jsonify({ + 'success': False, + 'error': 'API_ERROR', + 'message': str(e), + 'by_kd_code': {}, + 'order_count': 0 + }), 500 + + @geoyoung_bp.route('/order-today', methods=['GET']) def api_geoyoung_order_today(): """ diff --git a/backend/templates/admin_rx_usage.html b/backend/templates/admin_rx_usage.html index 2b1d257..3812d86 100644 --- a/backend/templates/admin_rx_usage.html +++ b/backend/templates/admin_rx_usage.html @@ -894,7 +894,7 @@