fix: rx-usage 쿼리에 PS_Type!=9 조건 추가 (실제 조제된 약만 집계)

- patient_query: 대체조제 원본 처방 제외
- rx_query: 대체조제 원본 처방 제외
- PS_Type=9는 대체조제시 원래 처방된 약(조제 안됨)
- 기타 배치 스크립트 및 문서 추가
This commit is contained in:
thug0bin
2026-03-09 21:54:32 +09:00
parent f92abf94c8
commit e470deaefc
10 changed files with 1909 additions and 121 deletions

View File

@@ -143,6 +143,8 @@ def api_submit_order():
# 도매상별 주문 처리
if wholesaler_id == 'geoyoung':
result = submit_geoyoung_order(order, dry_run)
elif wholesaler_id == 'dongwon':
result = submit_dongwon_order(order, dry_run)
else:
result = {
'success': False,
@@ -517,6 +519,8 @@ def api_quick_submit():
submit_result = submit_sooin_order(order, dry_run, cart_only=cart_only)
elif order['wholesaler_id'] == 'baekje':
submit_result = submit_baekje_order(order, dry_run, cart_only=cart_only)
elif order['wholesaler_id'] == 'dongwon':
submit_result = submit_dongwon_order(order, dry_run, cart_only=cart_only)
else:
submit_result = {'success': False, 'error': f"Wholesaler {order['wholesaler_id']} not supported"}
@@ -1387,3 +1391,226 @@ def api_drugs_preferred_vendors():
'count': len(results),
'results': results
})
def submit_dongwon_order(order: dict, dry_run: bool, cart_only: bool = True) -> dict:
"""
동원약품 주문 제출
Args:
order: 주문 정보
dry_run: True=시뮬레이션만, False=실제 주문
cart_only: True=장바구니만, False=주문 확정까지
"""
order_id = order['id']
items = order['items']
# 상태 업데이트
update_order_status(order_id, 'pending',
f'동원 주문 시작 (dry_run={dry_run}, cart_only={cart_only})')
results = []
success_count = 0
failed_count = 0
try:
from dongwon_api import get_dongwon_session
dongwon_session = get_dongwon_session()
if dry_run:
# ─────────────────────────────────────────
# DRY RUN: 재고 확인만
# ─────────────────────────────────────────
for item in items:
kd_code = item.get('kd_code') or item.get('drug_code')
spec = item.get('specification', '')
# 재고 검색
search_result = dongwon_session.search_products(kd_code)
matched = None
available_specs = []
spec_stocks = {}
if search_result.get('success'):
for dongwon_item in search_result.get('items', []):
s = dongwon_item.get('spec', '')
available_specs.append(s)
spec_stocks[s] = dongwon_item.get('stock', 0)
# 규격 매칭
if spec in s or s in spec:
if matched is None or dongwon_item.get('stock', 0) > matched.get('stock', 0):
matched = dongwon_item
if matched:
stock = matched.get('stock', 0)
if stock >= item['order_qty']:
status = 'success'
result_code = 'OK'
result_message = f"[DRY RUN] 주문 가능: 재고 {stock}, 단가 {matched.get('price', 0):,}"
success_count += 1
elif stock > 0:
status = 'failed'
result_code = 'LOW_STOCK'
result_message = f"[DRY RUN] 재고 부족: {stock}개 (요청: {item['order_qty']})"
failed_count += 1
else:
status = 'failed'
result_code = 'OUT_OF_STOCK'
result_message = f"[DRY RUN] 재고 없음"
failed_count += 1
else:
status = 'failed'
result_code = 'NOT_FOUND'
result_message = f"[DRY RUN] 동원에서 규격 {spec} 미발견"
failed_count += 1
update_item_result(item['id'], status, result_code, result_message)
results.append({
'item_id': item['id'],
'drug_code': item.get('drug_code') or item.get('kd_code'),
'product_name': item.get('product_name') or item.get('drug_name', ''),
'specification': spec,
'order_qty': item['order_qty'],
'status': status,
'result_code': result_code,
'result_message': result_message,
'matched_spec': matched.get('spec') if matched else None,
'stock': matched.get('stock') if matched else 0,
'price': matched.get('price') if matched else 0
})
update_order_status(order_id, 'dry_run_complete',
f'[DRY RUN] 완료: 성공 {success_count}, 실패 {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
}
else:
# ─────────────────────────────────────────
# 실제 주문: 장바구니 담기 (또는 주문 확정)
# ─────────────────────────────────────────
cart_items = []
for item in items:
kd_code = item.get('kd_code') or item.get('drug_code')
internal_code = item.get('dongwon_code') or item.get('internal_code')
spec = item.get('specification', '')
order_qty = item['order_qty']
# internal_code가 없으면 검색해서 찾기
if not internal_code:
search_result = dongwon_session.search_products(kd_code)
if search_result.get('success') and search_result.get('items'):
for dongwon_item in search_result['items']:
s = dongwon_item.get('spec', '')
if spec in s or s in spec:
internal_code = dongwon_item.get('internal_code')
break
# 규격 매칭 안 되면 첫 번째 결과 사용
if not internal_code and search_result['items']:
internal_code = search_result['items'][0].get('internal_code')
product_name = item.get('product_name') or item.get('drug_name', '')
if internal_code:
cart_items.append({
'internal_code': internal_code,
'quantity': order_qty
})
update_item_result(item['id'], 'success', 'CART_READY',
f'장바구니 준비 완료: {internal_code}')
results.append({
'item_id': item['id'],
'drug_code': kd_code,
'product_name': product_name,
'specification': spec,
'order_qty': order_qty,
'status': 'success',
'result_code': 'CART_READY',
'result_message': f'장바구니 준비 완료: {internal_code}',
'internal_code': internal_code
})
success_count += 1
else:
update_item_result(item['id'], 'failed', 'NOT_FOUND',
f'동원에서 제품 미발견: {kd_code}')
results.append({
'item_id': item['id'],
'drug_code': kd_code,
'product_name': product_name,
'specification': spec,
'order_qty': order_qty,
'status': 'failed',
'result_code': 'NOT_FOUND',
'result_message': f'동원에서 제품 미발견'
})
failed_count += 1
# safe_order 사용 (장바구니 백업/복구)
if cart_items:
if cart_only:
# 장바구니만 담기
for cart_item in cart_items:
dongwon_session.add_to_cart(
cart_item['internal_code'],
cart_item['quantity']
)
update_order_status(order_id, 'cart_added',
f'동원 장바구니 담기 완료: {len(cart_items)}개 품목')
else:
# safe_order로 주문 (기존 장바구니 백업/복구)
order_result = dongwon_session.safe_order(
items_to_order=cart_items,
memo=order.get('memo', ''),
dry_run=False
)
if order_result.get('success'):
update_order_status(order_id, 'completed',
f'동원 주문 완료: {order_result.get("ordered_count", 0)}개 품목')
else:
update_order_status(order_id, 'failed',
f'동원 주문 실패: {order_result.get("error", "unknown")}')
# 응답 생성
if cart_only:
note = '동원약품 장바구니에 담김. 동원몰에서 최종 확정 필요.'
else:
note = None
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,
'note': note
}
except Exception as e:
logger.error(f"동원 주문 오류: {e}", exc_info=True)
update_order_status(order_id, 'error', f'동원 주문 오류: {str(e)}')
return {
'success': False,
'order_id': order_id,
'wholesaler': 'dongwon',
'error': str(e)
}