diff --git a/CLAUDECODE.md b/CLAUDECODE.md new file mode 100644 index 0000000..be92641 --- /dev/null +++ b/CLAUDECODE.md @@ -0,0 +1,441 @@ +# 청춘약국 마일리지 QR 시스템 + +## 프로젝트 개요 +약국 POS 시스템과 연동하여 고객이 QR 코드를 스캔하면 자동으로 마일리지가 적립되는 시스템 + +--- + +## 🌐 접속 URL (외부 접속 가능) + +### 실시간 서버 (리버스 프록시) +- **메인 페이지**: https://mile.0bin.in/ +- **간편 적립**: https://mile.0bin.in/claim?t={토큰} +- **마이페이지**: https://mile.0bin.in/my-page +- **관리자 페이지**: https://mile.0bin.in/admin + +### 로컬 서버 +- **로컬 주소**: http://localhost:7001/ +- **서버 포트**: 7001 +- **실행 명령**: `cd backend && python app.py` + +--- + +## 📂 프로젝트 구조 + +``` +pharmacy-pos-qr-system/ +├── backend/ +│ ├── app.py # Flask 웹 서버 (포트 7001) +│ ├── db/ +│ │ ├── dbsetup.py # DB 연결 관리자 (MSSQL + SQLite) +│ │ ├── mileage_schema.sql # SQLite 스키마 +│ │ └── mileage.db # SQLite 데이터베이스 파일 +│ ├── utils/ +│ │ ├── qr_token_generator.py # QR 토큰 생성 (SHA256 해시) +│ │ └── qr_label_printer.py # QR 라벨 인쇄 (Brother QL-810W) +│ ├── gui/ +│ │ └── pos_sales_gui.py # POS 판매 GUI (PyQt5) +│ ├── templates/ # Flask HTML 템플릿 +│ │ ├── claim_form.html # 간편 적립 페이지 +│ │ ├── my_page.html # 마이페이지 +│ │ ├── my_page_login.html # 마이페이지 로그인 +│ │ ├── admin.html # 관리자 대시보드 +│ │ └── error.html # 에러 페이지 +│ └── test_integration.py # 통합 테스트 스크립트 +└── CLAUDECODE.md # 이 문서 +``` + +--- + +## 🚀 핵심 기능 + +### Phase 2: QR 라벨 인쇄 ✅ +1. **토큰 생성**: SHA256 해시 기반, 30일 유효기간 +2. **QR 코드**: 200x200px, 높은 오류 복원력 (ERROR_CORRECT_H) +3. **URL 최적화**: 약 68자 (빠른 스캔) + - 예시: `https://pharmacy.example.com/claim?t=TEST20260123145834:795d07519294` +4. **Brother QL-810W 프린터**: 29mm 가로형 라벨 (800x306px) +5. **POS GUI 통합**: QR 생성 버튼, 미리보기 모드 + +### Phase 3: 간편 적립 웹앱 ✅ +1. **간편 가입/적립**: 전화번호 + 이름만 입력 +2. **자동 회원 생성**: 신규 사용자 자동 등록 +3. **마일리지 원장**: 모든 적립 내역 추적 +4. **마이페이지**: 전화번호로 포인트 조회 +5. **관리자 페이지**: 전체 사용자/적립 현황 조회 +6. **거래 세부 조회**: MSSQL 연동으로 판매 상품 상세 확인 (모달 팝업) +7. **모던 UI**: Noto Sans KR 폰트, 반응형 디자인 +8. **POS GUI 통합**: SQLite 적립 사용자 정보 표시 (이름, 전화번호) +9. **실시간 동기화**: 30초마다 자동 새로고침으로 적립 상태 실시간 반영 + +--- + +## 📊 데이터베이스 + +### SQLite (mileage.db) +위치: `backend/db/mileage.db` + +#### 1. users (사용자) +```sql +- id: 사용자 ID (자동 증가) +- nickname: 이름 +- phone: 전화번호 (하이픈 제거, 10-11자리) +- mileage_balance: 포인트 잔액 +- created_at: 가입일 +``` + +#### 2. claim_tokens (QR 토큰) +```sql +- id: 토큰 ID +- transaction_id: 거래 번호 (UNIQUE) +- token_hash: SHA256 해시 (UNIQUE) +- total_amount: 판매 금액 +- claimable_points: 적립 포인트 (3%) +- expires_at: 만료일 (30일) +- claimed_at: 적립 완료 시간 +- claimed_by_user_id: 적립한 사용자 +``` + +#### 3. mileage_ledger (마일리지 원장) +```sql +- id: 원장 ID +- user_id: 사용자 ID +- transaction_id: 거래 번호 +- points: 포인트 변동량 +- balance_after: 변동 후 잔액 +- reason: 사유 (CLAIM, USE 등) +- description: 상세 설명 +``` + +### MSSQL (POS 시스템 - PIT3000) + +위치: `PM_PRES` 데이터베이스 + +#### SALE_MAIN (판매 헤더) + +```sql +- SL_NO_order: 거래 번호 (Primary Key) +- SL_DT_appl: 거래 날짜 +- InsertTime: 거래 일시 +- SL_MY_total: 총액 (할인 전) +- SL_MY_discount: 할인 금액 +- SL_MY_sale: 판매 금액 (할인 후) +- SL_MY_credit: 외상 금액 +- SL_MY_recive: 수금 금액 +- SL_NM_custom: 고객명 +``` + +#### SALE_SUB (판매 상세) + +```sql +- SL_NO_order: 거래 번호 (Foreign Key) +- DrugCode: 약품 코드 +- SL_NM_item: 수량 (decimal) +- SL_INPUT_PRICE: 입력 단가 +- SL_TOTAL_PRICE: 합계 금액 +``` + +#### CD_GOODS (약품 마스터 - PM_DRUG 데이터베이스) + +```sql +- DrugCode: 약품 코드 (Primary Key) +- GoodsName: 약품명 +``` + +**JOIN 예시**: +```sql +SELECT + S.DrugCode, + ISNULL(G.GoodsName, '(약품명 없음)') AS goods_name, + S.SL_NM_item AS quantity, + S.SL_INPUT_PRICE 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 = :transaction_id +``` + +--- + +## 🔐 보안 정책 + +1. **토큰 보안** + - `token_raw`: QR 코드에만 포함 (DB 저장 X) + - `token_hash`: SHA256 해시만 DB 저장 (64자) + - `nonce`: 6바이트 암호학적 난수 (12자 hex) + - 동일 거래도 매번 다른 토큰 생성 + +2. **1회성 보장** + - `claimed_at IS NULL` 검증 + - `UNIQUE(transaction_id)` 제약 + +3. **만료 기간** + - 30일 후 자동 만료 + - `expires_at` 필드로 관리 + +--- + +## 🧪 테스트 방법 + +### 1. QR 토큰 생성 및 라벨 테스트 +```bash +cd backend +python test_integration.py +``` + +출력 예시: +``` +[OK] QR URL: https://pharmacy.example.com/claim?t=TEST20260123145834:795d07519294 +[OK] URL 길이: 68 문자 +[OK] 적립 포인트: 2250P +[OK] 이미지 저장: backend/samples/temp/qr_receipt_TEST20260123145834_20260123_145834.png +``` + +### 2. Flask 서버 실행 +```bash +cd backend +python app.py +``` + +서버 접속: http://localhost:7001/ + +### 3. 전체 흐름 테스트 +1. **QR 생성**: `test_integration.py` 실행 +2. **웹앱 접속**: 생성된 URL로 이동 +3. **간편 적립**: 전화번호 + 이름 입력 +4. **마이페이지**: 적립 내역 확인 +5. **관리자 페이지**: 전체 현황 확인 + +--- + +## 📝 API 엔드포인트 + +### GET / +메인 페이지 (안내) + +### GET /claim?t={transaction_id}:{nonce} +간편 적립 페이지 +- 토큰 검증 +- 구매 금액 및 적립 포인트 표시 +- 전화번호/이름 입력 폼 + +### POST /api/claim +마일리지 적립 API +```json +{ + "transaction_id": "거래번호", + "nonce": "12자 hex", + "phone": "전화번호", + "name": "이름" +} +``` + +응답: +```json +{ + "success": true, + "message": "2250P 적립 완료!", + "points": 2250, + "balance": 2250, + "is_new_user": true +} +``` + +### GET /my-page +마이페이지 (로그인) + +### GET /my-page?phone={전화번호} +마이페이지 (포인트 조회) + +### GET /admin +관리자 대시보드 +- 총 가입자 수 +- 누적 포인트 잔액 +- QR 발행 건수 +- 적립 완료율 +- 최근 가입 사용자 (20명) +- 최근 적립 내역 (50건) +- 최근 QR 발행 내역 (20건) + +### GET /admin/transaction/{transaction_id} + +거래 세부 내역 조회 API (MSSQL 연동) + +응답: + +```json +{ + "success": true, + "transaction": { + "id": "20260123000042", + "date": "2026-01-23 14:30:15", + "customer_name": "홍길동", + "total_amount": 50000, + "discount": 5000, + "sale_amount": 45000, + "credit": 0, + "received": 45000 + }, + "items": [ + { + "code": "A001234", + "name": "타이레놀 500mg", + "qty": 2, + "price": 5000, + "total": 10000 + } + ] +} +``` + +--- + +## 🎨 UI/UX 특징 + +### 디자인 시스템 +- **폰트**: Noto Sans KR (Google Fonts) +- **컬러**: + - Primary: `#6366f1` (인디고) + - Secondary: `#8b5cf6` (바이올렛) + - Background: `#f5f7fa` + - Text: `#212529`, `#495057`, `#868e96` +- **Border Radius**: 14px ~ 24px +- **그림자**: `0 4px 24px rgba(0, 0, 0, 0.06)` + +### 애니메이션 +- **체크마크**: stroke-dasharray 애니메이션 +- **버튼**: scale(0.98) on active +- **성공 아이콘**: scaleIn + bounce + +### 반응형 +- 모바일 최적화 (min-width: 420px) +- 테이블 스크롤 지원 +- Touch-friendly 버튼 크기 + +--- + +## ⚙️ 설정 파일 + +### QR 토큰 생성 (qr_token_generator.py) +```python +MILEAGE_RATE = 0.03 # 3% 적립 +TOKEN_EXPIRY_DAYS = 30 # 30일 유효기간 +QR_BASE_URL = "https://mile.0bin.in/claim" +``` + +### 라벨 프린터 (qr_label_printer.py) +```python +PRINTER_IP = "192.168.0.168" +PRINTER_PORT = 9100 +PRINTER_MODEL = "QL-810W" +LABEL_TYPE = "29" # 29mm 라벨 +``` + +### Flask 서버 (app.py) +```python +app.run(host='0.0.0.0', port=7001, debug=True) +``` + +--- + +## 🔧 유지보수 + +### DB 백업 +```bash +# SQLite 백업 +sqlite3 backend/db/mileage.db ".backup 'backup/mileage_backup_20260123.db'" + +# 또는 단순 복사 +cp backend/db/mileage.db backup/mileage_backup_20260123.db +``` + +### DB 조회 +```bash +# SQLite 연결 +sqlite3 backend/db/mileage.db + +# 사용자 조회 +SELECT * FROM users; + +# 적립 내역 조회 +SELECT * FROM mileage_ledger; + +# QR 토큰 조회 +SELECT * FROM claim_tokens; +``` + +### 로그 확인 +Flask 서버는 콘솔에 로그를 출력합니다: +``` +[DB Manager] SQLite 기존 DB 연결: E:\cclabel\pharmacy-pos-qr-system\backend\db\mileage.db +* Running on http://0.0.0.0:7001 +``` + +--- + +## 🚨 트러블슈팅 + +### 1. QR 코드가 인식되지 않을 때 +- QR 크기: 200x200px (충분히 큼) +- Error correction: H (30% 복원) +- URL 길이: 68자 (최적화됨) +- 조명 확인, 카메라 초점 확인 + +### 2. 적립이 안 될 때 +- 토큰 만료 확인 (30일) +- 이미 적립된 토큰인지 확인 (`claimed_at`) +- DB 연결 상태 확인 + +### 3. 프린터 연결 안 될 때 +- IP 주소 확인: `192.168.0.168` +- 네트워크 연결 확인 +- 프린터 전원 확인 + +### 4. 한글이 깨질 때 +- 폰트 경로 확인: `C:\Windows\Fonts\malgunbd.ttf` +- 폴백 폰트 사용 여부 로그 확인 + +--- + +## 📌 TODO / 개선 사항 + +### Phase 4 (선택) +- [ ] 카카오 로그인 연동 (customer_identities 테이블 활용) +- [ ] SMS 알림 (적립 완료 시 문자 발송) +- [ ] 실제 도메인 적용 (QR_BASE_URL 변경) +- [ ] HTTPS 적용 (SSL 인증서) +- [ ] 포인트 사용 기능 (결제 시 차감) +- [ ] 관리자 로그인 (비밀번호 보호) +- [ ] 통계 그래프 (Chart.js) +- [ ] 엑셀 내보내기 (사용자/적립 내역) + +--- + +## 📞 문의 + +- **프로젝트**: 청춘약국 마일리지 QR 시스템 +- **개발 기간**: 2026년 1월 +- **기술 스택**: Python, Flask, SQLite, PyQt5, Brother QL +- **접속 URL**: https://mile.0bin.in/ + +--- + +## 📚 참고 자료 + +### 주요 라이브러리 +- Flask: 웹 프레임워크 +- SQLite3: 경량 데이터베이스 +- qrcode: QR 코드 생성 +- Pillow: 이미지 처리 +- brother_ql: Brother QL 프린터 제어 +- PyQt5: POS GUI + +### 외부 링크 +- Flask 문서: https://flask.palletsprojects.com/ +- Brother QL Python: https://github.com/pklaus/brother_ql +- QRCode 문서: https://pypi.org/project/qrcode/ + +--- + +**마지막 업데이트**: 2026-01-23 +**버전**: Phase 3 완료 (간편 적립 + 관리자 페이지 + 거래 세부 조회)