feat: 처방약품 사용량 페이지 - 주문량 지오영+수인 합산
- GET /api/geoyoung/orders/summary-by-kd 추가 - admin_rx_usage.html: 두 도매상 병렬 조회 후 합산 표시 - 콘솔에 도매상별 주문량 로깅
This commit is contained in:
parent
e5744e4f0f
commit
33c6cd2d5c
@ -567,6 +567,106 @@ def api_geoyoung_order_detail(order_num):
|
||||
}), 500
|
||||
|
||||
|
||||
@geoyoung_bp.route('/orders/summary-by-kd', methods=['GET'])
|
||||
def api_geoyoung_orders_by_kd():
|
||||
"""
|
||||
지오영 주문량 KD코드별 집계 API
|
||||
|
||||
GET /api/geoyoung/orders/summary-by-kd?start_date=2026-03-01&end_date=2026-03-07
|
||||
|
||||
Returns:
|
||||
{
|
||||
"success": true,
|
||||
"order_count": 4,
|
||||
"by_kd_code": {
|
||||
"670400830": {
|
||||
"product_name": "레바미피드정",
|
||||
"spec": "100T",
|
||||
"boxes": 2,
|
||||
"units": 200
|
||||
}
|
||||
},
|
||||
"total_products": 15
|
||||
}
|
||||
"""
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
today = datetime.now().strftime("%Y-%m-%d")
|
||||
start_date = request.args.get('start_date', today).strip()
|
||||
end_date = request.args.get('end_date', today).strip()
|
||||
|
||||
def parse_spec(spec: str) -> int:
|
||||
"""규격에서 수량 추출 (30T → 30, 100C → 100)"""
|
||||
if not spec:
|
||||
return 1
|
||||
match = re.search(r'(\d+)', spec)
|
||||
return int(match.group(1)) if match else 1
|
||||
|
||||
try:
|
||||
session = get_geo_session()
|
||||
|
||||
# 주문 목록 조회 (items 포함)
|
||||
orders_result = session.get_order_list(start_date, end_date)
|
||||
|
||||
if not orders_result.get('success'):
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': orders_result.get('error', 'ORDERS_FETCH_FAILED'),
|
||||
'by_kd_code': {},
|
||||
'order_count': 0
|
||||
})
|
||||
|
||||
orders = orders_result.get('orders', [])
|
||||
|
||||
# KD코드별 집계
|
||||
kd_summary = {}
|
||||
|
||||
for order in orders:
|
||||
# 지오영은 get_order_list에서 items도 같이 반환
|
||||
for item in order.get('items', []):
|
||||
kd_code = item.get('kd_code', '')
|
||||
if not kd_code:
|
||||
continue
|
||||
|
||||
product_name = item.get('product_name', '')
|
||||
spec = item.get('spec', '')
|
||||
quantity = item.get('quantity', 0) or item.get('order_qty', 0)
|
||||
per_unit = parse_spec(spec)
|
||||
total_units = quantity * per_unit
|
||||
|
||||
if kd_code not in kd_summary:
|
||||
kd_summary[kd_code] = {
|
||||
'product_name': product_name,
|
||||
'spec': spec,
|
||||
'boxes': 0,
|
||||
'units': 0
|
||||
}
|
||||
|
||||
kd_summary[kd_code]['boxes'] += quantity
|
||||
kd_summary[kd_code]['units'] += total_units
|
||||
|
||||
logger.info(f"지오영 주문량 집계: {start_date}~{end_date}, {len(orders)}건 주문, {len(kd_summary)}개 품목")
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'order_count': len(orders),
|
||||
'period': {'start': start_date, 'end': end_date},
|
||||
'by_kd_code': kd_summary,
|
||||
'total_products': len(kd_summary)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"지오영 주문량 집계 오류: {e}")
|
||||
return jsonify({
|
||||
'success': False,
|
||||
'error': 'API_ERROR',
|
||||
'message': str(e),
|
||||
'by_kd_code': {},
|
||||
'order_count': 0
|
||||
}), 500
|
||||
|
||||
|
||||
@geoyoung_bp.route('/order-today', methods=['GET'])
|
||||
def api_geoyoung_order_today():
|
||||
"""
|
||||
|
||||
@ -894,7 +894,7 @@
|
||||
<script>
|
||||
let usageData = [];
|
||||
let cart = [];
|
||||
let orderDataByKd = {}; // 수인약품 주문량 (KD코드별)
|
||||
let orderDataByKd = {}; // 도매상 주문량 합산 (KD코드별) - 지오영 + 수인
|
||||
|
||||
// 초기화
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
@ -907,20 +907,53 @@
|
||||
loadOrderData(); // 수인약품 주문량 로드
|
||||
});
|
||||
|
||||
// ──────────────── 수인약품 주문량 조회 ────────────────
|
||||
// ──────────────── 도매상 주문량 조회 (지오영 + 수인 합산) ────────────────
|
||||
async function loadOrderData() {
|
||||
const startDate = document.getElementById('startDate').value;
|
||||
const endDate = document.getElementById('endDate').value;
|
||||
|
||||
orderDataLoading = true;
|
||||
orderDataByKd = {};
|
||||
|
||||
try {
|
||||
const res = await fetch(`/api/sooin/orders/summary-by-kd?start_date=${startDate}&end_date=${endDate}`);
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
orderDataByKd = data.by_kd_code || {};
|
||||
console.log('📦 수인약품 주문량:', Object.keys(orderDataByKd).length, '품목,', data.order_count, '건 주문');
|
||||
// 지오영 + 수인 병렬 조회
|
||||
const [geoRes, sooinRes] = await Promise.all([
|
||||
fetch(`/api/geoyoung/orders/summary-by-kd?start_date=${startDate}&end_date=${endDate}`).then(r => r.json()).catch(() => ({ success: false })),
|
||||
fetch(`/api/sooin/orders/summary-by-kd?start_date=${startDate}&end_date=${endDate}`).then(r => r.json()).catch(() => ({ success: false }))
|
||||
]);
|
||||
|
||||
let totalOrders = 0;
|
||||
|
||||
// 지오영 데이터 합산
|
||||
if (geoRes.success && geoRes.by_kd_code) {
|
||||
for (const [kd, data] of Object.entries(geoRes.by_kd_code)) {
|
||||
if (!orderDataByKd[kd]) {
|
||||
orderDataByKd[kd] = { product_name: data.product_name, spec: data.spec, boxes: 0, units: 0, sources: [] };
|
||||
}
|
||||
orderDataByKd[kd].boxes += data.boxes || 0;
|
||||
orderDataByKd[kd].units += data.units || 0;
|
||||
orderDataByKd[kd].sources.push('지오영');
|
||||
}
|
||||
totalOrders += geoRes.order_count || 0;
|
||||
console.log('🏭 지오영 주문량:', Object.keys(geoRes.by_kd_code).length, '품목,', geoRes.order_count, '건');
|
||||
}
|
||||
|
||||
// 수인 데이터 합산
|
||||
if (sooinRes.success && sooinRes.by_kd_code) {
|
||||
for (const [kd, data] of Object.entries(sooinRes.by_kd_code)) {
|
||||
if (!orderDataByKd[kd]) {
|
||||
orderDataByKd[kd] = { product_name: data.product_name, spec: data.spec, boxes: 0, units: 0, sources: [] };
|
||||
}
|
||||
orderDataByKd[kd].boxes += data.boxes || 0;
|
||||
orderDataByKd[kd].units += data.units || 0;
|
||||
orderDataByKd[kd].sources.push('수인');
|
||||
}
|
||||
totalOrders += sooinRes.order_count || 0;
|
||||
console.log('💜 수인 주문량:', Object.keys(sooinRes.by_kd_code).length, '품목,', sooinRes.order_count, '건');
|
||||
}
|
||||
|
||||
console.log('📦 합산 주문량:', Object.keys(orderDataByKd).length, '품목,', totalOrders, '건 주문');
|
||||
|
||||
} catch(err) {
|
||||
console.warn('주문량 조회 실패:', err);
|
||||
orderDataByKd = {};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user