Merge pull request !9991 from 李鹏宇/dev
This commit is contained in:
李鹏宇
2026-03-20 09:03:32 +00:00
committed by Gitee
+80 -199
View File
@@ -169,155 +169,113 @@ class SoongWorkflowRecord(models.Model):
_logger.warning(f"Failed to get urgency_level from {record.res_model}: {e}")
record.urgency_level = 'normal'
@api.depends('employee_ids', 'res_model', 'res_id', 'soong_state', 'reclaim_state', 'approve_state')
@api.depends('employee_ids', 'res_model', 'res_id', 'soong_state', 'reclaim_state', 'approve_state', 'users_ids')
def _compute_is_to_do(self):
"""保留原有计算逻辑(已优化批量查询,参考之前的版本)"""
current_uid = self.env.user.id
current_employees = self.env['hr.employee'].search([('user_id', '=', current_uid)])
active_employee_ids = current_employees.ids if current_employees else []
if not active_employee_ids:
self.is_to_do = False
return
# 批量优化:预加载员工映射(仅查1次)
all_employees = self.env['hr.employee'].search([('user_state', '=', 'in')])
emp_to_user = {emp.id: emp.user_id.id for emp in all_employees if emp.user_id}
# 第一步:批量处理条件1(approve_state=start)
condition1_records = self.filtered(
lambda r: not r.reclaim_state and r.approve_state == 'start' and
set(active_employee_ids) & set(r.employee_ids.ids + r.employee2_ids.ids)
for rec in self:
rec.is_to_do = False
valid_records = self.filtered(
lambda r: current_uid in r.users_ids.ids
)
condition1_records.is_to_do = True
# 第二步:批量处理条件2(log_ids/log_ids2)
remaining_records = self - condition1_records
remaining_records.is_to_do = False
# 按res_model分组批量查询log(核心优化)
model_res_ids = defaultdict(list)
rec_model_res_map = {}
for rec in remaining_records.filtered(lambda r: not r.reclaim_state and r.res_model and r.res_id):
model_res_ids[rec.res_model].append(rec.res_id)
rec_model_res_map[rec.id] = (rec.res_model, rec.res_id)
# 批量查log满足条件的记录ID
valid_rec_ids = []
for model_name, res_ids in model_res_ids.items():
if not res_ids:
continue
TargetModel = self.env[model_name].sudo()
if not valid_records:
return
start_records = valid_records.filtered(lambda r: r.approve_state == 'start')
start_records.is_to_do = True
remaining_records = valid_records - start_records
if not remaining_records:
return
for rec in remaining_records:
log_domain = [
('res_id', 'in', res_ids),
('done_by', 'in', list(emp_to_user.values())),
("model", "=", rec.res_model ),
("res_id", "=", rec.res_id),
('done_by', '=', current_uid),
('approval_state', 'in', ['0', '1'])
]
# 批量查log_ids
log1_valid_res_ids = TargetModel.log_ids.search(log_domain).mapped('res_id')
# 批量查log_ids2
log2_valid_res_ids = TargetModel.log_ids2.search(log_domain).mapped('res_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:
valid_rec_ids.append(rec_id)
self.browse(valid_rec_ids).is_to_do = True
has_valid_log1 = self.env['soong.workflow.log'].search_count(log_domain) > 0
has_valid_log2 = self.env['soong.workflow.log2'].search_count(log_domain) > 0
if has_valid_log1 or has_valid_log2:
rec.is_to_do = True
def _search_is_to_do(self, operator, value):
"""搜索待办状态:仅打印总耗时"""
current_uid = self.env.user.id
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:
# 第一步:基础过滤 - 只处理包含当前用户的记录
base_domain = [('users_ids', 'in', [current_uid])]
candidate_records = self.search(base_domain)
if not candidate_records:
return [('id', '=', False)]
base_domain = [
('reclaim_state', '=', False),
'|',
('employee_ids', 'in', active_employee_ids),
('employee2_ids', 'in', active_employee_ids)
]
# 处理 "is_to_do = True" 或 "is_to_do != False" 的情况
if (operator == '=' and value) or (operator == '!=' and not value):
candidate_records = self.search(base_domain)
if not candidate_records:
return [('id', '=', False)]
# 条件1:approve_state为start的记录ID
condition1_ids = candidate_records.filtered(
lambda r: r.approve_state == 'start' and not r.reclaim_state
lambda r: r.approve_state == 'start'
).ids
model_res_ids = defaultdict(list)
rec_model_res_map = {}
for rec in candidate_records - self.browse(condition1_ids):
if rec.res_model and rec.res_id:
model_res_ids[rec.res_model].append(rec.res_id)
rec_model_res_map[rec.id] = (rec.res_model, rec.res_id)
# 条件2:非start状态,且日志符合条件的记录ID
remaining_records = candidate_records - self.browse(condition1_ids)
# 仅筛选有res_model/res_id且非草稿/非start的记录
target_records = remaining_records.filtered(
lambda r: r.res_model and r.res_id and r.approve_state not in ['draft', 'start']
)
condition2_rec_ids = []
for model_name, res_ids in model_res_ids.items():
if not res_ids:
continue
TargetModel = self.env[model_name].sudo()
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')
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')
if target_records:
# 逐条检查日志(完全对齐compute逻辑,移除try-except)
for rec in target_records:
# 日志筛选条件(和compute逻辑完全一致)
log_domain = [
("model", "=", rec.res_model),
("res_id", "=", rec.res_id),
('done_by', '=', current_uid),
('approval_state', 'in', ['0', '1'])
]
# 直接查询soong.workflow.log和log2模型
has_valid_log1 = self.env['soong.workflow.log'].search_count(log_domain) > 0
has_valid_log2 = self.env['soong.workflow.log2'].search_count(log_domain) > 0
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)
if has_valid_log1 or has_valid_log2:
condition2_rec_ids.append(rec.id)
# 合并符合条件的记录ID
valid_ids = list(set(condition1_ids + condition2_rec_ids))
domain = [('id', 'in', valid_ids)]
domain = [('id', 'in', valid_ids)] if valid_ids else [('id', '=', False)]
elif (operator == '=' and not value) or (operator == '!=' and value):
candidate_records = self.search(base_domain)
if not candidate_records:
return [('id', '=', False)]
condition1_invalid_ids = candidate_records.filtered(
lambda r: r.approve_state == 'start' and not r.reclaim_state
todo_ids = []
# 条件1:approve_state为start的待办ID
condition1_todo_ids = candidate_records.filtered(
lambda r: r.approve_state == 'start'
).ids
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:
model_res_ids[rec.res_model].append(rec.res_id)
rec_model_res_map[rec.id] = (rec.res_model, rec.res_id)
# 条件2:日志符合条件的待办ID
remaining_records = candidate_records - self.browse(condition1_todo_ids)
target_records = remaining_records.filtered(
lambda r: r.res_model and r.res_id and r.approve_state not in ['draft', 'start']
)
condition2_invalid_ids = []
for model_name, res_ids in model_res_ids.items():
if not res_ids:
continue
TargetModel = self.env[model_name].sudo()
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')
log2_domain = log1_domain.copy()
log2_valid_res_ids = TargetModel.log_ids2.search(log2_domain).mapped('res_id')
condition2_todo_ids = []
if target_records:
for rec in target_records:
log_domain = [
("model", "=", rec.res_model),
("res_id", "=", rec.res_id),
('done_by', '=', current_uid),
('approval_state', 'in', ['0', '1'])
]
has_valid_log1 = self.env['soong.workflow.log'].search_count(log_domain) > 0
has_valid_log2 = self.env['soong.workflow.log2'].search_count(log_domain) > 0
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)
if has_valid_log1 or has_valid_log2:
condition2_todo_ids.append(rec.id)
invalid_ids = list(set(condition1_invalid_ids + condition2_invalid_ids))
domain = [('id', 'not in', invalid_ids)]
todo_ids = list(set(condition1_todo_ids + condition2_todo_ids))
# 非待办 = 基础候选记录 - 待办记录
all_candidate_ids = candidate_records.ids
non_todo_ids = [rec_id for rec_id in all_candidate_ids if rec_id not in todo_ids]
domain = [('id', 'in', non_todo_ids)] if non_todo_ids else [('id', '=', False)]
else:
# 不支持的操作符
domain = [('id', '=', False)]
return domain
@@ -669,90 +627,13 @@ class SoongWorkflowRecord(models.Model):
@api.model
def get_view(self, view_id=None, view_type='form', **options):
"""优化后:批量查询+批量写入,消除嵌套循环"""
# ========== 第一步:批量查询所有目标记录(仅1次搜索) ==========
current_user_id = self.env.user.id
all_records = self.search([
('users_ids', 'in', current_user_id),
('soong_state', '!=', 'active'),
('reclaim_state', '=', False)
])
if not all_records:
return super().get_view(view_id, view_type, **options)
model_res_ids = defaultdict(list)
rec_model_res_map = {rec.id: (rec.res_model, rec.res_id) for rec in all_records if rec.res_model and rec.res_id}
for rec_id, (model, res_id) in rec_model_res_map.items():
model_res_ids[model].append(res_id)
log_data = defaultdict(dict)
for model_name, res_ids in model_res_ids.items():
if not res_ids:
continue
try:
TargetModel = self.env[model_name].sudo()
has_log1 = 'log_ids' in TargetModel._fields
has_log2 = 'log_ids2' in TargetModel._fields
# 批量查log_ids(当前用户,仅当字段存在时)
if has_log1:
log1_domain = [('res_id', 'in', res_ids), ('done_by', '=', current_user_id)]
log1_records = TargetModel.log_ids.search(log1_domain)
for log in log1_records:
if log.res_id not in log_data[model_name]:
log_data[model_name][log.res_id] = {'log1_states': [], 'log2_states': [],
'has_archive_log': False}
log_data[model_name][log.res_id]['log1_states'].append(log.approval_state)
if log.name == '归档':
log_data[model_name][log.res_id]['has_archive_log'] = True
log_data[model_name][log.res_id]['archive_state'] = log.approval_state
# 批量查log_ids2(当前用户,仅当字段存在时)
if has_log2:
log2_domain = [('res_id', 'in', res_ids), ('done_by.name', '=', self.env.user.name)]
log2_records = TargetModel.log_ids2.search(log2_domain)
for log2 in log2_records:
if log2.res_id not in log_data[model_name]:
log_data[model_name][log2.res_id] = {'log1_states': [], 'log2_states': [],
'has_archive_log': False}
log_data[model_name][log2.res_id]['log2_states'].append(log2.approval_state)
except Exception:
continue
to_write = defaultdict(list) # {状态: [记录ID]}
for rec in all_records:
if rec.id not in rec_model_res_map:
continue
model, res_id = rec_model_res_map[rec.id]
if model not in log_data or res_id not in log_data[model]:
continue
log_info = log_data[model][res_id]
# 处理归档日志优先级最高
if log_info['has_archive_log']:
if log_info['archive_state'] in ['0', '1']:
to_write['to_active'].append(rec.id)
elif log_info['archive_state'] == '2':
to_write['active'].append(rec.id)
continue
# 处理普通log_ids
log1_states = log_info['log1_states']
if any(s in ['0', '1'] for s in log1_states):
to_write['to_do'].append(rec.id)
elif all(s == '2' for s in log1_states if s):
to_write['done'].append(rec.id)
# 处理log_ids2
log2_states = log_info['log2_states']
if log2_states:
if any(s in ['0', '1'] for s in log2_states):
to_write['to_do'].append(rec.id)
elif all(s == '2' for s in log2_states):
to_write['done'].append(rec.id)
for state, rec_ids in to_write.items():
if rec_ids:
self.browse(rec_ids).write({'soong_state': state})
all_records._compute_is_done()
all_records._compute_is_to_do()
return super().get_view(view_id, view_type, **options)