diff --git a/backend/app.py b/backend/app.py index 69689f7..1303209 100644 --- a/backend/app.py +++ b/backend/app.py @@ -6,6 +6,9 @@ Flask 웹 서버 - QR 마일리지 적립 import sys import os +# 현재 디렉토리를 Python path에 추가 (PM2 실행 시 utils 모듈 찾기 위함) +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) + # Windows 콘솔 UTF-8 강제 (한글 깨짐 방지) if sys.platform == 'win32': import io @@ -39,9 +42,18 @@ except ImportError: logging.warning("OpenAI 라이브러리가 설치되지 않았습니다. AI 분석 기능을 사용할 수 없습니다.") # Path setup -sys.path.insert(0, os.path.dirname(__file__)) +BACKEND_DIR = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, BACKEND_DIR) from db.dbsetup import DatabaseManager +# OTC 라벨 프린터 import +try: + from utils.otc_label_printer import generate_preview_image, print_otc_label + OTC_LABEL_AVAILABLE = True +except ImportError as e: + OTC_LABEL_AVAILABLE = False + logging.warning(f"OTC 라벨 프린터 모듈 로드 실패: {e}") + app = Flask(__name__) app.secret_key = 'pharmacy-qr-mileage-secret-key-2026' @@ -4132,6 +4144,29 @@ def api_rx_usage(): 'today': row.today_patients # 오늘 사용한 환자 } for row in patient_rows} + # 조회 기간 내 주문량 조회 (orders.db에서) + import sqlite3 + orders_db_path = os.path.join(os.path.dirname(__file__), 'db', 'orders.db') + orders_conn = sqlite3.connect(orders_db_path) + orders_cur = orders_conn.cursor() + + # 조회 기간 내 성공한 주문량 집계 + orders_cur.execute(''' + SELECT + oi.drug_code, + SUM(oi.order_qty) as ordered_qty, + SUM(oi.total_dose) as ordered_dose + FROM order_items oi + JOIN orders o ON oi.order_id = o.id + WHERE o.order_date >= ? AND o.order_date <= ? + AND o.status IN ('submitted', 'success', 'confirmed') + AND oi.status IN ('success', 'pending') + GROUP BY oi.drug_code + ''', (start_date, end_date)) + + ordered_map = {row[0]: {'qty': row[1] or 0, 'dose': row[2] or 0} for row in orders_cur.fetchall()} + orders_conn.close() + # 전문의약품 품목별 사용량 집계 쿼리 (현재고: IM_total.IM_QT_sale_debit, 위치: CD_item_position.CD_NM_sale) rx_query = text(""" SELECT @@ -4185,6 +4220,13 @@ def api_rx_usage(): # 소수 환자 약품인지 확인 (1년간 3명 이하) patient_info = patient_map.get(drug_code) + # 조회 기간 내 주문량 + order_info = ordered_map.get(drug_code, {'qty': 0, 'dose': 0}) + ordered_dose = order_info['dose'] + + # 잔여 필요량 = 사용량 - 주문량 (음수면 0) + remaining_dose = max(0, dose - ordered_dose) + items.append({ 'drug_code': drug_code, 'product_name': product_name, @@ -4197,9 +4239,11 @@ def api_rx_usage(): 'current_stock': int(row.current_stock or 0), # 현재고 'location': row.location or '', # 약국 내 위치 'thumbnail': None, - 'patient_count': patient_info['count'] if patient_info else None, # 1년간 사용 환자 수 (3명 이하만) - 'patient_names': patient_info['names'] if patient_info else None, # 환자 이름 (3명 이하만) - 'today_patients': patient_info['today'] if patient_info else None # 오늘 사용한 환자 + 'patient_count': patient_info['count'] if patient_info else None, + 'patient_names': patient_info['names'] if patient_info else None, + 'today_patients': patient_info['today'] if patient_info else None, + 'ordered_dose': ordered_dose, # 조회 기간 내 주문량 + 'remaining_dose': remaining_dose # 잔여 필요량 }) total_qty += qty @@ -6332,7 +6376,8 @@ def api_preview_otc_label(): dosage_instruction = data.get('dosage_instruction', '') usage_tip = data.get('usage_tip', '') - from utils.otc_label_printer import generate_preview_image + if not OTC_LABEL_AVAILABLE: + return jsonify({'success': False, 'error': 'OTC 라벨 모듈이 로드되지 않았습니다.'}), 500 preview_url = generate_preview_image(drug_name, effect, dosage_instruction, usage_tip) @@ -6364,7 +6409,8 @@ def api_print_otc_label(): dosage_instruction = data.get('dosage_instruction', '') usage_tip = data.get('usage_tip', '') - from utils.otc_label_printer import print_otc_label + if not OTC_LABEL_AVAILABLE: + return jsonify({'success': False, 'error': 'OTC 라벨 모듈이 로드되지 않았습니다.'}), 500 success = print_otc_label(drug_name, effect, dosage_instruction, usage_tip)