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

View File

@ -580,6 +580,7 @@ interface QueryParams {
isAsc: string | undefined; isAsc: string | undefined;
advancedFilters?: any[]; advancedFilters?: any[];
has_stock?: string; has_stock?: string;
enableWarningSort?: boolean;
} }
interface CascaderOption { interface CascaderOption {
@ -880,6 +881,8 @@ const querySearchType = (queryString: string, cb: any) => {
const getList = () => { const getList = () => {
loading.value = true; loading.value = true;
// 强制注入预警排序开关(基于权限)
queryParams.enableWarningSort = userStore.hasPermission('material_list:view_warning');
// Stringify advancedFilters to JSON string as backend expects // Stringify advancedFilters to JSON string as backend expects
const params = { const params = {
...queryParams, ...queryParams,