diff --git a/soong_workflow/models/soong_workflow_record.py b/soong_workflow/models/soong_workflow_record.py index e17918d4a..2a4ed2f6e 100644 --- a/soong_workflow/models/soong_workflow_record.py +++ b/soong_workflow/models/soong_workflow_record.py @@ -1,11 +1,12 @@ # -*- 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__) @@ -228,89 +229,103 @@ 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包含当前用户)和原有逻辑 - """ + """搜索待办状态:仅打印总耗时""" + current_uid = self.env.user.id - # 1. 获取当前用户关联的员工ID - current_employees = self.env['hr.employee'].search([('user_id', '=', current_uid)]) + 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)] + 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) - 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)] + + condition1_ids = candidate_records.filtered( + lambda r: r.approve_state == 'start' and not r.reclaim_state + ).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: - 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_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 log1_ok or log2_ok: - valid_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_rec_ids.append(rec_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的记录 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 + condition1_invalid_ids = candidate_records.filtered( + lambda r: r.approve_state == 'start' and not r.reclaim_state + ).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: - 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() + 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') - 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) + + 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') @@ -697,7 +712,6 @@ class SoongWorkflowRecord(models.Model): elif log2.approval_state in ['0', '1']: record.write({'soong_state': 'to_do'}) record._compute_is_done() - record._compute_is_to_do() return super(SoongWorkflowRecord, self).get_view(view_id, view_type, **options) def to_do_process_reminders(self): diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard.py b/soong_workflow/wizard/soong_workflow_comment_wizard.py index a67f45169..260b8eb18 100644 --- a/soong_workflow/wizard/soong_workflow_comment_wizard.py +++ b/soong_workflow/wizard/soong_workflow_comment_wizard.py @@ -453,7 +453,7 @@ class SoongWorkflowCommentWizard(models.TransientModel): ("model", "=", self.res_model), ("res_id", "=", self.res_id), ("done_by", "=", query_user_id), - ("node_id", "=", self.node_btn_id.node_id.id) + ("node_id", "=", self.node_btn_id.node_id.id), ], order="lase_click_date DESC", limit=1 @@ -522,9 +522,9 @@ class SoongWorkflowCommentWizard(models.TransientModel): ("res_id", "=", self.res_id), ("node_id", "=", next_node_id.id), ('node_btn_name', '!=', '1'), + ('approval_state', '!=', '2'), ("done_by", "=", employee.user_id.id) ]) - if not next_node_employee_log: # 创建初步记录,状态为"待审批" next_node_employee_log = self.sudo().env["soong.workflow.log"].create({