# pmr_api.py - 조제관리(PMR) Blueprint API # PharmaIT3000 MSSQL 연동 (192.168.0.4) from flask import Blueprint, jsonify, request, render_template import pyodbc from datetime import datetime, date import logging pmr_bp = Blueprint('pmr', __name__, url_prefix='/pmr') # ───────────────────────────────────────────────────────────── # MSSQL 연결 설정 (PharmaIT3000 - 192.168.0.4) # ───────────────────────────────────────────────────────────── MSSQL_CONFIG = { 'server': '192.168.0.4\\PM2014', 'username': 'sa', 'password': 'tmddls214!%(', 'driver': 'ODBC Driver 17 for SQL Server' } def get_mssql_connection(database='PM_PRES'): """MSSQL 연결 획득""" conn_str = ( f"DRIVER={{{MSSQL_CONFIG['driver']}}};" f"SERVER={MSSQL_CONFIG['server']};" f"DATABASE={database};" f"UID={MSSQL_CONFIG['username']};" f"PWD={MSSQL_CONFIG['password']};" "TrustServerCertificate=yes;" "Connection Timeout=10" ) return pyodbc.connect(conn_str, timeout=10) # ───────────────────────────────────────────────────────────── # 조제관리 페이지 # ───────────────────────────────────────────────────────────── @pmr_bp.route('/') def pmr_index(): """조제관리 메인 페이지""" return render_template('pmr.html') # ───────────────────────────────────────────────────────────── # API: 날짜별 처방전 목록 # ───────────────────────────────────────────────────────────── @pmr_bp.route('/api/prescriptions', methods=['GET']) def get_prescriptions_by_date(): """ 날짜별 처방전 목록 조회 Query Params: - date: YYYY-MM-DD (기본값: 오늘) """ try: date_str = request.args.get('date', date.today().strftime('%Y-%m-%d')) # YYYYMMDD 형식으로 변환 date_yyyymmdd = date_str.replace('-', '') conn = get_mssql_connection('PM_PRES') cursor = conn.cursor() cursor.execute(""" SELECT PreSerial, Day_Serial, PassDay, Paname, PaNum, CusCode, InsName, Drname, PresTime, PreGubun, PRICE_T, PRICE_P, PRICE_C FROM PS_MAIN WHERE PassDay = ? ORDER BY Day_Serial ASC """, (date_yyyymmdd,)) prescriptions = [] for row in cursor.fetchall(): # 주민번호에서 나이/성별 추출 panum = row.PaNum or '' age = None gender = None if len(panum) >= 7: try: birth_year = int(panum[:2]) gender_code = panum[6] if len(panum) > 6 else '' # 성별 및 세기 판단 if gender_code in ['1', '2', '5', '6']: birth_year += 1900 elif gender_code in ['3', '4', '7', '8']: birth_year += 2000 else: birth_year += 1900 gender = '남' if gender_code in ['1', '3', '5', '7'] else '여' age = datetime.now().year - birth_year except: pass prescriptions.append({ 'prescription_id': row.PreSerial, 'order_number': row.Day_Serial, 'date': row.PassDay, 'patient_name': row.Paname, 'patient_id': row.PaNum[:6] + '******' if row.PaNum and len(row.PaNum) > 6 else row.PaNum, 'patient_code': row.CusCode, 'hospital': row.InsName, 'doctor': row.Drname, 'time': row.PresTime, 'type': '급여' if row.PreGubun == '0' else '비급여' if row.PreGubun == '9' else row.PreGubun, 'age': age, 'gender': gender, 'price_total': row.PRICE_T, 'price_patient': row.PRICE_P, 'price_claim': row.PRICE_C }) conn.close() return jsonify({ 'success': True, 'date': date_str, 'count': len(prescriptions), 'prescriptions': prescriptions }) except Exception as e: logging.error(f"PMR 처방전 목록 조회 오류: {e}") return jsonify({'success': False, 'error': str(e)}), 500 # ───────────────────────────────────────────────────────────── # API: 처방전 상세 (약품 목록) # ───────────────────────────────────────────────────────────── @pmr_bp.route('/api/prescription/', methods=['GET']) def get_prescription_detail(prescription_id): """ 처방전 상세 정보 (약품 목록 포함) """ try: conn = get_mssql_connection('PM_PRES') cursor = conn.cursor() # 처방전 기본 정보 cursor.execute(""" SELECT PreSerial, Day_Serial, PassDay, Paname, PaNum, CusCode, InsName, Drname, PresTime, PreGubun, PRICE_T, PRICE_P, PRICE_C FROM PS_MAIN WHERE PreSerial = ? """, (prescription_id,)) rx_row = cursor.fetchone() if not rx_row: conn.close() return jsonify({'success': False, 'error': '처방전을 찾을 수 없습니다'}), 404 # 처방 약품 목록 (PS_sub_pharm 테이블 확인 필요) cursor.execute(""" SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PS_sub_pharm' """) sub_columns = [row[0] for row in cursor.fetchall()] # 약품 목록 조회 medications = [] if 'PreSerial' in sub_columns: cursor.execute(""" SELECT * FROM PS_sub_pharm WHERE PreSerial = ? ORDER BY 1 """, (prescription_id,)) med_columns = [col[0] for col in cursor.description] for row in cursor.fetchall(): med_dict = dict(zip(med_columns, row)) medications.append({ 'medication_code': med_dict.get('GoodsCode') or med_dict.get('PCODE') or '', 'med_name': med_dict.get('GoodsName') or med_dict.get('PNAME') or '', 'dosage': med_dict.get('Once_Qty') or med_dict.get('POESSION') or 0, 'frequency': med_dict.get('Times') or med_dict.get('PTIMES') or 0, 'duration': med_dict.get('Days') or med_dict.get('PDAY') or 0, 'total_qty': med_dict.get('Total_Qty') or 0, 'type': med_dict.get('PS_Type', '0') }) conn.close() # 나이/성별 계산 panum = rx_row.PaNum or '' age = None gender = None if len(panum) >= 7: try: birth_year = int(panum[:2]) gender_code = panum[6] if gender_code in ['1', '2', '5', '6']: birth_year += 1900 elif gender_code in ['3', '4', '7', '8']: birth_year += 2000 gender = '남' if gender_code in ['1', '3', '5', '7'] else '여' age = datetime.now().year - birth_year except: pass return jsonify({ 'success': True, 'prescription': { 'prescription_id': rx_row.PreSerial, 'order_number': rx_row.Day_Serial, 'date': rx_row.PassDay, 'time': rx_row.PresTime, 'hospital': rx_row.InsName, 'doctor': rx_row.Drname, 'type': '급여' if rx_row.PreGubun == '0' else '비급여', 'price_total': rx_row.PRICE_T, 'price_patient': rx_row.PRICE_P }, 'patient': { 'name': rx_row.Paname, 'code': rx_row.CusCode, 'age': age, 'gender': gender }, 'medications': medications, 'medication_count': len(medications) }) except Exception as e: logging.error(f"PMR 처방전 상세 조회 오류: {e}") return jsonify({'success': False, 'error': str(e)}), 500 # ───────────────────────────────────────────────────────────── # API: 통계 (당일 요약) # ───────────────────────────────────────────────────────────── @pmr_bp.route('/api/stats', methods=['GET']) def get_daily_stats(): """당일 조제 통계""" try: date_str = request.args.get('date', date.today().strftime('%Y-%m-%d')) date_yyyymmdd = date_str.replace('-', '') conn = get_mssql_connection('PM_PRES') cursor = conn.cursor() # 처방전 수 cursor.execute(""" SELECT COUNT(*) as cnt FROM PS_MAIN WHERE PassDay = ? """, (date_yyyymmdd,)) total_prescriptions = cursor.fetchone()[0] # 총 금액 cursor.execute(""" SELECT ISNULL(SUM(PRICE_T), 0) as total, ISNULL(SUM(PRICE_P), 0) as patient, ISNULL(SUM(PRICE_C), 0) as claim FROM PS_MAIN WHERE PassDay = ? """, (date_yyyymmdd,)) price_row = cursor.fetchone() conn.close() return jsonify({ 'success': True, 'date': date_str, 'stats': { 'total_prescriptions': total_prescriptions, 'total_amount': price_row[0] if price_row else 0, 'patient_amount': price_row[1] if price_row else 0, 'claim_amount': price_row[2] if price_row else 0 } }) except Exception as e: logging.error(f"PMR 통계 조회 오류: {e}") return jsonify({'success': False, 'error': str(e)}), 500 # ───────────────────────────────────────────────────────────── # API: DB 연결 테스트 # ───────────────────────────────────────────────────────────── @pmr_bp.route('/api/test', methods=['GET']) def test_connection(): """DB 연결 테스트""" try: conn = get_mssql_connection('PM_PRES') cursor = conn.cursor() cursor.execute("SELECT @@VERSION") version = cursor.fetchone()[0] conn.close() return jsonify({ 'success': True, 'server': MSSQL_CONFIG['server'], 'version': version[:100] + '...' }) except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500