- wholesale 패키지 연동 (SooinSession, GeoYoungSession) - Flask Blueprint 분리 (sooin_api.py, geoyoung_api.py) - order_context 스키마 확장 (wholesaler_id, internal_code 등) - 수인약품 개별 취소 기능 (cancel_item, restore_item) - 문서 추가: WHOLESALE_API_INTEGRATION.md - 테스트 스크립트들
317 lines
8.0 KiB
Markdown
317 lines
8.0 KiB
Markdown
# 전문의약품 사용량 조회 + 지오영 주문 시스템
|
|
|
|
> 작성일: 2026-03-06
|
|
> 상태: 1단계 완료 (재고 조회), 2단계 진행 예정 (자동 주문)
|
|
|
|
---
|
|
|
|
## 📋 개요
|
|
|
|
약국의 전문의약품(처방전 조제) 사용량을 기간별로 조회하고, 지오영 도매상에서 재고를 확인하여 주문까지 연결하는 시스템.
|
|
|
|
### 핵심 기능
|
|
1. **사용량 조회**: 기간별 전문의약품 사용량 집계
|
|
2. **현재고 표시**: PIT3000 재고 데이터 연동
|
|
3. **지오영 재고 조회**: 도매상 재고 실시간 확인
|
|
4. **규격별 표시**: 30T, 100T, 300T 등 다양한 규격
|
|
5. **주문 장바구니**: 선택 품목 장바구니 담기
|
|
|
|
---
|
|
|
|
## 🗂️ 파일 구조
|
|
|
|
```
|
|
pharmacy-pos-qr-system/backend/
|
|
├── app.py # Flask 메인 (Blueprint 등록)
|
|
├── geoyoung_api.py # 지오영 API 모듈 ⭐ NEW
|
|
└── templates/
|
|
├── admin_rx_usage.html # 전문의약품 사용량 페이지 ⭐ NEW
|
|
└── admin_usage.html # OTC 사용량 페이지 ⭐ NEW
|
|
```
|
|
|
|
---
|
|
|
|
## 🔗 API 엔드포인트
|
|
|
|
### 1. 전문의약품 사용량 조회
|
|
```
|
|
GET /api/rx-usage?start_date=2026-03-01&end_date=2026-03-06&sort=qty_desc
|
|
```
|
|
|
|
**파라미터:**
|
|
| 파라미터 | 설명 | 예시 |
|
|
|---------|------|------|
|
|
| start_date | 시작일 (YYYY-MM-DD) | 2026-03-01 |
|
|
| end_date | 종료일 (YYYY-MM-DD) | 2026-03-06 |
|
|
| search | 검색어 (약품명, 코드) | 레바미피드 |
|
|
| sort | 정렬 (qty_desc, qty_asc, name_asc, amount_desc, rx_desc) | qty_desc |
|
|
|
|
**응답:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"items": [
|
|
{
|
|
"drug_code": "670400830",
|
|
"product_name": "휴니즈레바미피드정_(0.1g/1정)",
|
|
"supplier": "(주)휴온스메디텍",
|
|
"total_qty": 15,
|
|
"total_dose": 980,
|
|
"total_amount": 12500,
|
|
"prescription_count": 45,
|
|
"current_stock": 3809,
|
|
"barcode": "",
|
|
"thumbnail": null
|
|
}
|
|
],
|
|
"stats": {
|
|
"period_days": 6,
|
|
"product_count": 312,
|
|
"total_qty": 1500,
|
|
"total_dose": 15042,
|
|
"total_amount": 321837881
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. 지오영 재고 조회 (보험코드)
|
|
```
|
|
GET /api/geoyoung/stock?kd_code=670400830
|
|
```
|
|
|
|
**응답:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"keyword": "670400830",
|
|
"count": 2,
|
|
"items": [
|
|
{
|
|
"insurance_code": "670400830",
|
|
"manufacturer": "휴온스메디텍",
|
|
"product_name": "레바미피드정 300T 휴온스메디케어(구.휴니즈)",
|
|
"specification": "300T",
|
|
"stock": 0
|
|
},
|
|
{
|
|
"insurance_code": "670400830",
|
|
"manufacturer": "휴온스메디텍",
|
|
"product_name": "레바미피드정 30T 휴온스메디케어(구.휴니즈)",
|
|
"specification": "30T",
|
|
"stock": 0
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### 3. 지오영 재고 조회 (제품명 → 성분 추출)
|
|
```
|
|
GET /api/geoyoung/stock-by-name?product_name=휴니즈레바미피드정_(0.1g/1정)
|
|
```
|
|
|
|
성분명 "레바미피드"를 추출하여 검색 → 여러 제약사 제품 반환
|
|
|
|
### 4. 지오영 세션 상태
|
|
```
|
|
GET /api/geoyoung/session-status
|
|
```
|
|
|
|
---
|
|
|
|
## 🗄️ 데이터베이스 구조
|
|
|
|
### MSSQL - PM_PRES (처방전)
|
|
|
|
**PS_sub_pharm** - 처방 상세
|
|
| 컬럼 | 설명 |
|
|
|------|------|
|
|
| PreSerial | 처방전 일련번호 |
|
|
| Indate | 조제일 (YYYYMMDD) |
|
|
| DrugCode | 약품코드 |
|
|
| QUAN | 수량 |
|
|
| Days | 투약일수 |
|
|
| DRUPRICE | 약가 |
|
|
|
|
### MSSQL - PM_DRUG (약품)
|
|
|
|
**CD_GOODS** - 약품 마스터
|
|
| 컬럼 | 설명 |
|
|
|------|------|
|
|
| DrugCode | 약품코드 (PK) |
|
|
| GoodsName | 약품명 |
|
|
| SplName | 제조사명 |
|
|
| BARCODE | 바코드 |
|
|
|
|
**IM_total** - 현재고 ⭐ 중요
|
|
| 컬럼 | 설명 |
|
|
|------|------|
|
|
| DrugCode | 약품코드 |
|
|
| **IM_QT_sale_debit** | **현재고 수량** |
|
|
|
|
### 현재고 조회 쿼리
|
|
```sql
|
|
SELECT
|
|
P.DrugCode,
|
|
G.GoodsName,
|
|
ISNULL(IT.IM_QT_sale_debit, 0) as current_stock
|
|
FROM PS_sub_pharm P
|
|
LEFT JOIN PM_DRUG.dbo.CD_GOODS G ON P.DrugCode = G.DrugCode
|
|
LEFT JOIN PM_DRUG.dbo.IM_total IT ON P.DrugCode = IT.DrugCode
|
|
```
|
|
|
|
---
|
|
|
|
## 🏭 지오영 API 연동
|
|
|
|
### 아키텍처
|
|
```
|
|
[브라우저] → [Flask API] → [GeoyoungSession] → [지오영 웹]
|
|
↓
|
|
[Playwright 로그인] (최초 1회)
|
|
↓
|
|
[requests 검색] (이후 빠름)
|
|
```
|
|
|
|
### 세션 관리 (geoyoung_api.py)
|
|
```python
|
|
class GeoyoungSession:
|
|
"""싱글톤 패턴, 세션 30분 유지"""
|
|
|
|
def login(self):
|
|
# Playwright로 로그인 → 쿠키 획득
|
|
# requests 세션에 쿠키 복사
|
|
|
|
def search_stock(self, keyword):
|
|
# requests로 빠른 검색
|
|
# POST /Home/PartialSearchProduct
|
|
```
|
|
|
|
### 성능
|
|
| 요청 | 소요시간 | 비고 |
|
|
|------|----------|------|
|
|
| 첫 요청 (로그인) | ~12초 | Playwright 브라우저 |
|
|
| 이후 요청 | **~2.5초** | requests 재사용 |
|
|
| 세션 유효기간 | 30분 | 자동 재로그인 |
|
|
|
|
### 지오영 로그인 정보
|
|
```
|
|
URL: https://gwn.geoweb.kr
|
|
ID: 7390
|
|
PW: trajet6640
|
|
```
|
|
|
|
---
|
|
|
|
## 💻 UI 사용법
|
|
|
|
### 페이지 접속
|
|
```
|
|
http://localhost:7001/admin/rx-usage
|
|
```
|
|
|
|
### 기능
|
|
1. **날짜 선택**: 시작일/종료일 지정
|
|
2. **검색**: 약품명, 코드로 필터
|
|
3. **정렬**: 투약량순, 처방건수순, 금액순
|
|
4. **지오영 조회**: 행 **더블클릭** → 모달
|
|
5. **장바구니**: 체크 후 "장바구니 추가"
|
|
6. **주문서**: "주문서 생성" → 클립보드 복사
|
|
|
|
### 색상 의미 (현재고)
|
|
- 🟢 초록: 재고 충분 (현재고 > 사용량)
|
|
- 🟡 노랑: 재고 부족 (현재고 < 사용량)
|
|
- 🔴 빨강: 재고 없음 (0)
|
|
|
|
---
|
|
|
|
## 🚀 향후 개발 계획
|
|
|
|
### 2단계: 자동 주문
|
|
- [ ] 지오영 장바구니 담기 API
|
|
- [ ] 주문 확정 API (dry_run 모드)
|
|
- [ ] 주문 내역 SQLite 저장
|
|
|
|
### 3단계: 다중 도매상
|
|
- [ ] 수인 API 연동
|
|
- [ ] 도매상 선택 UI
|
|
- [ ] 재고 비교 (A사 vs B사)
|
|
|
|
### 4단계: 스마트 주문
|
|
- [ ] 사용량 기반 최적 규격 추천
|
|
- 예: 220개 필요 → "30T x 8개" vs "300T x 1개"
|
|
- [ ] 분할 주문 (오전/오후)
|
|
- [ ] 주문 누적 관리
|
|
|
|
### 5단계: 주문 DB
|
|
```sql
|
|
-- SQLite: orders.db
|
|
CREATE TABLE orders (
|
|
id INTEGER PRIMARY KEY,
|
|
order_date TEXT,
|
|
wholesaler TEXT, -- 'geoyoung', 'sooin'
|
|
drug_code TEXT,
|
|
product_name TEXT,
|
|
specification TEXT, -- '30T', '300T'
|
|
quantity INTEGER,
|
|
status TEXT, -- 'pending', 'ordered', 'delivered'
|
|
created_at TEXT
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 트러블슈팅
|
|
|
|
### 문제: 지오영 로그인 실패
|
|
**원인**: requests만으로는 로그인 불가 (JavaScript 필요)
|
|
**해결**: Playwright 하이브리드 방식 (로그인만 Playwright)
|
|
|
|
### 문제: 검색 결과 0개
|
|
**원인**: 보험코드가 아닌 내부 코드로 검색
|
|
**해결**: 보험코드(KD코드) 사용, 또는 성분명으로 재검색
|
|
|
|
### 문제: 현재고가 0으로 표시
|
|
**원인**: IM_inventory 테이블이 비어있음
|
|
**해결**: `IM_total.IM_QT_sale_debit` 컬럼 사용
|
|
|
|
### 문제: Flask 서버 시작 안됨
|
|
**원인**: stdout 인코딩 문제 (Start-Process 사용 시)
|
|
**해결**: geoyoung_api.py에서 stdout 재설정 코드 제거
|
|
|
|
---
|
|
|
|
## 📝 관련 파일 참조
|
|
|
|
### 지오영 크롤러 원본
|
|
```
|
|
c:\Users\청춘약국\source\person-lookup-web-local\crawler\
|
|
├── gangwon_geoyoung_api.py # API 클라이언트
|
|
├── gangwon_geoyoung_order.py # 주문 자동화 (order_by_kd_code)
|
|
└── gangwon_geoyoung_crawler.py # 데이터 크롤링
|
|
```
|
|
|
|
### 주문 함수 사용 예시
|
|
```python
|
|
from gangwon_geoyoung_order import order_by_kd_code
|
|
|
|
# 테스트 (실제 주문 안함)
|
|
result = await order_by_kd_code("670400830", quantity=10, dry_run=True)
|
|
|
|
# 실제 주문
|
|
result = await order_by_kd_code("670400830", quantity=10, dry_run=False)
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ 체크리스트
|
|
|
|
- [x] 전문의약품 사용량 조회 API
|
|
- [x] 현재고 표시 (IM_total)
|
|
- [x] 지오영 재고 조회 API
|
|
- [x] 지오영 세션 관리 (속도 개선)
|
|
- [x] UI 모달 (더블클릭)
|
|
- [x] 장바구니 기능
|
|
- [ ] 지오영 실제 주문 연동
|
|
- [ ] 주문 내역 DB 저장
|
|
- [ ] 다중 도매상 지원
|