feat(material): 物料列表新增「采购在途」自动标识,预警邮件改用活跃单静音
base_service.get_list: 新增 isPurchasing 字段,与待采购池共用同一份活跃单判定。放在预警权限 判断之外 —— 能看到物料列表的人都该知道这个物料已经在采购了。 inventory_task: 静音条件从人工标记 is_ordered 改为「该物料无活跃采购单」。 ★ 为什么必须同时改邮件:预警邮件由出库执行流程触发(outbound_service 出库 完成后的调用),功能是活的;而它的静音入口(前端人工「标记已采购」)随本次 改造一并移除。若不改这里,用户会彻底失去静音能力,每个缺货物料在每次出库后 都会发信。自动判定在建单时静默、单据驳回或强制结案后自动恢复,比人工标记准。 两张表的判定口径都由 utils/purchase_activity.py 提供,不各写一遍。
This commit is contained in:
@ -171,6 +171,10 @@ class MaterialBaseService:
|
||||
|
||||
# 导入预警设置模型
|
||||
from app.models.base import MaterialWarningSetting
|
||||
# 「采购在途」判定 —— 与待采购池(purchase_service.get_pending_purchase_pool)
|
||||
# 共用同一份定义,避免两处口径漂移:有活跃采购单(待审批/已通过/部分到货未齐)
|
||||
# 即为在途;单据驳回或强制结案后自动解除。
|
||||
from app.utils.purchase_activity import active_purchase_exists
|
||||
|
||||
# ============================================================
|
||||
# 【核心修复】使用子查询方案:将聚合结果作为子查询
|
||||
@ -199,7 +203,11 @@ class MaterialBaseService:
|
||||
MaterialWarningSetting.yellow_threshold.label('warning_yellow'),
|
||||
MaterialWarningSetting.red_threshold.label('warning_red'),
|
||||
MaterialWarningSetting.red_emails.label('warning_red_emails'),
|
||||
MaterialWarningSetting.yellow_emails.label('warning_yellow_emails')
|
||||
MaterialWarningSetting.yellow_emails.label('warning_yellow_emails'),
|
||||
# ★ 只加列、不参与排序:enableWarningSort 用的是固定的 order_by
|
||||
# 表达式,与 SELECT 列表无关;且 sort_field_map 里没有它,
|
||||
# 前端无法按此列排序。既有行为逐位不变。
|
||||
active_purchase_exists(MaterialBase.id).label('is_purchasing')
|
||||
).outerjoin(inner_sub, MaterialBase.id == inner_sub.c.base_id) \
|
||||
.outerjoin(MaterialWarningSetting, MaterialBase.id == MaterialWarningSetting.base_id)
|
||||
|
||||
@ -423,6 +431,7 @@ class MaterialBaseService:
|
||||
# 说明查询只返回了 MaterialBase 单一对象
|
||||
item = row
|
||||
inv = avail = warning_enabled = warning_yellow = warning_red = None
|
||||
is_purchasing = False
|
||||
else:
|
||||
# 说明返回了 Row 对象 (包含多个字段)
|
||||
item = row[0]
|
||||
@ -433,6 +442,7 @@ class MaterialBaseService:
|
||||
warning_red = row[5] if len(row) > 5 else 0
|
||||
warning_red_emails = row[6] if len(row) > 6 else None
|
||||
warning_yellow_emails = row[7] if len(row) > 7 else None
|
||||
is_purchasing = row[8] if len(row) > 8 else False
|
||||
|
||||
# 安全兜底
|
||||
if not hasattr(item, 'to_dict'):
|
||||
@ -442,6 +452,10 @@ class MaterialBaseService:
|
||||
item_dict['inventoryCount'] = float(inv) if inv is not None else 0
|
||||
item_dict['availableCount'] = float(avail) if avail is not None else 0
|
||||
|
||||
# ★ 「采购在途」放在预警权限判断**之外**:能看到物料列表的人
|
||||
# 都应该知道这个物料已经在采购了(即使他没有查看预警的门槛)。
|
||||
item_dict['isPurchasing'] = bool(is_purchasing)
|
||||
|
||||
# 处理预警信息(仅当用户有权限时)
|
||||
if has_warning_permission:
|
||||
item_dict['warningEnabled'] = bool(warning_enabled) if warning_enabled is not None else False
|
||||
|
||||
Reference in New Issue
Block a user