diff --git a/inventory-backend/app/api/v1/scrap.py b/inventory-backend/app/api/v1/scrap.py index ed1b423..5453f91 100644 --- a/inventory-backend/app/api/v1/scrap.py +++ b/inventory-backend/app/api/v1/scrap.py @@ -503,14 +503,19 @@ def _current_user_role(): @jwt_required() @permission_required('scrap_apply') def scrap_check_approval(): - """提交前预检:判断所选库存(物料)是否命中“需审批”""" + """ + 提交前预检:报废一律需审批,本接口返回 need_approval=true, + 并附带命中「需审批物料」标记的明细,供前端展示审批提示文案。 + """ try: from app.services.approval_control import resolve_approval_control + from app.services.scrap_approval_service import SCRAP_ALWAYS_REQUIRES_APPROVAL data = request.get_json() or {} items = data.get('items', []) or [] - need, flagged = resolve_approval_control(items) + _, flagged = resolve_approval_control(items) return jsonify({'code': 200, 'msg': 'success', - 'data': {'need_approval': need, 'materials': flagged}}), 200 + 'data': {'need_approval': SCRAP_ALWAYS_REQUIRES_APPROVAL, + 'materials': flagged}}), 200 except Exception as e: traceback.print_exc() return jsonify({'code': 500, 'msg': f'预检失败: {str(e)}'}), 500 diff --git a/inventory-backend/app/services/scrap_approval_service.py b/inventory-backend/app/services/scrap_approval_service.py index 5dd0f35..0e3f9cd 100644 --- a/inventory-backend/app/services/scrap_approval_service.py +++ b/inventory-backend/app/services/scrap_approval_service.py @@ -21,6 +21,16 @@ def _beijing(): return beijing_time() +# ============================================================================= +# ★ 业务规则(单一事实来源):报废一律需审批 +# +# 与出库/借库不同,报废不过滤 is_approval_required —— 无论物料是否命中该标记, +# 所有报废申请都必须由指定审批人审批通过后才能执行。 +# 前端 apply/index.vue 的「审批人」必填项与此规则保持一致。 +# ============================================================================= +SCRAP_ALWAYS_REQUIRES_APPROVAL = True + + STOCK_MODELS = {} @@ -101,21 +111,19 @@ class ScrapApprovalService: 'available_at_apply': avail, }) - # ★ 是否需审批:命中需审批物料 或 库管代建(force_approval) + # ★ 报废一律需审批(见 SCRAP_ALWAYS_REQUIRES_APPROVAL)。 + # resolve_approval_control 仍调用,但仅用于生成「哪些物料命中需审批」的提示文案, + # 不再用它决定是否需要审批。 from app.services.approval_control import resolve_approval_control - need_approval, flagged_materials = resolve_approval_control(normalized) - if force_approval: - need_approval = True - if need_approval and not approver_id: - if force_approval: - raise ValueError("库管代建报废申请必须选择审批人后再提交") - _names = ";".join(f"{m['name']}({m['spec_model'] or '-'})" for m in flagged_materials) - raise ValueError(f"以下物料需审批报废:{_names}。请选择审批人后再提交") + _, flagged_materials = resolve_approval_control(normalized) - if approver_id: - allowed_approvers = [{"type": "user", "value": int(approver_id)}] - elif not need_approval: - allowed_approvers = [] + if not approver_id: + if flagged_materials: + _names = ";".join(f"{m['name']}({m['spec_model'] or '-'})" for m in flagged_materials) + raise ValueError(f"以下物料需审批报废:{_names}。请选择审批人后再提交") + raise ValueError("报废申请必须选择审批人后再提交") + + allowed_approvers = [{"type": "user", "value": int(approver_id)}] req = ScrapApproval( request_no=ScrapApprovalService.generate_request_no(), @@ -125,17 +133,12 @@ class ScrapApprovalService: req.set_items(normalized) req.set_allowed_approvers(allowed_approvers) - if need_approval: - req.status = 0 # 待审批 - else: - # 默认不审批:直接进入“待执行” - req.status = 1 - req.actual_approver_id = applicant_id - req.approved_at = _beijing() + # ★ 恒为「待审批」,不再走免审批自动通过分支 + req.status = 0 db.session.add(req) db.session.commit() - logger.info(f"[ScrapApproval] 提交成功 {req.request_no} need_approval={need_approval}") + logger.info(f"[ScrapApproval] 提交成功 {req.request_no} approver={approver_id}") return req # ------------------------------------------------------------------