diff --git a/soong_workflow/models/soong_workflow_mixin.py b/soong_workflow/models/soong_workflow_mixin.py index 83eed17af..a6897403f 100644 --- a/soong_workflow/models/soong_workflow_mixin.py +++ b/soong_workflow/models/soong_workflow_mixin.py @@ -296,20 +296,21 @@ class SoongWorkflowMixin(models.AbstractModel): node_name_list = [node_name.name for node_name in node_list] index = self_state # 部门转入范围和条件判断才会创建 - for node in node_name_list[index + 1:]: - self.env['trans.link'].create({ - 'node_button_id': btn_rec.id, - 'name': node, - 'link_type': 'trans', - 'record_id': self.id, - }) + + # 存储实际会执行的节点路径 + actual_path_nodes = [] + + # 第一步:跟踪整个工作流路径,只保留实际会执行的节点 while index < len(node_list): current_node = node_list[index] + actual_path_nodes.append(current_node) if not current_node.out_link_ids: index = 20 # 防止死循环 break + # 获取当前节点的部门 current_department = self.department_id + # 处理多个输出链接的情况 if len(current_node.out_link_ids) > 1: # 筛选与当前节点部门匹配的后续节点 @@ -318,19 +319,25 @@ class SoongWorkflowMixin(models.AbstractModel): target_node = link.node_to # 如果目标节点有部门限制,且与当前节点部门匹配 if target_node.department_id and (target_node.department_id == current_department or - current_department in self.get_all_sub_departments(target_node.department_id)): + current_department in self.get_all_sub_departments( + target_node.department_id)): valid_nodes.append((target_node, link)) + + # 尝试父部门匹配 if not valid_nodes and current_department and current_department.parent_id: parent_department = current_department.parent_id for link in current_node.out_link_ids: target_node = link.node_to if target_node.department_id and (target_node.department_id == parent_department or - parent_department in self.get_all_sub_departments(target_node.department_id)): + parent_department in self.get_all_sub_departments( + target_node.department_id)): valid_nodes.append((target_node, link)) + # 如果没有找到匹配的节点,抛出错误 if not valid_nodes: current_dept_name = current_department.name if current_department else "未指定部门" raise ValidationError(f"没有找到符合当前部门( {current_dept_name} )的后续节点!") + # 选择第一个匹配的节点 next_node, matched_link = valid_nodes[0] matched_key = next_node.name @@ -339,9 +346,31 @@ class SoongWorkflowMixin(models.AbstractModel): matched_link = current_node.out_link_ids[0] next_node = matched_link.node_to matched_key = next_node.name - # 更新索引并跳出循环 + + # 更新索引 index = state_list.index(matched_key) - break + if index >= len(node_list): + break + + # 第二步:根据实际路径创建trans.link记录并生成domain + actual_path_links = [] + for node in actual_path_nodes[1:]: # 跳过当前节点 + link = self.env['trans.link'].create({ + 'node_button_id': btn_rec.id, + 'name': node.name, + 'link_type': 'trans', + 'record_id': self.id, + }) + actual_path_links.append(link) + + # 第三步:创建domain条件 + if actual_path_links: + # 获取所有创建的trans.link的ID + trans_link_ids = [link.id for link in actual_path_links] + # 创建domain条件 + trans_domain = [('id', 'in', trans_link_ids)] + else: + trans_domain = [] # 如果没有路径节点,返回空domain is_supervising = False if self._module in ['yuthon_official']: @@ -362,8 +391,11 @@ class SoongWorkflowMixin(models.AbstractModel): "default_log_ids": logs.ids, "default_node_btn_id": btn_rec.id, "default_is_supervising": is_supervising, - "default_trans_link_id": self.env['trans.link'].search([])[0].id if btn_rec.name == '转交' else False, - "default_return_link_id": self.env['trans.link'].search([])[0].id if btn_rec.name == '退回' else False, + "default_trans_link_id": self.env['trans.link'].search(trans_domain, limit=1).id if btn_rec.name == '转交' else False, + "all_workflow_links": trans_link_ids, + "default_return_link_id": self.env['trans.link'].search( + [('link_type', '=', 'return'), ('record_id', '=', self.id)], + limit=1).id if btn_rec.name == '退回' else False, }, } diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard.py b/soong_workflow/wizard/soong_workflow_comment_wizard.py index 85c750a21..c5fc47e09 100644 --- a/soong_workflow/wizard/soong_workflow_comment_wizard.py +++ b/soong_workflow/wizard/soong_workflow_comment_wizard.py @@ -31,6 +31,12 @@ class SoongWorkflowCommentWizard(models.TransientModel): trans_link_id = fields.Many2one('trans.link', string='转交节点') document_ids = fields.Many2many('ir.attachment', string="附件") return_link_id = fields.Many2one('trans.link', string='退回节点') + invalid_link_ids = fields.Many2many( + 'trans.link', + string='无审批人节点', + compute='_compute_invalid_link_ids', + help='没有找到符合条件审批人的节点' + ) employee_trans_domain_ids = fields.Many2many('hr.employee', 'employee_trans_domain_ids_rel', string="传阅人员", store=True) @@ -119,86 +125,140 @@ class SoongWorkflowCommentWizard(models.TransientModel): ]) self.employee_ids1 = employee_user_role_ids + @api.depends('trans_link_id') + def _compute_invalid_link_ids(self): + for record in self: + invalid_links = self.env['trans.link'] + ctx_links = self.env.context.get('all_workflow_links', []) + all_links = self.env['trans.link'].browse(ctx_links) if isinstance(ctx_links, (list, tuple)) else ctx_links + record_id = self.env[record.res_model].browse(record.res_id) if record.res_model and record.res_id else None + + for link in all_links: + if not link or isinstance(link, int): + continue + + # 使用封装方法 + approvers = self._get_approvers_for_link(link, record_id) + if not approvers: + invalid_links |= link + + record.invalid_link_ids = invalid_links + @api.onchange('trans_link_id') def onchange_trans_employee_ids(self): - self.employee_ids1 = False - record_id = self.env[self.res_model].search([('id', '=', self.res_id)]) - for ret in self.trans_link_id: - workflow_id = self.trans_link_id.node_button_id.workflow_id - node = workflow_id.node_ids.search([('name', '=', self.trans_link_id.name), ('workflow_id', '=', workflow_id.id)]) - button = node.button_ids[0] if node.button_ids else False - if not button: + for record in self: + if not record.trans_link_id: continue - link_users_id = button.users_role_id - link_users_group_ids = button.users_role_group_ids - # 获取六个布尔字段的值 - is_automatic = button.is_automatic - is_automatic_company = button.is_automatic_company - is_automatic_group = button.is_automatic_group - is_logged_by = button.is_logged_by - is_logged_company = button.is_logged_company - is_logged_group = button.is_logged_group - employee_user_role_ids = False - # 构建部门筛选条件 - department_domain = [] - # 按当前申请人自动匹配 - if is_automatic: # 申请人-本部门 - department_domain = ['|', ('department_id', '=', record_id.department_id.id), ('department_ids', 'in', record_id.department_id.id)] - elif is_automatic_company or is_automatic_group: # 申请人-本公司/本集团 - # 查找user_id或users_id字段 + record_id = self.env[record.res_model].browse(record.res_id) if record.res_model and record.res_id else None + for link in record.trans_link_id: + employee_user_role_ids = self._get_approvers_for_link(link, record_id) + workflow_id = link.node_button_id.workflow_id + node = workflow_id.node_ids.search([ + ('name', '=', link.name), + ('workflow_id', '=', workflow_id.id) + ]) + record.approval_concatenation = node.approval_concatenation + record.employee_trans_domain_ids = employee_user_role_ids + record.employee_ids1 = employee_user_role_ids + + def _get_approvers_for_link(self, link, record_id=None): + """ + 参数: + link: trans.link 记录对象 + record_id: 关联的业务记录对象 + 返回: + hr.employee 记录集(可能为空) + """ + if not link or isinstance(link, int): + return self.env['hr.employee'] + workflow_id = link.node_button_id.workflow_id + node = workflow_id.node_ids.search([ + ('name', '=', link.name), + ('workflow_id', '=', workflow_id.id) + ]) + button = node.button_ids[0] if node.button_ids else False + if not button: + return self.env['hr.employee'] + + link_users_id = button.users_role_id + link_users_group_ids = button.users_role_group_ids + is_automatic = button.is_automatic + is_automatic_company = button.is_automatic_company + is_automatic_group = button.is_automatic_group + is_logged_by = button.is_logged_by + is_logged_company = button.is_logged_company + is_logged_group = button.is_logged_group + + # 部门筛选条件 + department_domain = [] + if record_id: + # 申请人自动匹配逻辑 + if is_automatic: + department_domain = ['|', + ('department_id', '=', record_id.department_id.id), + ('department_ids', 'in', record_id.department_id.id)] + elif is_automatic_company or is_automatic_group: applicant_field = None - for field_name, field_data in record_id._fields.items(): - if field_name in ['user_id', 'users_id']: - field_value = getattr(record_id, field_name) - if field_value: - applicant_field = field_value + for field_name in ['user_id', 'users_id']: + if hasattr(record_id, field_name): + applicant_field = getattr(record_id, field_name) + if applicant_field: break - # 如果找到申请人字段,则处理公司/集团逻辑 if applicant_field and hasattr(applicant_field, 'company_id'): - if is_automatic_company: # 申请人-本公司 - company_departments = self.env['hr.department'].search( - [('company_id', '=', applicant_field.company_id.id)]).ids - department_domain = [('department_id', 'in', company_departments)] - elif is_automatic_group: # 申请人-本集团 + if is_automatic_company: + company_departments = self.env['hr.department'].search([ + ('company_id', '=', applicant_field.company_id.id) + ]).ids + department_domain = ['|', + ('department_id', 'in', company_departments), + ('department_ids', 'in', company_departments)] + elif is_automatic_group: parent_company = applicant_field.company_id.parent_id - group_departments = self.env['hr.department'].search( - [('company_id', 'child_of', parent_company.id)]).ids if parent_company else [] - department_domain = [('department_id', 'in', group_departments)] - else: - department_domain = [] - # 按当前登录人自动匹配 - elif is_logged_by: # 登录人-本部门 - department_domain = [('department_id', '=', self.env.user.department_id.id)] - elif is_logged_company: # 登录人-本公司 - company_departments = self.env['hr.department'].search( - [('company_id', '=', self.env.user.company_id.id)]).ids - department_domain = [('department_id', 'in', company_departments)] - elif is_logged_group: # 登录人-本集团 + group_departments = self.env['hr.department'].search([ + ('company_id', 'child_of', parent_company.id) + ]).ids if parent_company else [] + department_domain = ['|', + ('department_id', 'in', group_departments), + ('department_ids', 'in', group_departments)] + # 登录人自动匹配逻辑 + elif is_logged_by: + department_domain = ['|', + ('department_id', '=', self.env.user.department_id.id), + ('department_ids', 'in', self.env.user.department_id.id)] + elif is_logged_company: + company_departments = self.env['hr.department'].search([ + ('company_id', '=', self.env.user.company_id.id) + ]).ids + department_domain = ['|', + ('department_id', 'in', company_departments), + ('department_ids', 'in', company_departments)] + elif is_logged_group: parent_company = self.env.user.company_id.parent_id - group_departments = self.env['hr.department'].search( - [('company_id', 'child_of', parent_company.id)]).ids if parent_company else [] - department_domain = [('department_id', 'in', group_departments)] - # 处理角色筛选条件 - if link_users_id: - role_domain = ['|', ('user_role_id', '=', link_users_id.id), ('user_role_ids', 'in', link_users_id.id)] - company_domain = [('company_id', '=', self.env.user.company_id.id)] - # 自动匹配:结合角色和部门筛选 - domain = role_domain + company_domain + department_domain - employee_user_role_ids = 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)] - company_domain = [('company_id', '=', self.env.user.company_id.id)] - # 自动匹配 - domain = role_domain + company_domain + department_domain - employee_user_role_ids = self.env['hr.employee'].sudo().search(domain) - # 设置结果 - self.approval_concatenation = node.approval_concatenation - self.employee_trans_domain_ids = employee_user_role_ids - self.employee_ids1 = employee_user_role_ids - # 特殊处理:分发按钮 - if '分发' in ret.name: - self.employee_ids1 = record_id.users_id.employee_id + group_departments = self.env['hr.department'].search([ + ('company_id', 'child_of', parent_company.id) + ]).ids if parent_company else [] + department_domain = ['|', + ('department_id', 'in', group_departments), + ('department_ids', 'in', group_departments)] + # 角色筛选 + if link_users_id: + role_domain = ['|', + ('user_role_id', '=', link_users_id.id), + ('user_role_ids', 'in', link_users_id.id)] + company_domain = [('company_id', '=', self.env.user.company_id.id)] + domain = role_domain + company_domain + department_domain + 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)] + company_domain = [('company_id', '=', self.env.user.company_id.id)] + domain = role_domain + company_domain + department_domain + return self.env['hr.employee'].sudo().search(domain) + # 特殊分发按钮 + if '分发' in link.name and record_id and hasattr(record_id, 'users_id'): + return record_id.users_id.employee_id + return self.env['hr.employee'] # 默认返回空记录集 def add_comment(self): self.ensure_one() diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml b/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml index 21b568b12..18c09b46f 100644 --- a/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml +++ b/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml @@ -10,6 +10,7 @@
+ @@ -49,7 +50,7 @@ - +