# 수인약품 (Sooin) API 문서 ## 개요 - **회사명**: 수인약품 - **웹사이트**: http://sooinpharm.co.kr - **인증방식**: Playwright 로그인 → requests 쿠키 재사용 (세션 30분 유효) ## 인증 정보 (환경변수) ``` SOOIN_USER_ID=thug0bin SOOIN_PASSWORD=@Trajet6640 SOOIN_VENDOR_CODE=50911 SOOIN_VENDOR_NAME=청춘약국 ``` ## 핵심 URL 구조 ### 기존 구현된 URL | URL | 용도 | |-----|------| | `/Homepage/intro.asp` | 로그인 페이지 | | `/Service/Order/Order.asp` | 제품 검색 | | `/Service/Order/BagOrder.asp` | 장바구니 추가 | | `/Service/Order/Bag.asp` | 장바구니 조회 | | `/Service/Order/ControlBag.asp` | 장바구니 항목 제어 (취소/복원) | | `/Service/Order/OrderEnd.asp` | 주문 전송 (확정) | | `/Service/Order/PhysicInfo.asp` | 제품 상세 정보 | | `/Service/SalesLedger/SalesLedger.asp` | 잔고/매출 조회 | ### 🆕 신규 구현 필요 URL (주문 조회) | URL | 용도 | |-----|------| | `/Service/Report/Report.asp` | **주문 내역 목록 조회** | | `/Service/Report/Report.asp?f=view&orderNum=...` | **주문 상세 조회** | ## 주문 조회 URL 분석 ### 주문 목록 URL 예시 ``` http://sooinpharm.co.kr/Service/Report/Report.asp? sDate=2026-03-01 # 시작일 &eDate=2026-03-07 # 종료일 &tx_ven=50911 # 거래처 코드 (SOOIN_VENDOR_CODE) &currVenNm=청춘약국 # 거래처명 (URL 인코딩됨) &orderStatus=0 # 주문상태 (0=전체?) &ListOrder=0 # 정렬 (0=기본) &PhysicNm= # 제품명 필터 (선택) &sg= # 미확인 &page=1 # 페이지 번호 ``` ### 주문 상세 URL 예시 ``` http://sooinpharm.co.kr/Service/Report/Report.asp? f=view # view 모드 (상세 조회) &orderNum=202603095091177 # 주문번호 (YYYYMMDD + 거래처코드 + 순번?) &Ifflag= # 미확인 &sDate=2026-03-01 &eDate=2026-03-07 &PhysicNm= &ListOrder=0 &tx_ven=50911 &currVenNm=청춘약국 &orderStatus=0 &sg= &page=1 ``` ### 주문번호 구조 분석 - `202603095091177` → `20260309` (날짜) + `50911` (거래처코드) + `77` (순번?) - 형식: `YYYYMMDD` + `VENDOR_CODE` + `SEQ` ## API 엔드포인트 ### Flask Blueprint: `/api/sooin/*` | Method | Endpoint | 설명 | |--------|----------|------| | GET | `/api/sooin/stock` | 재고 조회 | | GET | `/api/sooin/session-status` | 세션 상태 확인 | | GET | `/api/sooin/balance` | 잔고(미수금) 조회 | | GET | `/api/sooin/monthly-sales` | 월간 매출 조회 | | GET | `/api/sooin/cart` | 장바구니 조회 | | POST | `/api/sooin/cart/clear` | 장바구니 비우기 | | POST | `/api/sooin/cart/cancel` | 장바구니 항목 취소 | | POST | `/api/sooin/cart/restore` | 취소 항목 복원 | | POST | `/api/sooin/order` | 주문 (장바구니 추가) | | POST | `/api/sooin/confirm` | 주문 확정 | | POST | `/api/sooin/full-order` | 전체 주문 (검색→담기→확정) | | POST | `/api/sooin/order-batch` | 일괄 주문 | | **GET** | **`/api/sooin/orders`** | **✅ 주문 목록 조회** | | **GET** | **`/api/sooin/orders/`** | **✅ 주문 상세 조회** | | **GET** | **`/api/sooin/orders/today-summary`** | **✅ 오늘 주문 집계** | ## 🆕 신규 구현 목표: 주문 조회 API ### 목적 1. **오늘 주문한 약 목록 조회** - 주문이 정상적으로 들어갔는지 확인 2. **제품별 주문량 집계** - 오늘의 총 주문량을 제품별로 파악 ### 구현할 API 엔드포인트 #### 1. 주문 목록 조회 ``` GET /api/sooin/orders?start_date=2026-03-01&end_date=2026-03-07 ``` **응답 예시:** ```json { "success": true, "orders": [ { "order_num": "202603095091177", "order_date": "2026-03-09", "order_time": "14:30:25", "total_amount": 125000, "item_count": 5, "status": "완료" } ], "total_count": 10 } ``` #### 2. 주문 상세 조회 ``` GET /api/sooin/orders/ ``` **응답 예시:** ```json { "success": true, "order_num": "202603095091177", "order_date": "2026-03-09", "items": [ { "product_code": "32495", // 수인 내부코드 "kd_code": "073100220", // KD코드 (있으면) "product_name": "코자정50mg", "spec": "30T", "quantity": 2, "unit_price": 15000, "amount": 30000 } ], "total_amount": 125000 } ``` #### 3. 오늘 주문 집계 (제품별) ``` GET /api/sooin/orders/today-summary ``` **응답 예시:** ```json { "success": true, "date": "2026-03-09", "summary": [ { "kd_code": "073100220", "product_name": "코자정50mg", "total_quantity": 10, "total_amount": 150000, "order_count": 3 } ], "grand_total_amount": 500000, "grand_total_items": 25 } ``` ## 파일 구조 ``` pharmacy-wholesale-api/ ├── wholesale/ │ ├── __init__.py │ ├── base.py # 공통 베이스 클래스 │ ├── sooin.py # 수인약품 핵심 로직 ← 여기에 주문 조회 메서드 추가 │ ├── geoyoung.py │ └── baekje.py └── .env # 인증 정보 pharmacy-pos-qr-system/ ├── backend/ │ ├── app.py # 메인 Flask 앱 │ ├── sooin_api.py # 수인약품 Flask Blueprint ← 여기에 API 엔드포인트 추가 │ ├── wholesale_path.py # wholesale 패키지 경로 설정 │ └── templates/ │ └── admin_rx_usage.html # 프론트엔드 (주문 조회 UI 추가 가능) └── docs/ └── SOOIN_API.md # 이 문서 ``` ## 구현 가이드 ### 1단계: SooinSession에 메서드 추가 (`wholesale/sooin.py`) ```python def get_order_list(self, start_date: str, end_date: str) -> dict: """주문 목록 조회""" # /Service/Report/Report.asp 파싱 pass def get_order_detail(self, order_num: str) -> dict: """주문 상세 조회""" # /Service/Report/Report.asp?f=view&orderNum=... 파싱 pass def get_today_order_summary(self) -> dict: """오늘 주문 제품별 집계""" # get_order_list + get_order_detail 조합 pass ``` ### 2단계: Flask API 엔드포인트 추가 (`sooin_api.py`) ```python @sooin_bp.route('/orders', methods=['GET']) def api_sooin_orders(): """주문 목록 조회""" pass @sooin_bp.route('/orders/', methods=['GET']) def api_sooin_order_detail(order_num): """주문 상세 조회""" pass @sooin_bp.route('/orders/today-summary', methods=['GET']) def api_sooin_today_summary(): """오늘 주문 집계""" pass ``` ## 주의사항 1. **인코딩**: 수인약품 사이트는 `euc-kr` 인코딩 사용 2. **세션 유지**: 30분 세션 타임아웃, 자동 재로그인 필요 3. **HTML 파싱**: BeautifulSoup으로 테이블 구조 파싱 4. **에러 처리**: 로그인 실패, 네트워크 오류 등 처리 필요