feat: PMR OTC 구매 이력 기능
- /pmr/api/patient/<cus_code>/otc: OTC 구매 이력 API
- SALE_MAIN + SALE_SUB (PRESERIAL='V' = OTC)
- 💊 OTC 뱃지 클릭 → 모달로 구매 이력 표시
- 자주 구매하는 품목 요약
- 방문/금액 통계
This commit is contained in:
@@ -650,3 +650,134 @@ def get_patient_history(cus_code):
|
||||
except Exception as e:
|
||||
logging.error(f"환자 이전 처방 조회 오류: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
# API: 환자 OTC 구매 이력
|
||||
# ─────────────────────────────────────────────────────────────
|
||||
@pmr_bp.route('/api/patient/<cus_code>/otc', methods=['GET'])
|
||||
def get_patient_otc_history(cus_code):
|
||||
"""
|
||||
환자 OTC (일반의약품) 구매 이력 조회
|
||||
|
||||
Args:
|
||||
cus_code: 환자 고유코드 (CusCode = SL_CD_custom)
|
||||
|
||||
Query Params:
|
||||
- limit: 최대 조회 건수 (기본 20, 최대 100)
|
||||
"""
|
||||
try:
|
||||
limit = min(int(request.args.get('limit', 20)), 100)
|
||||
|
||||
conn = get_mssql_connection('PM_PRES')
|
||||
cursor = conn.cursor()
|
||||
|
||||
# OTC 거래 목록 조회 (PRESERIAL = 'V' = OTC 판매)
|
||||
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,))
|
||||
|
||||
# 먼저 거래 목록 수집
|
||||
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 ''
|
||||
})
|
||||
|
||||
# 최근 limit개만
|
||||
orders = orders[:limit]
|
||||
|
||||
if not orders:
|
||||
conn.close()
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'cus_code': cus_code,
|
||||
'count': 0,
|
||||
'purchases': []
|
||||
})
|
||||
|
||||
# 각 거래의 품목 조회
|
||||
purchases = []
|
||||
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():
|
||||
items.append({
|
||||
'drug_code': item_row.DrugCode or '',
|
||||
'name': item_row.GoodsName or item_row.DrugCode or '',
|
||||
'quantity': int(item_row.SL_NM_item or 0),
|
||||
'price': int(item_row.SL_TOTAL_PRICE or 0),
|
||||
'category': item_row.PRINT_TYPE or ''
|
||||
})
|
||||
|
||||
purchases.append({
|
||||
**order,
|
||||
'items': items,
|
||||
'item_count': len(items)
|
||||
})
|
||||
|
||||
conn.close()
|
||||
|
||||
# 통계 계산
|
||||
total_amount = sum(p['amount'] for p in purchases)
|
||||
total_visits = len(purchases)
|
||||
|
||||
# 자주 구매하는 품목 집계
|
||||
item_freq = {}
|
||||
for p in purchases:
|
||||
for item in p['items']:
|
||||
key = item['drug_code']
|
||||
if key not in item_freq:
|
||||
item_freq[key] = {
|
||||
'name': item['name'],
|
||||
'category': item['category'],
|
||||
'count': 0,
|
||||
'total_qty': 0
|
||||
}
|
||||
item_freq[key]['count'] += 1
|
||||
item_freq[key]['total_qty'] += item['quantity']
|
||||
|
||||
# 빈도순 정렬
|
||||
frequent_items = sorted(item_freq.values(), key=lambda x: x['count'], reverse=True)[:10]
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'cus_code': cus_code,
|
||||
'count': len(purchases),
|
||||
'summary': {
|
||||
'total_visits': total_visits,
|
||||
'total_amount': total_amount,
|
||||
'frequent_items': frequent_items
|
||||
},
|
||||
'purchases': purchases
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"환자 OTC 구매 이력 조회 오류: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
Reference in New Issue
Block a user