diff --git a/inventory-backend/app/api/v1/bom.py b/inventory-backend/app/api/v1/bom.py index b78b64d..cb3e9ea 100644 --- a/inventory-backend/app/api/v1/bom.py +++ b/inventory-backend/app/api/v1/bom.py @@ -218,8 +218,8 @@ def delete_bom(bom_no): if not exist: return jsonify({'code': 404, 'msg': 'BOM 不存在'}), 404 - # 删除 - query.delete() + # 删除(改为对象级删除以触发审计事件) + db.session.delete(exist) db.session.commit() return jsonify({ 'code': 200, diff --git a/inventory-backend/app/api/v1/inbound/stock.py b/inventory-backend/app/api/v1/inbound/stock.py index f8eaee5..3bafad2 100644 --- a/inventory-backend/app/api/v1/inbound/stock.py +++ b/inventory-backend/app/api/v1/inbound/stock.py @@ -444,7 +444,11 @@ def clear_draft(): # 清除指定会话 query = query.filter_by(session_id=session_id) - count = query.delete() + # 改为对象级删除以触发审计事件 + records = query.all() + count = len(records) + for rec in records: + db.session.delete(rec) db.session.commit() return jsonify({"message": f"已清除 {count} 条记录", "count": count}), 200 @@ -461,8 +465,11 @@ def start_new_session(): 清空整张草稿表,返回新的 session_id """ try: - # 清空整张草稿表 - deleted_count = StocktakeDraft.query.delete() + # 清空整张草稿表(改为对象级删除以触发审计事件) + all_records = StocktakeDraft.query.all() + deleted_count = len(all_records) + for rec in all_records: + db.session.delete(rec) db.session.commit() # 生成新的 session_id @@ -1148,10 +1155,14 @@ def generate_missing_stocktake(): # ★ 幂等性保护:先删除当前 session 下系统自动生成的漏盘记录 # 特征:user_id == 'system' (表示由系统自动生成) - deleted_count = StocktakeDraft.query.filter( + # 改为对象级删除以触发审计事件 + system_records = StocktakeDraft.query.filter( StocktakeDraft.session_id == session_id, StocktakeDraft.user_id == 'system' - ).delete() + ).all() + deleted_count = len(system_records) + for rec in system_records: + db.session.delete(rec) if deleted_count > 0: db.session.commit() print(f"[generate_missing] 已清理 {deleted_count} 条历史漏盘记录") diff --git a/inventory-backend/app/services/bom_service.py b/inventory-backend/app/services/bom_service.py index 61a20a6..9e3bac1 100644 --- a/inventory-backend/app/services/bom_service.py +++ b/inventory-backend/app/services/bom_service.py @@ -189,8 +189,10 @@ class BomService: raise ValueError(f'保存失败!当前子件配置与已有版本 {ver} 完全一致,请勿重复保存') # ===== 执行保存 ===== - # 仅删除当前版本的旧记录 - BomTable.query.filter_by(bom_no=bom_no, version=version).delete() + # 仅删除当前版本的旧记录(改为对象级删除以触发审计事件) + old_records = BomTable.query.filter_by(bom_no=bom_no, version=version).all() + for rec in old_records: + db.session.delete(rec) for child in children: bom = BomTable( @@ -260,7 +262,11 @@ class BomService: existing = BomTable.query.filter_by(parent_id=parent_id).first() bom_no = existing.bom_no if existing else BomService.generate_bom_no() - BomTable.query.filter_by(bom_no=bom_no, version=version).delete() + # 改为对象级删除以触发审计事件 + old_records = BomTable.query.filter_by(bom_no=bom_no, version=version).all() + for rec in old_records: + db.session.delete(rec) + for item in child_list: bom = BomTable( bom_no=bom_no, version=version, parent_id=parent_id, diff --git a/inventory-backend/app/services/permission_service.py b/inventory-backend/app/services/permission_service.py index e8f2a75..0124ca1 100644 --- a/inventory-backend/app/services/permission_service.py +++ b/inventory-backend/app/services/permission_service.py @@ -109,8 +109,10 @@ class PermissionService: try: # 1. 开启事务 (Flask-SQLAlchemy 自动管理,但明确逻辑更好) - # 2. 删除该角色旧的所有权限 - SysRolePermission.query.filter_by(role_code=role_code).delete() + # 2. 删除该角色旧的所有权限(改为对象级删除以触发审计事件) + old_perms = SysRolePermission.query.filter_by(role_code=role_code).all() + for p in old_perms: + db.session.delete(p) # 3. 准备新数据 if permissions: @@ -374,10 +376,14 @@ class PermissionService: ).all() for menu in legacy_menus: - # 删除关联的权限 - SysRolePermission.query.filter_by(target_code=menu.code).delete() - # 删除关联的元素 - SysElement.query.filter_by(menu_code=menu.code).delete() + # 删除关联的权限(改为对象级删除以触发审计事件) + old_perms = SysRolePermission.query.filter_by(target_code=menu.code).all() + for p in old_perms: + db.session.delete(p) + # 删除关联的元素(改为对象级删除以触发审计事件) + old_elements = SysElement.query.filter_by(menu_code=menu.code).all() + for e in old_elements: + db.session.delete(e) # 删除菜单 db.session.delete(menu) print(f"🗑️ 已清理旧版库存盘点菜单: {menu.code} ({menu.name})") @@ -456,8 +462,10 @@ class PermissionService: ).all() for menu in orphaned_menus: print(f"🗑️ 清理根级别冗余菜单: {menu.code} ({menu.name})") - # 删除关联的权限 - SysRolePermission.query.filter_by(target_code=menu.code).delete() + # 删除关联的权限(改为对象级删除以触发审计事件) + old_perms = SysRolePermission.query.filter_by(target_code=menu.code).all() + for p in old_perms: + db.session.delete(p) db.session.delete(menu) # 第二步:清理重复菜单(同一个 code 存在多条记录,保留 ID 最小的) @@ -473,13 +481,20 @@ class PermissionService: # 保留第一条,删除其他 for dup in duplicates[1:]: print(f"🗑️ 清理重复菜单: {dup.code} (id={dup.id}, name={dup.name})") - SysRolePermission.query.filter_by(target_code=dup.code).delete() - SysElement.query.filter_by(menu_code=dup.code).delete() + # 改为对象级删除以触发审计事件 + old_perms = SysRolePermission.query.filter_by(target_code=dup.code).all() + for p in old_perms: + db.session.delete(p) + old_elements = SysElement.query.filter_by(menu_code=dup.code).all() + for e in old_elements: + db.session.delete(e) db.session.delete(dup) # 第三步:强制重新设置所有子菜单的 parent_id,确保没有遗漏 - # 先将所有子菜单的 parent_id 设为 None,然后重新设置 - SysMenu.query.filter(SysMenu.code.in_(child_codes)).update({SysMenu.parent_id: None}) + # 改为对象级更新以触发审计事件 + child_menus = SysMenu.query.filter(SysMenu.code.in_(child_codes)).all() + for m in child_menus: + m.parent_id = None # 创建或更新菜单 menu_map = {} # code -> menu obj