\"fix: let frontend dictate warning sort flag and add SQL numeric casting\"

This commit is contained in:
DXC
2026-03-12 08:53:09 +08:00
parent f0ec9a68d7
commit 7e403a87cd
2 changed files with 16 additions and 22 deletions

View File

@ -6,7 +6,7 @@ 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, case, desc, asc
from sqlalchemy import or_, and_, func, case, desc, asc, cast, Numeric, text
import traceback
import json
import io
@ -309,36 +309,27 @@ class MaterialBaseService:
order_by_column = filters.get('orderByColumn', '')
is_asc = filters.get('isAsc', None)
# 检查是否启用了预警智能排序
enable_warning_sort = has_warning_permission and filters.get('enableWarningSort', False)
# 信任前端传递的预警排序开关(前端已基于权限注入)
enable_warning_sort = filters.get('enableWarningSort', False)
if enable_warning_sort:
from sqlalchemy import text
print("====== [DEBUG] 执行虚拟列强排模式 ======")
# 1. 建立虚拟列标签 (显式暴露出计算结果)
print("====== [DEBUG] 成功进入预警强排逻辑 ======")
# 强制统一数据类型
red_val = cast(MaterialWarningSetting.red_threshold, Numeric)
yellow_val = cast(MaterialWarningSetting.yellow_threshold, Numeric)
inv_val = cast(total_inv, Numeric)
warning_level = case([
(and_(MaterialWarningSetting.is_enabled.is_(True), total_inv <= MaterialWarningSetting.red_threshold), 2),
(and_(MaterialWarningSetting.is_enabled.is_(True), total_inv <= MaterialWarningSetting.yellow_threshold), 1)
(and_(MaterialWarningSetting.is_enabled.is_(True), inv_val <= red_val), 2),
(and_(MaterialWarningSetting.is_enabled.is_(True), inv_val <= yellow_val), 1)
], else_=0).label('sort_level')
# 红色组内部:缺口越大越靠前 DESC
red_shortage = case([
(and_(MaterialWarningSetting.is_enabled.is_(True), total_inv <= MaterialWarningSetting.red_threshold),
MaterialWarningSetting.red_threshold - total_inv)
(and_(MaterialWarningSetting.is_enabled.is_(True), inv_val <= red_val), red_val - inv_val)
], else_=0).label('sort_red')
# 黄色组内部:距离红线越近越靠前 ASC
yellow_distance = case([
(and_(MaterialWarningSetting.is_enabled.is_(True), total_inv > MaterialWarningSetting.red_threshold, total_inv <= MaterialWarningSetting.yellow_threshold),
total_inv - MaterialWarningSetting.red_threshold)
(and_(MaterialWarningSetting.is_enabled.is_(True), inv_val > red_val, inv_val <= yellow_val), inv_val - red_val)
], else_=999999).label('sort_yellow')
# 2. 将虚拟列加入查询 (使其成为真实可引用的字段)
query = query.add_columns(warning_level, red_shortage, yellow_distance)
# 3. 清除任何杂乱排序,使用原生 text 强行指引数据库按虚拟列名排序
query = query.order_by(None).order_by(
text("sort_level DESC"),
text("sort_red DESC"),