This commit is contained in:
李鹏宇
2026-03-20 19:10:40 +08:00
4 changed files with 133 additions and 126 deletions
+117 -122
View File
@@ -169,153 +169,142 @@ 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',
'employee2_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
# 关键修改:不再查users_ids,改为查当前用户对应的hr.employee记录
current_employee = self.env['hr.employee'].search([('user_id', '=', current_uid)], limit=1)
if not current_employee:
# 若当前用户无对应员工记录,所有记录均为非待办
for rec in self:
rec.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}
# 第一步:批量处理条件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)
# 初始化所有记录为非待办(上下文流畅,保留原有初始化逻辑)
self.is_to_do = False
valid_records = self.filtered(
lambda r: (current_employee.id in r.employee_ids.ids or current_employee.id in r.employee2_ids.ids)
and not r.reclaim_state
)
condition1_records.is_to_do = True
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
# 第二步:批量处理条件2(log_ids/log_ids2)
remaining_records = self - condition1_records
remaining_records.is_to_do = False
target_records = remaining_records.filtered(
lambda r: r.res_model and r.res_id and r.approve_state not in ['draft', 'start']
)
if not target_records:
return
# 按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)
# 批量查询日志(性能优化保留,逻辑不变)
model_res_id_pairs = [(rec.res_model, rec.res_id) for rec in target_records]
log1_domain = [
('model', 'in', list({m for m, _ in model_res_id_pairs})),
('res_id', 'in', list({r for _, r in model_res_id_pairs})),
('done_by', '=', current_uid),
('approval_state', 'in', ['0', '1'])
]
log2_domain = log1_domain.copy()
# 批量查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()
log_domain = [
('res_id', 'in', res_ids),
('done_by', 'in', list(emp_to_user.values())),
('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_log1_pairs = set()
log1_records = self.env['soong.workflow.log'].search(log1_domain)
for log in log1_records:
valid_log1_pairs.add((log.model, log.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
valid_log2_pairs = set()
log2_records = self.env['soong.workflow.log2'].search(log2_domain)
for log in log2_records:
valid_log2_pairs.add((log.model, log.res_id))
valid_pairs = valid_log1_pairs | valid_log2_pairs
for rec in target_records:
if (rec.res_model, rec.res_id) in valid_pairs:
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:
current_employee = self.env['hr.employee'].search([('user_id', '=', current_uid)], limit=1)
if not current_employee:
return [('id', '=', False)]
base_domain = [
'|',
('employee_ids', 'in', [current_employee.id]),
('employee2_ids', 'in', [current_employee.id]),
('reclaim_state', '=', False)
]
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)
]
# 以下所有逻辑完全不变,和你原来一致
if (operator == '=' and value) or (operator == '!=' and not value):
candidate_records = self.search(base_domain)
if not candidate_records:
return [('id', '=', False)]
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)
remaining_records = candidate_records - self.browse(condition1_ids)
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),
if target_records:
model_res_id_pairs = [(rec.res_model, rec.res_id) for rec in target_records]
log_domain = [
('model', 'in', list({m for m, _ in model_res_id_pairs})),
('res_id', 'in', list({r for _, r in model_res_id_pairs})),
('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')
log1_valid_pairs = set(
(log.model, log.res_id) for log in self.env['soong.workflow.log'].search(log_domain))
log2_valid_pairs = set(
(log.model, log.res_id) for log in self.env['soong.workflow.log2'].search(log_domain))
valid_pairs = log1_valid_pairs | log2_valid_pairs
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)
for rec in target_records:
if (rec.res_model, rec.res_id) in valid_pairs:
condition2_rec_ids.append(rec.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_todo_ids = candidate_records.filtered(lambda r: r.approve_state == 'start').ids
condition1_invalid_ids = candidate_records.filtered(
lambda r: r.approve_state == 'start' and not r.reclaim_state
).ids
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']
)
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)
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),
condition2_todo_ids = []
if target_records:
model_res_id_pairs = [(rec.res_model, rec.res_id) for rec in target_records]
log_domain = [
('model', 'in', list({m for m, _ in model_res_id_pairs})),
('res_id', 'in', list({r for _, r in model_res_id_pairs})),
('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')
log1_valid_pairs = set(
(log.model, log.res_id) for log in self.env['soong.workflow.log'].search(log_domain))
log2_valid_pairs = set(
(log.model, log.res_id) for log in self.env['soong.workflow.log2'].search(log_domain))
valid_pairs = log1_valid_pairs | log2_valid_pairs
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)
for rec in target_records:
if (rec.res_model, rec.res_id) in valid_pairs:
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)]
@@ -669,15 +658,21 @@ class SoongWorkflowRecord(models.Model):
@api.model
def get_view(self, view_id=None, view_type='form', **options):
current_user_id = self.env.user.id
all_records = self.search([
('users_ids', 'in', current_user_id),
('soong_state', '!=', 'active'),
])
if not all_records:
return super().get_view(view_id, view_type, **options)
all_records._compute_is_done()
all_records._compute_is_to_do()
return super().get_view(view_id, view_type, **options)
current_employee = self.env['hr.employee'].search([('user_id', '=', current_user_id)], limit=1)
view = super().get_view(view_id, view_type, **options)
if not current_employee:
return view
if view_type == 'list':
all_records = self.search([
'|',
('employee_ids', 'in', [current_employee.id]),
('employee2_ids', 'in', [current_employee.id]),
('reclaim_state', '=', False) # 补回丢失的过滤条件
]) # 限制最大记录数,避免性能问题
if all_records:
all_records._compute_is_done()
all_records._compute_is_to_do()
return view
def to_do_process_reminders(self):
workflow_records = self.env['soong.workflow.record'].search([
@@ -386,10 +386,8 @@ class SoongWorkflowCommentWizard(models.TransientModel):
return self.env['hr.employee'].sudo().search(domain)
elif link_users_group_ids:
role_domain = ['|', '|', ('user_role_id', 'in', link_users_group_ids.user_role_ids.ids),
('user_role_ids', 'in', link_users_group_ids.user_role_ids.ids),
('role_group_ids', 'in', link_users_group_ids.ids)
]
role_domain = ['|', ('user_role_id', 'in', link_users_group_ids.user_role_ids.ids),
('user_role_ids', 'in', link_users_group_ids.user_role_ids.ids),]
if user_role_domain:
role_domain = ['|'] + role_domain + user_role_domain
domain = role_domain + company_domain + department_domain
@@ -51,6 +51,7 @@ class YuthonRenewalApproval(models.Model):
new_version = f"V{new_version_num:.1f}"
new_contract_vals = original_contract.copy_data()[0]
new_contract_type_id = original_contract.contract_type_id.id
original_contract.state = 'close'
if original_contract.contract_type_id and original_contract.contract_type_id.name:
contract_type_name = original_contract.contract_type_id.name
if '一签' in contract_type_name:
@@ -237,6 +237,19 @@ class IssueMeetingLine(models.Model):
decision_results = fields.Selection([('agree', '通过'), ('disagree', '重新上会'), ('rejected', '驳回')], string="决策结果")
decision_details = fields.Text(string="决策详情")
@api.onchange('issue_library_id')
def onchange_issue_library_id(self):
if self.issue_library_id:
dept_manager = self.env['hr.employee'].search([
('active', '=', True),
('user_role_id.name', '=', '部门经理'),
'|',
('department_id', '=', self.issue_library_id.department_id.id),
('department_ids', 'in', [self.issue_library_id.department_id.id])
], limit=1)
if dept_manager:
self.employee_id = dept_manager.id
def open_record(self):
form_id = self.env.ref('yuthon_issue.view_issue_library_form').id
return {