diff --git a/backend/app.py b/backend/app.py index 86ba9c4..bb99d5e 100644 --- a/backend/app.py +++ b/backend/app.py @@ -3009,7 +3009,7 @@ def api_member_history(phone): """ 회원 구매 이력 통합 조회 API - 마일리지 적립/사용 내역 (SQLite) - - POS 구매 이력 (MSSQL) + - transaction_id로 POS 품목 조회 (MSSQL) """ try: # 전화번호 정규화 @@ -3022,6 +3022,8 @@ def api_member_history(phone): 'purchases': [] } + transaction_ids = [] # 적립된 거래번호 수집 + # 1. 마일리지 내역 조회 (SQLite) try: sqlite_conn = db_manager.get_sqlite_connection() @@ -3037,76 +3039,57 @@ def api_member_history(phone): if user: user_id = user['id'] - # 적립/사용 내역 조회 + # 적립/사용 내역 조회 (claim_tokens 조인으로 금액 포함) cursor.execute(""" SELECT ml.points, ml.balance_after, ml.reason, - ml.description, ml.transaction_id, ml.created_at + ml.description, ml.transaction_id, ml.created_at, + ct.total_amount FROM mileage_ledger ml + LEFT JOIN claim_tokens ct ON ml.transaction_id = ct.transaction_id WHERE ml.user_id = ? ORDER BY ml.created_at DESC LIMIT 50 """, (user_id,)) transactions = cursor.fetchall() + tx_list = [] + for t in transactions: + tx_data = { + 'points': t['points'], + 'balance_after': t['balance_after'], + 'reason': t['reason'], + 'description': t['description'], + 'transaction_id': t['transaction_id'], + 'created_at': t['created_at'], + 'total_amount': t['total_amount'], + 'items': [] # 나중에 POS에서 채움 + } + tx_list.append(tx_data) + + # 적립 거래번호 수집 + if t['transaction_id'] and t['reason'] == 'CLAIM': + transaction_ids.append(t['transaction_id']) + result['mileage'] = { 'user_id': user_id, 'name': user['nickname'] or '', 'phone': user['phone'], 'balance': user['mileage_balance'] or 0, 'member_since': user['created_at'], - 'transactions': [{ - 'points': t['points'], - 'balance_after': t['balance_after'], - 'reason': t['reason'], - 'description': t['description'], - 'transaction_id': t['transaction_id'], - 'created_at': t['created_at'] - } for t in transactions] + 'transactions': tx_list } except Exception as e: logging.warning(f"마일리지 조회 실패: {e}") - # 2. POS 구매 이력 조회 (MSSQL) - try: - base_session = db_manager.get_session('PM_BASE') - pres_session = db_manager.get_session('PM_PRES') - drug_session = db_manager.get_session('PM_DRUG') - - # 전화번호로 고객코드 조회 - 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}).fetchone() - - if cus_row: - cuscode = cus_row.CUSCODE - result['pos_customer'] = { - 'cuscode': cuscode, - 'name': cus_row.PANAME - } + # 2. transaction_id로 POS 품목 조회 (MSSQL) + if transaction_ids and result['mileage']: + try: + pres_session = db_manager.get_session('PM_PRES') - # 구매 이력 조회 (최근 30일) - purchase_query = text(""" - SELECT - M.SL_NO_order as order_no, - M.SL_DT_appl as order_date, - M.SL_MY_total as total_amount, - M.SL_MY_discount as discount - FROM SALE_MAIN M - WHERE M.SL_CD_custom = :cuscode - AND M.SL_DT_appl >= CONVERT(VARCHAR(8), DATEADD(DAY, -30, GETDATE()), 112) - ORDER BY M.SL_DT_appl DESC, M.SL_NO_order DESC - """) - orders = pres_session.execute(purchase_query, {'cuscode': cuscode}).fetchall() - - purchases = [] - for order in orders[:20]: # 최대 20건 - # 주문 상세 (품목) + # 각 거래번호별 품목 조회 + items_by_tx = {} + for tx_id in transaction_ids[:30]: # 최대 30건 items_query = text(""" SELECT S.DrugCode, @@ -3117,25 +3100,23 @@ def api_member_history(phone): LEFT JOIN PM_DRUG.dbo.CD_GOODS G ON S.DrugCode = G.DrugCode WHERE S.SL_NO_order = :order_no """) - items = pres_session.execute(items_query, {'order_no': order.order_no}).fetchall() + items = pres_session.execute(items_query, {'order_no': tx_id}).fetchall() - purchases.append({ - 'order_no': order.order_no, - 'date': order.order_date, - 'total': float(order.total_amount) if order.total_amount else 0, - 'discount': float(order.discount) if order.discount else 0, - 'items': [{ - 'drug_code': item.DrugCode, - 'name': item.GoodsName or '알 수 없음', - 'quantity': float(item.quantity) if item.quantity else 1, - 'price': float(item.price) if item.price else 0 - } for item in items] - }) + items_by_tx[tx_id] = [{ + 'drug_code': item.DrugCode, + 'name': item.GoodsName or '알 수 없음', + 'quantity': float(item.quantity) if item.quantity else 1, + 'price': float(item.price) if item.price else 0 + } for item in items] - result['purchases'] = purchases - - except Exception as e: - logging.warning(f"POS 구매 이력 조회 실패: {e}") + # 마일리지 내역에 품목 추가 + for tx in result['mileage']['transactions']: + tx_id = tx.get('transaction_id') + if tx_id and tx_id in items_by_tx: + tx['items'] = items_by_tx[tx_id] + + except Exception as e: + logging.warning(f"POS 품목 조회 실패: {e}") return jsonify(result) diff --git a/backend/templates/admin_members.html b/backend/templates/admin_members.html index 020134d..ff35749 100644 --- a/backend/templates/admin_members.html +++ b/backend/templates/admin_members.html @@ -906,6 +906,25 @@ month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }) : ''; + // 품목 렌더링 + let itemsHtml = ''; + if (tx.items && tx.items.length > 0) { + itemsHtml = ` +