feat: 의약품 마스터 DB 연동 (ATTACH DATABASE)
- medicine_master.db (305,522행) CSV→SQLite 변환 완료 - get_db()에서 ATTACH DATABASE로 자동 연결 - GET /api/medicine-master/search: 상품명/업체명/표준코드 검색 - GET /api/medicine-master/categories: 전문일반구분별 통계 - config.py에 MEDICINE_MASTER_PATH 추가 - 취소된 제품 자동 필터링, 카테고리 필터 지원 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
725f14c59a
commit
c0d55f8e16
73
app.py
73
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']):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user