feat(purchase): 新增待采购池接口(防重复采购)
GET /api/v1/purchase/pending-pool:找出「有效供给仍低于预警线」的物料。 有效供给 = 物理总库存 + 在途量 过滤规则 = 有效供给 <= 红/黄阈值 才进池 建议采购量 = max(1, 目标阈值 - 有效供给) ★ 为什么不用「有活跃单就排除」:红线 10、库存 0、某采购员只建了一张 数量 5 的单时,该物料会立刻从池中消失,剩下 5 个缺口永远无人认领。 改为按量计算后它继续留池,suggested_qty 自动降到 5。 ★ 用 <= 而非 < 是与业务方确认后刻意维持的口径(与物料列表预警、预警邮件 同源),勿擅自改成严格小于 —— 只改本接口会造成「列表亮黄灯、池子却排除」 的撕裂,真要改必须三处一起动。代价是恰好等于阈值时建议量落到保底的 1, 前端 tooltip 已单独说明,不展示算不成立的错误算式。 权限:新增 inbound_purchase:pending_pool(注册为 sys_element 而非新建 SysMenu)。因 ensure_default_permissions 在角色已有权限时整段跳过,另写了 存量角色自动迁移,并按源行镜像 company_name 避免跨公司作用域泄漏。
This commit is contained in:
@ -423,3 +423,37 @@ def search_material_for_purchase():
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
return jsonify({'code': 500, 'msg': str(e)}), 500
|
||||
|
||||
|
||||
# --------------------------------------------------------
|
||||
# 9. 待采购池(防重复采购)
|
||||
# GET /api/v1/purchase/pending-pool?page=1&limit=20&keyword=xxx
|
||||
# --------------------------------------------------------
|
||||
@purchase_bp.route('/pending-pool', methods=['GET'])
|
||||
@jwt_required()
|
||||
@permission_required('inbound_purchase:pending_pool')
|
||||
def get_pending_purchase_pool():
|
||||
"""
|
||||
待采购清单:库存已触及预警线、且没有活跃采购单的物料。
|
||||
|
||||
防重逻辑的核心 —— 物料一旦有在途采购单(待审批/已通过/部分到货未齐),
|
||||
立即从本列表中消失;单据被驳回或强制结案后才会重新回流。
|
||||
"""
|
||||
try:
|
||||
page = request.args.get('page', 1, type=int)
|
||||
limit = request.args.get('limit', 20, type=int)
|
||||
keyword = request.args.get('keyword', '').strip() or None
|
||||
category = request.args.get('category', '').strip() or None
|
||||
material_type = request.args.get('type', '').strip() or None
|
||||
|
||||
warning_status = request.args.get('warning_status', type=int)
|
||||
|
||||
result = PurchaseService.get_pending_purchase_pool(
|
||||
page=page, per_page=limit, keyword=keyword,
|
||||
category=category, material_type=material_type,
|
||||
warning_status=warning_status,
|
||||
)
|
||||
return jsonify({'code': 200, 'msg': '获取成功', 'data': result}), 200
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
return jsonify({'code': 500, 'msg': f'获取失败: {str(e)}'}), 500
|
||||
|
||||
Reference in New Issue
Block a user