diff --git a/soong_workflow/models/soong_workflow_mixin.py b/soong_workflow/models/soong_workflow_mixin.py index f52f2fe83..7bd317f49 100644 --- a/soong_workflow/models/soong_workflow_mixin.py +++ b/soong_workflow/models/soong_workflow_mixin.py @@ -741,28 +741,62 @@ class SoongWorkflowMixin(models.AbstractModel): [('link_type', '=', 'return'), ('record_id', '=', self.id)], limit=1 ).sorted('sequence')[:1].id if btn_rec.name == '退回' else False - return { - "name": _("评论"), - "type": "ir.actions.act_window", - "view_mode": "form", - "res_model": "soong.workflow.comment.wizard", - "views": [(wizard.id, "form")], - "view_id": wizard.id, - "target": "new", - "context": { - "default_return_link_id": return_link_id, - "default_res_id": self.id, - 'default_comment_note_id': comment_note_id, - "default_code": self.code, - "default_workflow_record_id": workflow_record_id.id, - 'default_illustrate':btn_rec.node_id.illustrate, - "default_res_model": self._name, - "default_node_btn_id": btn_rec.id, - "default_is_supervising": is_supervising, - "default_trans_link_id": trans_link_id, - "all_workflow_links": trans_link_ids, - }, - } + if btn_rec.name == '转交' and trans_link_ids: + all_links = self.env['trans.link'].browse(trans_link_ids) + invalid_links = self.env['trans.link'] + current_link = self.env['trans.link'].browse(trans_link_id) + if current_link and all_links: + sorted_all_links = all_links.sorted('sequence') + for idx, link in enumerate(sorted_all_links): + approvers = self._get_approvers_for_link(link, self) + if len(approvers) == 1: + current_approver = approvers[0] + node_id = self.workflow_id.node_ids.search([ + ('name', '=', link.name), + ('workflow_id', '=', self.workflow_id.id) + ], limit=1) + if node_id: + # 下一个相同审批人跳过 + if node_id.same_user_skip_type == 'next': + if idx + 1 < len(sorted_all_links): + next_link = sorted_all_links[idx + 1] + next_approvers = self._get_approvers_for_link(next_link, self) + if len(next_approvers) == 1 and next_approvers[0] == current_approver: + invalid_links |= next_link + # 上一个相同审批人跳过 + if node_id.same_user_skip_type == 'prev': + if idx - 1 >= 0: + prev_link = sorted_all_links[idx - 1] + prev_approvers = self._get_approvers_for_link(prev_link, self) + if len(prev_approvers) == 1 and prev_approvers[0] == current_approver: + invalid_links |= prev_link + + allowed_link_ids = [lid for lid in trans_link_ids if lid not in invalid_links.ids] + default_trans_link_id = allowed_link_ids[0] if allowed_link_ids else trans_link_id + + return { + "name": _("评论"), + "type": "ir.actions.act_window", + "view_mode": "form", + "res_model": "soong.workflow.comment.wizard", + "views": [(wizard.id, "form")], + "view_id": wizard.id, + "target": "new", + "context": { + "default_return_link_id": return_link_id, + "default_res_id": self.id, + 'default_comment_note_id': comment_note_id, + "default_code": self.code, + "default_workflow_record_id": workflow_record_id.id, + 'default_illustrate':btn_rec.node_id.illustrate, + "default_res_model": self._name, + "default_node_btn_id": btn_rec.id, + "default_is_supervising": is_supervising, + "default_trans_link_id": default_trans_link_id, + "all_workflow_links": allowed_link_ids, + "default_invalid_link_ids": invalid_links.ids, + }, + } def get_all_sub_departments(self, department, level=0, print_tree=True): all_departments = department.child_ids @@ -1588,6 +1622,169 @@ class SoongWorkflowMixin(models.AbstractModel): msg = str(msg) _logger.info(msg) + 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_priority_list = ["分发", "下发", "转交", "结束"] + button = False + if node.button_ids: + found_target_btn = False + for btn_name in button_priority_list: + for btn in sorted(node.button_ids, key=lambda x: x.sequence): + if btn.name == btn_name: + is_in_scope = True + if not btn.is_review_invisible: + button = btn + found_target_btn = True + break + if btn.is_review_invisible: + domain = eval(btn.invisible_expression) + model = record_id.env[record_id._name] + matched = model.search(domain + [('id', '=', record_id.id)]) + is_in_scope = bool(matched) + if is_in_scope: + button = btn + found_target_btn = True + break + if found_target_btn: + break + + 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 + is_dep = button.is_dep + is_field = button.specify_field_id + + if button.reviewer_id: + employee = self.env['hr.employee'].search([ + ('user_id', '=', button.reviewer_id.id), + ], limit=1) + return employee + + # 部门和公司筛选条件 + department_domain = [] + company_domain = [] + user_role_domain = [] + + if record_id: + # 获取当前用户和申请人的相关信息 + current_user = self.env.user + applicant = None + + # 获取申请人的用户对象 + for field_name in ['user_id', 'users_id']: + if hasattr(record_id, field_name): + applicant = getattr(record_id, field_name) + if applicant: + break + + # 根据勾选的条件设置域条件(只勾选一个) + if is_automatic and record_id.department_id: + dept_id = record_id.department_id.id + # 按当前申请人自动匹配-本部门(保留部门和公司条件) + applicant_dept_ids = applicant.employee_ids.department_ids.ids + department_domain = [ + '|', '|', '|', + ('department_id', '=', dept_id), + ('department_ids', 'in', [dept_id]), + ('department_id', 'in', applicant_dept_ids), + ('department_ids', 'in', applicant_dept_ids), + ] + company_domain = [('company_id', '=', applicant.company_id.id)] + + elif is_automatic_company and applicant and hasattr(applicant, 'company_id'): + # 按当前申请人自动匹配-本公司(仅保留公司条件) + company_id = applicant.company_id.id + company_domain = [('company_id', '=', company_id)] + + elif is_automatic_group and applicant and hasattr(applicant, 'company_id'): + # 按当前申请人自动匹配-本集团(仅保留公司条件) + parent_company = applicant.company_id.parent_id + if parent_company: + group_company_ids = self.env['res.company'].search([('id', 'child_of', parent_company.id)]).ids + company_domain = [('company_id', 'in', group_company_ids)] + + elif is_dep and hasattr(record_id, 'department_id1') and record_id.department_id1: + department_id1 = record_id.department_id1.id + department_domain = ['|', ('department_id', '=', department_id1), + ('department_ids', 'in', department_id1)] + user_role_domain = ['|', ('user_role_id', '=', button.role_id.user_role_ids.ids), + ('user_role_ids', 'in', button.role_id.user_role_ids.ids)] + + elif is_logged_by and current_user.department_id: + # 按当前登录人自动匹配-本部门(保留部门和公司条件) + department_domain = ['|', ('department_id', '=', current_user.department_id.id), + ('department_ids', 'in', current_user.department_id.id)] + company_domain = [('company_id', '=', current_user.company_id.id)] + + elif is_logged_company: + # 按当前登录人自动匹配-本公司(仅保留公司条件) + company_id = current_user.company_id.id + company_domain = [('company_id', '=', company_id)] + + elif is_logged_group: + # 按当前登录人自动匹配-本集团(仅保留公司条件) + parent_company = current_user.company_id.parent_id + if parent_company: + group_company_ids = self.env['res.company'].search([('id', 'child_of', parent_company.id)]).ids + company_domain = [('company_id', 'in', group_company_ids)] + elif is_field: + field_name = button.specify_field_id.name + field_value = record_id[field_name] + if field_value: + if button.specify_field_id.relation == 'res.users': + employee = self.env['hr.employee'].sudo().search( + [('user_id', '=', field_value.id)], + limit=1 + ) + if employee: + return employee + elif button.specify_field_id.relation == 'hr.employee': + return field_value + else: + department_domain = ['|', ('department_id', '=', field_value.id), + ('department_ids', 'in', field_value.id)] + + if link_users_id: + role_domain = ['|', ('user_role_id', '=', link_users_id.id), ('user_role_ids', 'in', link_users_id.id)] + if user_role_domain: + role_domain = ['|'] + role_domain + user_role_domain + 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), ] + if user_role_domain: + role_domain = ['|'] + role_domain + user_role_domain + 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'] # 默认返回空记录集 + class SoongWorkflowLine(models.Model): _name = "soong.workflow.line" diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard.py b/soong_workflow/wizard/soong_workflow_comment_wizard.py index ae59dd19d..386b53fe7 100644 --- a/soong_workflow/wizard/soong_workflow_comment_wizard.py +++ b/soong_workflow/wizard/soong_workflow_comment_wizard.py @@ -40,7 +40,6 @@ class SoongWorkflowCommentWizard(models.TransientModel): invalid_link_ids = fields.Many2many( 'trans.link', string='跳过相同人员', - compute='_compute_invalid_link_ids', help='跳过相同人员的节点' ) @@ -162,55 +161,12 @@ 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 - current_link = record.trans_link_id - if current_link and all_links: - sorted_all_links = all_links.sorted('sequence') - for idx, link in enumerate(sorted_all_links): - approvers = self._get_approvers_for_link(link, record_id) - # 如果当前审批人是 1 个人,才判断跳过 - if len(approvers) == 1: - current_approver = approvers[0] - # 跳过规则 next:跳过【下一个】节点 - node_id = record_id.workflow_id.node_ids.search([ - ('name', '=', link.name), - ('workflow_id', '=', record_id.workflow_id.id) - ]) - if node_id.same_user_skip_type == 'next': - # 有下一个节点 - if idx + 1 < len(sorted_all_links): - next_link = sorted_all_links[idx + 1] - next_approvers = self._get_approvers_for_link(next_link, record_id) - # 下一个节点也是 1 个人,且和当前是同一个 - if len(next_approvers) == 1 and next_approvers[0] == current_approver: - invalid_links |= next_link # 下一个节点无效(跳过) - - # 跳过规则 prev:跳过【上一个】节点 - if node_id.same_user_skip_type == 'prev': - # 有上一个节点 - if idx - 1 >= 0: - prev_link = sorted_all_links[idx - 1] - prev_approvers = self._get_approvers_for_link(prev_link, record_id) - # 上一个节点也是 1 个人,且和当前是同一个 - if len(prev_approvers) == 1 and prev_approvers[0] == current_approver: - invalid_links |= prev_link - - record.invalid_link_ids = invalid_links - @api.onchange('trans_link_id') def onchange_trans_employee_ids(self): for record in self: record_id = self.env[record.res_model].browse(record.res_id) if record.res_model and record.res_id else None 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 - - valid_links = all_links - record.invalid_link_ids + valid_links = self.env['trans.link'].browse(ctx_links) if isinstance(ctx_links, (list, tuple)) else ctx_links record.is_selection = False if self.node_btn_name == '退回': @@ -268,7 +224,7 @@ class SoongWorkflowCommentWizard(models.TransientModel): ('user_id', 'in', user_ids.ids) ]) else: - employee_user_role_ids = self._get_approvers_for_link(link, record_id) + employee_user_role_ids = record_id._get_approvers_for_link(link, record_id) workflow_id = link.node_button_id.workflow_id node = workflow_id.node_ids.search([ ('name', '=', link.name), @@ -309,169 +265,6 @@ class SoongWorkflowCommentWizard(models.TransientModel): record.is_selection = True record._onchange_is_selection() - 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_priority_list = ["分发", "下发", "转交", "结束"] - button = False - if node.button_ids: - found_target_btn = False - for btn_name in button_priority_list: - for btn in sorted(node.button_ids, key=lambda x: x.sequence): - if btn.name == btn_name: - is_in_scope = True - if not btn.is_review_invisible: - button = btn - found_target_btn = True - break - if btn.is_review_invisible: - domain = eval(btn.invisible_expression) - model = record_id.env[record_id._name] - matched = model.search(domain + [('id', '=', record_id.id)]) - is_in_scope = bool(matched) - if is_in_scope: - button = btn - found_target_btn = True - break - if found_target_btn: - break - - 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 - is_dep = button.is_dep - is_field = button.specify_field_id - - if button.reviewer_id: - employee = self.env['hr.employee'].search([ - ('user_id', '=', button.reviewer_id.id), - ], limit=1) - return employee - - # 部门和公司筛选条件 - department_domain = [] - company_domain = [] - user_role_domain = [] - - if record_id: - # 获取当前用户和申请人的相关信息 - current_user = self.env.user - applicant = None - - # 获取申请人的用户对象 - for field_name in ['user_id', 'users_id']: - if hasattr(record_id, field_name): - applicant = getattr(record_id, field_name) - if applicant: - break - - # 根据勾选的条件设置域条件(只勾选一个) - if is_automatic and record_id.department_id: - dept_id = record_id.department_id.id - # 按当前申请人自动匹配-本部门(保留部门和公司条件) - applicant_dept_ids = applicant.employee_ids.department_ids.ids - department_domain = [ - '|', '|', '|', - ('department_id', '=', dept_id), - ('department_ids', 'in', [dept_id]), - ('department_id', 'in', applicant_dept_ids), - ('department_ids', 'in', applicant_dept_ids), - ] - company_domain = [('company_id', '=', applicant.company_id.id)] - - elif is_automatic_company and applicant and hasattr(applicant, 'company_id'): - # 按当前申请人自动匹配-本公司(仅保留公司条件) - company_id = applicant.company_id.id - company_domain = [('company_id', '=', company_id)] - - elif is_automatic_group and applicant and hasattr(applicant, 'company_id'): - # 按当前申请人自动匹配-本集团(仅保留公司条件) - parent_company = applicant.company_id.parent_id - if parent_company: - group_company_ids = self.env['res.company'].search([('id', 'child_of', parent_company.id)]).ids - company_domain = [('company_id', 'in', group_company_ids)] - - elif is_dep and hasattr(record_id, 'department_id1') and record_id.department_id1: - department_id1 = record_id.department_id1.id - department_domain = ['|', ('department_id', '=', department_id1), - ('department_ids', 'in', department_id1)] - user_role_domain = ['|', ('user_role_id', '=', button.role_id.user_role_ids.ids), - ('user_role_ids', 'in', button.role_id.user_role_ids.ids)] - - elif is_logged_by and current_user.department_id: - # 按当前登录人自动匹配-本部门(保留部门和公司条件) - department_domain = ['|', ('department_id', '=', current_user.department_id.id), - ('department_ids', 'in', current_user.department_id.id)] - company_domain = [('company_id', '=', current_user.company_id.id)] - - elif is_logged_company: - # 按当前登录人自动匹配-本公司(仅保留公司条件) - company_id = current_user.company_id.id - company_domain = [('company_id', '=', company_id)] - - elif is_logged_group: - # 按当前登录人自动匹配-本集团(仅保留公司条件) - parent_company = current_user.company_id.parent_id - if parent_company: - group_company_ids = self.env['res.company'].search([('id', 'child_of', parent_company.id)]).ids - company_domain = [('company_id', 'in', group_company_ids)] - elif is_field: - field_name = button.specify_field_id.name - field_value = record_id[field_name] - if field_value: - if button.specify_field_id.relation == 'res.users': - employee = self.env['hr.employee'].sudo().search( - [('user_id', '=', field_value.id)], - limit=1 - ) - if employee: - return employee - elif button.specify_field_id.relation == 'hr.employee': - return field_value - else: - department_domain = ['|', ('department_id', '=', field_value.id), - ('department_ids', 'in', field_value.id)] - - if link_users_id: - role_domain = ['|', ('user_role_id', '=', link_users_id.id), ('user_role_ids', 'in', link_users_id.id)] - if user_role_domain: - role_domain = ['|'] + role_domain + user_role_domain - 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),] - if user_role_domain: - role_domain = ['|'] + role_domain + user_role_domain - 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 _send_workflow_notifications(self, partners=None): """ 通知前端刷新红点、播放音频 :param partners: 需要通知的用户(res.partner),未传则通知所有