@@ -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,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<form string="意见">
|
||||
<group invisible="1">
|
||||
<field name="approval_concatenation" widget="radio"/>
|
||||
<field name="invalid_link_ids" widget="many2many_tags"/>
|
||||
<field name="comment"/>
|
||||
</group>
|
||||
<group invisible="node_btn_name in ['分发', '结束', '收回']">
|
||||
@@ -49,7 +50,7 @@
|
||||
<!-- 退回意见退回类型 -->
|
||||
<field name="return_link_id" invisible="node_btn_name != '退回'" string="退回节点"/>
|
||||
<!-- 转交人员 -->
|
||||
<field name="trans_link_id" string="转交节点" invisible="node_btn_name == '退回'"/>
|
||||
<field name="trans_link_id" string="转交节点" invisible="node_btn_name == '退回'" domain="[('id', 'not in', invalid_link_ids)]"/>
|
||||
<field name="employee_trans_domain_ids" invisible="1"/>
|
||||
<field name="employee_ids1" widget="many2many_tags" string="人员范围" invisible="1"/>
|
||||
<field name="employee_ids" widget="many2many_tags" string="人员范围" domain="[('id', 'in', employee_ids1)]" options="{'no_create': True}"/>
|
||||
|
||||
Reference in New Issue
Block a user