From 23fc10a25fb98687fda8e8595ae988051b4adea8 Mon Sep 17 00:00:00 2001 From: yueli Date: Thu, 16 Jul 2026 14:14:43 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20Day2=E5=B0=B1=E7=BB=AA=20=E2=80=94=20?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=A1=AC=E5=8C=96+=E7=B4=A2=E5=BC=95?= =?UTF-8?q?=E8=A1=A5=E5=85=A8+=E5=85=A8=E5=B1=80=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## base_service.py — MaterialBase删除硬化 - 新增 BomTable 引用检查(bom_usage_count) - 物料被BOM引用时禁止删除,提示「请先解除BOM绑定」 ## models/base.py + bom.py — 缺失索引补全 - material_base: company_name + is_enabled 添加 index=True - bom_table: is_enabled 添加 index=True ## __init__.py — 全局异常处理 - @app.errorhandler(ValueError) → 400 + 自定义消息 - @app.errorhandler(404/405) → 标准错误 - @app.errorhandler(Exception) → 500 + 通用消息 堆栈仅记录服务器日志,不泄露到前端 --- inventory-backend/app/__init__.py | 31 ++++++++++++++++++- inventory-backend/app/models/base.py | 4 +-- inventory-backend/app/models/bom.py | 2 +- .../app/services/inbound/base_service.py | 9 ++++-- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/inventory-backend/app/__init__.py b/inventory-backend/app/__init__.py index 780feff..babe5d4 100644 --- a/inventory-backend/app/__init__.py +++ b/inventory-backend/app/__init__.py @@ -1,6 +1,6 @@ # 文件路径: inventory-backend/app/__init__.py -from flask import Flask +from flask import Flask, jsonify from config import Config from app.extensions import db, migrate, cors, jwt from app.api.v1.scan import scan_bp @@ -295,4 +295,33 @@ def create_app(): except Exception as e: print(f"⚠️ 模型预加载发生未知错误: {e}") + # ========================================================= + # 4. 全局异常处理(面向生产:不泄露堆栈) + # ========================================================= + import logging + import traceback + + @app.errorhandler(ValueError) + def handle_value_error(e): + """业务校验异常 → 400 + 自定义消息""" + return jsonify({'code': 400, 'msg': str(e)}), 400 + + @app.errorhandler(404) + def handle_not_found(e): + return jsonify({'code': 404, 'msg': '资源不存在'}), 404 + + @app.errorhandler(405) + def handle_method_not_allowed(e): + return jsonify({'code': 405, 'msg': '请求方法不允许'}), 405 + + @app.errorhandler(Exception) + def handle_unhandled_exception(e): + """兜底:任何未捕获异常 → 500 + 通用消息,堆栈仅记录日志""" + app.logger.error(f"Unhandled exception: {type(e).__name__}: {e}\n{traceback.format_exc()}") + return jsonify({ + 'code': 500, + 'msg': '系统繁忙,请稍后再试', + 'error': 'Internal Server Error' + }), 500 + return app diff --git a/inventory-backend/app/models/base.py b/inventory-backend/app/models/base.py index ba4cf24..809ce9c 100644 --- a/inventory-backend/app/models/base.py +++ b/inventory-backend/app/models/base.py @@ -13,7 +13,7 @@ class MaterialBase(db.Model): # 1. 基础字段 id = db.Column(db.Integer, primary_key=True) - company_name = db.Column(db.String(255), comment='所属公司') + company_name = db.Column(db.String(255), index=True, comment='所属公司') # ★ 多租户过滤高频列 name = db.Column(db.String(255), nullable=False, index=True, comment='名称') # ★ 模糊搜索/精确定位高频列 common_name = db.Column(db.String(255), comment='俗名') @@ -34,7 +34,7 @@ class MaterialBase(db.Model): manual_link_remark = db.Column(db.Text, default='', comment='说明书备注') # 启用状态 - is_enabled = db.Column(db.Boolean, default=True, comment='是否启用') + is_enabled = db.Column(db.Boolean, default=True, index=True, comment='是否启用') # ★ 状态过滤高频列 # 强制质检标记(采购入库时必须上传检测报告) is_inspection_required = db.Column(db.Boolean, default=False, comment='是否强制要求质检') diff --git a/inventory-backend/app/models/bom.py b/inventory-backend/app/models/bom.py index f437815..ffc11ee 100644 --- a/inventory-backend/app/models/bom.py +++ b/inventory-backend/app/models/bom.py @@ -26,7 +26,7 @@ class BomTable(db.Model): remark = db.Column(db.Text, comment='备注') # ★ 新增:启用状态 - is_enabled = db.Column(db.Boolean, default=True, comment='是否启用') + is_enabled = db.Column(db.Boolean, default=True, index=True, comment='是否启用') # ★ 状态过滤高频列 # 约束: 保证同一版本下的父子对唯一,允许不同版本存在 __table_args__ = ( diff --git a/inventory-backend/app/services/inbound/base_service.py b/inventory-backend/app/services/inbound/base_service.py index 561cab0..0e02570 100644 --- a/inventory-backend/app/services/inbound/base_service.py +++ b/inventory-backend/app/services/inbound/base_service.py @@ -7,6 +7,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 app.models.bom import BomTable from sqlalchemy import or_, and_, func, case, desc, asc, cast, Numeric, text import traceback import json @@ -746,8 +747,11 @@ class MaterialBaseService: buy_usage_count = StockBuy.query.filter_by(base_id=m_id).count() semi_usage_count = StockSemi.query.filter_by(base_id=m_id).count() prod_usage_count = StockProduct.query.filter_by(base_id=m_id).count() + bom_usage_count = BomTable.query.filter( + or_(BomTable.parent_id == m_id, BomTable.child_id == m_id) + ).count() - total_usage = buy_usage_count + semi_usage_count + prod_usage_count + total_usage = buy_usage_count + semi_usage_count + prod_usage_count + bom_usage_count if total_usage > 0: raise ValueError( @@ -755,7 +759,8 @@ class MaterialBaseService: f"- 采购库存记录: {buy_usage_count} 条\n" f"- 半成品库存记录: {semi_usage_count} 条\n" f"- 成品库存记录: {prod_usage_count} 条\n" - f"请先清理相关库存或仅‘禁用’此条目。" + f"- BOM配方引用: {bom_usage_count} 条\n" + f"请先清理相关库存/BOM绑定或仅「禁用」此条目。" ) # 删除时同步清理向量记录