feat: OTC 모달에 제품 썸네일 이미지 표시

- product_images.db에서 thumbnail_base64 조회
- drug_code로 이미지 매칭
- 이미지 없으면 💊 placeholder
This commit is contained in:
thug0bin 2026-03-04 23:59:13 +09:00
parent ebf2e8a016
commit 088d88878a
2 changed files with 76 additions and 8 deletions

View File

@ -3,6 +3,8 @@
from flask import Blueprint, jsonify, request, render_template, send_file from flask import Blueprint, jsonify, request, render_template, send_file
import pyodbc import pyodbc
import sqlite3
from pathlib import Path
from datetime import datetime, date from datetime import datetime, date
import logging import logging
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
@ -711,6 +713,8 @@ def get_patient_otc_history(cus_code):
# 각 거래의 품목 조회 # 각 거래의 품목 조회
purchases = [] purchases = []
all_drug_codes = []
for order in orders: for order in orders:
cursor.execute(""" cursor.execute("""
SELECT SELECT
@ -728,12 +732,15 @@ def get_patient_otc_history(cus_code):
items = [] items = []
for item_row in cursor.fetchall(): for item_row in cursor.fetchall():
drug_code = item_row.DrugCode or ''
all_drug_codes.append(drug_code)
items.append({ items.append({
'drug_code': item_row.DrugCode or '', 'drug_code': drug_code,
'name': item_row.GoodsName or item_row.DrugCode or '', 'name': item_row.GoodsName or drug_code,
'quantity': int(item_row.SL_NM_item or 0), 'quantity': int(item_row.SL_NM_item or 0),
'price': int(item_row.SL_TOTAL_PRICE or 0), 'price': int(item_row.SL_TOTAL_PRICE or 0),
'category': item_row.PRINT_TYPE or '' 'category': item_row.PRINT_TYPE or '',
'image': None
}) })
purchases.append({ purchases.append({
@ -744,6 +751,34 @@ def get_patient_otc_history(cus_code):
conn.close() conn.close()
# 제품 이미지 조회 (product_images.db)
image_map = {}
try:
img_db_path = Path(__file__).parent / 'db' / 'product_images.db'
if img_db_path.exists() and all_drug_codes:
img_conn = sqlite3.connect(str(img_db_path))
img_cursor = img_conn.cursor()
placeholders = ','.join(['?' for _ in all_drug_codes])
img_cursor.execute(f'''
SELECT drug_code, thumbnail_base64
FROM product_images
WHERE drug_code IN ({placeholders}) AND thumbnail_base64 IS NOT NULL
''', all_drug_codes)
for row in img_cursor.fetchall():
image_map[row[0]] = row[1]
img_conn.close()
except Exception as img_err:
logging.warning(f"제품 이미지 조회 오류: {img_err}")
# 이미지 매핑
for purchase in purchases:
for item in purchase['items']:
if item['drug_code'] in image_map:
item['image'] = image_map[item['drug_code']]
# 통계 계산 # 통계 계산
total_amount = sum(p['amount'] for p in purchases) total_amount = sum(p['amount'] for p in purchases)
total_visits = len(purchases) total_visits = len(purchases)

View File

@ -261,14 +261,40 @@
} }
.otc-purchase-item { .otc-purchase-item {
display: flex; display: flex;
justify-content: space-between; align-items: center;
padding: 5px 0; gap: 10px;
padding: 8px 0;
font-size: 0.85rem; font-size: 0.85rem;
border-bottom: 1px solid #f1f5f9; border-bottom: 1px solid #f1f5f9;
} }
.otc-purchase-item:last-child { border-bottom: none; } .otc-purchase-item:last-child { border-bottom: none; }
.otc-purchase-item .name { color: #1e293b; } .otc-purchase-item .thumb {
.otc-purchase-item .qty { color: #64748b; } width: 40px;
height: 40px;
border-radius: 6px;
object-fit: cover;
background: #f1f5f9;
flex-shrink: 0;
}
.otc-purchase-item .thumb-placeholder {
width: 40px;
height: 40px;
border-radius: 6px;
background: #e2e8f0;
display: flex;
align-items: center;
justify-content: center;
color: #94a3b8;
font-size: 1.2rem;
flex-shrink: 0;
}
.otc-purchase-item .info {
flex: 1;
min-width: 0;
}
.otc-purchase-item .name { color: #1e293b; font-weight: 500; }
.otc-purchase-item .category { font-size: 0.75rem; color: #64748b; }
.otc-purchase-item .qty { color: #64748b; white-space: nowrap; }
/* 약품 목록 */ /* 약품 목록 */
.medication-list { .medication-list {
@ -1118,7 +1144,14 @@
<div class="otc-purchase-items"> <div class="otc-purchase-items">
${p.items.map(item => ` ${p.items.map(item => `
<div class="otc-purchase-item"> <div class="otc-purchase-item">
<span class="name">${item.name}</span> ${item.image
? `<img class="thumb" src="data:image/jpeg;base64,${item.image}" alt="">`
: `<div class="thumb-placeholder">💊</div>`
}
<div class="info">
<div class="name">${item.name}</div>
${item.category ? `<div class="category">${item.category}</div>` : ''}
</div>
<span class="qty">${item.quantity}개 / ${item.price.toLocaleString()}원</span> <span class="qty">${item.quantity}개 / ${item.price.toLocaleString()}원</span>
</div> </div>
`).join('')} `).join('')}