diff --git a/app.py b/app.py index ff9c093..c9665fb 100644 --- a/app.py +++ b/app.py @@ -15,7 +15,7 @@ from werkzeug.utils import secure_filename import json from contextlib import contextmanager from excel_processor import ExcelProcessor -from config import DATABASE_PATH, STATIC_PATH, TEMPLATES_PATH +from config import DATABASE_PATH, MEDICINE_MASTER_PATH, STATIC_PATH, TEMPLATES_PATH # Flask 앱 초기화 app = Flask(__name__, static_folder='static', template_folder='templates') @@ -42,6 +42,10 @@ def get_db(): conn = sqlite3.connect(app.config['DATABASE']) conn.row_factory = sqlite3.Row # 딕셔너리 형태로 반환 conn.execute('PRAGMA foreign_keys = ON') # 외래키 제약 활성화 + # 의약품 마스터 DB 연결 (읽기 전용 참조) + medicine_db = str(MEDICINE_MASTER_PATH) + if os.path.exists(medicine_db): + conn.execute(f"ATTACH DATABASE '{medicine_db}' AS med_master") try: yield conn conn.commit() @@ -3768,6 +3772,73 @@ def convert_to_otc(compound_id): except Exception as e: return jsonify({'error': str(e)}), 500 +# ==================== 의약품 마스터 검색 API ==================== + +@app.route('/api/medicine-master/search', methods=['GET']) +def search_medicine_master(): + """의약품 마스터 검색 (medicine_master.db ATTACH 활용)""" + try: + q = request.args.get('q', '').strip() + category = request.args.get('category', '') # 전문일반구분 필터 + limit = min(int(request.args.get('limit', 50)), 200) + + if not q or len(q) < 2: + return jsonify({'success': False, 'error': '검색어는 2자 이상 입력하세요'}), 400 + + with get_db() as conn: + cursor = conn.cursor() + + where_clauses = ["(m.product_name LIKE ? OR m.company_name LIKE ? OR m.standard_code LIKE ? OR m.notes LIKE ?)"] + params = [f'%{q}%', f'%{q}%', f'%{q}%', f'%{q}%'] + + if category: + where_clauses.append("m.category = ?") + params.append(category) + + # 취소된 제품 제외 + where_clauses.append("(m.cancel_date IS NULL OR m.cancel_date = '')") + + params.append(limit) + + cursor.execute(f""" + SELECT m.id, m.product_name, m.company_name, m.spec, + m.total_quantity, m.form_type, m.package_type, + m.item_std_code, m.category, m.representative_code, + m.standard_code, m.ingredient_name_code, m.notes, + m.atc_code + FROM med_master.medicine_master m + WHERE {' AND '.join(where_clauses)} + ORDER BY m.product_name, m.spec + LIMIT ? + """, params) + + results = [dict(row) for row in cursor.fetchall()] + + return jsonify({'success': True, 'data': results, 'count': len(results)}) + + except Exception as e: + return jsonify({'success': False, 'error': str(e)}), 500 + +@app.route('/api/medicine-master/categories', methods=['GET']) +def get_medicine_categories(): + """의약품 마스터 카테고리 목록 (전문일반구분)""" + try: + with get_db() as conn: + cursor = conn.cursor() + cursor.execute(""" + SELECT category, COUNT(*) as cnt + FROM med_master.medicine_master + WHERE category != '' AND (cancel_date IS NULL OR cancel_date = '') + GROUP BY category + ORDER BY cnt DESC + """) + categories = [{'name': row['category'], 'count': row['cnt']} for row in cursor.fetchall()] + + return jsonify({'success': True, 'data': categories}) + except Exception as e: + return jsonify({'success': False, 'error': str(e)}), 500 + + if __name__ == '__main__': # 데이터베이스 초기화 if not os.path.exists(app.config['DATABASE']): diff --git a/config.py b/config.py index 2e7579d..683a450 100644 --- a/config.py +++ b/config.py @@ -12,6 +12,7 @@ PROJECT_ROOT = Path(__file__).parent # 데이터베이스 경로 - 항상 절대 경로 사용 DATABASE_PATH = PROJECT_ROOT / 'database' / 'kdrug.db' +MEDICINE_MASTER_PATH = PROJECT_ROOT / 'database' / 'medicine_master.db' # 기타 자주 사용하는 경로들 STATIC_PATH = PROJECT_ROOT / 'static'