@@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import time
|
||||
from odoo import models, fields, api, _
|
||||
from odoo import models, exceptions
|
||||
from odoo.exceptions import ValidationError, UserError
|
||||
import logging
|
||||
from datetime import datetime, date, time, timedelta
|
||||
from datetime import datetime, date, timedelta
|
||||
import re
|
||||
from collections import defaultdict
|
||||
_logger = logging.getLogger(__name__)
|
||||
@@ -75,7 +75,6 @@ class SoongWorkflowRecord(models.Model):
|
||||
is_unlink = fields.Boolean(string="是否可删", compute='_compute_is_unlink')
|
||||
is_to_do = fields.Boolean(
|
||||
string="是否是待办流程",
|
||||
compute='_compute_is_to_do',
|
||||
search='_search_is_to_do',
|
||||
)
|
||||
|
||||
@@ -169,74 +168,16 @@ 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')
|
||||
def _compute_is_to_do(self):
|
||||
"""计算待办状态:
|
||||
1. approve_state为start 且 employee_ids包含当前用户关联员工 → 待办
|
||||
2. 原有逻辑:log_ids/log_ids2满足条件 → 待办
|
||||
"""
|
||||
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:
|
||||
for record in self:
|
||||
record.is_to_do = False
|
||||
return
|
||||
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}
|
||||
for record in self.filtered(lambda r: not r.reclaim_state):
|
||||
record.is_to_do = False
|
||||
all_record_emp_ids = record.employee_ids.ids + record.employee2_ids.ids
|
||||
if record.approve_state == 'start' and set(active_employee_ids) & set(all_record_emp_ids) and not record.reclaim_state:
|
||||
record.is_to_do = True
|
||||
continue
|
||||
# 原有逻辑:仅当新增条件不满足时,才执行原有log_ids/log_ids2判断
|
||||
record_emp_ids = [emp.id for emp in record.employee_ids if emp.id in active_employee_ids]
|
||||
if not record_emp_ids:
|
||||
continue
|
||||
|
||||
record_user_ids = [emp_to_user[emp_id] for emp_id in record_emp_ids if emp_id in emp_to_user]
|
||||
if not record_user_ids:
|
||||
continue
|
||||
|
||||
target_record = None
|
||||
if record.res_model and record.res_id:
|
||||
try:
|
||||
target_record = self.env[record.res_model].browse(record.res_id).exists()
|
||||
except (exceptions.MissingError, exceptions.AccessError):
|
||||
continue
|
||||
|
||||
if not target_record:
|
||||
continue
|
||||
|
||||
is_todo = False
|
||||
# 检查log_ids
|
||||
target_logs = target_record.log_ids.filtered(
|
||||
lambda l: l.done_by.id in record_user_ids and l.approval_state in ['0', '1']
|
||||
)
|
||||
if target_logs:
|
||||
is_todo = True
|
||||
|
||||
# 检查log_ids2
|
||||
if not is_todo:
|
||||
target_log2 = target_record.log_ids2.filtered(
|
||||
lambda l: l.done_by.id in record_user_ids and l.approval_state in ['0', '1']
|
||||
)
|
||||
if target_log2:
|
||||
is_todo = True
|
||||
|
||||
# 设置最终待办状态
|
||||
record.is_to_do = is_todo
|
||||
|
||||
def _search_is_to_do(self, operator, value):
|
||||
"""优化版:批量查询+预加载,3000条记录耗时1-3秒"""
|
||||
"""搜索待办状态:仅打印总耗时"""
|
||||
|
||||
current_uid = self.env.user.id
|
||||
# 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),
|
||||
'|',
|
||||
@@ -244,43 +185,33 @@ class SoongWorkflowRecord(models.Model):
|
||||
('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)
|
||||
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) 映射
|
||||
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:批量查询所有目标模型的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减少权限校验
|
||||
|
||||
# 批量查log_ids满足条件的res_id
|
||||
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')
|
||||
|
||||
# 批量查log_ids2满足条件的res_id
|
||||
log2_domain = [
|
||||
('res_id', 'in', res_ids),
|
||||
('done_by', '=', current_uid),
|
||||
@@ -288,28 +219,23 @@ class SoongWorkflowRecord(models.Model):
|
||||
]
|
||||
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):
|
||||
# 场景2:搜索is_to_do=False的记录
|
||||
candidate_records = self.search(base_domain)
|
||||
if not candidate_records:
|
||||
return [('id', '=', False)]
|
||||
|
||||
# 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):
|
||||
@@ -322,14 +248,12 @@ class SoongWorkflowRecord(models.Model):
|
||||
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')
|
||||
|
||||
@@ -338,13 +262,10 @@ class SoongWorkflowRecord(models.Model):
|
||||
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')
|
||||
|
||||
Reference in New Issue
Block a user