fix(bom): BOM 三态互斥 + active_only排除归档 + 详情主备注

- get_bom_list active_only 补 is_archived==False,出库/借库“按BOM套餐”不再泄漏归档版本
- get_bom_detail 返回顶层 remark,详情弹窗主备注可回显
- 状态互斥:update_enabled 切启/停即清归档;update_archived 归档→废弃(enabled=False)、取消归档→启用;停用视图排除归档
This commit is contained in:
yueli
2026-09-09 13:00:41 +08:00
parent c8cf2bd52b
commit 2a9e2e4560

View File

@ -152,11 +152,11 @@ class BomService:
if status == 'enabled': if status == 'enabled':
query = query.filter(BomTable.is_enabled == True, BomTable.is_archived == False) query = query.filter(BomTable.is_enabled == True, BomTable.is_archived == False)
elif status == 'disabled': elif status == 'disabled':
query = query.filter(BomTable.is_enabled == False) query = query.filter(BomTable.is_enabled == False, BomTable.is_archived == False)
elif status == 'archived': elif status == 'archived':
query = query.filter(BomTable.is_archived == True) query = query.filter(BomTable.is_archived == True)
elif active_only: elif active_only:
query = query.filter(BomTable.is_enabled == True) query = query.filter(BomTable.is_enabled == True, BomTable.is_archived == False)
# 【行级数据隔离】基于 JWT 多租户公司过滤 # 【行级数据隔离】基于 JWT 多租户公司过滤
company_limit = get_current_company_filter() company_limit = get_current_company_filter()
@ -263,7 +263,7 @@ class BomService:
if status == 'enabled': if status == 'enabled':
query = query.filter(BomTable.is_enabled == True, BomTable.is_archived == False) query = query.filter(BomTable.is_enabled == True, BomTable.is_archived == False)
elif status == 'disabled': elif status == 'disabled':
query = query.filter(BomTable.is_enabled == False) query = query.filter(BomTable.is_enabled == False, BomTable.is_archived == False)
elif status == 'archived': elif status == 'archived':
query = query.filter(BomTable.is_archived == True) query = query.filter(BomTable.is_archived == True)
@ -404,6 +404,7 @@ class BomService:
'parent_name': parent_material.name if parent_material else '', 'parent_name': parent_material.name if parent_material else '',
'parent_spec': parent_material.spec_model if parent_material else '', 'parent_spec': parent_material.spec_model if parent_material else '',
'is_enabled': first.BomTable.is_enabled, 'is_enabled': first.BomTable.is_enabled,
'remark': first.BomTable.remark or '', # ★ 主表备注
'children': children 'children': children
} }
@ -544,10 +545,9 @@ class BomService:
@staticmethod @staticmethod
def update_enabled(bom_no, version, is_enabled): def update_enabled(bom_no, version, is_enabled):
""" """
仅更新某 BOM 版本(整组行)的启用状态,供列表/只读视图"启用/停用"开关使用 三态互斥:切“启用/停用”时同步清除“归档”
启用=在用;停用=有问题/暂停;两者都与归档互斥。
不触碰子件结构;成功后清除该 bom_no 的缓存。 不触碰子件结构;成功后清除该 bom_no 的缓存。
注意:只按 bom_no+version 精确匹配,不加 is_enabled/is_archived 等多余过滤——
停用/归档中的版本只要记录存在即可继续改状态。
""" """
bom_no = (bom_no or '').strip() bom_no = (bom_no or '').strip()
version = (version or '').strip() version = (version or '').strip()
@ -558,6 +558,7 @@ class BomService:
raise ValueError(f'BOM不存在bom_no={bom_no}, version={version}') raise ValueError(f'BOM不存在bom_no={bom_no}, version={version}')
for rec in rows: for rec in rows:
rec.is_enabled = bool(is_enabled) rec.is_enabled = bool(is_enabled)
rec.is_archived = False # 切启/停即退出归档(三者互斥)
db.session.commit() db.session.commit()
_cache_delete(bom_no, version) _cache_delete(bom_no, version)
logger.info(f"[BOM Cache] update_enabled → 缓存已失效 bom_no={bom_no} version={version} enabled={is_enabled}") logger.info(f"[BOM Cache] update_enabled → 缓存已失效 bom_no={bom_no} version={version} enabled={is_enabled}")
@ -566,8 +567,9 @@ class BomService:
@staticmethod @staticmethod
def update_archived(bom_no, version, archived): def update_archived(bom_no, version, archived):
""" """
仅更新某 BOM 版本(整组行)的归档标记。 三态互斥归档:归档=彻底废弃is_archived=True 且 is_enabled=False
归档=仍启用可查看/编辑,但不再作为其它 BOM 子件的引用候选;取消归档恢复正常引用 取消归档=恢复“启用(在用)”is_archived=False 且 is_enabled=True
归档后不出现在启用/停用视图、不作为子件引用候选。
""" """
bom_no = (bom_no or '').strip() bom_no = (bom_no or '').strip()
version = (version or '').strip() version = (version or '').strip()
@ -576,8 +578,10 @@ class BomService:
rows = BomTable.query.filter_by(bom_no=bom_no, version=version).all() rows = BomTable.query.filter_by(bom_no=bom_no, version=version).all()
if not rows: if not rows:
raise ValueError(f'BOM不存在bom_no={bom_no}, version={version}') raise ValueError(f'BOM不存在bom_no={bom_no}, version={version}')
target_archived = bool(archived)
for rec in rows: for rec in rows:
rec.is_archived = bool(archived) rec.is_archived = target_archived
rec.is_enabled = not target_archived # 归档→停用;取消归档→启用(互斥)
db.session.commit() db.session.commit()
_cache_delete(bom_no, version) _cache_delete(bom_no, version)
logger.info(f"[BOM Cache] update_archived → 缓存已失效 bom_no={bom_no} version={version} archived={archived}") logger.info(f"[BOM Cache] update_archived → 缓存已失效 bom_no={bom_no} version={version} archived={archived}")