From 2a9e2e4560f84c9158b54443a613540112362c5a Mon Sep 17 00:00:00 2001 From: yueli Date: Wed, 9 Sep 2026 13:00:41 +0800 Subject: [PATCH] =?UTF-8?q?fix(bom):=20BOM=20=E4=B8=89=E6=80=81=E4=BA=92?= =?UTF-8?q?=E6=96=A5=20+=20active=5Fonly=E6=8E=92=E9=99=A4=E5=BD=92?= =?UTF-8?q?=E6=A1=A3=20+=20=E8=AF=A6=E6=83=85=E4=B8=BB=E5=A4=87=E6=B3=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - get_bom_list active_only 补 is_archived==False,出库/借库“按BOM套餐”不再泄漏归档版本 - get_bom_detail 返回顶层 remark,详情弹窗主备注可回显 - 状态互斥:update_enabled 切启/停即清归档;update_archived 归档→废弃(enabled=False)、取消归档→启用;停用视图排除归档 --- inventory-backend/app/services/bom_service.py | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/inventory-backend/app/services/bom_service.py b/inventory-backend/app/services/bom_service.py index 726d17b..e6c5e47 100644 --- a/inventory-backend/app/services/bom_service.py +++ b/inventory-backend/app/services/bom_service.py @@ -152,11 +152,11 @@ class BomService: if status == 'enabled': query = query.filter(BomTable.is_enabled == True, BomTable.is_archived == False) elif status == 'disabled': - query = query.filter(BomTable.is_enabled == False) + query = query.filter(BomTable.is_enabled == False, BomTable.is_archived == False) elif status == 'archived': query = query.filter(BomTable.is_archived == True) elif active_only: - query = query.filter(BomTable.is_enabled == True) + query = query.filter(BomTable.is_enabled == True, BomTable.is_archived == False) # 【行级数据隔离】基于 JWT 多租户公司过滤 company_limit = get_current_company_filter() @@ -263,7 +263,7 @@ class BomService: if status == 'enabled': query = query.filter(BomTable.is_enabled == True, BomTable.is_archived == False) elif status == 'disabled': - query = query.filter(BomTable.is_enabled == False) + query = query.filter(BomTable.is_enabled == False, BomTable.is_archived == False) elif status == 'archived': query = query.filter(BomTable.is_archived == True) @@ -404,6 +404,7 @@ class BomService: 'parent_name': parent_material.name if parent_material else '', 'parent_spec': parent_material.spec_model if parent_material else '', 'is_enabled': first.BomTable.is_enabled, + 'remark': first.BomTable.remark or '', # ★ 主表备注 'children': children } @@ -544,10 +545,9 @@ class BomService: @staticmethod def update_enabled(bom_no, version, is_enabled): """ - 仅更新某 BOM 版本(整组行)的启用状态,供列表/只读视图"启用/停用"开关使用。 + 三态互斥:切“启用/停用”时同步清除“归档”。 + 启用=在用;停用=有问题/暂停;两者都与归档互斥。 不触碰子件结构;成功后清除该 bom_no 的缓存。 - 注意:只按 bom_no+version 精确匹配,不加 is_enabled/is_archived 等多余过滤—— - 停用/归档中的版本只要记录存在即可继续改状态。 """ bom_no = (bom_no or '').strip() version = (version or '').strip() @@ -558,6 +558,7 @@ class BomService: raise ValueError(f'BOM不存在(bom_no={bom_no}, version={version})') for rec in rows: rec.is_enabled = bool(is_enabled) + rec.is_archived = False # 切启/停即退出归档(三者互斥) db.session.commit() _cache_delete(bom_no, version) logger.info(f"[BOM Cache] update_enabled → 缓存已失效 bom_no={bom_no} version={version} enabled={is_enabled}") @@ -566,8 +567,9 @@ class BomService: @staticmethod def update_archived(bom_no, version, archived): """ - 仅更新某 BOM 版本(整组行)的归档标记。 - 归档=仍启用可查看/编辑,但不再作为其它 BOM 子件的引用候选;取消归档即恢复正常引用。 + 三态互斥归档:归档=彻底废弃(is_archived=True 且 is_enabled=False); + 取消归档=恢复“启用(在用)”(is_archived=False 且 is_enabled=True)。 + 归档后不出现在启用/停用视图、不作为子件引用候选。 """ bom_no = (bom_no or '').strip() version = (version or '').strip() @@ -576,8 +578,10 @@ class BomService: rows = BomTable.query.filter_by(bom_no=bom_no, version=version).all() if not rows: raise ValueError(f'BOM不存在(bom_no={bom_no}, version={version})') + target_archived = bool(archived) for rec in rows: - rec.is_archived = bool(archived) + rec.is_archived = target_archived + rec.is_enabled = not target_archived # 归档→停用;取消归档→启用(互斥) db.session.commit() _cache_delete(bom_no, version) logger.info(f"[BOM Cache] update_archived → 缓存已失效 bom_no={bom_no} version={version} archived={archived}")