fix(purchase): 待采购清单的参考价格改按 material_list:referencePrice 管控
修复一个权限旁路:待采购清单的「参考单价」原本后端无条件返回、前端列也没有 任何门控,而 material_list:referencePrice 只授予 SUPER_ADMIN 与 SUPERVISOR。 结果是 WAREHOUSE_MGR(库管) / INBOUND(入库员) / SALES(销售) 虽然都持有 inbound_purchase:pending_pool、能打开待采购清单,就会看到参考价格 —— 而这个 数字他们在物料列表里是被挡住的。等于本页面成了绕过该权限的后门。 参考价格来自 material_base.reference_price,与物料列表同源,因此复用同一个 权限码管控,不另造新码(同源数据用同码,口径才不会漂)。 改动: - 后端 get_pending_purchase_pool 新增 include_reference_price 参数, fail-closed 默认 False;无权限时**整个字段不返回**而不是给 None - 新增 _has_material_reference_price_perm(),判定方式与既有的 _filter_purchase_prices 保持一致(超管/主管放行 + 逐个权限码比对) - 前端「参考单价」列加 hasPermission 门控,TS 类型改为可选 ★ 只挡前端等于没挡(接口仍然裸奔),前后端必须同时改。
This commit is contained in:
@ -536,7 +536,8 @@ class PurchaseService:
|
||||
@staticmethod
|
||||
def get_pending_purchase_pool(page=1, per_page=20, keyword=None,
|
||||
category=None, material_type=None,
|
||||
warning_status=None):
|
||||
warning_status=None,
|
||||
include_reference_price=False):
|
||||
"""
|
||||
待采购池:找出「**有效供给**仍不足、需要再买」的物料。
|
||||
|
||||
@ -561,6 +562,12 @@ class PurchaseService:
|
||||
- 阈值可能为 None,红黄两个阈值**各自独立**判断,不能 coalesce 成一个
|
||||
- 用 `<=` 而非 `<` —— 恰好等于阈值即算不足
|
||||
|
||||
★ 参考价格(reference_price)默认**不返回**(fail-closed)。
|
||||
它是 material_base.reference_price,属于受 material_list:referencePrice
|
||||
管控的价格数据 —— 与物料列表同源,就必须同码管控,否则这里会变成
|
||||
绕过该权限的后门(物料列表看不到、待采购清单却看得到)。
|
||||
调用方(API 层)按权限显式传 include_reference_price=True。
|
||||
|
||||
★ 关于 `<=`(2026-09-18 与业务方确认,**刻意维持,勿擅自改成 `<`**):
|
||||
阈值是「警戒下限」,到线即需关注;且物料列表预警、预警邮件用的是同一套
|
||||
`<=` 口径(那是系统原有约定,不是本接口另立的)。若只把本接口改成 `<`,
|
||||
@ -738,7 +745,11 @@ class PurchaseService:
|
||||
'company_name': material.company_name or '',
|
||||
'image': PurchaseService._first_image(material.product_image),
|
||||
'purchase_link': material.purchase_link or '',
|
||||
'reference_price': float(material.reference_price) if material.reference_price is not None else None,
|
||||
# fail-closed:无权限时整个字段不出现,而不是给 None ——
|
||||
# 前端据字段是否存在决定列是否渲染,语义更干净
|
||||
**({'reference_price': float(material.reference_price)
|
||||
if material.reference_price is not None else None}
|
||||
if include_reference_price else {}),
|
||||
'inventory_count': inv,
|
||||
'available_count': avail,
|
||||
# 在途量与有效供给一并返回,前端才能向采购员解释「为什么只建议买这么多」
|
||||
|
||||
Reference in New Issue
Block a user