feat: POS GUI 회원 마일리지 내역 조회 기능 추가
- UserMileageDialog 클래스 추가 * 전화번호로 회원 정보 및 적립 내역 조회 * 회원 정보: 이름, 전화번호, 포인트 잔액, 가입일 * 적립 내역 테이블: 날짜, 구분(적립/사용), 포인트, 잔액, 설명 * 최근 50건 표시 - 적립 사용자 클릭 시 모달 팝업 * 적립자명, 전화번호, 적립포인트 컬럼 클릭 가능 * 녹색 볼드 + 밑줄로 클릭 가능 표시 * 툴팁 추가: '클릭하여 회원 마일리지 내역 보기' - cellClicked 이벤트 핸들러 연결 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
3b8f8b232c
commit
3102940c09
@ -363,6 +363,151 @@ class SaleDetailDialog(QDialog):
|
||||
conn.close()
|
||||
|
||||
|
||||
class UserMileageDialog(QDialog):
|
||||
"""
|
||||
회원 마일리지 내역 조회 팝업
|
||||
적립 사용자 클릭 시 해당 회원의 적립 내역 표시
|
||||
"""
|
||||
|
||||
def __init__(self, phone, parent=None):
|
||||
"""
|
||||
Args:
|
||||
phone: 전화번호
|
||||
parent: 부모 위젯
|
||||
"""
|
||||
super().__init__(parent)
|
||||
self.phone = phone
|
||||
self.setWindowTitle(f'회원 마일리지 내역')
|
||||
self.setModal(True)
|
||||
self.resize(800, 500)
|
||||
self.init_ui()
|
||||
self.load_user_info()
|
||||
|
||||
def init_ui(self):
|
||||
"""UI 초기화"""
|
||||
layout = QVBoxLayout()
|
||||
|
||||
# 회원 정보 그룹박스
|
||||
info_group = QGroupBox('회원 정보')
|
||||
info_layout = QVBoxLayout()
|
||||
info_group.setLayout(info_layout)
|
||||
|
||||
self.info_label = QLabel('조회 중...')
|
||||
self.info_label.setStyleSheet('font-size: 13px; padding: 10px; background: #f5f7fa; border-radius: 8px;')
|
||||
info_layout.addWidget(self.info_label)
|
||||
|
||||
layout.addWidget(info_group)
|
||||
|
||||
# 적립 내역 테이블
|
||||
history_group = QGroupBox('적립 내역')
|
||||
history_layout = QVBoxLayout()
|
||||
history_group.setLayout(history_layout)
|
||||
|
||||
self.history_table = QTableWidget()
|
||||
self.history_table.setColumnCount(5)
|
||||
self.history_table.setHorizontalHeaderLabels([
|
||||
'날짜', '구분', '포인트', '잔액', '설명'
|
||||
])
|
||||
self.history_table.setColumnWidth(0, 150)
|
||||
self.history_table.setColumnWidth(1, 80)
|
||||
self.history_table.setColumnWidth(2, 100)
|
||||
self.history_table.setColumnWidth(3, 100)
|
||||
self.history_table.setColumnWidth(4, 300)
|
||||
history_layout.addWidget(self.history_table)
|
||||
|
||||
layout.addWidget(history_group)
|
||||
|
||||
# 닫기 버튼
|
||||
close_btn = QPushButton('닫기')
|
||||
close_btn.setStyleSheet('background-color: #2196F3; color: white; padding: 8px; font-weight: bold;')
|
||||
close_btn.clicked.connect(self.close)
|
||||
layout.addWidget(close_btn)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def load_user_info(self):
|
||||
"""SQLite에서 회원 정보 및 적립 내역 조회"""
|
||||
conn = None
|
||||
try:
|
||||
db_manager = DatabaseManager()
|
||||
conn = db_manager.get_sqlite_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 전화번호로 사용자 조회
|
||||
cursor.execute("""
|
||||
SELECT id, nickname, phone, mileage_balance, created_at
|
||||
FROM users WHERE phone = ?
|
||||
""", (self.phone,))
|
||||
|
||||
user = cursor.fetchone()
|
||||
|
||||
if not user:
|
||||
self.info_label.setText('등록되지 않은 회원입니다.')
|
||||
return
|
||||
|
||||
# 회원 정보 표시
|
||||
info_text = f"""
|
||||
<b>이름:</b> {user['nickname']}<br>
|
||||
<b>전화번호:</b> {user['phone']}<br>
|
||||
<b>포인트 잔액:</b> <span style="color: #4CAF50; font-weight: bold;">{user['mileage_balance']:,}P</span><br>
|
||||
<b>가입일:</b> {user['created_at']}
|
||||
"""
|
||||
self.info_label.setText(info_text)
|
||||
|
||||
# 적립 내역 조회
|
||||
cursor.execute("""
|
||||
SELECT points, balance_after, reason, description, created_at
|
||||
FROM mileage_ledger
|
||||
WHERE user_id = ?
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 50
|
||||
""", (user['id'],))
|
||||
|
||||
transactions = cursor.fetchall()
|
||||
|
||||
# 테이블에 데이터 채우기
|
||||
self.history_table.setRowCount(len(transactions))
|
||||
for row_idx, tx in enumerate(transactions):
|
||||
from PyQt5.QtGui import QColor
|
||||
|
||||
# 날짜
|
||||
date_item = QTableWidgetItem(tx['created_at'])
|
||||
self.history_table.setItem(row_idx, 0, date_item)
|
||||
|
||||
# 구분 (CLAIM, USE 등)
|
||||
reason_text = '적립' if tx['reason'] == 'CLAIM' else '사용'
|
||||
reason_item = QTableWidgetItem(reason_text)
|
||||
reason_item.setTextAlignment(Qt.AlignCenter)
|
||||
if tx['reason'] == 'CLAIM':
|
||||
reason_item.setForeground(QColor('#4CAF50'))
|
||||
else:
|
||||
reason_item.setForeground(QColor('#f03e3e'))
|
||||
self.history_table.setItem(row_idx, 1, reason_item)
|
||||
|
||||
# 포인트 (우측 정렬)
|
||||
points_item = QTableWidgetItem(f"{tx['points']:+,}P")
|
||||
points_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||
if tx['points'] > 0:
|
||||
points_item.setForeground(QColor('#4CAF50'))
|
||||
else:
|
||||
points_item.setForeground(QColor('#f03e3e'))
|
||||
self.history_table.setItem(row_idx, 2, points_item)
|
||||
|
||||
# 잔액 (우측 정렬)
|
||||
balance_item = QTableWidgetItem(f"{tx['balance_after']:,}P")
|
||||
balance_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||
self.history_table.setItem(row_idx, 3, balance_item)
|
||||
|
||||
# 설명
|
||||
self.history_table.setItem(row_idx, 4, QTableWidgetItem(tx['description']))
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, '오류', f'회원 정보 조회 실패:\n{str(e)}')
|
||||
finally:
|
||||
if conn:
|
||||
conn.close()
|
||||
|
||||
|
||||
class POSSalesGUI(QMainWindow):
|
||||
"""
|
||||
POS 판매 내역 조회 메인 GUI
|
||||
@ -447,6 +592,7 @@ class POSSalesGUI(QMainWindow):
|
||||
self.sales_table.setColumnWidth(7, 100)
|
||||
self.sales_table.setSelectionBehavior(QTableWidget.SelectRows)
|
||||
self.sales_table.doubleClicked.connect(self.show_sale_detail)
|
||||
self.sales_table.cellClicked.connect(self.on_cell_clicked)
|
||||
|
||||
sales_layout.addWidget(self.sales_table)
|
||||
|
||||
@ -546,7 +692,9 @@ class POSSalesGUI(QMainWindow):
|
||||
claimed_name_item.setForeground(QColor('#4CAF50'))
|
||||
font = QFont()
|
||||
font.setBold(True)
|
||||
font.setUnderline(True) # 밑줄 추가로 클릭 가능 표시
|
||||
claimed_name_item.setFont(font)
|
||||
claimed_name_item.setToolTip('클릭하여 회원 마일리지 내역 보기')
|
||||
self.sales_table.setItem(row, 5, claimed_name_item)
|
||||
|
||||
# 전화번호 (SQLite)
|
||||
@ -555,7 +703,9 @@ class POSSalesGUI(QMainWindow):
|
||||
claimed_phone_item.setForeground(QColor('#4CAF50'))
|
||||
font = QFont()
|
||||
font.setBold(True)
|
||||
font.setUnderline(True) # 밑줄 추가로 클릭 가능 표시
|
||||
claimed_phone_item.setFont(font)
|
||||
claimed_phone_item.setToolTip('클릭하여 회원 마일리지 내역 보기')
|
||||
self.sales_table.setItem(row, 6, claimed_phone_item)
|
||||
|
||||
# 적립포인트 (SQLite)
|
||||
@ -565,7 +715,9 @@ class POSSalesGUI(QMainWindow):
|
||||
claimed_points_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||
font = QFont()
|
||||
font.setBold(True)
|
||||
font.setUnderline(True) # 밑줄 추가로 클릭 가능 표시
|
||||
claimed_points_item.setFont(font)
|
||||
claimed_points_item.setToolTip('클릭하여 회원 마일리지 내역 보기')
|
||||
self.sales_table.setItem(row, 7, claimed_points_item)
|
||||
|
||||
def on_query_error(self, error_msg):
|
||||
@ -585,6 +737,24 @@ class POSSalesGUI(QMainWindow):
|
||||
detail_dialog = SaleDetailDialog(order_no, self)
|
||||
detail_dialog.exec_()
|
||||
|
||||
def on_cell_clicked(self, row, column):
|
||||
"""테이블 셀 클릭 이벤트 - 적립 사용자 클릭 시 마일리지 내역 표시"""
|
||||
# 컬럼 5(적립자명), 6(전화번호), 7(적립포인트) 중 하나를 클릭했는지 확인
|
||||
if column not in [5, 6, 7]:
|
||||
return
|
||||
|
||||
# 전화번호 가져오기 (6번 컬럼)
|
||||
phone_item = self.sales_table.item(row, 6)
|
||||
if not phone_item or not phone_item.text():
|
||||
# 적립 사용자가 없는 경우
|
||||
return
|
||||
|
||||
phone = phone_item.text()
|
||||
|
||||
# 회원 마일리지 내역 Dialog 표시
|
||||
mileage_dialog = UserMileageDialog(phone, self)
|
||||
mileage_dialog.exec_()
|
||||
|
||||
def generate_qr_label(self):
|
||||
"""선택된 판매 건에 대해 QR 라벨 생성"""
|
||||
# 선택된 행 확인
|
||||
|
||||
Loading…
Reference in New Issue
Block a user