From 0654f1feef6dce13c025ae048a069c4f494652ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?=
<9664676+pengyuthon@user.noreply.gitee.com>
Date: Wed, 10 Jun 2026 17:33:52 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../views/soong_workflow_record.xml | 2 +-
.../wizard/soong_workflow_comment_wizard.py | 52 ++++++++++++++++++-
.../soong_workflow_comment_wizard_view.xml | 6 +++
yuthon_issue/models/issue_library.py | 21 ++++++++
yuthon_issue/views/issue_library_views.xml | 10 ++++
5 files changed, 89 insertions(+), 2 deletions(-)
diff --git a/soong_workflow/views/soong_workflow_record.xml b/soong_workflow/views/soong_workflow_record.xml
index 70a0bdf82..9a4283683 100644
--- a/soong_workflow/views/soong_workflow_record.xml
+++ b/soong_workflow/views/soong_workflow_record.xml
@@ -459,7 +459,7 @@
ir.actions.act_window
soong.workflow.record
tree,kanban,search
- [('reclaim_state', '=', False), ('is_company', '=', True),('approve_state','!=','start'),('approvals_group_id.name', 'not in', ['考勤', '人事'])]
+ [('reclaim_state', '=', False), ('approve_state','!=','start'),('approvals_group_id.name', 'not in', ['考勤', '人事']), '|', ('users_ids', 'in', [uid]), ('member_of_department', '=', 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 89c28c297..398237a2f 100644
--- a/soong_workflow/wizard/soong_workflow_comment_wizard.py
+++ b/soong_workflow/wizard/soong_workflow_comment_wizard.py
@@ -19,6 +19,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
res_model = fields.Char()
res_id = fields.Integer()
code = fields.Char()
+
log_ids = fields.Many2many(comodel_name="soong.workflow.log")
node_btn_id = fields.Many2one(comodel_name="soong.workflow.node.button")
node_btn_name = fields.Char(string="动作名称", related='node_btn_id.name')
@@ -35,6 +36,51 @@ class SoongWorkflowCommentWizard(models.TransientModel):
workflow_record_id = fields.Many2one('soong.workflow.record', string="流程")
is_selection = fields.Boolean(string="是否自动选择")
trans_link_id = fields.Many2one('trans.link', string='转交节点', ondelete='set null')
+ is_avoid = fields.Boolean(string='是否回避')
+ allowed_issue_ids = fields.Many2many('issue.library', 'soong_comment_wizard_allowed_issue_rel',
+ 'wizard_id', 'issue_id', string='可选议题')
+ avoid_issue_ids = fields.Many2many('issue.library', 'soong_comment_wizard_avoid_issue_rel',
+ 'wizard_id', 'issue_id', string='回避议题')
+ avoid_comment = fields.Char(string='回避意见')
+
+ @api.model
+ def default_get(self, fields_list):
+ res = super().default_get(fields_list)
+ ctx = self.env.context
+ res_model = ctx.get('default_res_model') or res.get('res_model')
+ res_id = ctx.get('default_res_id') or res.get('res_id')
+ if res_model and res_id:
+ source = self.env[res_model].browse(res_id)
+ if hasattr(source, 'line_ids'):
+ res['allowed_issue_ids'] = [(6, 0, source.line_ids.mapped('issue_id').ids)]
+ return res
+
+ @api.onchange('avoid_issue_ids')
+ def _onchange_avoid_issue_ids(self):
+ if self.avoid_issue_ids and self.allowed_issue_ids:
+ invalid = self.avoid_issue_ids - self.allowed_issue_ids
+ if invalid:
+ self.avoid_issue_ids = [(6, 0, (self.avoid_issue_ids - invalid).ids)]
+ return {
+ 'warning': {
+ 'title': '无效议题',
+ 'message': f'以下议题不在当前申报范围内,已自动移除:{", ".join(invalid.mapped("name"))}',
+ }
+ }
+
+ @api.onchange('is_avoid')
+ def _onchange_is_avoid(self):
+ if not self.is_avoid:
+ self.avoid_issue_ids = [(5, 0, 0)]
+ self.avoid_comment = False
+
+ def _handle_avoidance(self):
+ """回避处理:勾选回避且选了议题时,在对应议题中记录回避"""
+ if not self.is_avoid or not self.avoid_issue_ids:
+ return
+ for issue in self.avoid_issue_ids:
+ issue.log_avoidance(self.env.user, self.avoid_comment or '')
+
document_ids = fields.Many2many('ir.attachment', string="附件")
return_link_id = fields.Many2one('trans.link', string='退回节点', ondelete='set null')
invalid_link_ids = fields.Many2many(
@@ -130,7 +176,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
])
self.employee_ids2 = self.env['hr.employee'].search(domain)
- @api.depends('comment_note_id', 'comment_note')
+ @api.depends('comment_note_id', 'comment_note', 'avoid_comment')
def _compute_comment(self):
for record in self:
comment_parts = []
@@ -138,6 +184,8 @@ class SoongWorkflowCommentWizard(models.TransientModel):
comment_parts.append(record.comment_note_id.name)
if record.comment_note:
comment_parts.append(record.comment_note)
+ if record.avoid_comment:
+ comment_parts.append(f'【回避意见】{record.avoid_comment}')
record.comment = " ".join(comment_parts) if comment_parts else ""
@api.depends('user_id.employee_ids.user_role_ids', 'user_id.employee_ids.user_role_id')
@@ -564,6 +612,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
title=record_id._description + '传阅/抄送,测试提醒',
description=description, url=url,
btntxt="查看详情")
+ self._handle_avoidance()
if self.node_btn_name == '退回':
if not self.return_link_id:
raise UserError('请选择退回节点')
@@ -970,6 +1019,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
title=title,
description=f"标题为{record_id.name}的{title}已结束,请归档",
url=url, btntxt="查看详情")
+ self._handle_avoidance()
if self.node_btn_name == "分发":
record_id.is_send = True
menu_id = self.env['ir.ui.menu'].search([('name', '=', '行政收文')], limit=1)
diff --git a/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml b/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml
index ba475968e..8cf556148 100644
--- a/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml
+++ b/soong_workflow/wizard/soong_workflow_comment_wizard_view.xml
@@ -12,6 +12,7 @@
+
@@ -136,6 +137,11 @@
+
+
+
+
退回节点
diff --git a/yuthon_issue/models/issue_library.py b/yuthon_issue/models/issue_library.py
index 3b3e1c4b0..7eea5915a 100644
--- a/yuthon_issue/models/issue_library.py
+++ b/yuthon_issue/models/issue_library.py
@@ -71,6 +71,7 @@ class IssueLibrary(models.Model):
issue_approval_id = fields.Many2one('issue.approval', string="关联议题审批")
issue_library_line_ids = fields.One2many('issue.library.line', 'issue_library_id', string="决策明细")
issue_library_approval_line_ids = fields.One2many('issue.library.approval.line', 'issue_library_id', string='流程记录')
+ avoid_line_ids = fields.One2many('issue.library.avoid.line', 'issue_library_id', string='回避记录')
approval_decision_sequence = fields.Char(string="决策清单事项")
is_booking = fields.Boolean(string="是否上会")
issues_result = fields.Html(string="会议结果")
@@ -113,6 +114,15 @@ class IssueLibrary(models.Model):
is_push_depart = fields.Boolean(string="部门推送")
is_meeting = fields.Boolean(string="已过会", compute='_compute_meeting', store=True)
+ def log_avoidance(self, avoid_user, avoid_comment=''):
+ """记录回避信息"""
+ self.env['issue.library.avoid.line'].create({
+ 'issue_library_id': self.id,
+ 'avoid_user_id': avoid_user.id,
+ 'avoid_date': fields.Datetime.now() + timedelta(hours=8),
+ 'avoid_comment': avoid_comment,
+ })
+
def correction_confirm(self):
for rec in self:
rec.is_confirm = False
@@ -1006,3 +1016,14 @@ class IssueLibraryRoomLine(models.Model):
'target': 'current',
}
+
+class IssueLibraryAvoidLine(models.Model):
+ _name = 'issue.library.avoid.line'
+ _description = '回避记录'
+ _order = 'avoid_date desc'
+
+ issue_library_id = fields.Many2one('issue.library', string='关联议题')
+ avoid_user_id = fields.Many2one('res.users', string='回避人', default=lambda self: self.env.user)
+ avoid_date = fields.Datetime(string='回避时间', default=fields.Datetime.now)
+ avoid_comment = fields.Text(string='回避意见')
+
diff --git a/yuthon_issue/views/issue_library_views.xml b/yuthon_issue/views/issue_library_views.xml
index 763698f3c..da8fca6f3 100644
--- a/yuthon_issue/views/issue_library_views.xml
+++ b/yuthon_issue/views/issue_library_views.xml
@@ -328,6 +328,16 @@
+
+
+
+
+
+
+
+
+
+