Files
gzth/soong_workflow/wizard/soong_workflow_comment_wizard.py
T

969 lines
58 KiB
Python

# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from email.policy import default
from odoo import fields, models, api
from odoo.exceptions import UserError, ValidationError
from datetime import datetime, date, time, timedelta
import logging
_logger = logging.getLogger(__name__)
class SoongWorkflowCommentWizard(models.TransientModel):
_name = "soong.workflow.comment.wizard"
_description = "Soong Workflow Comment Wizard"
_inherit = ['mail.thread.main.attachment', 'mail.activity.mixin']
_transient_max_count = 0
name = fields.Char(string="name")
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')
user_id = fields.Many2one('res.users', string='用户', default=lambda self: self.env.user)
user_role_ids = fields.Many2many('soong.user.role', string="角色", compute='_compute_user_role_ids', store=True)
node_link_len = fields.Char(string="转交2")
is_supervising = fields.Boolean(string="是否督办")
comment_note_id = fields.Many2one('soong.note', string="常用意见")
comment_note = fields.Text(string="意见")
illustrate = fields.Text(string="说明")
comment = fields.Char(compute='_compute_comment', store=True)
state_list = fields.Char(string="状态列表")
record_id = fields.Integer()
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')
document_ids = fields.Many2many('ir.attachment', string="附件")
return_link_id = fields.Many2one('trans.link', string='退回节点', ondelete='set null')
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)
filter_personnel_ids = fields.Many2many('hr.employee', 'filter_personnel_rel', 'custom_id', 'employee_id', string="过滤人员", store=True)
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)
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='并:任何人均给意见,最后一个完成的人转交到下一节点.'
'串:都会收到消息,但任意一个人转交后,即到下一节点,其他人将不再显示,相当于收回.')
is_automatic = fields.Boolean('是否自动匹配')
company_id = fields.Many2one('res.company', '公司', default=lambda self: self.env.user.company_id)
is_this_company = fields.Boolean('本公司', default=True)
employee_ids1 = fields.Many2many('hr.employee', 'employee_ids1_rel', 'custom_id1', 'employee_id1', string="转交人员", store=True)
@api.onchange('is_selection')
def _onchange_is_selection(self):
domain = [('id', 'in', self.employee_ids1.ids)]
if self.is_selection:
if self.is_this_company:
domain.append(('company_id', '=', self.company_id.id))
all_employees = self.env['hr.employee'].search(domain)
self.employee_ids = all_employees
else:
self.employee_ids = False
@api.onchange('employee_ids1')
def _onchange_employee_ids1(self):
filtered_employees = self.employee_ids1.filtered(
lambda emp: emp.company_id.id == self.company_id.id
)
if len(filtered_employees) == 1:
self.employee_ids = filtered_employees
else:
self.employee_ids = False
@api.constrains('employee_ids')
def _check_employee_ids(self):
if not self.employee_ids and self.node_btn_name == '转交':
raise ValidationError("必须有转交人员")
@api.depends('comment_note_id', 'comment_note')
def _compute_comment(self):
for record in self:
comment_parts = []
if record.comment_note_id:
comment_parts.append(record.comment_note_id.name)
if record.comment_note:
comment_parts.append(record.comment_note)
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')
def _compute_user_role_ids(self):
for record in self:
if record.user_id and record.user_id.employee_ids:
role_ids_from_employee = record.user_id.employee_ids.user_role_ids
role_id_from_field = record.user_id.employee_ids.user_role_id
if role_id_from_field:
record.user_role_ids = role_ids_from_employee | role_id_from_field
else:
record.user_role_ids = role_ids_from_employee
else:
record.user_role_ids = False
@api.onchange('record_id')
def _onchange_record_id(self):
record_id = self.env[self.res_model].search([('id', '=', self.res_id)])
self.record_id = record_id
@api.onchange('return_link_id')
def onchange_employee_ids(self):
record_id = self.env[self.res_model].search([('id', '=', self.res_id)])
for ret in self.return_link_id:
if ret.name in ['拟办', '申请人']:
if hasattr(record_id, 'user_id') and record_id.user_id:
employee_ids1 = self.env['hr.employee'].search([('user_id', '=', record_id.user_id.id)])
elif hasattr(record_id, 'users_id') and record_id.users_id:
employee_ids1 = self.env['hr.employee'].search([('user_id', '=', record_id.users_id.id)])
self.employee_ids1 = employee_ids1
elif self.node_btn_name == '退回':
target_log = record_id.log_ids.filtered(lambda l: l.name == ret.name)
if target_log and target_log.done_by:
if target_log.done_by:
employee = self.env['hr.employee'].sudo().search([('user_id', '=', target_log.done_by.id)], limit=1)
self.employee_ids1 = employee
else:
self.employee_ids1 = self.env['hr.employee']
# next_list = []
# workflow_id = self.return_link_id.node_button_id.workflow_id
# state_list = [i.node_name for i in workflow_id.node_ids]
# if ret.name == '询价':
# name = 'draft'
# else:
# name = ret.name
# self_state = state_list.index(name)
# button_ids = workflow_id.node_ids[self_state].button_ids
# for btn in button_ids:
# next_list.append(btn.name)
# if '转交' not in next_list:
# raise UserError('配置错误,请配置当前{}的转交按钮'.format(btn.name))
# else:
# if btn.is_automatic:
# employee_user_role_id = self.env['hr.employee'].search(
# ['|', ('user_role_id', '=', btn.users_role_id.id),
# ('user_role_id', 'in', btn.users_role_group_ids.user_role_ids.ids),
# ('department_id', '=', record_id.department_id.id)])
# self.employee_ids1 = employee_user_role_id
# else:
# employee_user_role_ids = self.env['hr.employee'].search(
# ['|', ('user_role_id', '=', btn.users_role_id.id),
# ('user_role_id', 'in', btn.users_role_group_ids.user_role_ids.ids),
# ])
# 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):
if link.id == current_link.id and link.sequence == current_link.sequence:
approvers = self._get_approvers_for_link(link, record_id)
log_records = record_id.log_ids
approved_users = log_records.filtered(lambda log: log.node_btn_name != '1' and log.done_by).mapped('done_by.employee_ids')
approved_employee_ids = approved_users.ids
employee_ids = approvers.ids
if len(approvers) > 1:
is_all_included = all(emp_id in approved_employee_ids for emp_id in employee_ids)
if is_all_included:
if idx + 1 < len(sorted_all_links):
self.trans_link_id = sorted_all_links[idx + 1]
invalid_links |= current_link
break
record.invalid_link_ids = invalid_links
@api.onchange('trans_link_id')
def onchange_trans_employee_ids(self):
for record in self:
if not record.trans_link_id:
continue
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_priority_list = ["分发", "下发", "转交", "结束"]
button = False
if node.button_ids:
for btn_name in button_priority_list:
for btn in node.button_ids:
if btn.name == btn_name: # 匹配优先级按钮名称
is_in_scope = True
if not btn.is_review_invisible:
button = btn
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:
target_btn = btn
button = 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:
# 按当前申请人自动匹配-本部门(保留部门和公司条件)
department_domain = ['|', ('department_id', '=', record_id.department_id.id),
('department_ids', 'in', record_id.department_id.id)]
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
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 add_comment(self):
self.ensure_one()
cx = self.env.context.copy() or {}
record_id = self.env[self.res_model].search([('id', '=', self.res_id)])
is_admin = self.env.user.has_group('soong_workflow.group_soong_workflow_manager')
log_done_by_ids = [log.done_by.id for log in record_id.log_ids if log.done_by]
if self.node_btn_name == '转交':
has_comment_note = bool(self.comment_note_id)
has_comment = bool(self.comment and self.comment.strip())
if not has_comment_note and not has_comment:
raise UserError('请填写备注')
self_node_id = record_id.workflow_id.node_ids.search(
[('name', '=', record_id.state), ('workflow_id', '=', record_id.workflow_id.id)])
log = self.env['soong.workflow.log'].search([("model", "=", self.res_model),
("res_id", "=", self.res_id)])
query_user_id = self.env.user.id
if is_admin and record_id:
if hasattr(record_id, 'user_id') and record_id.user_id:
query_user_id = record_id.user_id.id
elif hasattr(record_id, 'users_id') and record_id.users_id:
query_user_id = record_id.users_id.id
if len(log) > 1 and is_admin:
current_node_log = self.sudo().env["soong.workflow.log"].search(
[("model", "=", self.res_model),
("res_id", "=", self.res_id),
("node_id", "=", self.node_btn_id.node_id.id)
],
order="lase_click_date DESC",
limit=1
)
else:
current_node_log = self.sudo().env["soong.workflow.log"].search(
[
("model", "=", self.res_model),
("res_id", "=", self.res_id),
("done_by", "=", query_user_id),
("node_id", "=", self.node_btn_id.node_id.id)
],
order="lase_click_date DESC",
limit=1
)
# 创建或更新当前用户的审批记录
if not current_node_log:
self.sudo().env["soong.workflow.log"].create({
"code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"node_id": self.node_btn_id.node_id.id,
"workflow_id": self.node_btn_id.workflow_id.id,
"done_by": query_user_id,
"node_btn_name": "0",
"node_btn_id": self.node_btn_id.id,
"lase_click_date": fields.Datetime.now(),
"approval_state": "2", # 已完成
"comment": self.comment,
})
else:
current_node_log.write({
"comment": self.comment,
"approval_state": "2", # 已完成
'document_ids': [(6, 0, self.document_ids.ids)],
"lase_click_date": fields.Datetime.now()
})
# 检查是否为并审模式
if self.approval_concatenation == 'bing': # 并审模式考勤异常
# 获取当前节点应该审批的所有员工
expected_employees = self.employee_ids
if record_id.log_ids2:
log_employee_id = record_id.log_ids2.mapped('done_by').employee_id.id
if log_employee_id in expected_employees.ids:
raise UserError('该员工已传阅,请勿重复转交')
# 查找下一个节点
next_node_id = record_id.workflow_id.node_ids.search([
('name', '=', self.trans_link_id.name),
('workflow_id', '=', record_id.workflow_id.id)
])
completed_logs = self.sudo().env["soong.workflow.log"].search([
("model", "=", self.res_model),
("res_id", "=", self.res_id),
("node_id", "=", self.node_btn_id.node_id.id),
("node_btn_name", "=", "4"),
("approval_state", "!=", "2")
])
all_completed = len(completed_logs) == 0
next_node_log_records = self.env["soong.workflow.log"]
if all_completed:
for employee in expected_employees:
# 检查该员工在下一节点是否已有记录
next_node_employee_log = self.sudo().env["soong.workflow.log"].search([
("model", "=", self.res_model),
("res_id", "=", self.res_id),
("node_id", "=", next_node_id.id),
('node_btn_name', '!=', '1'),
("done_by", "=", employee.user_id.id)
])
if not next_node_employee_log:
# 创建初步记录,状态为"待审批"
next_node_employee_log = self.sudo().env["soong.workflow.log"].create({
"code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"node_id": next_node_id.id,
"workflow_id": self.node_btn_id.workflow_id.id,
"done_by": employee.user_id.id,
"node_btn_name": "4",
"approval_state": "0", # 待审批
})
next_node_log_records += next_node_employee_log
workflow_record_id = self.env['soong.workflow.record'].sudo().search([('code', '=', record_id.code)])
if self.employee_ids:
workflow_record_id.users_ids = [(4, employee.user_id.id) for employee in self.employee_ids if employee.user_id]
workflow_record_id.employee_ids = self.employee_ids.ids
workflow_record_id.approve_state = "pending" # 待审批
related_record = self.env[self.res_model].browse(self.res_id)
if hasattr(related_record, 'self_users_ids'):
user_ids = [employee.user_id.id for employee in self.employee_ids if employee.user_id]
related_record.self_users_ids = [(6, 0, user_ids)] if user_ids else [(5,)]
if not self.trans_link_id.name:
raise UserError('无转交节点')
record_id.write({'state': self.trans_link_id.name})
if self.circulated_employee_ids:
workflow_record_id.is_log2 = True
workflow_record_id.employee2_ids = [(6, 0, self.circulated_employee_ids.ids)]
for employee in self.employee_ids:
action_id = self.env['ir.actions.act_window'].search([('res_model', '=', self.res_model)])[0]
target_url = f'https://oa.thtzjt.com/web#id={record_id.id}&cids=2&active_id={action_id.id}&model={record_id._name}&view_type=form'
url = self.sudo().env["wecom.apps"].generate_oauth_login_url(target_url, employee.user_id.id)
_logger.info(f"===================当前的url为{url}=============================")
title = record_id._description
if 'Purchase Order' == record_id._description:
title = '采购订单'
if 'Room Booking' == record_id._description:
title = '会议通知'
result_data = self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa', user_id=employee.wecom_userid, title=title,
description="标题: {}\n".format(record_id.name) + self.env.user.name + ' ' + str(
fields.Datetime.now() + timedelta(hours=8)),
url=url, btntxt="查看详情")
if result_data and 'msgid' in result_data[-1]:
msg_id = result_data[-1]['msgid']
target_logs = next_node_log_records.filtered(lambda l: l.done_by.id == employee.user_id.id)
if target_logs:
target_logs.msg_id = msg_id
else: # 串审模式 (沿用原有逻辑)
# 查找下一个节点
next_node_id = record_id.workflow_id.node_ids.search([
('name', 'ilike', self.trans_link_id.name),
('workflow_id', '=', record_id.workflow_id.id)
])
for employee_id in self.employee_ids:
# 创建下一节点的审批记录
self.sudo().env["soong.workflow.log"].create({
"code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"node_id": next_node_id.id,
"workflow_id": self.node_btn_id.workflow_id.id,
"done_by": employee_id.user_id.id if self.employee_ids else query_user_id,
"node_btn_name": "3",
"lase_click_date": fields.Datetime.now(),
"approval_state": "1", # 待审批
})
# 更新业务记录状态
related_record = self.env[self.res_model].browse(self.res_id)
if hasattr(related_record, 'self_users_ids'):
user_ids = [employee.user_id.id for employee in self.employee_ids if employee.user_id]
related_record.self_users_ids = [(6, 0, user_ids)] if user_ids else [(5,)]
record_id.write({'state': self.trans_link_id.name})
workflow_record_id = self.env['soong.workflow.record'].sudo().search([('code', '=', record_id.code)])
if self.employee_ids:
workflow_record_id.users_ids = [(4, employee.user_id.id) for employee in self.employee_ids if
employee.user_id]
workflow_record_id.employee_ids = self.employee_ids.ids
workflow_record_id.approve_state = "pending" # 待审批
for employee in self.circulated_employee_ids:
record_id = self.env[self.res_model].search([('id', '=', self.res_id)])
self.sudo().env["soong.workflow.record.copy"].create({
"code": record_id.code,
"name": record_id.name,
"res_model": self.res_model,
"workflow_id": self.node_btn_id.workflow_id.id,
"res_id": self.res_id,
"done_by": employee.user_id.id,
"approval_state_copy": "0",
})
if employee.user_id.id not in log_done_by_ids:
self.sudo().env["soong.workflow.log2"].create({
"model": self.res_model,
"res_id": self.res_id,
"node_id": self.node_btn_id.node_id.id,
"workflow_id": self.node_btn_id.workflow_id.id,
"done_by": employee.user_id.id,
"node_btn_id": self.node_btn_id.id,
"approval_state": "0",
})
action_id = self.env['ir.actions.act_window'].search([('res_model', '=', self.res_model)])[0]
# url = f'https://oa.thtzjt.com/web#id={record_id.id}&cids=2&action={action_id.id}&model={self.res_model}&view_type=from&menu_id={record_id.id}'
# description = "标题: {}\n".format(record_id.name) + self.env.user.name + ' ' + str(fields.Datetime.now() + timedelta(hours=8))
# self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa', user_id=employee.wecom_userid, title=record_id._description + "传阅/抄送",description=description, url=url, btntxt="查看详情")
if self.node_btn_name == '退回':
record_id.write({'state': self.return_link_id.name})
next_node_id = record_id.workflow_id.node_ids.search([('name', '=', self.return_link_id.name), ('workflow_id', '=', record_id.workflow_id.id)])
for next_link in record_id.workflow_id.link_ids:
if next_link.name.split('-> ')[0].strip() == self.return_link_id.name.strip():
next_node_id = next_link.node_from
record_id.log_ids[-1].write({'approval_state': '2',
"lase_click_date": fields.Datetime.now(),
"comment": self.comment,
"node_btn_name": "1"})
self.sudo().env["soong.workflow.log"].create({
"code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"node_id": next_node_id.id,
"workflow_id": self.node_btn_id.workflow_id.id,
"done_by": self.employee_ids[0].user_id.id,
"approval_state": "0",
"node_btn_id": self.node_btn_id.id,
})
workflow_record_id = self.env['soong.workflow.record'].sudo().search([('code', '=', record_id.code)])
workflow_record_id.employee_ids = self.employee_ids
related_record = self.env[self.res_model].browse(self.res_id)
user_ids = [employee.user_id.id for employee in self.employee_ids if employee.user_id]
if hasattr(related_record, 'self_users_ids'):
related_record.self_users_ids = [(6, 0, user_ids)] if user_ids else [(5,)]
workflow_record_id.users_ids = [(6, 0, user_ids)]
if self.node_btn_name in ['结束', '确认']:
is_work_remind = False
current_user = self.env.user
current_datetime = fields.Datetime.now()
is_admin = current_user.has_group('base.group_system')
if is_admin:
record_id.log_ids[-1].sudo().write({
'comment': self.comment,
'approval_state': "2",
'lase_click_date': fields.Datetime.now() - timedelta(hours=8),
'document_ids': [(6, 0, self.document_ids.ids)]
})
self.env['soong.workflow.record'].search([('code', '=', record_id.code)]).write({'approve_state': 'end',
"employee_ids": False,
"node_id": False, })
record_id.work_end = True
if record_id.log_ids:
user_log = record_id.log_ids.filtered(lambda log: log.done_by == current_user)
if user_log:
user_log.write({
'comment': self.comment,
'approval_state': "2",
'lase_click_date': current_datetime,
'document_ids': [(6, 0, self.document_ids.ids)]
})
if (record_id.log_ids2 or record_id.log_ids.filtered(lambda log: log.name == '承办')) and self.node_btn_name == '确认':
user_log2 = record_id.log_ids2.filtered(lambda log: log.done_by == current_user)
user_log1 = record_id.log_ids.filtered(lambda log: log.done_by == current_user)
if user_log2:
user_log2.write({
'commit': self.comment,
'approval_state': "2",
'lase_click_date': current_datetime,
})
if user_log1:
user_log1.write({
'comment': self.comment,
'approval_state': "2",
'lase_click_date': current_datetime,
})
for employee in self.circulated_employee_ids:
action_id = self.env['ir.actions.act_window'].search([('res_model', '=', self.res_model)])[0]
url = f'https://oa.thtzjt.com/web#id={record_id.id}&cids=2&action={action_id.id}&model={self.res_model}&view_type=from&menu_id={record_id.id}'
description = "标题: {}\n".format(record_id.name) + self.env.user.name + ' ' + str(fields.Datetime.now() + timedelta(hours=8))
workflow_record_id = self.env['soong.workflow.record'].sudo().search([('code', '=', record_id.code)])
workflow_record_id.users_ids = [(4, employee.user_id.id) for employee in self.circulated_employee_ids if employee.user_id]
workflow_record_id.employee_ids = [(4, employee.id)]
record_id = self.env[self.res_model].search([('id', '=', self.res_id)])
self.sudo().env["soong.workflow.record.copy"].create({
"code": record_id.code,
"name": record_id.name,
"res_model": self.res_model,
"workflow_id": self.node_btn_id.workflow_id.id,
"res_id": self.res_id,
"done_by": employee.user_id.id,
"approval_state_copy": "0",
})
if employee.user_id.id not in log_done_by_ids:
self.sudo().env["soong.workflow.log2"].create({
"model": self.res_model,
"res_id": self.res_id,
"node_id": self.node_btn_id.node_id.id,
"workflow_id": self.node_btn_id.workflow_id.id,
"done_by": employee.user_id.id,
"node_btn_id": self.node_btn_id.id,
"approval_state": "0",
})
# self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa', user_id=employee.wecom_userid,
# title=record_id._description + "传阅/抄送",
# description=description, url=url,
# btntxt="查看详情")
# if not record_id.log_ids2.search([('approval_state', '=', '0')]) or record_id.log_ids2:
last_log = record_id.log_ids[-1] if record_id.log_ids else None
if last_log:
same_name_logs = record_id.log_ids.filtered(
lambda log: log.name == last_log.name and log.node_btn_name == '4' and log.id != last_log.id
)
all_approved = all(log.approval_state in ['2', '3'] for log in same_name_logs) or not same_name_logs
log2_ids_all_qualified = True
if record_id.log_ids2:
log2_ids_all_qualified = all(log2.approval_state in ['2', '3'] for log2 in record_id.log_ids2)
if all_approved and log2_ids_all_qualified and not self.circulated_employee_ids:
workflow_record = self.env['soong.workflow.record'].search([('code', '=', record_id.code)],
limit=1)
has_archive_btn = any(btn_name.name == '归档' for btn_name in self.node_btn_id.node_id.button_ids)
if has_archive_btn:
log_id = record_id.log_ids.filtered(lambda l: l.name == '归档')
employee_id = self.env['hr.employee'].sudo().search([('user_id', '=', record_id.log_ids[0].done_by.id)], limit=1)
if workflow_record:
workflow_record.write({
'approve_state': 'end',
'employee_ids': [(6, 0, [employee_id.id])],
'soong_state': 'to_active',
'node_id': False,
})
if not log_id:
self.env["soong.workflow.log"].create({
'name': '归档',
"code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"workflow_id": self.node_btn_id.workflow_id.id,
"lase_click_date": fields.Datetime.now(),
"done_by": record_id.log_ids[0].done_by.id,
"approval_state": "0",
"node_btn_id": self.node_btn_id.id,
})
is_work_remind = True
else:
log_id.write({
"approval_state": "2",
})
workflow_record.write({
'soong_state': 'active',
'employee_ids': False,
})
else:
if workflow_record:
workflow_record.write({
'approve_state': 'end',
'employee_ids': False,
'node_id': False,
'soong_state': 'done',
})
record_id.work_end = True
# 给申请人发消息
if is_work_remind:
biz_record = self.env[self.res_model].browse(self.res_id)
if hasattr(biz_record, 'user_id') and biz_record.user_id:
employee = biz_record.user_id.employee_ids
elif hasattr(biz_record, 'users_id') and biz_record.users_id:
employee = biz_record.users_id.employee_ids
action_id = self.env['ir.actions.act_window'].search([('res_model', '=', self.res_model)])[0]
recipients = []
if self.node_btn_id.workflow_id.archive_type == 'applicant':
biz_record = self.env[self.res_model].browse(self.res_id)
if hasattr(biz_record, 'user_id') and biz_record.user_id:
employee = biz_record.user_id.employee_ids
elif hasattr(biz_record, 'users_id') and biz_record.users_id:
employee = biz_record.users_id.employee_ids
recipients.append(employee)
elif self.node_btn_id.workflow_id.archive_type == 'role':
role_ids = self.node_btn_id.workflow_id.role_ids
employees = self.env['hr.employee'].search([
'|',
('user_role_id', 'in', role_ids.ids),
('user_role_ids', 'in', role_ids.ids)
])
recipients = [emp for emp in employees]
else:
employees = self.node_btn_id.workflow_id.employee_ids
recipients = [emp for emp in employees]
for employee in recipients:
target_url = f'https://oa.thtzjt.com/web#id={record_id.id}&cids=2&active_id={action_id.id}&model={record_id._name}&view_type=form'
url = self.sudo().env["wecom.apps"].generate_oauth_login_url(target_url, employee.user_id.id)
if self.res_model == 'purchase.order':
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa',
user_id=employee.wecom_userid,
title='采购审批单',
description=f"{record_id.name}审批结束,可采购入库",
url=url, btntxt="查看详情")
else:
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa',
user_id=employee.wecom_userid,
title=record_id._description,
description=f"标题为{record_id.name}的{record_id._description}已结束,请归档",
url=url, btntxt="查看详情")
# self.node_btn_id.with_context(cx).run()
if self.node_btn_name == "分发":
record_id.is_send = True
menu_id = self.env['ir.ui.menu'].search([('name', '=', '行政收文')], limit=1)
workflow_record_id = self.env['soong.workflow.record'].sudo().search([('code', '=', record_id.code)])
action_id = self.env['ir.actions.act_window'].search([('res_model', '=', self.res_model)])[0]
target_url = f'https://oa.thtzjt.com/web#id={record_id.id}&cids=2&menu_id={menu_id.id}&active_id={action_id.id}&model={record_id._name}&view_type=form'
description = "标题: {}\n".format(record_id.name) + self.env.user.name + ' ' + str(fields.Datetime.now() + timedelta(hours=8))
if self.employee_ids:
workflow_record_id.users_ids = [(4, employee.user_id.id) for employee in self.employee_ids if employee.user_id]
next_node_id = record_id.workflow_id.node_ids.search([('name', '=', '董事长'), ('workflow_id', '=', record_id.workflow_id.id)])
record_id.log_ids[-1].write({"comment": self.comment, "approval_state": "2", "lase_click_date": fields.Datetime.now()})
log_id = self.sudo().env["soong.workflow.log"].create({
"code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"node_id": next_node_id.id,
"workflow_id": self.node_btn_id.workflow_id.id,
"done_by": self.employee_ids.user_id.id,
"node_btn_name": "0",
})
url = self.sudo().env["wecom.apps"].generate_oauth_login_url(target_url, self.employee_ids.user_id.id)
result_data = self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa', user_id=self.employee_ids.wecom_userid, title=record_id._description, description=description, url=url, btntxt="查看详情")
if result_data and 'msgid' in result_data[-1]:
msg_id = result_data[-1]['msgid']
log_id.msg_id = msg_id
for emp in self.dep_manager_employee_ids:
workflow_record_id.users_ids = [(4, employee.user_id.id) for employee in self.dep_manager_employee_ids if employee.user_id]
next_node_id = record_id.workflow_id.node_ids.search([('name', '=', '承办'), ('workflow_id', '=', record_id.workflow_id.id)])
log_id = self.sudo().env["soong.workflow.log"].create({
"code": self.code,
"model": self.res_model,
"res_id": self.res_id,
"node_id": next_node_id.id,
"workflow_id": self.node_btn_id.workflow_id.id,
"done_by": emp.user_id.id,
"node_btn_name": "4",
})
url = self.sudo().env["wecom.apps"].generate_oauth_login_url(target_url, emp.user_id.id)
result_data = self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa', user_id=emp.wecom_userid, title=record_id._description + "承办", description=description, url=url, btntxt="查看详情")
if result_data and 'msgid' in result_data[-1]:
msg_id = result_data[-1]['msgid']
log_id.msg_id = msg_id
for employee in self.circulated_employee_ids:
workflow_record_id.users_ids = [(4, employee.user_id.id) for employee in self.circulated_employee_ids if employee.user_id]
record_id = self.env[self.res_model].search([('id', '=', self.res_id)])
self.sudo().env["soong.workflow.record.copy"].create({
"code": record_id.code,
"name": record_id.name,
"res_model": self.res_model,
"workflow_id": self.node_btn_id.workflow_id.id,
"res_id": self.res_id,
"done_by": employee.user_id.id,
"approval_state_copy": "0",
})
if employee.user_id.id not in log_done_by_ids:
log2_domain = [
('model', '=', self.res_model),
('res_id', '=', self.res_id),
('node_id', '=', self.node_btn_id.node_id.id),
('done_by', '=', employee.user_id.id),
]
log2_id = self.sudo().env["soong.workflow.log2"].search(log2_domain, limit=1)
if not log2_id:
log2_id = self.sudo().env["soong.workflow.log2"].create({
"model": self.res_model,
"res_id": self.res_id,
"node_id": self.node_btn_id.node_id.id,
"workflow_id": self.node_btn_id.workflow_id.id,
"done_by": employee.user_id.id,
"node_btn_id": self.node_btn_id.id,
"approval_state": "0",
})
url = self.sudo().env["wecom.apps"].generate_oauth_login_url(target_url, employee.user_id.id)
result_data = self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa', user_id=employee.wecom_userid, title=record_id._description + "传阅/抄送",description=description, url=url, btntxt="查看详情")
if result_data and 'msgid' in result_data[-1]:
msg_id = result_data[-1]['msgid']
log2_id.msg_id = msg_id
workflow_record_id.employee_ids = self.dep_manager_employee_ids + self.employee_ids + self.circulated_employee_ids
record_id.log_ids[-1].write({"comment": self.comment, "approval_state": "2", "lase_click_date": fields.Datetime.now()})
if self.node_btn_name == "收回":
current_user = self.env.user
record = self.env[self.res_model].search([('id', '=', self.res_id)])
is_admin = current_user.has_group('base.group_system') or current_user.has_group('base.group_admin')
log_ids = record.log_ids.sorted('sequence')
log_to_delete = log_ids.filtered(lambda log: log.name == record.state)
if self.res_model == 'yuthon.official.incoming.normal':
director_logs = log_ids.filtered(lambda log: '董事长' in (log.name or ''))
if len(director_logs) == 2:
log_to_delete = log_ids[-1:]
if not is_admin:
invalid_logs = log_to_delete.filtered(
lambda log: log.approval_state in ['1', '2'] and log.node_btn_name != '1'
)
if invalid_logs:
raise UserError('当前状态不可以收回')
total_log_count = len(log_ids)
deleted_log_count = len(log_to_delete)
prev_log_index = (total_log_count - deleted_log_count) - 1
other_log_index = total_log_count - deleted_log_count
if prev_log_index < 0 or prev_log_index >= len(log_ids):
raise UserError('无有效的上一级审批明细行,无法执行收回操作')
prev_log = log_ids[prev_log_index]
related_record = self.env[self.res_model].browse(self.res_id)
done_by_list = []
for index in range(other_log_index):
done_by_list.append(log_ids[index].done_by.id)
if hasattr(related_record, 'self_users_ids'):
related_record.self_users_ids = [(6, 0, [prev_log.done_by.id])]
self.env['soong.workflow.record'].search([('code', '=', record.code)]).write(
{"employee_ids": [(6, 0, [prev_log.done_by.employee_ids.id])],
"users_ids": [(6, 0, done_by_list)],
'soong_state': 'to_do'
})
for log_delete in log_to_delete:
self.sudo().env["wecom.apps"].back_message(log_delete.msg_id, category='approval')
log_to_delete.unlink()
if record.log_ids2:
for log_id2 in record.log_ids2:
self.sudo().env["wecom.apps"].back_message(log_id2.msg_id, category='approval')
record.log_ids2.unlink()
prev_log.write({'approval_state': '1'})
record.write({'state': prev_log.name,
'work_end': False,
})
self.node_btn_id.with_context(cx).run()
if self.node_btn_name == '归档':
menu_id = self.env['ir.ui.menu'].search([('name', '=', '行政收文')], limit=1)
action_id = self.env['ir.actions.act_window'].search([('res_model', '=', self.res_model)])[0]
target_url = f'https://oa.thtzjt.com/web#id={record_id.id}&cids=2&menu_id={menu_id.id}&active_id={action_id.id}&model={record_id._name}&view_type=form'
description = "标题: {}\n".format(record_id.name) + self.env.user.name + ' ' + str(fields.Datetime.now() + timedelta(hours=8))
record = self.env[self.res_model].search([('id', '=', self.res_id)])
record.log_ids[-1].write({'is_active_operate': True,
'approval_state': '1'
})
workflow_record_id = self.env['soong.workflow.record'].sudo().search([('code', '=', record_id.code)])
if not self.circulated_employee_ids:
record.log_ids[-1].write({'approval_state': '2'})
if self.document_ids:
record.log_ids[-1].write({'document_ids': [(6, 0, self.document_ids.ids)]})
record.log_ids[-1].write({"comment": self.comment})
workflow_record_id.write({'soong_state': 'active',
'employee_ids':False
})
if self.circulated_employee_ids:
for employee in self.circulated_employee_ids:
if employee.user_id.id not in log_done_by_ids:
log2_domain = [
('model', '=', self.res_model),
('res_id', '=', self.res_id),
('node_id', '=', self.node_btn_id.node_id.id),
('done_by', '=', employee.user_id.id),
]
log2_id = self.sudo().env["soong.workflow.log2"].search(log2_domain, limit=1)
if not log2_id:
workflow_record_id.users_ids = [(4, employee.user_id.id) for employee in self.circulated_employee_ids if employee.user_id]
log2_id = self.sudo().env["soong.workflow.log2"].create({
"model": self.res_model,
"res_id": self.res_id,
"node_id": self.node_btn_id.node_id.id,
"workflow_id": self.node_btn_id.workflow_id.id,
"done_by": employee.user_id.id,
"node_btn_id": self.node_btn_id.id,
"approval_state": "0",
})
url = self.sudo().env["wecom.apps"].generate_oauth_login_url(target_url, employee.user_id.id)
result_data = self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa',
user_id=employee.wecom_userid,
title=record_id._description + "传阅/抄送",
description=description,
url=url,
btntxt="查看详情")
if result_data and 'msgid' in result_data[-1]:
msg_id = result_data[-1]['msgid']
log2_id.msg_id = msg_id
if self.node_btn_name != "收回":
tree_id = self.env.ref("soong_workflow.soong_workflow_record_my_tree").id
kanban_id = self.env.ref("soong_workflow.soong_workflow_record_kanban").id
# self.red_reload()
return {
'type': 'ir.actions.client',
'tag': 'flush_badge_wkf',
'params': {
'tree_id': tree_id,
'kanban_id': kanban_id,
'uid': self.env.uid,
}
}
# return {
# 'name': '流程待办',
# 'view_mode': 'tree',
# 'res_model': 'soong.workflow.record',
# 'type': 'ir.actions.act_window',
# 'views': [[tree_id, 'tree']],
# 'domain': [('users_ids', 'in', self.env.uid), ('reclaim_state', '=', False), ('soong_state', '=', 'to_do')],
# 'context': {
# 'header_search_default_approve_state': 1,
# 'header_search_default_to_do': 1,
# 'check_employee': 1
# }
# }
# def red_reload(self):
# return {
# 'type': 'ir.actions.client',
# 'tag': 'flush_badge',
# }
def update_self_users_ids(self):
related_record = self.env[self.res_model].browse(self.res_id)
if hasattr(related_record, 'self_users_ids'):
user_ids = [employee.user_id.id for employee in self.employee_ids if employee.user_id]
related_record.self_users_ids = [(6, 0, user_ids)] if user_ids else [(5,)]