diff --git a/backend/pmr_api.py b/backend/pmr_api.py index 51b410f..fc3e8ec 100644 --- a/backend/pmr_api.py +++ b/backend/pmr_api.py @@ -38,6 +38,21 @@ def get_mssql_connection(database='PM_PRES'): return pyodbc.connect(conn_str, timeout=10) +def warmup_db_connection(): + """앱 시작 시 DB 연결 미리 생성 (첫 요청 속도 개선)""" + try: + conn = get_mssql_connection('PM_PRES') + conn.cursor().execute("SELECT 1") + conn.close() + logging.info("[PMR] DB 연결 warmup 완료") + except Exception as e: + logging.warning(f"[PMR] DB warmup 실패: {e}") + + +# 앱 로드 시 warmup 실행 +warmup_db_connection() + + # ───────────────────────────────────────────────────────────── # 조제관리 페이지 # ───────────────────────────────────────────────────────────── @@ -726,36 +741,69 @@ def get_patient_otc_history(cus_code): conn = get_mssql_connection('PM_PRES') cursor = conn.cursor() - # OTC 거래 목록 조회 (PRESERIAL = 'V' = OTC 판매) + # ✅ 최적화: 한번의 쿼리로 거래 + 품목 모두 조회 (JOIN) cursor.execute(""" SELECT m.SL_NO_order, m.SL_DT_appl, m.InsertTime, m.SL_MY_sale, - m.SL_NM_custom - FROM SALE_MAIN m - WHERE m.SL_CD_custom = ? - AND m.PRESERIAL = 'V' - ORDER BY m.InsertTime DESC - """, (cus_code,)) + m.SL_NM_custom, + s.DrugCode, + g.GoodsName, + s.SL_NM_item, + s.SL_TOTAL_PRICE, + mc.PRINT_TYPE + FROM ( + SELECT TOP (?) * + FROM SALE_MAIN + WHERE SL_CD_custom = ? AND PRESERIAL = 'V' + ORDER BY InsertTime DESC + ) m + LEFT JOIN SALE_SUB s ON m.SL_NO_order = s.SL_NO_order + LEFT JOIN PM_DRUG.dbo.CD_GOODS g ON s.DrugCode = g.DrugCode + LEFT JOIN PM_DRUG.dbo.CD_MC mc ON s.DrugCode = mc.DRUGCODE + ORDER BY m.InsertTime DESC, s.DrugCode + """, (limit, cus_code)) + + # 결과를 order_no별로 그룹핑 + orders_dict = {} + all_drug_codes = [] - # 먼저 거래 목록 수집 - orders = [] for row in cursor.fetchall(): - orders.append({ - 'order_no': row.SL_NO_order, - 'date': row.SL_DT_appl, - 'datetime': row.InsertTime.strftime('%Y-%m-%d %H:%M') if row.InsertTime else '', - 'amount': int(row.SL_MY_sale or 0), - 'customer_name': row.SL_NM_custom or '' - }) + order_no = row.SL_NO_order + + if order_no not in orders_dict: + orders_dict[order_no] = { + 'order_no': order_no, + 'date': row.SL_DT_appl, + 'datetime': row.InsertTime.strftime('%Y-%m-%d %H:%M') if row.InsertTime else '', + 'amount': int(row.SL_MY_sale or 0), + 'customer_name': row.SL_NM_custom or '', + 'items': [] + } + + # 품목 추가 (DrugCode가 있는 경우만) + if row.DrugCode: + drug_code = row.DrugCode + all_drug_codes.append(drug_code) + orders_dict[order_no]['items'].append({ + 'drug_code': drug_code, + 'name': row.GoodsName or drug_code, + 'quantity': int(row.SL_NM_item or 0), + 'price': int(row.SL_TOTAL_PRICE or 0), + 'category': row.PRINT_TYPE or '', + 'image': None + }) - # 최근 limit개만 - orders = orders[:limit] + conn.close() - if not orders: - conn.close() + # dict → list 변환 + purchases = list(orders_dict.values()) + for p in purchases: + p['item_count'] = len(p['items']) + + if not purchases: return jsonify({ 'success': True, 'cus_code': cus_code, @@ -763,46 +811,6 @@ def get_patient_otc_history(cus_code): 'purchases': [] }) - # 각 거래의 품목 조회 - purchases = [] - all_drug_codes = [] - - for order in orders: - cursor.execute(""" - SELECT - s.DrugCode, - g.GoodsName, - s.SL_NM_item, - s.SL_TOTAL_PRICE, - mc.PRINT_TYPE - FROM SALE_SUB s - LEFT JOIN PM_DRUG.dbo.CD_GOODS g ON s.DrugCode = g.DrugCode - LEFT JOIN PM_DRUG.dbo.CD_MC mc ON s.DrugCode = mc.DRUGCODE - WHERE s.SL_NO_order = ? - ORDER BY s.DrugCode - """, (order['order_no'],)) - - items = [] - for item_row in cursor.fetchall(): - drug_code = item_row.DrugCode or '' - all_drug_codes.append(drug_code) - items.append({ - 'drug_code': drug_code, - 'name': item_row.GoodsName or drug_code, - 'quantity': int(item_row.SL_NM_item or 0), - 'price': int(item_row.SL_TOTAL_PRICE or 0), - 'category': item_row.PRINT_TYPE or '', - 'image': None - }) - - purchases.append({ - **order, - 'items': items, - 'item_count': len(items) - }) - - conn.close() - # 제품 이미지 조회 (product_images.db) image_map = {} try: diff --git a/backend/templates/pmr.html b/backend/templates/pmr.html index 1202763..3413106 100644 --- a/backend/templates/pmr.html +++ b/backend/templates/pmr.html @@ -1880,10 +1880,15 @@ if (data.success && data.count > 0) { otcData = data; - // OTC 뱃지 추가 (질병 뱃지 앞에) + // OTC 뱃지 추가 (맨 앞에) const rxInfo = document.getElementById('rxInfo'); - const otcBadge = `💊 OTC ${data.count}건`; - rxInfo.innerHTML = otcBadge + rxInfo.innerHTML; + if (rxInfo && !rxInfo.querySelector('.otc-badge')) { + const otcBadge = document.createElement('span'); + otcBadge.className = 'otc-badge'; + otcBadge.onclick = showOtcModal; + otcBadge.innerHTML = `💊 OTC ${data.count}건`; + rxInfo.insertBefore(otcBadge, rxInfo.firstChild); + } } else { otcData = null; }