diff --git a/soong_workflow/models/soong_workflow_record.py b/soong_workflow/models/soong_workflow_record.py
index 7e29c7be2..26e8ca35c 100644
--- a/soong_workflow/models/soong_workflow_record.py
+++ b/soong_workflow/models/soong_workflow_record.py
@@ -69,6 +69,18 @@ class SoongWorkflowRecord(models.Model):
soong_state = fields.Selection([('to_do', '待办'), ('done', '已办'),('to_active', '待归档'), ('active', '已归档')], string="流程状态", default="to_do")
member_of_department = fields.Boolean("是否是本部门数据", compute='_compute_part_of_department',
search='_search_part_of_department')
+ special_member_visible = fields.Boolean(
+ "特殊权限可见(人事/考勤)",
+ compute='_compute_special_member_visible',
+ search='_search_special_member_visible',
+ help="当前用户属于『本部-角色-人事专员』或『考勤-用户』用户组时,可查看对应的(仅本公司的)人事/考勤流程",
+ )
+ dept_query_visible = fields.Boolean(
+ "部门查询可见(排除考勤/人事)",
+ compute='_compute_dept_query_visible',
+ search='_search_dept_query_visible',
+ help="本部门可见,但排除审批分组为考勤/人事的流程(二者仅对特殊权限组可见)",
+ )
# 人力资源流程的发生日期
workflow_happen_date = fields.Date(string="发生日期")
@@ -613,6 +625,78 @@ class SoongWorkflowRecord(models.Model):
domain = ['!'] + domain
return domain
+ # ------------------------------------------------------------------
+ # 特殊权限可见:人事专员 / 考勤-用户 用户组可查看对应(仅本公司)流程
+ # ------------------------------------------------------------------
+ @api.depends_context('uid', 'company')
+ @api.depends('approvals_group_id', 'company_id')
+ def _compute_special_member_visible(self):
+ user = self.env.user
+ hr_group = self.env['res.groups'].sudo().search([('name', '=', '本部-角色-人事专员')], limit=1)
+ kq_group = self.env['res.groups'].sudo().search([('name', '=', '考勤-用户')], limit=1)
+ is_hr_user = bool(hr_group and user in hr_group.users)
+ is_kq_user = bool(kq_group and user in kq_group.users)
+ active_company_ids = self.env.companies.ids
+ for record in self:
+ visible = False
+ if record.approvals_group_id and record.company_id.id in active_company_ids:
+ group_name = record.approvals_group_id.name
+ if group_name == '人事' and is_hr_user:
+ visible = True
+ elif group_name == '考勤' and is_kq_user:
+ visible = True
+ record.special_member_visible = visible
+
+ def _search_special_member_visible(self, operator, value):
+ user = self.env.user
+ hr_group = self.env['res.groups'].sudo().search([('name', '=', '本部-角色-人事专员')], limit=1)
+ kq_group = self.env['res.groups'].sudo().search([('name', '=', '集团-角色-考勤')], limit=1)
+ is_hr_user = bool(hr_group and user in hr_group.users)
+ is_kq_user = bool(kq_group and user in kq_group.users)
+ company_ids = self.env.companies.ids
+
+ # 注意:必须用扁平前缀形式(&/| 放在 domain 顶层),
+ # 不能把 ['&', ...] 作为子列表元素,否则 Odoo 会把它当叶子、把 & 当成字段名报错。
+ parts = []
+ if is_hr_user:
+ parts.append(['&', ('approvals_group_id.name', '=', '人事'), ('company_id', 'in', company_ids)])
+ if is_kq_user:
+ parts.append(['&', ('approvals_group_id.name', '=', '考勤'), ('company_id', 'in', company_ids)])
+
+ if not parts:
+ # 当前用户不属于任何特殊权限组,恒不满足
+ domain = [('id', '=', False)]
+ else:
+ domain = ['|'] * (len(parts) - 1)
+ for grp in parts:
+ domain += grp
+
+ if (operator == '=' and not value) or (operator == '!=' and value):
+ domain = ['!'] + domain
+ return domain
+
+ # ------------------------------------------------------------------
+ # 部门查询可见(排除考勤/人事):本部门数据 且 审批分组不是考勤/人事
+ # ------------------------------------------------------------------
+ @api.depends_context('uid', 'company')
+ @api.depends('member_of_department', 'approvals_group_id')
+ def _compute_dept_query_visible(self):
+ for record in self:
+ record.dept_query_visible = bool(
+ record.member_of_department
+ and record.approvals_group_id
+ and record.approvals_group_id.name not in ('考勤', '人事')
+ )
+
+ def _search_dept_query_visible(self, operator, value):
+ # 本部门数据 且 审批分组不是考勤/人事(member_of_department 由 search 方法内联展开,无嵌套)
+ domain = ['&',
+ ('approvals_group_id.name', 'not in', ['考勤', '人事']),
+ ('member_of_department', '=', True)]
+ if (operator == '=' and not value) or (operator == '!=' and value):
+ domain = ['!'] + domain
+ return domain
+
@api.model
def create(self, vals_list):
res = super().create(vals_list)
diff --git a/soong_workflow/views/soong_workflow_record.xml b/soong_workflow/views/soong_workflow_record.xml
index ec2c51da2..63a885a48 100644
--- a/soong_workflow/views/soong_workflow_record.xml
+++ b/soong_workflow/views/soong_workflow_record.xml
@@ -459,9 +459,15 @@
ir.actions.act_window
soong.workflow.record
tree,kanban,search
-
-
- [('reclaim_state', '=', False), ('approve_state','!=','start'), '|', ('create_uid', '=', uid), ('users_ids', 'in', [uid])]
+ [
+ ('reclaim_state', '=', False),
+ ('approve_state', '!=', 'start'),
+ '|',
+ '|',
+ ('users_ids', 'in', [uid]),
+ ('dept_query_visible', '=', True),
+ ('special_member_visible', '=', True)
+ ]
{'search_default_my_department_shifts': True, 'default_order': 'display_end_time desc'}
diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard.py b/soong_workflow/wizard/soong_workflow_comment_wizard.py
index 8797141ef..47470cb12 100644
--- a/soong_workflow/wizard/soong_workflow_comment_wizard.py
+++ b/soong_workflow/wizard/soong_workflow_comment_wizard.py
@@ -48,7 +48,11 @@ class SoongWorkflowCommentWizard(models.TransientModel):
employee_ids = fields.Many2many('hr.employee', 'employee_ids_rel', 'custom_id', 'employee_id', string="转交人员", store=True)
circulated_employee_ids = fields.Many2many('hr.employee', 'circulated_employee_rel', 'custom_id', 'employee_id', help='只可以看不可以评论,看过以后状态自动变为已阅', string="传阅人员", store=True)
dep_manager_employee_ids = fields.Many2many('hr.employee', 'dep_manager_employee_rel', 'custom_id', 'employee_id', string="承办", store=True)
- add_employee_ids = fields.Many2many('hr.employee', 'add_employee_rel', 'custom_id', 'employee_id', string="加签人员", help='点击确认以后评论的人员', store=True)
+ add_employee_ids = fields.Many2many('hr.employee', 'add_employee_rel', 'custom_id', 'employee_id', string="加签人员", help='点击确认以后评论的人员', store=True, domain="[('id', 'in', add_employee_filter_ids)]")
+ add_employee_filter_ids = fields.Many2many('hr.employee', 'add_employee_filter_rel', 'custom_id', 'employee_id', string="加签过滤人员",
+ default=lambda self: self._default_add_employee_filter_ids(),
+ help='当前登录人所在部门及子部门(递归)的员工,用于过滤加签人员可选范围')
+ is_return = fields.Boolean('是否返回', help='勾选之后,加签返回自己')
supervising_employee_ids = fields.Many2many('hr.employee', 'supervising_employee_rel', 'custom_id', 'employee_id', string="督办人员", store=True)
approval_concatenation = fields.Selection([('chuan', '串申'), ('bing', '并申')], string="审批形式",
help='并:任何人均给意见,最后一个完成的人转交到下一节点.'
@@ -133,6 +137,35 @@ class SoongWorkflowCommentWizard(models.TransientModel):
])
self.employee_ids2 = self.env['hr.employee'].search(domain)
+ def _default_add_employee_filter_ids(self):
+ """获取当前登录人所在部门及子部门(递归)的员工,作为加签人员的可选范围。
+
+ 参考 yuthon_notice._constrains_employee_related_fields 中的
+ get_department_employees(department_id),递归获取部门及其所有子部门下的员工。
+ """
+ department = self.env.user.department_id
+ if not department:
+ return self.env['hr.employee']
+
+ result = self.env['hr.employee']
+
+ def collect(dept):
+ nonlocal result
+ # 当前部门(含多部门字段 department_ids)下的员工
+ emps = self.env['hr.employee'].search([
+ ('company_id', '=', self.env.user.company_id.id),
+ '|',
+ ('department_id', '=', dept.id),
+ ('department_ids', 'in', dept.ids),
+ ])
+ result |= emps
+ # 递归处理子部门(部门及以下)
+ for child in dept.child_ids:
+ collect(child)
+
+ collect(department)
+ return result
+
@api.depends('comment_note_id', 'comment_note')
def _compute_comment(self):
for record in self:
@@ -754,7 +787,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
# 是否都完成了
all_done = all(log.approval_state == "2" for log in batch_logs)
# 如果都完成 → 创建一条新日志给加签发起人
- if all_done:
+ if all_done and self.is_return:
log_vals = {
"model": self.res_model,
"res_id": self.res_id,
diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml b/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml
index b6a1e9549..daa79a326 100644
--- a/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml
+++ b/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml
@@ -72,9 +72,10 @@
+
+ domain="[('id', 'in', add_employee_filter_ids)]"/>
@@ -152,6 +153,7 @@
+