pharmacy-pos-qr-system/backend/utils/drug_unit.py
thug0bin 80b3919ac9 feat(drug-usage): 단위 마스터 + 총사용량 표시 + 순차 API 호출
- drug_unit.py: SUNG_CODE 기반 단위 판별 함수 추가
- 조제 상세에 총사용량 + 단위 표시 (예: 1,230정)
- API 순차 호출로 DB 세션 충돌 방지
2026-03-11 21:47:53 +09:00

161 lines
4.6 KiB
Python

"""
약품 포장단위 판별 유틸리티
SUNG_CODE 기반으로 약품의 단위(정, 캡슐, mL, 포 등)를 판별
참고: person-lookup-web-local/dev_docs/pharmit_3000db_sung_code.md
"""
import re
# FormCode -> 기본 단위 매핑
FORM_CODE_UNIT_MAP = {
# 정제류
'TA': '', 'TB': '', 'TC': '', 'TD': '', 'TE': '',
'TF': '', 'TG': '', 'TH': '', 'TL': '', 'TR': '',
# 캡슐류
'CA': '캡슐', 'CB': '캡슐', 'CC': '캡슐', 'CD': '캡슐', 'CE': '캡슐',
'CH': '캡슐', 'CR': '캡슐', 'CS': '캡슐',
# 과립/산제
'GA': '', 'GB': '', 'GC': '', 'GN': '', 'PD': '',
# 액상제
'SS': 'mL', 'SY': 'mL', 'LQ': 'mL', 'SI': '앰플',
# 외용제
'EY': '', 'EN': '', 'EO': '', 'OS': '', 'OO': '튜브',
'GT': '', 'OT': '', 'OM': '', 'CT': '', 'CM': '',
'LT': '', 'PT': '', 'PC': '', 'SP': '',
# 좌제/질정
'SU': '', 'VT': '',
# 주사제
'IN': '바이알', 'IA': '앰플', 'IJ': '바이알', 'IP': '프리필드',
# 흡입제
'IH': '', 'NE': '앰플',
}
def get_drug_unit(goods_name: str, sung_code: str) -> str:
"""
약품명과 SUNG_CODE를 기반으로 포장단위를 판별
Args:
goods_name: 약품명 (예: "씨투스건조시럽_(0.5g)")
sung_code: SUNG_CODE (예: "100701ATB" - 마지막 2자리가 FormCode)
Returns:
포장단위 문자열 (예: "", "캡슐", "mL", "" 등)
"""
if not sung_code or len(sung_code) < 2:
return '' # 기본값
# FormCode 추출 (SUNG_CODE 마지막 2자리)
form_code = sung_code[-2:].upper()
# 건조시럽(SS) / 시럽(SY) 특수 처리
if form_code in ('SS', 'SY'):
return _get_syrup_unit(goods_name)
# 점안액(EY, OS) 특수 처리
if form_code in ('EY', 'OS'):
return _get_eye_drop_unit(goods_name)
# 안연고(OO) 특수 처리
if form_code == 'OO':
if '안연고' in goods_name or '눈연고' in goods_name:
return '튜브'
return ''
# 액제(LQ) 특수 처리
if form_code == 'LQ':
return _get_liquid_unit(goods_name)
# 파우더/산제(PD, GN) 특수 처리
if form_code in ('PD', 'GN'):
return _get_powder_unit(goods_name)
# 흡입제/스프레이(SI) 특수 처리
if form_code == 'SI':
if '흡입액' in goods_name or '네뷸' in goods_name:
return '앰플'
return ''
# 기본 매핑에서 찾기
return FORM_CODE_UNIT_MAP.get(form_code, '')
def _get_syrup_unit(goods_name: str) -> str:
"""시럽/건조시럽 단위 판별"""
# 개별 g 포장: (0.5g), (0.7g) 등 -> 포
if re.search(r'\([\d.]+g\)', goods_name):
return ''
# g/Xg 벌크 패턴 -> g
if re.search(r'_\([^)]+/\d+g\)', goods_name):
return 'g'
# 건조시럽/현탁용분말 -> mL
if '건조시럽' in goods_name or '현탁용분말' in goods_name:
return 'mL'
# 소용량 mL (5~30mL) -> 포
match = re.search(r'[_(/](\d+)mL\)', goods_name, re.IGNORECASE)
if match:
volume = int(match.group(1))
if volume <= 30:
return ''
return 'mL'
def _get_eye_drop_unit(goods_name: str) -> str:
"""점안액 단위 판별"""
# 소용량 (1mL 이하) = 일회용 -> 개
match = re.search(r'[_/\(]([\d.]+)mL\)', goods_name)
if match:
try:
volume = float(match.group(1))
if volume <= 1.0:
return ''
except ValueError:
pass
return ''
def _get_liquid_unit(goods_name: str) -> str:
"""액제 단위 판별"""
# 알긴산/거드액 -> 포
if '알긴' in goods_name or '거드' in goods_name:
return ''
# 외용액 -> 병
if any(k in goods_name for k in ['외용', '네일', '라카', '베이트', '더마톱', '라미실']):
return ''
# 점이/점비액 -> 병
if '점비' in goods_name or '이용액' in goods_name:
return ''
# 흡입액 -> 앰플
if '흡입' in goods_name or '네뷸' in goods_name:
return '앰플'
return 'mL'
def _get_powder_unit(goods_name: str) -> str:
"""파우더/산제 단위 판별"""
# 분모 10g 이상 = 벌크 -> g
match = re.search(r'_\([^)]+/(\d+(?:\.\d+)?)g\)', goods_name)
if match:
try:
denominator = float(match.group(1))
if denominator >= 10:
return 'g'
except ValueError:
pass
return ''