From a23e4bad4308bf3f0cfe88cd96f745408433baee Mon Sep 17 00:00:00 2001 From: thug0bin Date: Sat, 7 Mar 2026 22:49:12 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=95=BD=ED=92=88=EB=B3=84=20=EC=84=A0?= =?UTF-8?q?=ED=98=B8=20=EB=8F=84=EB=A7=A4=EC=83=81=20API=20+=20delivery=5F?= =?UTF-8?q?schedules=20=ED=85=8C=EC=9D=B4=EB=B8=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GET /api/order/drug/{code}/preferred-vendor: 약품별 선호 도매상 조회 - POST /api/order/drugs/preferred-vendors: 일괄 조회 - MSSQL 입고장 데이터 활용 (WH_main, WH_sub) - 최근 주문 도매상 + 최다 주문 도매상 반환 DB: - delivery_schedules 테이블 생성 (orders.db) - 도매상별 주문 마감시간/배송 도착시간 관리 --- backend/order_api.py | 160 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) diff --git a/backend/order_api.py b/backend/order_api.py index 7bbbc61..09f4110 100644 --- a/backend/order_api.py +++ b/backend/order_api.py @@ -1227,3 +1227,163 @@ def api_update_wholesaler_limit(wholesaler_id): 'success': True, 'message': f'{wholesaler_id} 한도 업데이트 완료' }) + + +# ========== 약품별 선호 도매상 API ========== + +def get_drug_preferred_vendor(drug_code: str, period_days: int = 365): + """ + 약품코드 기준 선호 도매상 조회 (MSSQL 입고장 데이터) + """ + import pyodbc + + CONN_STR = ( + 'DRIVER={ODBC Driver 17 for SQL Server};' + 'SERVER=192.168.0.4\\PM2014;' + 'DATABASE=PM_DRUG;' + 'UID=sa;' + 'PWD=tmddls214!%(;' + 'TrustServerCertificate=yes;' + 'Connection Timeout=10' + ) + + try: + conn = pyodbc.connect(CONN_STR, timeout=10) + cursor = conn.cursor() + + # 약품명 조회 + cursor.execute("SELECT GoodsName FROM CD_GOODS WHERE DrugCode = ?", drug_code) + row = cursor.fetchone() + drug_name = row[0] if row else '' + + # 도매상별 입고 통계 + query = """ + SELECT + c.CD_NM_custom AS vendor_name, + c.CD_CD_custom AS vendor_code, + COUNT(*) AS order_count, + SUM(ws.WH_NM_item_a) AS total_qty, + SUM(ws.WH_MY_amount_a) AS total_amount, + AVG(ws.WH_MY_unit_a) AS avg_unit_price, + MAX(wm.WH_DT_appl) AS last_order_date + FROM WH_sub ws + JOIN WH_main wm ON ws.WH_SR_stock = wm.WH_NO_stock + LEFT JOIN PM_BASE.dbo.CD_custom c ON wm.WH_CD_cust_sale = c.CD_CD_custom + WHERE ws.DrugCode = ? + AND wm.WH_DT_appl >= CONVERT(varchar(8), DATEADD(day, ?, GETDATE()), 112) + GROUP BY c.CD_NM_custom, c.CD_CD_custom + ORDER BY COUNT(*) DESC + """ + + cursor.execute(query, (drug_code, -period_days)) + rows = cursor.fetchall() + + if not rows: + conn.close() + return { + 'success': True, + 'drug_code': drug_code, + 'drug_name': drug_name, + 'recent_vendor': None, + 'most_frequent_vendor': None, + 'vendors': [], + 'message': '입고 이력 없음' + } + + vendors = [] + for r in rows: + vendors.append({ + 'vendor_name': r[0] or '알수없음', + 'vendor_code': r[1] or '', + 'order_count': r[2], + 'total_qty': float(r[3] or 0), + 'total_amount': float(r[4] or 0), + 'avg_unit_price': float(r[5] or 0), + 'last_order_date': r[6] + }) + + most_frequent = vendors[0] if vendors else None + + # 최근 주문 도매상 + recent_query = """ + SELECT TOP 1 + c.CD_NM_custom AS vendor_name, + c.CD_CD_custom AS vendor_code, + wm.WH_DT_appl AS order_date, + ws.WH_NM_item_a AS qty, + ws.WH_MY_unit_a AS unit_price + FROM WH_sub ws + JOIN WH_main wm ON ws.WH_SR_stock = wm.WH_NO_stock + LEFT JOIN PM_BASE.dbo.CD_custom c ON wm.WH_CD_cust_sale = c.CD_CD_custom + WHERE ws.DrugCode = ? + ORDER BY wm.WH_DT_appl DESC + """ + cursor.execute(recent_query, drug_code) + recent_row = cursor.fetchone() + + recent_vendor = None + if recent_row: + recent_vendor = { + 'vendor_name': recent_row[0] or '알수없음', + 'vendor_code': recent_row[1] or '', + 'order_date': recent_row[2], + 'qty': float(recent_row[3] or 0), + 'unit_price': float(recent_row[4] or 0) + } + + conn.close() + + return { + 'success': True, + 'drug_code': drug_code, + 'drug_name': drug_name, + 'recent_vendor': recent_vendor, + 'most_frequent_vendor': most_frequent, + 'vendors': vendors + } + + except Exception as e: + return { + 'success': False, + 'error': str(e), + 'drug_code': drug_code + } + + +@order_bp.route('/drug//preferred-vendor', methods=['GET']) +def api_drug_preferred_vendor(drug_code): + """ + 약품별 선호 도매상 조회 API + + GET /api/order/drug/670400830/preferred-vendor + GET /api/order/drug/670400830/preferred-vendor?period=180 + """ + period = request.args.get('period', 365, type=int) + result = get_drug_preferred_vendor(drug_code, period) + return jsonify(result) + + +@order_bp.route('/drugs/preferred-vendors', methods=['POST']) +def api_drugs_preferred_vendors(): + """ + 여러 약품의 선호 도매상 일괄 조회 + + POST /api/order/drugs/preferred-vendors + {"drug_codes": ["670400830", "654301800"], "period": 365} + """ + data = request.get_json() or {} + drug_codes = data.get('drug_codes', []) + period = data.get('period', 365) + + if not drug_codes: + return jsonify({'success': False, 'error': 'drug_codes required'}) + + results = {} + for code in drug_codes: + results[code] = get_drug_preferred_vendor(code, period) + + return jsonify({ + 'success': True, + 'count': len(results), + 'results': results + })