pharmacy-pos-qr-system/backend/sooin_api.py
thug0bin 1829c3efa7 feat: 지오영/수인 잔고 API 엔드포인트 추가
- GET /api/geoyoung/balance
- GET /api/sooin/balance
2026-03-06 16:15:23 +09:00

391 lines
11 KiB
Python

# -*- coding: utf-8 -*-
"""
수인약품 도매상 API - Flask Blueprint
핵심 로직은 wholesale 패키지에서 가져옴
이 파일은 Flask 웹 API 연동만 담당
"""
import time
import logging
from flask import Blueprint, jsonify, request as flask_request
# wholesale 패키지 경로 설정
import wholesale_path
# wholesale 패키지에서 핵심 클래스 가져오기
from wholesale import SooinSession
logger = logging.getLogger(__name__)
# Blueprint 생성
sooin_bp = Blueprint('sooin', __name__, url_prefix='/api/sooin')
# ========== 세션 관리 ==========
_sooin_session = None
def get_sooin_session():
global _sooin_session
if _sooin_session is None:
_sooin_session = SooinSession()
return _sooin_session
def search_sooin_stock(keyword: str, search_type: str = 'kd_code'):
"""수인약품 재고 검색 (동기, 빠름)"""
try:
session = get_sooin_session()
result = session.search_products(keyword)
if result.get('success'):
return {
'success': True,
'keyword': keyword,
'search_type': search_type,
'count': result['total'],
'items': result['items']
}
else:
return result
except Exception as e:
logger.error(f"수인약품 검색 오류: {e}")
return {'success': False, 'error': 'SEARCH_ERROR', 'message': str(e)}
# ========== Flask API Routes ==========
@sooin_bp.route('/stock', methods=['GET'])
def api_sooin_stock():
"""
수인약품 재고 조회 API
GET /api/sooin/stock?kd_code=073100220
GET /api/sooin/stock?keyword=코자정&type=name
"""
kd_code = flask_request.args.get('kd_code', '').strip()
keyword = flask_request.args.get('keyword', '').strip()
search_type = flask_request.args.get('type', 'kd_code').strip()
search_term = kd_code or keyword
if kd_code:
search_type = 'kd_code'
if not search_term:
return jsonify({
'success': False,
'error': 'MISSING_PARAM',
'message': 'kd_code 또는 keyword 파라미터가 필요합니다'
}), 400
try:
result = search_sooin_stock(search_term, search_type)
return jsonify(result)
except Exception as e:
logger.error(f"수인약품 API 오류: {e}")
return jsonify({
'success': False,
'error': 'API_ERROR',
'message': str(e)
}), 500
@sooin_bp.route('/session-status', methods=['GET'])
def api_session_status():
"""세션 상태 확인"""
session = get_sooin_session()
return jsonify({
'logged_in': session._logged_in,
'last_login': session._last_login,
'session_age_sec': int(time.time() - session._last_login) if session._last_login else None
})
@sooin_bp.route('/balance', methods=['GET'])
def api_sooin_balance():
"""
수인약품 잔고(미수금) 조회 API
GET /api/sooin/balance
Returns:
{
"success": true,
"balance": 14293001, // 현재 잔고 (누계합)
"prev_balance": 10592762, // 전일잔액
"monthly_sales": 3700239, // 월 매출
"yearly_sales": 34380314 // 연 누계 매출
}
"""
try:
session = get_sooin_session()
result = session.get_balance()
return jsonify(result)
except Exception as e:
logger.error(f"수인약품 잔고 조회 오류: {e}")
return jsonify({
'success': False,
'error': 'BALANCE_ERROR',
'message': str(e),
'balance': 0
}), 500
@sooin_bp.route('/cart', methods=['GET'])
def api_sooin_cart():
"""장바구니 조회 API"""
try:
session = get_sooin_session()
result = session.get_cart()
return jsonify(result)
except Exception as e:
return jsonify({'success': False, 'error': str(e), 'items': []}), 500
@sooin_bp.route('/cart/clear', methods=['POST'])
def api_sooin_cart_clear():
"""장바구니 비우기 API"""
try:
session = get_sooin_session()
result = session.clear_cart()
return jsonify(result)
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@sooin_bp.route('/cart/cancel', methods=['POST'])
def api_sooin_cart_cancel():
"""
장바구니 항목 취소 API
POST /api/sooin/cart/cancel
{ "row_index": 0 }
또는
{ "internal_code": "32495" }
"""
data = flask_request.get_json() or {}
row_index = data.get('row_index')
internal_code = data.get('internal_code')
if row_index is None and not internal_code:
return jsonify({
'success': False,
'error': 'MISSING_PARAM',
'message': 'row_index 또는 internal_code가 필요합니다'
}), 400
try:
session = get_sooin_session()
result = session.cancel_item(row_index=row_index, product_code=internal_code)
return jsonify(result)
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@sooin_bp.route('/cart/restore', methods=['POST'])
def api_sooin_cart_restore():
"""
취소된 항목 복원 API
POST /api/sooin/cart/restore
{ "row_index": 0 }
"""
data = flask_request.get_json() or {}
row_index = data.get('row_index')
internal_code = data.get('internal_code')
try:
session = get_sooin_session()
result = session.restore_item(row_index=row_index, product_code=internal_code)
return jsonify(result)
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@sooin_bp.route('/order', methods=['POST'])
def api_sooin_order():
"""
수인약품 주문 API (장바구니 추가)
POST /api/sooin/order
{
"kd_code": "073100220",
"quantity": 1,
"specification": "30T",
"check_stock": true
}
"""
data = flask_request.get_json()
if not data:
return jsonify({'success': False, 'error': 'NO_DATA'}), 400
kd_code = data.get('kd_code', '').strip()
quantity = data.get('quantity', 1)
specification = data.get('specification')
check_stock = data.get('check_stock', True)
if not kd_code:
return jsonify({
'success': False,
'error': 'MISSING_PARAM',
'message': 'kd_code가 필요합니다'
}), 400
try:
session = get_sooin_session()
result = session.quick_order(
kd_code=kd_code,
quantity=quantity,
spec=specification,
check_stock=check_stock
)
return jsonify(result)
except Exception as e:
logger.error(f"수인약품 주문 오류: {e}")
return jsonify({
'success': False,
'error': 'ORDER_ERROR',
'message': str(e)
}), 500
@sooin_bp.route('/confirm', methods=['POST'])
def api_sooin_confirm():
"""주문 확정 API"""
data = flask_request.get_json() or {}
memo = data.get('memo', '')
try:
session = get_sooin_session()
result = session.submit_order(memo)
return jsonify(result)
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@sooin_bp.route('/full-order', methods=['POST'])
def api_sooin_full_order():
"""
전체 주문 API (검색 → 장바구니 → 확정)
POST /api/sooin/full-order
{
"kd_code": "073100220",
"quantity": 1,
"specification": "30T",
"auto_confirm": true,
"memo": "자동주문"
}
"""
data = flask_request.get_json()
if not data or not data.get('kd_code'):
return jsonify({'success': False, 'error': 'kd_code required'}), 400
try:
session = get_sooin_session()
# 장바구니에 담기
cart_result = session.quick_order(
kd_code=data['kd_code'],
quantity=data.get('quantity', 1),
spec=data.get('specification'),
check_stock=data.get('check_stock', True)
)
if not cart_result.get('success'):
return jsonify(cart_result)
if not data.get('auto_confirm', True):
return jsonify(cart_result)
# 주문 확정
confirm_result = session.submit_order(data.get('memo', ''))
if confirm_result.get('success'):
return jsonify({
'success': True,
'message': f"{cart_result['product']['name']} {cart_result['quantity']}개 주문 완료",
'product': cart_result['product'],
'quantity': cart_result['quantity'],
'confirmed': True
})
else:
return jsonify({
'success': False,
'error': confirm_result.get('error', 'CONFIRM_FAILED'),
'message': f"장바구니 담기 성공, 주문 확정 실패",
'product': cart_result['product'],
'cart_added': True
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@sooin_bp.route('/order-batch', methods=['POST'])
def api_sooin_order_batch():
"""수인약품 일괄 주문 API"""
data = flask_request.get_json()
if not data or not data.get('items'):
return jsonify({'success': False, 'error': 'NO_ITEMS'}), 400
items = data.get('items', [])
check_stock = data.get('check_stock', True)
session = get_sooin_session()
results = []
success_count = 0
failed_count = 0
for item in items:
kd_code = item.get('kd_code', '').strip()
quantity = item.get('quantity', 1)
specification = item.get('specification')
if not kd_code:
results.append({
'kd_code': kd_code,
'success': False,
'error': 'MISSING_KD_CODE'
})
failed_count += 1
continue
try:
result = session.quick_order(
kd_code=kd_code,
quantity=quantity,
spec=specification,
check_stock=check_stock
)
result['kd_code'] = kd_code
result['requested_qty'] = quantity
results.append(result)
if result.get('success'):
success_count += 1
else:
failed_count += 1
except Exception as e:
results.append({
'kd_code': kd_code,
'success': False,
'error': 'EXCEPTION',
'message': str(e)
})
failed_count += 1
return jsonify({
'success': True,
'total': len(items),
'success_count': success_count,
'failed_count': failed_count,
'results': results
})