diff --git a/backend/app.py b/backend/app.py index 9891bee..f8e6fff 100644 --- a/backend/app.py +++ b/backend/app.py @@ -4933,9 +4933,9 @@ def api_admin_pos_live(): qr_record = sqlite_cursor.fetchone() qr_issued = bool(qr_record) - # SQLite에서 적립 사용자 조회 + # SQLite에서 적립 사용자 조회 (user_id 포함) sqlite_cursor.execute(""" - SELECT u.nickname, u.phone, ct.claimable_points + SELECT u.id as user_id, u.nickname, u.phone, ct.claimable_points FROM claim_tokens ct LEFT JOIN users u ON ct.claimed_by_user_id = u.id WHERE ct.transaction_id = ? AND ct.claimed_at IS NOT NULL @@ -4943,7 +4943,9 @@ def api_admin_pos_live(): claimed_user = sqlite_cursor.fetchone() # 적립 사용자 정보 분리 + claimed_user_id = None if claimed_user and claimed_user['nickname'] and claimed_user['phone']: + claimed_user_id = claimed_user['user_id'] claimed_name = claimed_user['nickname'] claimed_phone = claimed_user['phone'] claimed_points = claimed_user['claimable_points'] @@ -4952,6 +4954,23 @@ def api_admin_pos_live(): claimed_phone = "" claimed_points = 0 + # 반려동물 정보 조회 + pets_list = [] + if claimed_user_id: + sqlite_cursor.execute(""" + SELECT name, species, breed, photo_url + FROM pets + WHERE user_id = ? AND is_active = 1 + """, (claimed_user_id,)) + pets_rows = sqlite_cursor.fetchall() + for pet in pets_rows: + pets_list.append({ + 'name': pet['name'], + 'species': pet['species'], # dog, cat + 'breed': pet['breed'] or '', + 'photo_url': pet['photo_url'] or '' + }) + # 결제수단 판별 card_amt = float(card_total) if card_total else 0.0 cash_amt = float(cash_total) if cash_total else 0.0 @@ -4989,7 +5008,8 @@ def api_admin_pos_live(): 'claimed_name': claimed_name, 'claimed_phone': claimed_phone, 'claimed_points': claimed_points, - 'qr_issued': qr_issued + 'qr_issued': qr_issued, + 'pets': pets_list # 반려동물 정보 }) return jsonify({ diff --git a/backend/check_pets.py b/backend/check_pets.py new file mode 100644 index 0000000..efb9fa4 --- /dev/null +++ b/backend/check_pets.py @@ -0,0 +1,23 @@ +import sqlite3 + +conn = sqlite3.connect('db/mileage.db') +c = conn.cursor() + +# 테이블 구조 +c.execute("SELECT sql FROM sqlite_master WHERE name='pets'") +print("=== PETS TABLE SCHEMA ===") +print(c.fetchone()) + +# 샘플 데이터 +c.execute("SELECT * FROM pets LIMIT 5") +print("\n=== SAMPLE DATA ===") +for row in c.fetchall(): + print(row) + +# 컬럼명 +c.execute("PRAGMA table_info(pets)") +print("\n=== COLUMNS ===") +for col in c.fetchall(): + print(col) + +conn.close() diff --git a/backend/templates/admin_pos_live.html b/backend/templates/admin_pos_live.html index 8417698..05ee683 100644 --- a/backend/templates/admin_pos_live.html +++ b/backend/templates/admin_pos_live.html @@ -637,6 +637,60 @@ margin-top: 2px; } + /* ── 반려동물 카드 ── */ + .detail-pets-section { + margin: 16px 0; + } + .pets-grid { + display: flex; + gap: 10px; + flex-wrap: wrap; + } + .pet-card { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 14px; + background: linear-gradient(135deg, #fef3c7, #fde68a); + border-radius: 12px; + flex: 1; + min-width: 140px; + max-width: 200px; + } + .pet-photo { + width: 44px; + height: 44px; + border-radius: 50%; + object-fit: cover; + border: 2px solid #fff; + box-shadow: 0 2px 6px rgba(0,0,0,0.15); + } + .pet-photo-placeholder { + width: 44px; + height: 44px; + border-radius: 50%; + background: #fff; + display: flex; + align-items: center; + justify-content: center; + font-size: 22px; + box-shadow: 0 2px 6px rgba(0,0,0,0.1); + } + .pet-info { + flex: 1; + min-width: 0; + } + .pet-name { + font-weight: 700; + font-size: 14px; + color: #92400e; + } + .pet-breed { + font-size: 11px; + color: #a16207; + margin-top: 2px; + } + /* ── 반응형 ── */ @media (max-width: 768px) { .control-section { @@ -852,8 +906,15 @@ let claimedHtml = '-'; if (sale.claimed_name) { + // 반려동물 아이콘 생성 + let petIcons = ''; + if (sale.pets && sale.pets.length > 0) { + petIcons = sale.pets.map(p => + p.species === 'dog' ? '🐕' : p.species === 'cat' ? '🐈' : '🐾' + ).join(''); + } claimedHtml = ` -
${sale.claimed_name}
+
${sale.claimed_name} ${petIcons}
${formatPhone(sale.claimed_phone)}
`; } @@ -986,6 +1047,33 @@ ` : ''; + // 반려동물 섹션 + let petsSection = ''; + if (sale.pets && sale.pets.length > 0) { + const petsHtml = sale.pets.map(pet => { + const speciesIcon = pet.species === 'dog' ? '🐕' : pet.species === 'cat' ? '🐈' : '🐾'; + const speciesName = pet.species === 'dog' ? '강아지' : pet.species === 'cat' ? '고양이' : '반려동물'; + const photoHtml = pet.photo_url + ? `${pet.name}` + : `
${speciesIcon}
`; + return ` +
+ ${photoHtml} +
+
${speciesIcon} ${pet.name}
+
${pet.breed || speciesName}
+
+
+ `; + }).join(''); + petsSection = ` +
+
🐾 반려동물
+
${petsHtml}
+
+ `; + } + // 기본 정보 표시 document.getElementById('detailContent').innerHTML = ` @@ -1029,6 +1117,7 @@ ${claimedInfo} + ${petsSection}
📦 품목 목록
품목 로딩 중...