pharmacy-pos-qr-system/docs/WHOLESALE_API_INTEGRATION.md

5.6 KiB

도매상 API 통합 가이드

작성일: 2026-03-06
버전: 1.0

📦 패키지 구조

pharmacy-wholesale-api/           # 별도 리포지토리
├── wholesale/
│   ├── __init__.py              # SooinSession, GeoYoungSession 노출
│   ├── base.py                  # WholesaleSession 공통 인터페이스
│   ├── sooin.py                 # 수인약품 API
│   └── geoyoung.py              # 지오영 API
└── docs/
    └── SOOIN.md                 # 수인약품 상세 문서

pharmacy-pos-qr-system/backend/   # 기존 프로젝트
├── wholesale_path.py            # 패키지 경로 설정
├── sooin_api.py                 # Flask Blueprint (wholesale 사용)
└── geoyoung_api.py              # Flask Blueprint (wholesale 사용)

🔌 도매상별 API 특성

항목 지오영 수인약품
웹사이트 gwn.geoweb.kr sooinpharm.co.kr
인증 방식 Playwright → requests Playwright → requests
세션 유효시간 30분 30분
검색 코드 보험코드 (KD) KD코드 + 내부코드 (pc)
장바구니 추가 productCode 필요 internal_code (pc) 필요
개별 삭제 없음 체크박스 soft delete
장바구니 조회 PartialProductCart Bag.asp

🔑 핵심 발견: 코드 체계

지오영

보험코드 (KD코드) → 검색 → productCode (내부) → 장바구니 추가

수인약품

KD코드 → 검색 → internal_code (pc) → 장바구니 추가
                     ↓
              PhysicInfo.asp?pc=32495 에서 추출

⚠️ 중요: internal_code가 없으면 장바구니 추가 불가!


🛒 수인약품 개별 취소 (Soft Delete)

발견 과정

  • kind=delOne API 존재하지만 작동 안 함
  • 체크박스가 실제 "취소" 역할
  • ControlBag.asp AJAX 엔드포인트 발견

API 사용법

from wholesale import SooinSession

session = SooinSession()
session.login()

# 장바구니 조회 (체크 상태 포함)
cart = session.get_cart()
# cart['items'][0]['checked'] = False (활성)
# cart['items'][0]['active'] = True

# 항목 취소 (체크)
session.cancel_item(row_index=0)
# 또는
session.cancel_item(product_code="32495")

# 취소 복원 (체크 해제)
session.restore_item(row_index=0)

내부 동작

POST /Service/Order/ControlBag.asp
Content-Type: application/x-www-form-urlencoded; charset=euc-kr
X-Requested-With: XMLHttpRequest

vc=50911        (거래처코드)
pc=32495        (내부 제품코드)
f=true          (true=취소, false=복원)
pg=             (제품구분, 빈값)
pdno=           (제품번호, 빈값)
tmdt=           (기한, 빈값)

📊 SQLite 스키마 연동

order_context (AI 학습용)

-- 새로 추가된 필드 (2026-03-06)
wholesaler_id TEXT,        -- 'geoyoung' 또는 'sooin'
wholesaler_price INTEGER,  -- 도매상 가격
internal_code TEXT,        -- 도매상 내부 코드
was_cancelled BOOLEAN,     -- 취소 여부 (수인 soft delete)

도매상별 주문 시 기록할 데이터

order_context = {
    'drug_code': 'D12345',
    'product_name': '아세탑정',
    'wholesaler_id': 'sooin',
    'internal_code': '32495',        # 수인 내부코드
    'ordered_spec': '30T',
    'ordered_qty': 2,
    'wholesaler_price': 4800,
    'available_specs': '["30T", "500T"]',
    'spec_stocks': '{"30T": 0, "500T": 0}',  # 재고 상황
    'selection_reason': 'only_option',
    'was_cancelled': False
}

🔄 Flask API 엔드포인트

수인약품 (/api/sooin/*)

메서드 경로 설명
GET /stock 재고 검색
GET /cart 장바구니 조회
POST /order 장바구니 추가
POST /cart/clear 장바구니 비우기
POST /cart/cancel 항목 취소 (soft delete)
POST /cart/restore 항목 복원
POST /confirm 주문 전송

지오영 (/api/geoyoung/*)

메서드 경로 설명
GET /stock 재고 검색
GET /cart 장바구니 조회
POST /order 장바구니 추가
POST /cart/clear 장바구니 비우기
POST /cart/cancel 항목 삭제 (hard delete)
POST /cart/restore NOT_SUPPORTED
POST /confirm 주문 전송

개별 삭제 API 차이

도매상 cancel 동작 restore 가능 내부 API
수인 체크박스 soft delete 가능 ControlBag.asp
지오영 완전 삭제 불가 DataCart/del

📁 관련 문서

문서 위치 내용
AI ERP 자동주문 기획 docs/AI_ERP_AUTO_ORDER_SYSTEM.md 전체 시스템 설계
지오영 API 분석 docs/GEOYOUNG_API_REVERSE_ENGINEERING.md 지오영 리버스 엔지니어링
수인 API 분석 pharmacy-wholesale-api/docs/SOOIN.md 수인 리버스 엔지니어링
사용량 조회 가이드 docs/RX_USAGE_GEOYOUNG_GUIDE.md 처방 사용량 조회

체크리스트

완료

  • 지오영 API 연동
  • 수인약품 API 연동
  • 개별 취소 기능 (수인) - soft delete
  • 개별 삭제 기능 (지오영) - hard delete
  • Flask Blueprint 통합
  • wholesale 패키지 분리
  • SQLite 스키마 업데이트

진행 예정

  • daily_usage 자동 수집
  • AI 규격 선택 모델
  • AI 도매상 선택 모델
  • 자동 주문 Level 1 (승인 후 실행)

업데이트: 2026-03-06 by 용림 🐉