pharmacy-pos-qr-system/docs/SUIN_API_FIX.md
thug0bin 83ecf88bd4 feat(animal-chat): APC 코드 2024년 체계 지원 및 피부약 2단계 추천
## APC 코드 체계 확장
- 기존: 023%만 검색 (~2023년 제품만)
- 변경: 02% OR 92% + 13자리 검증
  - 02%: 2023년 이전 item_seq (9자리) 기반 APC
  - 92%: 2024년 이후 item_seq (10자리) 기반 APC
- 999% 등 청구프로그램 임의코드는 제외

## 동물약 챗봇 피부약 추천 개선
- 피부약 2단계 추천 구조 추가
  - 1차(치료): 의약품 (개시딘겔, 테르비덤 등)
  - 2차(보조케어): 의약외품 (스킨카솔 - 회복기 피부보호)
- 스킨카솔은 의약외품임을 명시하여 치료제로 오인 방지

## 기타
- RAG 테스트 스크립트 추가
- 수인약품 API 문서화
2026-03-11 14:20:44 +09:00

131 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 수인 API 주문 수량 파싱 문제 수정
**날짜**: 2026-03-09
**문제**: 라미실크림 15g 주문 시 **1개 → 15개**로 잘못 표시
**원인**: `parse_spec` 함수에서 용량 단위(g, ml)를 정량 단위(T, 정)로 착각
## 📋 문제 상황
| 도매상 | 제품 | 실제 주문 | 표시된 수량 |
|--------|------|----------|------------|
| 동원 | 라미실크림 15g | 1개 | **1개** ✅ |
| 수인 | 라미실크림 15g | 1개 | **15개** ❌ |
## 🔍 원인 분석
### 문제 코드 위치
- **파일**: `sooin_api.py` (Flask Blueprint)
- **API**: `GET /api/sooin/orders/summary-by-kd`
- **함수**: `parse_spec()`
### 기존 코드 (문제)
```python
def parse_spec(spec: str) -> int:
if not spec:
return 1
match = re.search(r'(\d+)', spec)
return int(match.group(1)) if match else 1
```
**문제점**: 규격에서 **숫자만 추출**
- `'30T'` → 30 (정제 30정) ✅
- `'15g'` → 15 🚨 **문제!** (튜브 15그램인데 15개로 계산)
### 계산 과정
```
수인 라미실크림 15g 1박스 주문
→ quantity = 1
→ per_unit = parse_spec('15g') = 15
→ total_units = 1 × 15 = 15개 ❌
```
### 동원 API는 정상인 이유
동원의 `parse_spec()` (wholesale/dongwon.py:1718-1720):
```python
# mg/ml 등의 용량 단위는 1로 처리
if re.search(r'\d+\s*(mg|ml|g)\b', spec, re.IGNORECASE):
return 1
```
## ✅ 수정 내용
### 수정된 코드
```python
def parse_spec(spec: str) -> int:
"""
규격에서 박스당 단위 수 추출
정량 단위 (T, 정, 캡슐, C, PTP, 포 등): 숫자 추출
용량 단위 (g, ml, mL, mg, L 등): 1 반환 (튜브/병 단위)
예시:
- '30T' → 30 (정제 30정)
- '100정(PTP)' → 100
- '15g' → 1 (튜브 1개)
- '10ml' → 1 (병 1개)
- '500mg' → 1 (용량 표시)
"""
if not spec:
return 1
spec_lower = spec.lower()
# 용량 단위 패턴: 숫자 + g/ml/mg/l (단독 또는 끝)
# 이 경우 튜브/병 단위이므로 1 반환
volume_pattern = r'^\d+\s*(g|ml|mg|l)(\s|$|\)|/)'
if re.search(volume_pattern, spec_lower):
return 1
# 정량 단위 패턴: 숫자 + T/정/캡슐/C/PTP/포
qty_pattern = r'(\d+)\s*(t|정|캡슐?|c|ptp|포|tab|cap)'
qty_match = re.search(qty_pattern, spec_lower)
if qty_match:
return int(qty_match.group(1))
# 기본: 숫자만 있으면 추출하되, 용량 단위 재확인
# 끝에 g/ml이 있으면 1 반환
if re.search(r'\d+(g|ml)$', spec_lower):
return 1
# 그 외 숫자 추출
match = re.search(r'(\d+)', spec)
return int(match.group(1)) if match else 1
```
### 수정 결과
| 규격 | 기존 결과 | 수정 후 결과 |
|------|----------|-------------|
| `'30T'` | 30 | 30 ✅ |
| `'100정(PTP)'` | 100 | 100 ✅ |
| `'15g'` | 15 ❌ | **1** ✅ |
| `'10ml'` | 10 ❌ | **1** ✅ |
| `'500mg'` | 500 ❌ | **1** ✅ |
## 📁 관련 파일
| 파일 | 역할 |
|------|------|
| `backend/sooin_api.py` | Flask Blueprint (수정됨) |
| `wholesale/sooin.py` | 수인약품 핵심 API 클래스 |
| `wholesale/dongwon.py` | 동원약품 API (참고) |
## 🔄 적용 방법
```bash
# Flask 서버 재시작
pm2 restart flask-pharmacy
```
## 🧪 테스트
```bash
# 수인 주문 조회 API 테스트
curl "http://localhost:7001/api/sooin/orders/summary-by-kd?start_date=2026-03-01&end_date=2026-03-09"
```
## 📝 참고
- **도매상 API 문서**: `docs/WHOLESALE_API_INTEGRATION.md`
- **수인 API 문서**: `docs/SOOIN_API.md`
- **동원 API**: 이미 올바른 `parse_spec` 로직 적용됨