From 66b3e4897f9e07beb610909d3717ca04b298815d Mon Sep 17 00:00:00 2001 From: yueli Date: Tue, 8 Sep 2026 13:58:43 +0800 Subject: [PATCH] =?UTF-8?q?fix(bom):=20get=5Fbom=5Fsummary=20=E5=85=B3?= =?UTF-8?q?=E9=94=AE=E8=AF=8D=E4=B8=8E=20list=20=E5=AF=B9=E9=BD=90=20+=20?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E6=9B=B4=E6=96=B0=E6=96=B9=E6=B3=95=E5=81=A5?= =?UTF-8?q?=E5=A3=AE=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - get_bom_summary 关键词过滤改为与 get_bom_list 同款子查询(同时匹配 bom_no、父件名/规格、子件名/规格),任意关键词下 summary 计数与 list 明细严格一致,消除“标题有数、表格为空” - update_enabled/update_archived 对 bom_no/version 做 strip 规范化,并细化“BOM不存在”报错(带上实际参数便于排查) --- inventory-backend/app/services/bom_service.py | 47 +++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/inventory-backend/app/services/bom_service.py b/inventory-backend/app/services/bom_service.py index c61e73d..726d17b 100644 --- a/inventory-backend/app/services/bom_service.py +++ b/inventory-backend/app/services/bom_service.py @@ -267,14 +267,35 @@ class BomService: elif status == 'archived': query = query.filter(BomTable.is_archived == True) - # 关键词搜索 + # 关键词搜索:与 get_bom_list 保持同一口径——子查询匹配 (bom_no, version), + # 同时覆盖 bom_no、父件名/规格、子件名/规格,保证任意关键字下 summary 计数与 list 明细绝对一致 if keyword: kw = f'%{keyword.strip()}%' - query = query.filter(or_( - BomTable.bom_no.ilike(kw), - MaterialBase.name.ilike(kw), - MaterialBase.spec_model.ilike(kw) - )) + kw_child_alias = db.aliased(MaterialBase) + match_subq = db.session.query( + BomTable.bom_no, + BomTable.version + ).join( + MaterialBase, BomTable.parent_id == MaterialBase.id + ).outerjoin( + kw_child_alias, BomTable.child_id == kw_child_alias.id + ).filter( + or_( + BomTable.bom_no.ilike(kw), + MaterialBase.name.ilike(kw), + MaterialBase.spec_model.ilike(kw), + kw_child_alias.name.ilike(kw), + kw_child_alias.spec_model.ilike(kw) + ) + ).distinct().subquery() + + query = query.join( + match_subq, + db.and_( + BomTable.bom_no == match_subq.c.bom_no, + BomTable.version == match_subq.c.version + ) + ) query = query.group_by(MaterialBase.category) \ .order_by(MaterialBase.category) @@ -525,10 +546,16 @@ class BomService: """ 仅更新某 BOM 版本(整组行)的启用状态,供列表/只读视图"启用/停用"开关使用。 不触碰子件结构;成功后清除该 bom_no 的缓存。 + 注意:只按 bom_no+version 精确匹配,不加 is_enabled/is_archived 等多余过滤—— + 停用/归档中的版本只要记录存在即可继续改状态。 """ + bom_no = (bom_no or '').strip() + version = (version or '').strip() + if not bom_no or not version: + raise ValueError('BOM编号/版本不能为空') rows = BomTable.query.filter_by(bom_no=bom_no, version=version).all() if not rows: - raise ValueError('BOM 不存在') + raise ValueError(f'BOM不存在(bom_no={bom_no}, version={version})') for rec in rows: rec.is_enabled = bool(is_enabled) db.session.commit() @@ -542,9 +569,13 @@ class BomService: 仅更新某 BOM 版本(整组行)的归档标记。 归档=仍启用可查看/编辑,但不再作为其它 BOM 子件的引用候选;取消归档即恢复正常引用。 """ + bom_no = (bom_no or '').strip() + version = (version or '').strip() + if not bom_no or not version: + raise ValueError('BOM编号/版本不能为空') rows = BomTable.query.filter_by(bom_no=bom_no, version=version).all() if not rows: - raise ValueError('BOM 不存在') + raise ValueError(f'BOM不存在(bom_no={bom_no}, version={version})') for rec in rows: rec.is_archived = bool(archived) db.session.commit()