From 404577e6b594d8ce95697bad2cf00785755cc7d1 Mon Sep 17 00:00:00 2001 From: DXC Date: Wed, 11 Mar 2026 17:17:10 +0800 Subject: [PATCH] \"fix: improve warning sort logic - red group by shortage desc, yellow group by safety distance asc\" --- .../app/services/inbound/base_service.py | 71 +++++++------------ 1 file changed, 24 insertions(+), 47 deletions(-) diff --git a/inventory-backend/app/services/inbound/base_service.py b/inventory-backend/app/services/inbound/base_service.py index c0af62e..3eb33d7 100644 --- a/inventory-backend/app/services/inbound/base_service.py +++ b/inventory-backend/app/services/inbound/base_service.py @@ -1,12 +1,12 @@ # 文件路径: app/services/inbound/base_service.py from app.extensions import db -from app.models.base import MaterialBase +from app.models.base import MaterialBase, MaterialWarningSetting from app.models.inbound.buy import StockBuy from app.models.inbound.semi import StockSemi from app.models.inbound.product import StockProduct # from app.models.inbound.service import StockService -from sqlalchemy import or_, and_, func +from sqlalchemy import or_, and_, func, case, desc, asc import traceback import json import io @@ -314,56 +314,33 @@ class MaterialBaseService: if enable_warning_sort: # 预警智能排序:先按预警状态排序,再按缺口/余量排序 - # 使用 CASE 表达式计算预警状态 - # 状态: 2=红(库存<=red), 1=黄(red<库存<=yellow), 0=正常/未开启 - from sqlalchemy import case - - # 计算预警状态 - warning_status = case( - ( - (MaterialWarningSetting.is_enabled == True) & - (total_inv <= MaterialWarningSetting.red_threshold), - 2 # 红色预警 - ), - ( - (MaterialWarningSetting.is_enabled == True) & - (total_inv > MaterialWarningSetting.red_threshold) & - (total_inv <= MaterialWarningSetting.yellow_threshold), - 1 # 黄色预警 - ), - else_=0 # 正常或未开启 - ).label('warning_status') - - # 红色组内部:按缺口降序 (red_threshold - inventory) - red_gap = case( - ( - (MaterialWarningSetting.is_enabled == True) & - (total_inv <= MaterialWarningSetting.red_threshold), - MaterialWarningSetting.red_threshold - total_inv - ), + # 状态层级:红(2) > 黄(1) > 常规(0) + warning_level = case( + (and_(MaterialWarningSetting.is_enabled == True, total_inv <= MaterialWarningSetting.red_threshold), 2), + (and_(MaterialWarningSetting.is_enabled == True, total_inv <= MaterialWarningSetting.yellow_threshold), 1), else_=0 - ).label('red_gap') + ) - # 黄色组内部:按余量升序 (inventory - red_threshold),离红线越近越靠前 - yellow_gap = case( - ( - (MaterialWarningSetting.is_enabled == True) & - (total_inv > MaterialWarningSetting.red_threshold) & - (total_inv <= MaterialWarningSetting.yellow_threshold), - total_inv - MaterialWarningSetting.red_threshold - ), - else_=999999 # 正常物料放在最后 - ).label('yellow_gap') + # 红色组内部:缺口越大越靠前 (red_threshold - total_inv) DESC + red_shortage = case( + (and_(MaterialWarningSetting.is_enabled == True, total_inv <= MaterialWarningSetting.red_threshold), + MaterialWarningSetting.red_threshold - total_inv), + else_=0 + ) - # 添加排序字段到查询 - query = query.add_columns(warning_status, red_gap, yellow_gap) + # 黄色组内部:距离红线越近越靠前 (total_inv - red_threshold) ASC + yellow_distance = case( + (and_(MaterialWarningSetting.is_enabled == True, total_inv > MaterialWarningSetting.red_threshold, total_inv <= MaterialWarningSetting.yellow_threshold), + total_inv - MaterialWarningSetting.red_threshold), + else_=999999999 # 给一个极大值,让非黄色组沉底,不影响升序 + ) - # 强制排序规则:预警状态降序 -> 红色缺口降序 -> 黄色余量升序 -> 规格型号升序 + # 清除默认排序,应用全新的四级混合排序 query = query.order_by( - warning_status.desc(), - red_gap.desc(), - yellow_gap.asc(), - MaterialBase.spec_model.asc() + desc(warning_level), + desc(red_shortage), + asc(yellow_distance), + desc(MaterialBase.id) # 常规组兜底排序 ) elif order_by_column: # 字段映射