This commit is contained in:
李鹏宇
2025-02-07 19:18:42 +08:00
parent aea0d178da
commit 05888b2dc7
13 changed files with 170 additions and 92 deletions
@@ -18,6 +18,7 @@ MENU_BADGE_MODEL_FUNC_ENUM = {
'base.menu_action_res_users': {'model': 'file.preview.test', 'func': 'get_menu_badge_count'},
'yuthon_notice.yuthon_notice_my_menu': {'model': 'yuthon.notice', 'func': 'get_no_read_count'},
'soong_workflow.menu_workflow_approval_request_my': {'model': 'soong.workflow.record', 'func': 'get_no_read_count'},
'soong_workflow.menu_workflow_approval_request_copy': {'model': 'soong.workflow.record.copy', 'func': 'get_no_read_count'},
'yuthon_will_task.menu_yuthon_will_task_root': {'model': 'yuthon.will.task', 'func': 'read_number'},
'yuthon_property_approval.property_lease_contract_coming_menu': {'model': 'property.lease.contract', 'func': 'read_coming_count'},
'yuthon_property_approval.property_lease_contract_coming_due_menu': {'model': 'property.lease.contract', 'func': 'read_due_count'},
+1
View File
@@ -29,6 +29,7 @@
"views/soong_workflow_entrust_views.xml",
"views/soong_workflow_inspector_views.xml",
"views/soong_workflow_log_views.xml",
"views/soong_workflow_record_copy_views.xml",
"wizard/soong_workflow_comment_wizard_view.xml",
"wizard/soong_workflow_apostille_wizard_view.xml",
"wizard/soong_workflow_apostille_ok_wizard_view.xml",
+1
View File
@@ -5,6 +5,7 @@ from . import soong_workflow_node
from . import soong_workflow_link
from . import ir_model
from . import soong_workflow_record
from . import soong_workflow_record_copy
from . import soong_workflow_mixin
from . import soong_approval_users
from . import soong_hr_employee
+2 -1
View File
@@ -23,7 +23,7 @@ class SoongWorkflowLog(models.Model):
node_btn_name = fields.Selection([('0', ' '), ('1', '退回'), ('2', '加签')], string='节点功能', default='0')
done_by = fields.Many2one(comodel_name="res.users", string="审批人")
lase_click_date = fields.Datetime(string="操作时间")
approval_state = fields.Selection([('0', '待办'), ('1', '办理中'), ('2', '已办结')], string='审批状态', default='0')
approval_state = fields.Selection([('0', '待办'), ('1', '办理中'), ('2', '已办结'), ('3', '结束')], string='审批状态', default='0')
comment = fields.Char(string="意见")
date_create = fields.Datetime(string="时间", default=lambda self: fields.Datetime.now())
@@ -46,6 +46,7 @@ class SoongWorkflowLog(models.Model):
logs_obj = self.sudo().search([("res_id", "=", record.res_id), ("model", "=", record.model), ("workflow_id", "=", record.workflow_id.id), ("date_create", "<", record.date_create)])
record.sequence = len(logs_obj) + 1
class SoongWorkflowLog2(models.Model):
_name = "soong.workflow.log2"
_description = "Soong Workflow Log2"
+41 -67
View File
@@ -206,7 +206,7 @@ class SoongWorkflowMixin(models.AbstractModel):
# }
# )
if btn_rec.name not in ['转交', '加签', '加签确认', '退回']:
if btn_rec.name not in ['转交', '加签', '加签确认', '退回', '收回']:
record_obj = log_obj.search(
[
("model", "=", self._name),
@@ -231,7 +231,6 @@ class SoongWorkflowMixin(models.AbstractModel):
}
)
record_obj.write({"node_btn_id": btn_rec.id, "done_by": self.env.uid, "approval_state": "2"})
record_obj = log_obj.search(
[
("model", "=", self._name),
@@ -416,7 +415,7 @@ class SoongWorkflowMixin(models.AbstractModel):
"default_is_automatic": next_state.is_automatic,
"default_employee_ids": employee_ids,
"default_node_btn_id": btn_rec.id,
"default_trans_link_id": trans_link_id.id,
"default_trans_link_id": trans_link_id.id if btn_rec.name == '转交' else False,
"default_node_link_len": '转交2' if len(btn_rec.node_id.out_link_ids) > 1 and btn_rec.name == '转交' else '',
},
}
@@ -425,14 +424,13 @@ class SoongWorkflowMixin(models.AbstractModel):
def _update_wkf_records(self):
for rec in self:
record_obj = self.env["soong.workflow.record"].search([("res_model", "=", rec._name), ("res_id", "=", rec.id)])
record_id = self.env[rec._name].search([('id', '=', rec.id)])
current_user_id = self.env.user.id
button_ids = self.workflow_id.node_ids.search([('node_name', '=', self.state), ('workflow_id', '=', self.workflow_id.id)]).button_ids
# state_list = [i.node_name for i in self.workflow_id.node_ids]
# self_state = state_list.index(self.state)
# next_state = self.workflow_id.node_ids[self_state + 1].button_ids[0]
if self.state in ['申请人', 'start', '拟办']:
if not record_obj:
self.env["soong.workflow.record"].create({
"code": record_id.code,
"res_model": rec._name,
"res_id": rec.id,
"workflow_id": rec.workflow_id.id,
@@ -442,43 +440,41 @@ class SoongWorkflowMixin(models.AbstractModel):
"self_users": self.env.user.name,
})
elif self.state not in ['end']:
if button_ids:
self_state = button_ids[0]
else:
raise UserError('请配置节点按钮')
employee_user_role_ids = self.env['hr.employee'].search(['|', ('user_role_id', '=', self_state.users_role_id.id),
('user_role_ids', 'in', self_state.users_role_id.id)])
employee_user_role_id = self.env['hr.employee'].search(['|', ('user_role_id', '=', self_state.users_role_id.id),
('user_role_ids', 'in', self_state.users_role_id.id), '|',
('department_id', '=', self.department_id.id),
('department_ids', 'in', self.department_id.id)])
employee_ids = employee_user_role_ids if not self_state.is_automatic else employee_user_role_id
user_ids_list = []
for employee in employee_ids:
if employee.user_id:
user_ids_list.append((4, employee.user_id.id))
if not record_obj:
record_obj = self.env["soong.workflow.record"].create({
"res_model": rec._name,
"res_id": rec.id,
"workflow_id": rec.workflow_id.id,
"node_id": rec.node_id.id,
"done_by": self.env.uid,
"users_ids": [(4, current_user_id)],
"self_users": self.env.user.name,
})
record_obj.update({"workflow_id": rec.workflow_id.id,
"node_id": rec.node_id.id,
"done_by": self.env.uid,
"users_ids": user_ids_list,
"self_users": ','.join([employee.name for employee in employee_ids]),
})
if button_ids:
self_state = button_ids[0]
else:
raise UserError('请配置节点按钮')
employee_user_role_ids = self.env['hr.employee'].search(['|', ('user_role_id', '=', self_state.users_role_id.id),
('user_role_ids', 'in', self_state.users_role_id.id)])
employee_user_role_id = self.env['hr.employee'].search(['|', ('user_role_id', '=', self_state.users_role_id.id),
('user_role_ids', 'in', self_state.users_role_id.id), '|',
('department_id', '=', self.department_id.id),
('department_ids', 'in', self.department_id.id)])
employee_ids = employee_user_role_ids if not self_state.is_automatic else employee_user_role_id
user_ids_list = []
for employee in employee_ids:
if employee.user_id:
user_ids_list.append((4, employee.user_id.id))
if not record_obj:
record_obj = self.env["soong.workflow.record"].create({
"res_model": rec._name,
"res_id": rec.id,
"workflow_id": rec.workflow_id.id,
"node_id": rec.node_id.id,
"done_by": self.env.uid,
"users_ids": [(4, current_user_id)],
"self_users": self.env.user.name,
})
record_obj.update({"workflow_id": rec.workflow_id.id,
"node_id": rec.node_id.id,
"done_by": self.env.uid,
"users_ids": user_ids_list,
"self_users": ','.join([employee.name for employee in employee_ids]),
})
def unlink(self):
self.mapped("log_ids").unlink()
record_objs = self.env["soong.workflow.record"].search(
[("res_model", "=", self._name), ("res_id", "in", self.ids)]
)
record_objs = self.env["soong.workflow.record"].search([("res_model", "=", self._name), ("res_id", "in", self.ids)])
record_objs.unlink()
return super().unlink()
@@ -526,35 +522,13 @@ class SoongWorkflowMixin(models.AbstractModel):
return res
# 收回
# 状态变化的时候会出现一条记录是谁操作的?
def action_withdraw(self):
for record in self:
if self.state == 'start':
raise UserError('当前节点不允许收回')
employee_id = self.env['hr.employee']
state_list = []
for state in record.workflow_id.node_ids:
if state.name in ['拟办', '申请人']:
state_list.append('start')
elif state.name == '结束':
state_list.append('end')
else:
state_list.append(state.name)
self_node_id = record.workflow_id.node_ids.search(
[('name', '=', self.state), ('workflow_id', '=', record.workflow_id.id)])
transmitted = self_node_id.button_ids.search([('name', '=', '转交'), ('node_id', '=', self_node_id.id)])[0]
if transmitted.btn_hide:
if transmitted.review_type == 'user_role':
user_ids_list = employee_id.search(['|', ('user_role_id', '=', transmitted.users_role_id.id),
('user_role_ids', 'in', [transmitted.users_role_id.id])]).ids
if self.env.user.employee_id.id in user_ids_list:
raise UserError('当前节点不允许收回')
else:
state_index = state_list.index(self.state)
self.write({'state': state_list[state_index - 1]})
else:
raise UserError('请配置节点角色')
else:
raise UserError('当前节点不允许收回')
log_ids = record.log_ids.sorted('sequence')
log_ids[-1].unlink()
log_ids[-2].write({'approval_state': '1'})
record.write({'state': log_ids[-2].name})
def _remove_default_header(self, view_type, res):
"""
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError, UserError
class SoongWorkflowRecordCopy(models.Model):
_name = "soong.workflow.record.copy"
_description = "工作流记录传阅/抄送"
_order = 'lase_click_date'
def get_no_read_count(self):
return self.search_count([('approval_state_copy', '=', '0'), ('done_by', '=', self.env.user.id)])
code = fields.Char(string="流水号")
name = fields.Char(string="流程名称", store=True)
workflow_id = fields.Many2one(comodel_name="soong.workflow", string="审批类型", ondelete="restrict")
res_model = fields.Char(string="Res Model", required=True)
res_id = fields.Integer(string="Res ID", required=True)
done_by = fields.Many2one(comodel_name="res.users", string="抄送/传阅人")
approval_state_copy = fields.Selection([('0', '未读'), ('1', '已读')], string='状态', default='0')
lase_click_date = fields.Datetime(string="操作时间")
def open_record(self):
return {
"type": "ir.actions.act_window",
"res_model": self.res_model,
"res_id": self.res_id,
"name": self.name,
"view_mode": "form",
}
def read(self, fields=None, load='_classic_read'):
for i in self.search([('approval_state_copy', '=', '0'), ('done_by', '=', self.env.user.id)]):
record_id = self.env[i.res_model].search([('id', '=', i.res_id)])
j = record_id.log_ids2.search([('done_by', '=', self.env.user.id), ('res_id', '=', record_id.id)])
i.write({'approval_state_copy': '1'})
j.write({'approval_state': '1'})
# j.write({'approval_state': '1', 'lase_click_date': fields.Datetime.now()})
return super(SoongWorkflowRecordCopy, self).read(fields=fields, load=load)
@@ -15,6 +15,7 @@ access_soong_workflow_node_button_manager,soong_workflow_node_button_manager,mod
access_soong_workflow_link_manager,soong_workflow_link_manager,model_soong_workflow_link,soong_workflow.group_soong_workflow_manager,1,1,1,1
,,,,,,,
access_soong_workflow_record_user,soong_workflow_record_user,model_soong_workflow_record,soong_workflow.group_soong_workflow_user,1,1,1,1
access_soong_workflow_record_copy,soong_workflow_record_copy,model_soong_workflow_record_copy,soong_workflow.group_soong_workflow_user,1,1,1,1
access_soong_user_role,soong_user_role,model_soong_user_role,group_soong_workflow_user,1,1,1,1
access_soong_approval_users,soong_approval_users,model_soong_approval_users,soong_workflow.group_soong_workflow_user,1,1,1,1
access_soong_note,soong_note,model_soong_note,soong_workflow.group_soong_workflow_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
15 access_soong_workflow_link_manager soong_workflow_link_manager model_soong_workflow_link soong_workflow.group_soong_workflow_manager 1 1 1 1
16
17 access_soong_workflow_record_user soong_workflow_record_user model_soong_workflow_record soong_workflow.group_soong_workflow_user 1 1 1 1
18 access_soong_workflow_record_copy soong_workflow_record_copy model_soong_workflow_record_copy soong_workflow.group_soong_workflow_user 1 1 1 1
19 access_soong_user_role soong_user_role model_soong_user_role group_soong_workflow_user 1 1 1 1
20 access_soong_approval_users soong_approval_users model_soong_approval_users soong_workflow.group_soong_workflow_user 1 1 1 1
21 access_soong_note soong_note model_soong_note soong_workflow.group_soong_workflow_user 1 1 1 1
@@ -21,7 +21,6 @@
<field name="sequence" string=""/>
<field name="done_by" string=""/>
<field name="name" string=""/>
<field name="lase_click_date" string=""/>
<field name="approval_state" string=""/>
<field name="lase_click_date" string=""/>
</tree>
+1 -1
View File
@@ -14,7 +14,7 @@
<menuitem id="menu_workflow_approval_request_copy"
name="抄送/传阅流程"
parent="menu_soong_workflow_root"
action="soong_workflow_record_action"
action="soong_workflow_record_action_copy"
sequence="2"/>
<menuitem id="menu_workflow_approval_request_entrust"
name="委托流程"
@@ -27,10 +27,11 @@
<field name="approve_state" string="审批状态"/>
<field name="users_ids" string="用户" widget="many2many_tags" optional="hide"/>
<field name="self_users" string="当前经办人"/>
<field name="done_by" />
<field name="done_by"/>
<field name="write_date"/>
<field name="reclaim_state" column_invisible="1"/>
<button name="reclaim_record" type="object" string="删除" class="btn-primary" groups="soong_workflow.group_soong_workflow_manager"/>
<button name="reclaim_record" type="object" string="删除" class="btn-primary"
groups="soong_workflow.group_soong_workflow_manager"/>
</tree>
</field>
</record>
@@ -46,10 +47,11 @@
<field name="workflow_id" string="审批类型"/>
<field name="node_id" string="当前节点"/>
<field name="approve_state" string="审批状态"/>
<field name="users_ids" string="审批人" widget="many2many_tags"/>
<field name="users_ids" string="审批人" widget="many2many_tags"/>
<field name="write_date"/>
<field name="reclaim_state" column_invisible="1"/>
<button name="restore_record" type="object" string="还原" class="btn-primary" groups="soong_workflow.group_soong_workflow_manager"/>
<button name="restore_record" type="object" string="还原" class="btn-primary"
groups="soong_workflow.group_soong_workflow_manager"/>
</tree>
</field>
</record>
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>entrust
<data>
<record id="soong_workflow_record_copy_search" model="ir.ui.view">
<field name="name">soong.workflow.record.copy.search</field>
<field name="model">soong.workflow.record.copy</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="code"/>
</search>
</field>
</record>
<record id="soong_workflow_record_copy_tree" model="ir.ui.view">
<field name="name">soong.workflow.record.copy.tree</field>
<field name="model">soong.workflow.record.copy</field>
<field name="arch" type="xml">
<tree action="open_record" delete="false" type="object" create="false" default_order="lase_click_date desc">
<field name="code"/>
<field name="name"/>
<field name="done_by"/>
<field name="approval_state_copy"/>
<field name="lase_click_date" column_invisible="1"/>
</tree>
</field>
</record>
<record id="soong_workflow_record_action_copy" model="ir.actions.act_window">
<field name="name">抄送/传阅审批</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">soong.workflow.record.copy</field>
<field name="domain">[('done_by', '=', uid)]</field>
<field name="view_mode">tree</field>
</record>
</data>
</odoo>
@@ -116,19 +116,19 @@ class SoongWorkflowCommentWizard(models.TransientModel):
cx = self.env.context.copy() or {}
record_id = self.env[self.res_model].search([('id', '=', self.res_id)])
if self.node_btn_name == '转交':
# 生成当前节点的记录
self_node_id = record_id.workflow_id.node_ids.search([('name', '=', record_id.state), ('workflow_id', '=', record_id.workflow_id.id)])
# 工作流更新,转交节点日志记录。
now_record_obj = 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),
("workflow_id", "=", record_id.workflow_id.id),
("node_btn_name", "=", "0"),
("node_btn_id", "=", self.node_btn_id.id),
], order="lase_click_date DESC", limit=1)
])
# ("workflow_id", "=", record_id.workflow_id.id),
# ("node_btn_name", "=", "0"),
# ("node_btn_id", "=", self.node_btn_id.id),
# ], order="lase_click_date DESC", limit=1)
if not now_record_obj:
now_record_obj = self.sudo().env["soong.workflow.log"].create({
self.sudo().env["soong.workflow.log"].create({
"model": self.res_model,
"res_id": self.res_id,
"node_id": self.node_btn_id.node_id.id,
@@ -139,20 +139,40 @@ class SoongWorkflowCommentWizard(models.TransientModel):
"lase_click_date": fields.Datetime.now(),
"approval_state": "2"
})
now_record_obj.write({"comment": self.comment_note_id.name, "approval_state": "2"})
else:
now_record_obj.write({"comment": self.comment_note_id.name, "approval_state": "2", "lase_click_date": fields.Datetime.now()})
# 抄送传阅日志
if self_node_id.is_carbon_copy:
for employee in self_node_id.employee_ids:
if not employee.wecom_userid:
raise ("请同步{}的企业微信".format(employee.name))
# url = "https://oa.thtzjt.com/mail/view?model={}&res_id={}".format(self.res_model, record_id.id)
# self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa',
# user_id=employee.wecom_userid,
# title=record_id._description,
# description="标题: {}\n".format(
# record_id.name) + self.env.user.name + ' ' + str(
# fields.Datetime.now() + timedelta(
# hours=8)),
# url=url, btntxt="查看详情")
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",
})
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 = "https://oa.thtzjt.com/mail/view?model={}&res_id={}".format(self.res_model, record_id.id)
self.sudo().env["wecom.apps"].sync_send_message_textcard(category='oa', user_id=employee.wecom_userid,
title=record_id._description,
description="标题: {}\n".format(
record_id.name) + self.env.user.name + ' ' + str(
fields.Datetime.now() + timedelta(hours=8)),
url=url, btntxt="查看详情")
# partner_ids = self_node_id.employee_ids.user_id.partner_id.ids
# self.with_context(lang=self.env.lang)._message_auto_subscribe_notify(partner_ids, 'soong_workflow.message_soong_workflow_distribute')
# 转交逻辑--单线
@@ -211,6 +231,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
)
# partner_ids = self.employee_ids.user_id.partner_id.ids
# self.with_context(lang=self.env.lang)._message_auto_subscribe_notify(partner_ids, 'soong_workflow.message_soong_workflow_distribute')
# 加签
return self.node_btn_id.with_context(cx).run()
if self.node_btn_name == '退回':
# 当前节点的意见
@@ -21,7 +21,7 @@
<field name="trans_link_id" string="转交节点" invisible="node_btn_name == '退回'"/>
<field name="employee_ids" widget="many2many_tags" string="人员范围"/>
</group>
<group string="流程选择" invisible="node_btn_name != '分发'">
<group invisible="node_btn_name != '分发'">
<field name="comment_note_id" require="1"/>
<field name="employee_ids" widget="many2many_tags" string="董事长"/>
<field name="circulated_employee_ids" widget="many2many_tags"/>