feat(admin): 사용자 구매 이력에 MSSQL 직접 구매 통합

## 배경
- 기존: QR 적립된 구매만 표시 (SQLite claim_tokens)
- 문제: pos-live에서 고객 매핑한 구매가 안 보임

## 변경 사항
- admin_user_detail API에 MSSQL SALE_MAIN 조회 추가
- 전화번호 → CD_PERSON.CUSCODE → SALE_MAIN.SL_CD_custom 매칭
- QR 적립 구매와 POS 직접 구매 통합 표시
- 중복 제거: 이미 QR 적립된 건은 스킵
- 최근 30일, 최대 20건 조회

## 구매 소스 구분
- QR 적립: points > 0
- POS 직접 매핑: points = 0, source = 'pos'
This commit is contained in:
thug0bin 2026-03-11 23:26:22 +09:00
parent 9f10f8fdbb
commit 4a529fc891

View File

@ -1580,6 +1580,97 @@ def admin_user_detail(user_id):
print(f"[WARNING] MSSQL 조회 실패 (user {user_id}): {mssql_error}")
purchases = []
# 5-1. MSSQL 직접 구매 이력 추가 (QR 적립 안 된 구매)
# 전화번호 → CUSCODE → SALE_MAIN 조회
try:
if user['phone']:
phone_clean = user['phone'].replace('-', '').replace(' ', '')
base_session = db_manager.get_session('PM_BASE')
pres_session = db_manager.get_session('PM_PRES')
# 전화번호로 CUSCODE 조회
cuscode_query = text("""
SELECT TOP 1 CUSCODE, PANAME
FROM CD_PERSON
WHERE REPLACE(REPLACE(PHONE, '-', ''), ' ', '') = :phone
OR REPLACE(REPLACE(TEL_NO, '-', ''), ' ', '') = :phone
OR REPLACE(REPLACE(PHONE2, '-', ''), ' ', '') = :phone
""")
cus_row = base_session.execute(cuscode_query, {'phone': phone_clean}).fetchone()
if cus_row:
cuscode = cus_row.CUSCODE
# 이미 QR 적립된 transaction_id 목록
existing_tx_ids = {p['transaction_id'] for p in purchases}
# SALE_MAIN에서 이 고객의 구매 조회 (최근 30일, 최대 20건)
sale_query = text("""
SELECT TOP 20
M.SL_NO_order,
M.InsertTime,
M.SL_MY_sale
FROM SALE_MAIN M
WHERE M.SL_CD_custom = :cuscode
AND M.InsertTime >= DATEADD(day, -30, GETDATE())
ORDER BY M.InsertTime DESC
""")
sales = pres_session.execute(sale_query, {'cuscode': cuscode}).fetchall()
for sale in sales:
tx_id = sale.SL_NO_order
if tx_id in existing_tx_ids:
continue # 이미 QR 적립된 건 스킵
# 품목 조회
items_query = text("""
SELECT
S.DrugCode,
ISNULL(G.GoodsName, '(약품명 없음)') AS goods_name,
S.SL_NM_item AS quantity,
S.SL_NM_cost_a AS price,
S.SL_TOTAL_PRICE AS total
FROM SALE_SUB S
LEFT JOIN PM_DRUG.dbo.CD_GOODS G ON S.DrugCode = G.DrugCode
WHERE S.SL_NO_order = :tx_id
""")
items_raw = pres_session.execute(items_query, {'tx_id': tx_id}).fetchall()
items = [{
'code': item.DrugCode,
'barcode': '',
'name': item.goods_name,
'qty': int(item.quantity or 0),
'price': int(item.price or 0),
'total': int(item.total or 0),
'categories': []
} for item in items_raw]
# 상품 요약
if items:
first_item_name = items[0]['name']
items_count = len(items)
items_summary = first_item_name if items_count == 1 else f"{first_item_name}{items_count - 1}"
else:
items_summary = "상품 정보 없음"
items_count = 0
purchases.append({
'transaction_id': tx_id,
'date': str(sale.InsertTime)[:16].replace('T', ' ') if sale.InsertTime else '-',
'amount': int(sale.SL_MY_sale or 0),
'points': 0, # QR 적립 안 됨
'items_summary': items_summary,
'items_count': items_count,
'items': items,
'source': 'pos' # POS 직접 매핑 구매
})
# 날짜순 정렬 (최신 먼저)
purchases.sort(key=lambda x: x['date'], reverse=True)
except Exception as pos_purchase_error:
logging.warning(f"POS 구매 이력 조회 실패 (user {user_id}): {pos_purchase_error}")
# 6. 조제 이력 조회 (전화번호 → CUSCODE → PS_main)
prescriptions = []
pos_customer = None