feat: 백제약품 API 통합
- baekje_api.py: Flask Blueprint 추가 - order_api.py: submit_baekje_order 함수 추가 - admin_rx_usage.html: WHOLESALERS에 baekje 추가 - 환경변수: BAEKJE_USER_ID, BAEKJE_PASSWORD URL: https://ibjp.co.kr (약국용 웹 주문 시스템)
This commit is contained in:
@@ -443,6 +443,8 @@ def api_quick_submit():
|
||||
submit_result = submit_geoyoung_order(order, dry_run)
|
||||
elif order['wholesaler_id'] == 'sooin':
|
||||
submit_result = submit_sooin_order(order, dry_run)
|
||||
elif order['wholesaler_id'] == 'baekje':
|
||||
submit_result = submit_baekje_order(order, dry_run)
|
||||
else:
|
||||
submit_result = {'success': False, 'error': f"Wholesaler {order['wholesaler_id']} not supported"}
|
||||
|
||||
@@ -661,6 +663,202 @@ def submit_sooin_order(order: dict, dry_run: bool) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def submit_baekje_order(order: dict, dry_run: bool) -> dict:
|
||||
"""백제약품 주문 제출"""
|
||||
order_id = order['id']
|
||||
items = order['items']
|
||||
|
||||
# 상태 업데이트
|
||||
update_order_status(order_id, 'pending',
|
||||
f'백제약품 주문 시작 (dry_run={dry_run})')
|
||||
|
||||
results = []
|
||||
success_count = 0
|
||||
failed_count = 0
|
||||
|
||||
try:
|
||||
from baekje_api import get_baekje_session
|
||||
baekje_session = get_baekje_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 = baekje_session.search_products(kd_code)
|
||||
|
||||
matched = None
|
||||
available_specs = []
|
||||
spec_stocks = {}
|
||||
|
||||
if search_result.get('success'):
|
||||
for baekje_item in search_result.get('items', []):
|
||||
s = baekje_item.get('spec', '')
|
||||
available_specs.append(s)
|
||||
spec_stocks[s] = baekje_item.get('stock', 0)
|
||||
|
||||
# 규격 매칭
|
||||
if spec in s or s in spec:
|
||||
if matched is None or baekje_item.get('stock', 0) > matched.get('stock', 0):
|
||||
matched = baekje_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
|
||||
selection_reason = 'stock_available'
|
||||
elif stock > 0:
|
||||
status = 'failed'
|
||||
result_code = 'LOW_STOCK'
|
||||
result_message = f"[DRY RUN] 재고 부족: {stock}개 (요청: {item['order_qty']})"
|
||||
failed_count += 1
|
||||
selection_reason = 'low_stock'
|
||||
else:
|
||||
status = 'failed'
|
||||
result_code = 'OUT_OF_STOCK'
|
||||
result_message = f"[DRY RUN] 재고 없음"
|
||||
failed_count += 1
|
||||
selection_reason = 'out_of_stock'
|
||||
else:
|
||||
status = 'failed'
|
||||
result_code = 'NOT_FOUND'
|
||||
result_message = f"[DRY RUN] 백제에서 규격 {spec} 미발견"
|
||||
failed_count += 1
|
||||
selection_reason = 'not_found'
|
||||
|
||||
update_item_result(item['id'], status, result_code, result_message)
|
||||
|
||||
# AI 학습용 컨텍스트 저장
|
||||
save_order_context(item['id'], {
|
||||
'drug_code': item['drug_code'],
|
||||
'product_name': item['product_name'],
|
||||
'stock_at_order': item.get('current_stock', 0),
|
||||
'usage_7d': item.get('usage_qty', 0),
|
||||
'ordered_spec': spec,
|
||||
'ordered_qty': item['order_qty'],
|
||||
'available_specs': available_specs,
|
||||
'spec_stocks': spec_stocks,
|
||||
'selection_reason': selection_reason,
|
||||
'wholesaler_id': 'baekje'
|
||||
})
|
||||
|
||||
results.append({
|
||||
'item_id': item['id'],
|
||||
'drug_code': item['drug_code'],
|
||||
'product_name': item['product_name'],
|
||||
'specification': spec,
|
||||
'order_qty': item['order_qty'],
|
||||
'status': status,
|
||||
'result_code': result_code,
|
||||
'result_message': result_message,
|
||||
'available_specs': available_specs,
|
||||
'spec_stocks': spec_stocks,
|
||||
'price': matched.get('price') if matched else None
|
||||
})
|
||||
|
||||
# 상태 업데이트
|
||||
if failed_count == 0:
|
||||
update_order_status(order_id, 'completed',
|
||||
f'[DRY RUN] 백제 시뮬레이션 완료: {success_count}개 성공')
|
||||
elif success_count == 0:
|
||||
update_order_status(order_id, 'failed',
|
||||
f'[DRY RUN] 백제 시뮬레이션 완료: {failed_count}개 실패')
|
||||
else:
|
||||
update_order_status(order_id, 'partial',
|
||||
f'[DRY RUN] 백제 부분 성공: {success_count}개 성공, {failed_count}개 실패')
|
||||
|
||||
else:
|
||||
# ─────────────────────────────────────────
|
||||
# 실제 주문 (장바구니 추가)
|
||||
# ─────────────────────────────────────────
|
||||
for item in items:
|
||||
kd_code = item.get('kd_code') or item.get('drug_code')
|
||||
order_qty = item['order_qty']
|
||||
spec = item.get('specification', '')
|
||||
|
||||
try:
|
||||
# 장바구니 추가
|
||||
cart_result = baekje_session.add_to_cart(kd_code, order_qty)
|
||||
|
||||
if cart_result.get('success'):
|
||||
status = 'success'
|
||||
result_code = 'CART_ADDED'
|
||||
result_message = f"장바구니 추가 완료 (백제몰에서 확정 필요)"
|
||||
success_count += 1
|
||||
else:
|
||||
status = 'failed'
|
||||
result_code = cart_result.get('error', 'CART_FAILED')
|
||||
result_message = cart_result.get('message', '장바구니 추가 실패')
|
||||
failed_count += 1
|
||||
|
||||
except Exception as e:
|
||||
status = 'failed'
|
||||
result_code = 'ERROR'
|
||||
result_message = str(e)
|
||||
failed_count += 1
|
||||
|
||||
update_item_result(item['id'], status, result_code, result_message)
|
||||
|
||||
save_order_context(item['id'], {
|
||||
'drug_code': item['drug_code'],
|
||||
'product_name': item['product_name'],
|
||||
'stock_at_order': item.get('current_stock', 0),
|
||||
'usage_7d': item.get('usage_qty', 0),
|
||||
'ordered_spec': spec,
|
||||
'ordered_qty': order_qty,
|
||||
'selection_reason': 'user_order',
|
||||
'wholesaler_id': 'baekje'
|
||||
})
|
||||
|
||||
results.append({
|
||||
'item_id': item['id'],
|
||||
'drug_code': item['drug_code'],
|
||||
'product_name': item['product_name'],
|
||||
'specification': spec,
|
||||
'order_qty': order_qty,
|
||||
'status': status,
|
||||
'result_code': result_code,
|
||||
'result_message': result_message
|
||||
})
|
||||
|
||||
# 상태 업데이트
|
||||
if success_count > 0:
|
||||
update_order_status(order_id, 'pending',
|
||||
f'백제 장바구니 추가 완료: {success_count}개 (확정 필요)')
|
||||
else:
|
||||
update_order_status(order_id, 'failed',
|
||||
f'백제 주문 실패: {failed_count}개')
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
'dry_run': dry_run,
|
||||
'order_id': order_id,
|
||||
'order_no': order['order_no'],
|
||||
'wholesaler': 'baekje',
|
||||
'total_items': len(items),
|
||||
'success_count': success_count,
|
||||
'failed_count': failed_count,
|
||||
'results': results,
|
||||
'note': '실제 주문 시 장바구니에 담김. 백제몰(ibjp.co.kr)에서 최종 확정 필요.' if not dry_run else None
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"백제 주문 오류: {e}")
|
||||
update_order_status(order_id, 'failed', str(e))
|
||||
return {
|
||||
'success': False,
|
||||
'order_id': order_id,
|
||||
'error': str(e)
|
||||
}
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────
|
||||
# AI 학습용 API
|
||||
# ─────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user