refactor(vendor): 抽出缺貨 API 查詢服務
All checks were successful
CD Pipeline / deploy (push) Successful in 2m11s
All checks were successful
CD Pipeline / deploy (push) Successful in 2m11s
This commit is contained in:
@@ -19,6 +19,8 @@ from database.vendor_manager import VendorDatabaseManager
|
||||
from database.vendor_models import VendorStockout, VendorList, VendorEmail, EmailSendLog
|
||||
from services.logger_manager import SystemLogger
|
||||
from services.vendor_stockout_query_service import (
|
||||
get_stockout_api_list_payload,
|
||||
get_stockout_batches_payload,
|
||||
get_vendor_dashboard_stats,
|
||||
get_vendor_stockout_list_context,
|
||||
)
|
||||
@@ -331,104 +333,17 @@ def api_get_stockout_list():
|
||||
- sort_by: 排序方式 (created_at_desc/created_at_asc/vendor_code_asc/stockout_days_desc)
|
||||
"""
|
||||
try:
|
||||
# 取得查詢參數
|
||||
page = request.args.get('page', 1, type=int)
|
||||
page_size = request.args.get('page_size', 50, type=int)
|
||||
batch_number = request.args.get('batch_number')
|
||||
vendor_filter = request.args.get('vendor')
|
||||
status_filter = request.args.get('status')
|
||||
sort_by = request.args.get('sort_by', 'created_at_desc')
|
||||
|
||||
# 獲取 session
|
||||
session = vendor_db.get_session()
|
||||
|
||||
# 建立查詢
|
||||
query = session.query(VendorStockout)
|
||||
|
||||
# 套用篩選
|
||||
if batch_number:
|
||||
query = query.filter(VendorStockout.batch_id == batch_number)
|
||||
|
||||
if vendor_filter:
|
||||
query = query.filter(
|
||||
or_(
|
||||
VendorStockout.vendor_code.like(f'%{vendor_filter}%'),
|
||||
VendorStockout.vendor_name.like(f'%{vendor_filter}%')
|
||||
)
|
||||
)
|
||||
|
||||
if status_filter:
|
||||
query = query.filter(VendorStockout.status == status_filter)
|
||||
|
||||
# 套用排序
|
||||
if sort_by == 'created_at_asc':
|
||||
query = query.order_by(VendorStockout.created_at.asc())
|
||||
elif sort_by == 'vendor_code_asc':
|
||||
query = query.order_by(VendorStockout.vendor_code.asc())
|
||||
elif sort_by == 'stockout_days_desc':
|
||||
query = query.order_by(VendorStockout.safe_stock_days.desc())
|
||||
else: # created_at_desc
|
||||
query = query.order_by(VendorStockout.created_at.desc())
|
||||
|
||||
# 計算總數
|
||||
total = query.count()
|
||||
|
||||
# 分頁
|
||||
offset = (page - 1) * page_size
|
||||
records = query.offset(offset).limit(page_size).all()
|
||||
|
||||
# 轉換為 JSON 格式
|
||||
records_data = []
|
||||
for record in records:
|
||||
records_data.append({
|
||||
'id': record.id,
|
||||
'batch_number': record.batch_id,
|
||||
'vendor_code': record.vendor_code,
|
||||
'vendor_name': record.vendor_name,
|
||||
'product_code': record.product_code,
|
||||
'product_name': record.product_name,
|
||||
'stockout_days': record.safe_stock_days,
|
||||
'daily_avg_sales': float(record.daily_avg_sales) if record.daily_avg_sales else None,
|
||||
'current_stock': record.current_stock,
|
||||
'send_status': record.status or 'pending',
|
||||
'created_at': record.created_at.isoformat() if record.created_at else None,
|
||||
'notes': record.notes
|
||||
})
|
||||
|
||||
# 計算統計數據
|
||||
stats_query = session.query(VendorStockout)
|
||||
if batch_number:
|
||||
stats_query = stats_query.filter(VendorStockout.batch_id == batch_number)
|
||||
if vendor_filter:
|
||||
stats_query = stats_query.filter(
|
||||
or_(
|
||||
VendorStockout.vendor_code.like(f'%{vendor_filter}%'),
|
||||
VendorStockout.vendor_name.like(f'%{vendor_filter}%')
|
||||
)
|
||||
)
|
||||
|
||||
total_stats = stats_query.count()
|
||||
pending_count = stats_query.filter(or_(
|
||||
VendorStockout.status == 'pending',
|
||||
VendorStockout.status == None
|
||||
)).count()
|
||||
sent_count = stats_query.filter(VendorStockout.status == 'sent').count()
|
||||
vendor_count = session.query(VendorStockout.vendor_code).distinct().count()
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'data': {
|
||||
'records': records_data,
|
||||
'total': total,
|
||||
'page': page,
|
||||
'page_size': page_size,
|
||||
'stats': {
|
||||
'total': total_stats,
|
||||
'pending': pending_count,
|
||||
'sent': sent_count,
|
||||
'vendor_count': vendor_count
|
||||
}
|
||||
}
|
||||
'data': get_stockout_api_list_payload(
|
||||
vendor_db,
|
||||
page=request.args.get('page', 1, type=int),
|
||||
page_size=request.args.get('page_size', 50, type=int),
|
||||
batch_number=request.args.get('batch_number'),
|
||||
vendor_filter=request.args.get('vendor'),
|
||||
status_filter=request.args.get('status'),
|
||||
sort_by=request.args.get('sort_by', 'created_at_desc')
|
||||
)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
@@ -436,45 +351,20 @@ def api_get_stockout_list():
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return jsonify({'success': False, 'message': f'查詢失敗: {str(e)}'}), 500
|
||||
finally:
|
||||
if 'session' in locals():
|
||||
session.close()
|
||||
|
||||
|
||||
@vendor_bp.route('/api/stockout/batches', methods=['GET'])
|
||||
def api_get_stockout_batches():
|
||||
"""取得批次清單"""
|
||||
try:
|
||||
session = vendor_db.get_session()
|
||||
|
||||
# 查詢所有批次及其數量
|
||||
batches = session.query(
|
||||
VendorStockout.batch_id,
|
||||
func.count(VendorStockout.id).label('count'),
|
||||
func.max(VendorStockout.created_at).label('latest_date')
|
||||
).group_by(VendorStockout.batch_id)\
|
||||
.order_by(desc('latest_date'))\
|
||||
.all()
|
||||
|
||||
batch_data = []
|
||||
for batch in batches:
|
||||
batch_data.append({
|
||||
'batch_number': batch.batch_id,
|
||||
'count': batch.count,
|
||||
'latest_date': batch.latest_date.isoformat() if batch.latest_date else None
|
||||
})
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'data': batch_data
|
||||
'data': get_stockout_batches_payload(vendor_db)
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
sys_log.error(f"[API] 取得批次清單失敗 | 錯誤: {e}")
|
||||
return jsonify({'success': False, 'message': f'查詢失敗: {str(e)}'}), 500
|
||||
finally:
|
||||
if 'session' in locals():
|
||||
session.close()
|
||||
|
||||
|
||||
@vendor_bp.route('/api/stockout/<int:stockout_id>', methods=['PUT'])
|
||||
|
||||
Reference in New Issue
Block a user