pharmacy-pos-qr-system/docs/API_DEVELOPMENT_GUIDE.md
thug0bin e470deaefc fix: rx-usage 쿼리에 PS_Type!=9 조건 추가 (실제 조제된 약만 집계)
- patient_query: 대체조제 원본 처방 제외
- rx_query: 대체조제 원본 처방 제외
- PS_Type=9는 대체조제시 원래 처방된 약(조제 안됨)
- 기타 배치 스크립트 및 문서 추가
2026-03-09 21:54:32 +09:00

7.1 KiB

API 개발 가이드 및 트러블슈팅

📋 목차

  1. 도매상 주문 API 응답 형식
  2. 동원약품 API 버그 수정

도매상 주문 API 응답 형식

/api/order/quick-submit 응답 표준

모든 도매상(지오영, 수인, 백제, 동원)의 주문 응답은 동일한 형식을 따라야 합니다:

{
    "success": true,
    "dry_run": true,
    "cart_only": false,
    "order_id": 123,
    "order_no": "ORD-20260308-001",
    "wholesaler": "dongwon",
    "total_items": 1,
    "success_count": 1,
    "failed_count": 0,
    "results": [
        {
            "item_id": 456,
            "drug_code": "643900470",
            "product_name": "부루펜정200mg",
            "specification": "500정(병)",
            "order_qty": 1,
            "status": "success",
            "result_code": "OK",
            "result_message": "[DRY RUN] 주문 가능: 재고 9, 단가 17,000원",
            "price": 17000
        }
    ],
    "note": "장바구니에 담김. 도매상 사이트에서 최종 확정 필요."
}

⚠️ 필수 필드

필드 설명 비고
wholesaler 도매상 ID 프론트엔드에서 결과 모달 표시에 사용
success_count 성공 개수 최상위 레벨에 있어야 함 (summary 안에만 있으면 안됨)
failed_count 실패 개수 최상위 레벨에 있어야 함
order_no 주문번호 프론트엔드 결과 모달에 표시

동원약품 API 버그 수정

📅 수정일: 2026-03-08

🐛 문제

증상:

  • 동원약품으로 주문하면 결과 모달에 "지오영 주문 결과"로 표시됨
  • 성공/실패 개수가 "undefined"로 표시됨

원인: submit_dongwon_order() 함수의 응답에 다음 필드가 누락됨:

  1. wholesaler 필드 없음
  2. success_count, failed_countsummary 객체 안에만 있음 (최상위에 없음)
  3. order_no 필드 없음

🔧 수정 내용

파일: backend/order_api.py

수정 전 (dry_run 응답):

return {
    'success': True,
    'dry_run': True,
    'results': results,
    'summary': {
        'total': len(items),
        'success': success_count,
        'failed': failed_count
    }
}

수정 후:

return {
    'success': True,
    'dry_run': dry_run,
    'cart_only': cart_only,
    'order_id': order_id,
    'order_no': order['order_no'],
    'wholesaler': 'dongwon',
    'total_items': len(items),
    'success_count': success_count,
    'failed_count': failed_count,
    'results': results
}

검증

테스트 절차:

  1. http://localhost:7001/admin/rx-usage 접속
  2. 테이블에서 약품 더블클릭 → 도매상 재고 모달 열기
  3. 동원약품 섹션에서 "담기" 버튼 클릭
  4. 장바구니에서 "주문서 생성하기" 클릭
  5. "🧪 테스트" 버튼 클릭
  6. 결과 모달에서 확인:
    • 제목: "🏥 동원약품 주문 결과"
    • 성공: "1개"
    • 실패: "0개"

프론트엔드 장바구니 구조

addToCartFromWholesale() 함수

동원약품에서 "담기" 버튼 클릭 시 장바구니에 추가되는 아이템 구조:

const cartItem = {
    drug_code: '643900470',
    product_name: '부루펜정200mg',
    supplier: '동원약품',
    qty: 1,
    specification: '500정(병)',
    wholesaler: 'dongwon',           // ← 필터링에 사용
    internal_code: '16045',
    dongwon_code: '16045',           // ← 동원 API 호출에 사용
    unit_price: 17000
};

도매상 필터링 로직

const WHOLESALERS = {
    dongwon: {
        filterFn: (item) => item.supplier === '동원약품' || item.wholesaler === 'dongwon'
    }
};

📝 개발 시 체크리스트

새로운 도매상 API 추가 시:

  • submit_xxx_order() 함수 응답에 wholesaler 필드 포함
  • success_count, failed_count 최상위 레벨에 포함
  • order_no 필드 포함
  • 프론트엔드 WHOLESALERS 객체에 도매상 추가
  • filterFn 함수 정의
  • E2E 테스트 수행

주문량 조회 API (summary-by-kd)

📅 추가일: 2025-07-14

📋 개요

전문의약품 사용량 페이지(/admin/rx-usage)의 "주문량" 컬럼은 도매상별 주문량을 KD 코드 기준으로 합산하여 표시합니다.

⚠️ 필수 구현: /orders/summary-by-kd 엔드포인트

새로운 도매상 추가 시 반드시 구현해야 합니다!

요청

GET /api/{wholesaler}/orders/summary-by-kd?start_date=2025-07-01&end_date=2025-07-14

응답 형식 (표준)

{
    "success": true,
    "order_count": 4,
    "period": {
        "start": "2025-07-01",
        "end": "2025-07-14"
    },
    "by_kd_code": {
        "670400830": {
            "product_name": "레바미피드정100mg",
            "spec": "100T",
            "boxes": 2,
            "units": 200
        },
        "643900470": {
            "product_name": "부루펜정200mg",
            "spec": "500정(병)",
            "boxes": 1,
            "units": 500
        }
    },
    "total_products": 2
}

현재 구현 상태

도매상 엔드포인트 KD 코드 집계 비고
지오영 /api/geoyoung/orders/summary-by-kd 정상 작동
수인 /api/sooin/orders/summary-by-kd 정상 작동
백제 /api/baekje/orders/summary-by-kd 정상 작동
동원 /api/dongwon/orders/summary-by-kd ⚠️ 주문 건수만 제공, 품목별 집계 불가

동원약품 한계

동원약품 API(onLineOrderListAX)는 주문 목록만 반환하고, 각 주문의 상세 품목(items)을 제공하지 않습니다.

향후 개선 필요:

  • 동원 주문 상세 조회 API 탐색 필요
  • 또는 주문 상세 페이지 크롤링 구현

프론트엔드 연동

admin_rx_usage.htmlloadOrderData() 함수:

// 4사 병렬 조회
const [geoRes, sooinRes, baekjeRes, dongwonRes] = await Promise.all([
    fetch(`/api/geoyoung/orders/summary-by-kd?start_date=${startDate}&end_date=${endDate}`),
    fetch(`/api/sooin/orders/summary-by-kd?start_date=${startDate}&end_date=${endDate}`),
    fetch(`/api/baekje/orders/summary-by-kd?start_date=${startDate}&end_date=${endDate}`),
    fetch(`/api/dongwon/orders/summary-by-kd?start_date=${startDate}&end_date=${endDate}`)
]);

// 각 도매상 데이터를 KD 코드 기준으로 합산
if (dongwonRes.success && dongwonRes.by_kd_code) {
    for (const [kd, data] of Object.entries(dongwonRes.by_kd_code)) {
        orderDataByKd[kd].boxes += data.boxes || 0;
        orderDataByKd[kd].units += data.units || 0;
        orderDataByKd[kd].sources.push('동원');
    }
}

📝 새 도매상 추가 시 체크리스트

  • {wholesaler}_api.py/orders/summary-by-kd 엔드포인트 구현
  • 응답 형식 표준 준수 (by_kd_code, order_count 등)
  • admin_rx_usage.htmlloadOrderData()에 새 도매상 추가
  • 합산 로직에 새 도매상 데이터 추가
  • API 테스트 수행

마지막 업데이트: 2025-07-14