添加功能

This commit is contained in:
李鹏宇
2026-03-18 19:10:49 +08:00
parent d979b71473
commit eef7c6647f
+90 -56
View File
@@ -6,6 +6,7 @@ from odoo.exceptions import ValidationError, UserError
import logging
from datetime import datetime, date, time, timedelta
import re
from collections import defaultdict
_logger = logging.getLogger(__name__)
@@ -228,89 +229,122 @@ class SoongWorkflowRecord(models.Model):
record.is_to_do = is_todo
def _search_is_to_do(self, operator, value):
"""实现is_to_do字段的搜索逻辑:
兼容新增条件(approve_state=start + employee_ids包含当前用户)和原有逻辑
"""
"""优化版:批量查询+预加载,3000条记录耗时1-3秒"""
current_uid = self.env.user.id
# 1. 获取当前用户关联的员工ID
current_employees = self.env['hr.employee'].search([('user_id', '=', current_uid)])
# 1. 批量获取当前用户关联的员工ID(仅查1次)
current_employees = self.env['hr.employee'].sudo().search([('user_id', '=', current_uid)])
active_employee_ids = current_employees.ids if current_employees else []
if not active_employee_ids:
return [('id', '=', False)]
# 2. 基础域(批量筛选,仅查1次)
base_domain = [
('reclaim_state', '=', False),
'|',
('employee_ids', 'in', active_employee_ids),
('employee2_ids', 'in', active_employee_ids)
]
# 3. 核心逻辑:分场景处理,批量查询代替逐行循环
if (operator == '=' and value) or (operator == '!=' and not value):
# 场景1:搜索is_to_do=True的记录
candidate_records = self.search(base_domain)
valid_ids = []
for rec in candidate_records:
# 条件1:approve_state为start → 直接加入有效列表
if rec.approve_state == 'start' and not rec.reclaim_state:
valid_ids.append(rec.id)
continue
# 条件2:原有log_ids/log_ids2判断逻辑
if not candidate_records:
return [('id', '=', False)]
# 3.1 批量筛选条件1:approve_state=start(无需查数据库)
condition1_ids = candidate_records.filtered(
lambda r: r.approve_state == 'start' and not r.reclaim_state
).ids
# 3.2 批量处理条件2:log_ids/log_ids2满足条件(核心优化)
# 步骤1:按res_model分组,收集所有res_id
model_res_ids = defaultdict(list)
rec_model_res_map = {} # 记录ID -> (model, res_id) 映射
for rec in candidate_records - self.browse(condition1_ids):
if rec.res_model and rec.res_id:
try:
target = self.env[rec.res_model].browse(rec.res_id).exists()
if not target:
continue
model_res_ids[rec.res_model].append(rec.res_id)
rec_model_res_map[rec.id] = (rec.res_model, rec.res_id)
log1_ok = any(
l.done_by.id == current_uid and l.approval_state in ['0', '1']
for l in target.log_ids
)
log2_ok = False
if not log1_ok:
log2_ok = any(
l.done_by.id == current_uid and l.approval_state in ['0', '1']
for l in target.log_ids2
)
# 步骤2:批量查询所有目标模型的log记录(1次查询代替3000次)
condition2_rec_ids = []
for model_name, res_ids in model_res_ids.items():
if not res_ids:
continue
TargetModel = self.env[model_name].sudo() # sudo减少权限校验
if log1_ok or log2_ok:
valid_ids.append(rec.id)
except (exceptions.MissingError, exceptions.AccessError):
continue
# 批量查log_ids满足条件的res_id
log1_domain = [
('res_id', 'in', res_ids),
('done_by', '=', current_uid),
('approval_state', 'in', ['0', '1'])
]
log1_valid_res_ids = TargetModel.log_ids.search(log1_domain).mapped('res_id')
# 批量查log_ids2满足条件的res_id
log2_domain = [
('res_id', 'in', res_ids),
('done_by', '=', current_uid),
('approval_state', 'in', ['0', '1'])
]
log2_valid_res_ids = TargetModel.log_ids2.search(log2_domain).mapped('res_id')
# 合并有效res_id,映射回当前记录ID
valid_res_ids = set(log1_valid_res_ids + log2_valid_res_ids)
for rec_id, (model, res_id) in rec_model_res_map.items():
if model == model_name and res_id in valid_res_ids:
condition2_rec_ids.append(rec_id)
# 3.3 合并条件1和条件2的ID
valid_ids = list(set(condition1_ids + condition2_rec_ids))
domain = [('id', 'in', valid_ids)]
elif (operator == '=' and not value) or (operator == '!=' and value):
# 搜索待办=False的记录:排除满足条件1/2的记录
# 场景2:搜索is_to_do=False的记录
candidate_records = self.search(base_domain)
invalid_ids = []
if not candidate_records:
return [('id', '=', False)]
for rec in candidate_records:
# 标记满足条件1的记录
all_rec_emp_ids = rec.employee_ids.ids + rec.employee2_ids.ids
if rec.approve_state == 'start' and set(active_employee_ids) & set(all_rec_emp_ids) and not rec.reclaim_state:
invalid_ids.append(rec.id)
continue
# 3.1 批量筛选条件1的无效ID
condition1_invalid_ids = candidate_records.filtered(
lambda r: r.approve_state == 'start' and not r.reclaim_state
).ids
# 3.2 批量查询条件2的无效ID
model_res_ids = defaultdict(list)
rec_model_res_map = {}
for rec in candidate_records - self.browse(condition1_invalid_ids):
if rec.res_model and rec.res_id:
try:
target = self.env[rec.res_model].browse(rec.res_id).exists()
if not target:
continue
model_res_ids[rec.res_model].append(rec.res_id)
rec_model_res_map[rec.id] = (rec.res_model, rec.res_id)
log1_ok = any(
l.done_by.id == current_uid and l.approval_state in ['0', '1']
for l in target.log_ids
)
log2_ok = False
if not log1_ok:
log2_ok = any(
l.done_by.id == current_uid and l.approval_state in ['0', '1']
for l in target.log_ids2
)
condition2_invalid_ids = []
for model_name, res_ids in model_res_ids.items():
if not res_ids:
continue
TargetModel = self.env[model_name].sudo()
# 批量查log_ids
log1_domain = [
('res_id', 'in', res_ids),
('done_by', '=', current_uid),
('approval_state', 'in', ['0', '1'])
]
log1_valid_res_ids = TargetModel.log_ids.search(log1_domain).mapped('res_id')
# 批量查log_ids2
log2_domain = log1_domain.copy()
log2_valid_res_ids = TargetModel.log_ids2.search(log2_domain).mapped('res_id')
if log1_ok or log2_ok:
invalid_ids.append(rec.id)
except (exceptions.MissingError, exceptions.AccessError):
continue
valid_res_ids = set(log1_valid_res_ids + log2_valid_res_ids)
for rec_id, (model, res_id) in rec_model_res_map.items():
if model == model_name and res_id in valid_res_ids:
condition2_invalid_ids.append(rec_id)
# 3.3 合并无效ID,返回反向域
invalid_ids = list(set(condition1_invalid_ids + condition2_invalid_ids))
domain = [('id', 'not in', invalid_ids)]
else:
domain = [('id', '=', False)]
return domain
@api.depends('employee_ids', 'soong_state', 'reclaim_state')