pharmacy-pos-qr-system/docs/RX_USAGE_GEOYOUNG_GUIDE.md
thug0bin c1596a6d35 feat: 도매상 API 통합 및 스키마 업데이트
- 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
- 테스트 스크립트들
2026-03-06 11:50:46 +09:00

8.0 KiB

전문의약품 사용량 조회 + 지오영 주문 시스템

작성일: 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

응답:

{
  "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

응답:

{
  "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 현재고 수량

현재고 조회 쿼리

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)

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

-- 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  # 데이터 크롤링

주문 함수 사용 예시

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)

체크리스트

  • 전문의약품 사용량 조회 API
  • 현재고 표시 (IM_total)
  • 지오영 재고 조회 API
  • 지오영 세션 관리 (속도 개선)
  • UI 모달 (더블클릭)
  • 장바구니 기능
  • 지오영 실제 주문 연동
  • 주문 내역 DB 저장
  • 다중 도매상 지원