feat: POS GUI 할인 표시 + 적립자 클릭 버그 수정 + 결제수납 문서
- 할인 적용 건: 주황색 볼드로 "금액 (-할인액)" 표시 + 툴팁 상세 - on_cell_clicked 하드코딩 인덱스 → SALES_COLUMNS 기반 동적 인덱스로 수정 - docs/결제수납구조.md: CD_SUNAB 조인 키, 금액 구조, 결제수단 판별 로직 문서화 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ac59464612
commit
0c52542713
@ -76,7 +76,9 @@ class SalesQueryThread(QThread):
|
||||
M.SL_MY_sale,
|
||||
ISNULL(M.SL_NM_custom, '[비고객]') AS customer_name,
|
||||
ISNULL(S.card_total, 0) AS card_total,
|
||||
ISNULL(S.cash_total, 0) AS cash_total
|
||||
ISNULL(S.cash_total, 0) AS cash_total,
|
||||
ISNULL(M.SL_MY_total, 0) AS total_amount,
|
||||
ISNULL(M.SL_MY_discount, 0) AS discount
|
||||
FROM SALE_MAIN M
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1
|
||||
@ -94,7 +96,7 @@ class SalesQueryThread(QThread):
|
||||
|
||||
sales_list = []
|
||||
for row in rows:
|
||||
order_no, insert_time, sale_amount, customer, card_total, cash_total = row
|
||||
order_no, insert_time, sale_amount, customer, card_total, cash_total, total_amount, discount = row
|
||||
|
||||
# 품목 수 조회 (SALE_SUB)
|
||||
mssql_cursor.execute("""
|
||||
@ -144,10 +146,15 @@ class SalesQueryThread(QThread):
|
||||
pay_method = ''
|
||||
paid = (card_amt + cash_amt) > 0
|
||||
|
||||
disc_amt = float(discount) if discount else 0.0
|
||||
total_amt = float(total_amount) if total_amount else 0.0
|
||||
|
||||
sales_list.append({
|
||||
'order_no': order_no,
|
||||
'time': insert_time.strftime('%H:%M') if insert_time else '--:--',
|
||||
'amount': float(sale_amount) if sale_amount else 0.0,
|
||||
'discount': disc_amt,
|
||||
'total_before_dc': total_amt,
|
||||
'customer': customer,
|
||||
'pay_method': pay_method,
|
||||
'paid': paid,
|
||||
@ -833,8 +840,20 @@ class POSSalesGUI(QMainWindow):
|
||||
self.sales_table.setItem(row, COL['time'],
|
||||
QTableWidgetItem(sale['time']))
|
||||
|
||||
# 금액 (우측 정렬, 천단위 콤마)
|
||||
amount_item = QTableWidgetItem(f"{sale['amount']:,.0f}원")
|
||||
# 금액 (우측 정렬, 천단위 콤마, 할인 표시)
|
||||
if sale['discount'] > 0:
|
||||
amount_item = QTableWidgetItem(f"{sale['amount']:,.0f}원 (-{sale['discount']:,.0f})")
|
||||
amount_item.setForeground(QColor('#E65100'))
|
||||
f = QFont()
|
||||
f.setBold(True)
|
||||
amount_item.setFont(f)
|
||||
amount_item.setToolTip(
|
||||
f"원가: {sale['total_before_dc']:,.0f}원\n"
|
||||
f"할인: -{sale['discount']:,.0f}원\n"
|
||||
f"결제: {sale['amount']:,.0f}원"
|
||||
)
|
||||
else:
|
||||
amount_item = QTableWidgetItem(f"{sale['amount']:,.0f}원")
|
||||
amount_item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||
self.sales_table.setItem(row, COL['amount'], amount_item)
|
||||
|
||||
@ -937,12 +956,14 @@ class POSSalesGUI(QMainWindow):
|
||||
|
||||
def on_cell_clicked(self, row, column):
|
||||
"""테이블 셀 클릭 이벤트 - 적립 사용자 클릭 시 마일리지 내역 표시"""
|
||||
# 컬럼 5(적립자명), 6(전화번호), 7(적립포인트) 중 하나를 클릭했는지 확인
|
||||
if column not in [5, 6, 7]:
|
||||
# SALES_COLUMNS 기반 인덱스 사용
|
||||
COL = {key: i for i, (_, _, key) in enumerate(self.SALES_COLUMNS)}
|
||||
mileage_cols = [COL['claimed_name'], COL['claimed_phone'], COL['claimed_points']]
|
||||
if column not in mileage_cols:
|
||||
return
|
||||
|
||||
# 전화번호 가져오기 (6번 컬럼)
|
||||
phone_item = self.sales_table.item(row, 6)
|
||||
# 전화번호 가져오기
|
||||
phone_item = self.sales_table.item(row, COL['claimed_phone'])
|
||||
if not phone_item or not phone_item.text():
|
||||
# 적립 사용자가 없는 경우
|
||||
return
|
||||
|
||||
147
docs/결제수납구조.md
Normal file
147
docs/결제수납구조.md
Normal file
@ -0,0 +1,147 @@
|
||||
# PIT3000 결제/수납/할인 데이터 구조
|
||||
|
||||
## 핵심 테이블 관계
|
||||
|
||||
```
|
||||
SALE_MAIN (판매)
|
||||
└── SL_NO_order (PK, 주문번호)
|
||||
│
|
||||
├── SALE_SUB (품목 상세) — SL_NO_order로 조인
|
||||
│
|
||||
└── CD_SUNAB (수납/결제) — CD_SUNAB.PRESERIAL = SALE_MAIN.SL_NO_order
|
||||
```
|
||||
|
||||
**주의**: `CD_SUNAB.PRESERIAL`은 `SALE_MAIN.SL_NO_order`(주문번호)와 매칭됨.
|
||||
`SALE_MAIN.PRESERIAL`(처방번호)과는 다른 키임.
|
||||
|
||||
---
|
||||
|
||||
## SALE_MAIN 금액 컬럼
|
||||
|
||||
| 컬럼 | 설명 | 예시 |
|
||||
|------|------|------|
|
||||
| `SL_MY_total` | 원가 (할인 전) | 60,000 |
|
||||
| `SL_MY_discount` | 할인 금액 | 6,000 |
|
||||
| `SL_MY_sale` | **실판매가** (= total - discount) | 54,000 |
|
||||
| `SL_MY_recive` | 수납금액 (부가세 제외 추정) | 49,091 |
|
||||
| `SL_MY_credit` | 외상 금액 | 0 |
|
||||
| `SL_MY_dis_ratio` | 할인율 | 0 (미사용) |
|
||||
|
||||
### 금액 관계
|
||||
```
|
||||
SL_MY_sale = SL_MY_total - SL_MY_discount
|
||||
SL_MY_recive ≈ SL_MY_sale / 1.1 (부가세 제외 금액 추정)
|
||||
```
|
||||
|
||||
### 할인 빈도
|
||||
- 대부분의 거래: discount = 0 (할인 없음)
|
||||
- 할인 적용 건: 하루 2~5건 정도 (직원 할인, 대량 구매 등)
|
||||
- 할인 규모: 1,000원 ~ 수십만원까지 다양
|
||||
|
||||
---
|
||||
|
||||
## CD_SUNAB 결제수단 컬럼
|
||||
|
||||
### 금액 기반 결제수단 구분
|
||||
단일 구분 컬럼이 없음. **금액이 0보다 크면 해당 결제수단 사용**.
|
||||
|
||||
| 구분 | 카드 | 현금 | 외상 |
|
||||
|------|------|------|------|
|
||||
| 조제(ETC, 전문의약품) | `ETC_CARD` | `ETC_CASH` | `ETC_PAPER` |
|
||||
| OTC(일반의약품) | `OTC_CARD` | `OTC_CASH` | `OTC_PAPER` |
|
||||
|
||||
### 결제수단 판별 로직
|
||||
```python
|
||||
card_total = ETC_CARD + OTC_CARD
|
||||
cash_total = ETC_CASH + OTC_CASH
|
||||
|
||||
if card_total > 0 and cash_total > 0:
|
||||
결제수단 = "카드+현금"
|
||||
elif card_total > 0:
|
||||
결제수단 = "카드"
|
||||
elif cash_total > 0:
|
||||
결제수단 = "현금"
|
||||
else:
|
||||
결제수단 = "-" (미수납 또는 외상)
|
||||
```
|
||||
|
||||
### 카드 상세 정보
|
||||
| 컬럼 | 설명 | 예시 |
|
||||
|------|------|------|
|
||||
| `pMCHDATA` | 카드사 이름 | 비씨카드사, NH농협카드 |
|
||||
| `PCardName` | 카드사 이름 (별도) | KB국민카드 |
|
||||
| `pAPPROVAL_NUM` | 카드 승인번호 | 72139919 |
|
||||
| `pCARDINMODE` | 카드 입력 방식 | 1 (IC칩) |
|
||||
| `pTRDTYPE` | 거래 유형 | D1 (일반승인) |
|
||||
| `Appr_Gubun` | 승인 구분 | 9 (정상승인) |
|
||||
| `pCANCEL_NUM` | 취소 승인번호 | (취소 시) |
|
||||
|
||||
### 현금 상세 정보
|
||||
| 컬럼 | 설명 | 예시 |
|
||||
|------|------|------|
|
||||
| `nCASHINMODE` | 현금영수증 입력 방식 | 1, 2 (빈값=미발행) |
|
||||
| `nAPPROVAL_NUM` | 현금영수증 승인번호 | |
|
||||
| `nCHK_GUBUN` | 현금 체크 구분 | TASA |
|
||||
|
||||
---
|
||||
|
||||
## GUI 표시 방식
|
||||
|
||||
### 결제 컬럼
|
||||
- **카드**: 파란색 (#1976D2)
|
||||
- **현금**: 주황색 (#E65100)
|
||||
- **카드+현금**: 보라색 (#7B1FA2)
|
||||
- **-**: 회색 (수납 정보 없음)
|
||||
|
||||
### 수납 컬럼
|
||||
- **✓**: 녹색 (card + cash > 0)
|
||||
- **-**: 회색 (미수납)
|
||||
|
||||
### 할인 표시
|
||||
- 할인 없는 건: `12,000원` (기본)
|
||||
- 할인 있는 건: `54,000원 (-6,000)` 주황색 볼드
|
||||
- 마우스 툴팁: 원가 / 할인 / 결제 상세
|
||||
|
||||
---
|
||||
|
||||
## SQL 쿼리 (GUI에서 사용)
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
M.SL_NO_order,
|
||||
M.InsertTime,
|
||||
M.SL_MY_sale,
|
||||
ISNULL(M.SL_NM_custom, '[비고객]') AS customer_name,
|
||||
ISNULL(S.card_total, 0) AS card_total,
|
||||
ISNULL(S.cash_total, 0) AS cash_total,
|
||||
ISNULL(M.SL_MY_total, 0) AS total_amount,
|
||||
ISNULL(M.SL_MY_discount, 0) AS discount
|
||||
FROM SALE_MAIN M
|
||||
OUTER APPLY (
|
||||
SELECT TOP 1
|
||||
ISNULL(ETC_CARD, 0) + ISNULL(OTC_CARD, 0) AS card_total,
|
||||
ISNULL(ETC_CASH, 0) + ISNULL(OTC_CASH, 0) AS cash_total
|
||||
FROM CD_SUNAB
|
||||
WHERE PRESERIAL = M.SL_NO_order
|
||||
) S
|
||||
WHERE M.SL_DT_appl = ?
|
||||
ORDER BY M.InsertTime DESC
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 카드사 분포 (전체 데이터 기준)
|
||||
|
||||
| 카드사 | 건수 |
|
||||
|--------|------|
|
||||
| KB국민카드 | 6,106 |
|
||||
| NH농협카드 | 5,172 |
|
||||
| 비씨카드사 | 4,900 |
|
||||
| 하나카드 | 4,880 |
|
||||
| 신한카드 | 3,210 |
|
||||
| 삼성카드사 | 2,100 |
|
||||
| 현대카드사 | 1,960 |
|
||||
| 우리카드 | 1,285 |
|
||||
| 롯데카드사 | 837 |
|
||||
| 카카오페이 | 57 |
|
||||
| 모바일상품권 | 11 |
|
||||
Loading…
Reference in New Issue
Block a user