添加功能

This commit is contained in:
李鹏宇
2026-04-29 19:27:35 +08:00
parent 8582f9a4c1
commit 7b700f8a2c
2 changed files with 221 additions and 231 deletions
+219 -22
View File
@@ -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"
@@ -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),未传则通知所有