\"fix: let frontend dictate warning sort flag and add SQL numeric casting\"
This commit is contained in:
@ -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] 成功进入预警强排逻辑 ======")
|
||||
# 强制统一数据类型
|
||||
red_val = cast(MaterialWarningSetting.red_threshold, Numeric)
|
||||
yellow_val = cast(MaterialWarningSetting.yellow_threshold, Numeric)
|
||||
inv_val = cast(total_inv, Numeric)
|
||||
|
||||
print("====== [DEBUG] 执行虚拟列强排模式 ======")
|
||||
|
||||
# 1. 建立虚拟列标签 (显式暴露出计算结果)
|
||||
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"),
|
||||
|
||||
@ -580,6 +580,7 @@ interface QueryParams {
|
||||
isAsc: string | undefined;
|
||||
advancedFilters?: any[];
|
||||
has_stock?: string;
|
||||
enableWarningSort?: boolean;
|
||||
}
|
||||
|
||||
interface CascaderOption {
|
||||
@ -880,6 +881,8 @@ const querySearchType = (queryString: string, cb: any) => {
|
||||
|
||||
const getList = () => {
|
||||
loading.value = true;
|
||||
// 强制注入预警排序开关(基于权限)
|
||||
queryParams.enableWarningSort = userStore.hasPermission('material_list:view_warning');
|
||||
// Stringify advancedFilters to JSON string as backend expects
|
||||
const params = {
|
||||
...queryParams,
|
||||
|
||||
Reference in New Issue
Block a user