pengyuthon

This commit is contained in:
李鹏宇
2024-09-10 11:51:09 +08:00
parent cab951c626
commit d7699b397a
15 changed files with 179 additions and 286 deletions
-1
View File
@@ -22,7 +22,6 @@
"views/soong_workflow_record.xml",
"views/soong_approval_group.xml",
'wizard/approval_notice_wizard_views.xml',
'wizard/soong_transmitted_wizard_views.xml',
"wizard/soong_workflow_comment_wizard_view.xml",
"templates/soong_workflow_templates.xml",
],
+22 -17
View File
@@ -49,7 +49,8 @@ class SoongWorkflow(models.Model):
link_ids = fields.One2many(comodel_name="soong.workflow.link", inverse_name="workflow_id", string="Links")
remove_default_btn_until_end = fields.Boolean(string="是否覆盖表头按钮状态", default=False)
current_stage_highlight_color = fields.Char(default="rgb(0, 255, 255)",help="The color to highlight the current stage on flow",)
current_stage_highlight_color = fields.Char(default="rgb(0, 255, 255)",
help="The color to highlight the current stage on flow", )
start_time = fields.Datetime(string="生效日期", copy=False, default=fields.Datetime.now)
end_time = fields.Datetime(string="失效日期", copy=False)
is_enable = fields.Boolean(string="是否启用", default="False", compute="compute_is_enable", store=True)
@@ -106,15 +107,18 @@ class SoongWorkflow(models.Model):
@api.depends('start_time', 'end_time')
def compute_is_enable(self):
# 逻辑调整修改时间的时候判断有无要启用的,只准一个不能冲突
for rec in self:
if rec.start_time and rec.end_time:
if rec.start_time < datetime.datetime.now() and rec.end_time > datetime.datetime.now():
rec.is_enable = True
is_enable_ids = self.search([('model_id', '=', self.model_id.id), ('is_enable', '=', True)])
if len(is_enable_ids) <= 1:
for rec in self:
if rec.start_time and rec.end_time:
if rec.start_time < datetime.datetime.now() and rec.end_time > datetime.datetime.now():
rec.is_enable = True
else:
rec.is_enable = False
else:
rec.is_enable = False
else:
rec.is_enable = False
else:
raise UserError('工作流一个模型只能启用一个')
@api.constrains("node_ids")
def validate_nodes(self):
@@ -150,16 +154,17 @@ class SoongWorkflow(models.Model):
if not val["node_ids"]:
val["node_ids"] = [
(0, 0, {
"name": _("开始"),
"sequence": 1,
"node_name": "start",
"flow_start": True,
},),
"name": _("开始"),
"sequence": 1,
"node_name": "start",
"flow_start": True,
"button_ids": ''
},),
(0, 0, {
"name": _("结束"),
"sequence": 99,
"node_name": "end",
"flow_end": True,
"name": _("结束"),
"sequence": 99,
"node_name": "end",
"flow_end": True,
},), ]
return super().create(values)
+23 -71
View File
@@ -112,7 +112,7 @@ class SoongWorkflowMixin(models.AbstractModel):
def _add_comment(self, logs, btn_rec):
wizard = self.env.ref("soong_workflow.view_soong_workflow_comment_wizard")
return {
"name": _("Comment"),
"name": _("评论"),
"type": "ir.actions.act_window",
"view_mode": "form",
"res_model": "soong.workflow.comment.wizard",
@@ -162,6 +162,7 @@ class SoongWorkflowMixin(models.AbstractModel):
cx.update({"active_id": self.id, "active_ids": self.ids})
wkf_btn_obj = self.env["soong.workflow.node.button"]
btn_rec = wkf_btn_obj.search([("btn_key", "=", cx.get("btn_key", False))])
# 优化弹窗
if btn_rec:
log_obj = self._create_update_logs(btn_rec)
if btn_rec.has_comment:
@@ -242,37 +243,9 @@ class SoongWorkflowMixin(models.AbstractModel):
res = self._update_fields_view(view_type, res)
# res = self._add_state_tree_view(view_type, res)
res = self._add_soong_workflow_log(view_type, res, params)
# todo 后许可拓展退回层级
res = self._add_return_button(view_type, res)
# 转交 如果一条链路直接跳转,如果多条链路选择跳转
# res = self._add_transmitted_button(view_type, res)
return res
# 收回逻辑
def _add_return_button(self, view_type, res):
model = self._name
wkf_obj = self.env["soong.workflow"]
wkf_rec = wkf_obj.search([("model_id", "=", model), ('is_enable', '=', True)])
if not wkf_rec.is_enable_return_button:
return res
arch = etree.fromstring(res["arch"])
if view_type == "form":
header_el = arch.xpath("//form/header")
header_el = header_el[0] if header_el else False
if header_el:
button = etree.Element("button", {
"name": "action_return",
"type": "object",
"string": "收回",
"class": "btn-primary", # 按钮的样式
# "icon": "fa-undo", # 按钮图标 (如果需要)
})
header_el.append(button)
res["arch"] = etree.tostring(arch, encoding="unicode").replace("\t", "")
return res
# 收回
def action_return(self):
# 收回目前只支持指定用户和指定角色
for record in self:
@@ -309,56 +282,35 @@ class SoongWorkflowMixin(models.AbstractModel):
# 当前单据状态所在的位置
record_number = key.split('_')[1]
for key, values in result_dict.items():
if self.env.user.id in values:
# 当前用户所在节点
user_number = key.split('_')[1]
user_key = key
if values != [False]:
if self.env.user.id in values:
# 当前用户所在节点
user_number = key.split('_')[1]
user_key = key
else:
raise UserError('请配置节点的人员')
number = int(record_number) - int(user_number)
if number == 1:
self.write({'state': user_key.split('_')[0]})
else:
raise UserError('不可收回')
# for button in header_el.iter("button"):
# btn_invisible = "state != 'end'"
# if "invisible" in button.attrib:
# btn_invisible = btn_invisible + " or " + button.attrib["invisible"]
# button.set("invisible", btn_invisible)
# 转交
def _add_transmitted_button(self, view_type, res):
model = self._name
wkf_obj = self.env["soong.workflow"]
wkf_rec = wkf_obj.search([("model_id", "=", model), ('is_enable', '=', True)])
if not wkf_rec.is_enable_transmitted_button:
return res
arch = etree.fromstring(res["arch"])
if view_type == "form":
header_el = arch.xpath("//form/header")
header_el = header_el[0] if header_el else False
if header_el:
button = etree.Element("button", {
"name": "action_transmitted",
"type": "object",
"string": "转交",
"class": "btn-primary", # 按钮的样式
})
header_el.append(button)
res["arch"] = etree.tostring(arch, encoding="unicode").replace("\t", "")
return res
def action_transmitted(self):
# 当前节点对应的链路
node_ids = self.workflow_id.node_ids.search([('node_name', '=', self.state)])
# 判断链路是一个就跳转
# 是多个就弹窗选择
pass
if len(node_ids.out_link_ids) == 1:
state_next = node_ids.out_link_ids.name.split('-> ')[-1]
self.write({'state': state_next})
# 多个节点弹窗选择并发送消息提醒
elif len(node_ids.out_link_ids) > 1:
state_list = []
for node in node_ids.out_link_ids:
state_list.append(node.name.split('-> ')[-1])
# 传入每个节点的对应人员
else:
raise UserError('节点链路配置错误')
def _remove_default_header(self, view_type, res):
"""
+40 -67
View File
@@ -58,76 +58,49 @@ class SoongWorkflowNode(models.Model):
),
]
sequence = fields.Integer(
string="Sequence", default=10, help="Arrange node by defining sequence."
)
name = fields.Char(
string="Name", translate=True, help="Enter string name of the node."
)
node_name = fields.Char(
string="Technical Name",
help="Generated technical name which used by backend code.",
)
workflow_id = fields.Many2one(
comodel_name="soong.workflow",
string="Workflow Ref.",
ondelete="cascade",
required=True,
)
model_id = fields.Many2one(
"ir.model",
string="Model Ref.",
domain="[('state','=','base')]",
related="workflow_id.model_id",
required=True,
)
flow_start = fields.Boolean(
string="Flow Start", help="Check it if this node is the starting node."
)
flow_end = fields.Boolean(
string="Flow End", help="Check it if this node is the ending node."
)
is_visible = fields.Boolean(
string="Appear in Statusbar",
default=True,
help="Control visiability of the node/state in view.",
)
out_link_ids = fields.One2many(
comodel_name="soong.workflow.link",
inverse_name="node_from",
string="Outgoing Transitions",
)
in_link_ids = fields.One2many(
comodel_name="soong.workflow.link",
inverse_name="node_to",
string="Incoming Transitions",
)
field_ids = fields.One2many(
comodel_name="soong.workflow.node.field",
inverse_name="node_id",
string="Fields",
)
button_ids = fields.One2many(
comodel_name="soong.workflow.node.button",
inverse_name="node_id",
string="Buttons",
)
sequence = fields.Integer(string="Sequence", default=10, help="Arrange node by defining sequence.")
name = fields.Char(string="Name", translate=True, help="Enter string name of the node.")
node_name = fields.Char(string="Technical Name",help="Generated technical name which used by backend code.",)
workflow_id = fields.Many2one(comodel_name="soong.workflow",string="Workflow Ref.",ondelete="cascade",required=True,)
model_id = fields.Many2one("ir.model",string="Model Ref.",domain="[('state','=','base')]",related="workflow_id.model_id",required=True,)
flow_start = fields.Boolean(string="Flow Start", help="Check it if this node is the starting node.")
flow_end = fields.Boolean(string="Flow End", help="Check it if this node is the ending node.")
is_visible = fields.Boolean(string="Appear in Statusbar",default=True,help="Control visiability of the node/state in view.",)
out_link_ids = fields.One2many(comodel_name="soong.workflow.link",inverse_name="node_from",string="Outgoing Transitions",)
in_link_ids = fields.One2many(comodel_name="soong.workflow.link",inverse_name="node_to",string="Incoming Transitions",)
field_ids = fields.One2many(comodel_name="soong.workflow.node.field",inverse_name="node_id",string="Fields",)
button_ids = fields.One2many(comodel_name="soong.workflow.node.button",inverse_name="node_id",string="Buttons",)
diagram_position = fields.Char(readonly=True, string="Diagram Position")
bg_color = fields.Char(default=DEFAULT_BG_COLOR, string="Background Color")
label_color = fields.Char(default=DEFAULT_LABEL_COLOR, string="Label Color")
# Custom colors
use_custom_colors = fields.Boolean(
help="Select colors from the palette manually", string="Use Custom Colors"
)
res_bg_color = fields.Char(
compute="_compute_custom_colors", readonly=True, string="Backgroung Color"
)
res_label_color = fields.Char(
compute="_compute_custom_colors", readonly=True, string="Label Color"
)
use_custom_colors = fields.Boolean(help="Select colors from the palette manually", string="Use Custom Colors")
res_bg_color = fields.Char(compute="_compute_custom_colors", readonly=True, string="Backgroung Color")
res_label_color = fields.Char(compute="_compute_custom_colors", readonly=True, string="Label Color")
@api.model_create_multi
def create(self, values):
for val in values:
if val['node_name'] != 'end':
if not val["button_ids"]:
val["button_ids"] = [
(0, 0, {
"name": _("转交"),
"workflow_id": val['workflow_id'],
"sequence": 1,
"action_type": "code",
"code": "obj.action_transmitted()",
"has_comment": True,
},),
(0, 0, {
"name": _("收回"),
"workflow_id": val['workflow_id'],
"sequence": 2,
"action_type": "code",
"code": "obj.action_return()",
},)
]
return super().create(values)
@api.depends("bg_color", "label_color", "use_custom_colors", "flow_start", "flow_end")
def _compute_custom_colors(self):
@@ -210,7 +183,7 @@ class SoongWorkflowNodeButton(models.Model):
string="Icon",
help="Enter icon name like: fa-print, it's recommended to use FontAwesome Icons.",
)
has_comment = fields.Boolean(string="Comment", default=False)
has_comment = fields.Boolean(string="评论", default=False)
btn_key = fields.Char(string="Button Key", default=_generate_key)
btn_hide = fields.Boolean(
string="Hide Button if Condition isn't fulfilled",
+1 -3
View File
@@ -23,6 +23,4 @@ access_soong_approval_group,soong_approval_group,model_soong_approval_group,soon
access_soong_approval_notice_wizard,soong_approval_notice_wizard,model_soong_approval_notice_wizard,base.group_user,1,1,1,1
access_soong_workflow_log_user,soong_workflow_log_user,model_soong_workflow_log,soong_workflow.group_soong_workflow_user,1,1,1,1
access_soong_workflow_comment_wizard_user,soong_workflow_comment_wizard_user,model_soong_workflow_comment_wizard,soong_workflow.group_soong_workflow_user,1,1,1,1
access_soong_approval_transmitted_wizard,soong_approval_transmitted_wizard,model_soong_approval_transmitted_wizard,soong_workflow.group_soong_workflow_user,1,1,1,1
access_soong_workflow_comment_wizard_user,soong_workflow_comment_wizard_user,model_soong_workflow_comment_wizard,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
23 access_soong_workflow_log_user soong_workflow_log_user model_soong_workflow_log soong_workflow.group_soong_workflow_user 1 1 1 1
24 access_soong_workflow_comment_wizard_user soong_workflow_comment_wizard_user model_soong_workflow_comment_wizard soong_workflow.group_soong_workflow_user 1 1 1 1
25
26
@@ -27,6 +27,7 @@
<field name="current_stage_highlight_color" widget="color"/>
<field name="remove_default_btn_until_end"/>
<field name="is_enable_return_button"/>
<field name="is_enable_transmitted_button"/>
</group>
<group>
<field name="start_time"/>
-1
View File
@@ -3,7 +3,6 @@
from . import approval_notice_wizard
from . import soong_transmitted_wizard
from . import soong_workflow_comment_wizard
@@ -1,18 +0,0 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models, tools, _
from datetime import datetime, date, time, timedelta
from odoo.tools.safe_eval import safe_eval
from odoo.exceptions import ValidationError, UserError
import logging
_logger = logging.getLogger(__name__)
class SoongApprovalTransmittedWizard(models.TransientModel):
_name = 'soong.approval.transmitted.wizard'
_description = """ 转交弹窗 """
name = fields.Char(string='名称')
def confirm(self):
pass
@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="soong_approval_transmitted_wizard_form" model="ir.ui.view">
<field name="name">一键转交</field>
<field name="model">soong.approval.transmitted.wizard</field>
<field name="arch" type="xml">
<form>
<group>
<field name="name"/>
</group>
<!-- 对接消息通知 -->
<footer>
<button name="confirm" string="确认" type="object" class="oe_highlight"/>
<button string="返回" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
</odoo>
@@ -12,13 +12,16 @@ class SoongWorkflowCommentWizard(models.TransientModel):
res_id = fields.Integer()
log_ids = fields.Many2many(comodel_name="soong.workflow.log")
node_btn_id = fields.Many2one(comodel_name="soong.workflow.node.button")
button_type = fields.Selection([('trans', '转交'), ('other', '其他')], string="按钮类型", default='other')
comment_note_id = fields.Many2one('soong.note', required=True, string="意见")
comment_type = fields.Selection(related="comment_note_id.type", string="意见类型")
comment_return_type = fields.Char(related="comment_note_id.return_type", string="退回类型")
state_list = fields.Char(string="状态列表")
employee_ids = fields.Many2many('hr.employee', string="提醒经办人")
notice_message = fields.Char(string="消息通知")
def add_comment(self):
self.ensure_one()
cx = self.env.context.copy() or {}
self.log_ids.write({"comment": self.comment})
return self.node_btn_id.with_context(cx).run()
@@ -4,7 +4,7 @@ from odoo import api, fields, models
class YuthonHrDepartment(models.Model):
_inherit = "hr.department"
_order = 'department_code'
_order = 'department_code asc'
department_phone = fields.Char(string="部门电话")
department_fax = fields.Char(string="部门传真")
@@ -20,7 +20,7 @@ class YuthonHrEmployee(models.Model):
对原模型数据的隐藏,字段的开发和添加
"""
_inherit = "hr.employee"
_order = 'number'
_order = 'number asc'
# odoo里是这样做的,一个用户可以多个公司绑定多个员工,每个员工都有自己的部门和岗位
@@ -28,7 +28,6 @@ class YuthonHrEmployee(models.Model):
user_number = fields.Char(string="员工编号", default=lambda self: self.env['ir.sequence'].next_by_code('employee_code'))
use_user_type = fields.Selection([('formal', '正式职工'), ('labor', '劳务协议'),
('part_time', '兼职协议'), ('employment', '兼职用工')], string="用工形式")
job_lv_id = fields.Many2one('yuthon.job.lv', string="最新职级")
# 个人信息
user_salary = fields.Float(string="基本工资")
+1
View File
@@ -9,6 +9,7 @@
""",
'depends': ['base',
'board',
'spreadsheet_dashboard',
'yuthon_notice',
'soong_workflow',
'yuthon_issue',
+16 -16
View File
@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- 招聘 -->
<record id="hr_recruitment.menu_hr_recruitment_root" model="ir.ui.menu">
<field name="active">False</field>
</record>
<!-- <record id="hr_recruitment.menu_hr_recruitment_root" model="ir.ui.menu">-->
<!-- <field name="active">False</field>-->
<!-- </record>-->
<!-- 人事 -->
<record id="hr.menu_hr_root" model="ir.ui.menu">
<field name="active">False</field>
</record>
<!-- <record id="hr.menu_hr_root" model="ir.ui.menu">-->
<!-- <field name="active">False</field>-->
<!-- </record>-->
<!-- 出勤 -->
<record id="hr_attendance.menu_hr_attendance_root" model="ir.ui.menu">
<field name="active">False</field>
</record>
<!-- <record id="hr_attendance.menu_hr_attendance_root" model="ir.ui.menu">-->
<!-- <field name="active">False</field>-->
<!-- </record>-->
<!-- 绩效 -->
<record id="yuthon_performance.yuthon_performance_menu_config_root" model="ir.ui.menu">
<field name="active">False</field>
</record>
<!-- <record id="yuthon_performance.yuthon_performance_menu_config_root" model="ir.ui.menu">-->
<!-- <field name="active">False</field>-->
<!-- </record>-->
<!-- 人力资源 -->
<menuitem id="human_resources_menu_root_board"
@@ -208,12 +208,12 @@
parent="hr_attendance_root_board"
sequence="7"
action="resource.action_resource_calendar_form"/>
<menuitem id="holiday_manage_menu_root" name="假期管理"
parent="hr_attendance.menu_hr_attendance_root" sequence="9"/>
<menuitem id="holiday_manage_menu_root_board" name="假期管理"
parent="hr_attendance_root_board" sequence="9"/>
<menuitem id="holiday_manage_type_board" name="假期类型"
parent="holiday_manage_menu_root" action="holiday_manage_type_action" sequence="1"/>
parent="holiday_manage_menu_root_board" action="yuthon_hr_attendance.holiday_manage_type_action" sequence="1"/>
<menuitem id="holiday_manage_balance_board" name="假期余额"
parent="holiday_manage_menu_root" action="holiday_balance_action" sequence="4"/>
parent="holiday_manage_menu_root_board" action="yuthon_hr_attendance.holiday_balance_action" sequence="3"/>
<!-- <menuitem id="tianhe_holiday_setting_menu_board"-->
<!-- parent="hr_attendance_root_board"-->
<!-- sequence="9"-->
+69 -69
View File
@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- 工作流 -->
<record id="soong_workflow.menu_soong_workflow_root" model="ir.ui.menu">
<field name="active">False</field>
</record>
<!-- <record id="soong_workflow.menu_soong_workflow_root" model="ir.ui.menu">-->
<!-- <field name="active">False</field>-->
<!-- </record>-->
<!-- 议题 -->
<record id="yuthon_issue.tianhe_issue_library_menu_root" model="ir.ui.menu">
<field name="active">False</field>
</record>
<!-- <record id="yuthon_issue.tianhe_issue_library_menu_root" model="ir.ui.menu">-->
<!-- <field name="active">False</field>-->
<!-- </record>-->
<!-- 通知公告 -->
<record id="yuthon_notice.yuthon_notice_menu_config_root" model="ir.ui.menu">
<field name="active">False</field>
</record>
<!-- <record id="yuthon_notice.yuthon_notice_menu_config_root" model="ir.ui.menu">-->
<!-- <field name="active">False</field>-->
<!-- </record>-->
<!-- 会议室 -->
<record id="room.room_menu_root" model="ir.ui.menu">
<field name="active">False</field>
</record>
<!-- <record id="room.room_menu_root" model="ir.ui.menu">-->
<!-- <field name="active">False</field>-->
<!-- </record>-->
<!-- 网站 -->
<record id="website.menu_website_configuration" model="ir.ui.menu">
<field name="active">False</field>
@@ -91,76 +91,76 @@
sequence="5"/>
<!-- 议题库 -->
<menuitem id="tianhe_issue_library_menu_root_board"
name="议题库"
parent="spreadsheet_dashboard.spreadsheet_dashboard_menu_root"
sequence="7"/>
name="议题库"
parent="spreadsheet_dashboard.spreadsheet_dashboard_menu_root"
sequence="7"/>
<menuitem id="tianhe_issue_library_all_board"
parent="tianhe_issue_library_menu_root_board"
name="全部"
action="yuthon_issue.issue_library_action"
sequence="1"/>
parent="tianhe_issue_library_menu_root_board"
name="全部"
action="yuthon_issue.issue_library_action"
sequence="1"/>
<menuitem id="tianhe_issue_library_menu_root_board_will_board"
parent="tianhe_issue_library_menu_root_board"
name="待上会"
action="yuthon_issue.issue_library_action_will"
sequence="5"/>
parent="tianhe_issue_library_menu_root_board"
name="待上会"
action="yuthon_issue.issue_library_action_will"
sequence="5"/>
<menuitem id="tianhe_issue_library_menu_root_board_on_meet_board"
parent="tianhe_issue_library_menu_root_board"
name="已上会"
action="yuthon_issue.issue_library_action_done"
sequence="10"/>
parent="tianhe_issue_library_menu_root_board"
name="已上会"
action="yuthon_issue.issue_library_action_done"
sequence="10"/>
<menuitem id="tianhe_other_issue_library_menu_board"
parent="tianhe_issue_library_menu_root_board"
name="子部门议题库"
sequence="3"/>
parent="tianhe_issue_library_menu_root_board"
name="子部门议题库"
sequence="3"/>
<menuitem id="tianhe_issue_library_all2_board"
parent="tianhe_other_issue_library_menu_board"
name="全部"
action="yuthon_issue.issue_library_action2"
sequence="1"/>
parent="tianhe_other_issue_library_menu_board"
name="全部"
action="yuthon_issue.issue_library_action2"
sequence="1"/>
<menuitem id="other_issue_library_menu_will_board"
parent="tianhe_other_issue_library_menu_board"
name="待上会"
action="yuthon_issue.issue_library_action_will2"
sequence="3"/>
parent="tianhe_other_issue_library_menu_board"
name="待上会"
action="yuthon_issue.issue_library_action_will2"
sequence="3"/>
<menuitem id="other_issue_library_menu_on_meet_board"
parent="tianhe_other_issue_library_menu_board"
name="已上会"
action="yuthon_issue.issue_library_action_done2"
sequence="5"/>
parent="tianhe_other_issue_library_menu_board"
name="已上会"
action="yuthon_issue.issue_library_action_done2"
sequence="5"/>
<menuitem id="issue_approval_menu_board"
parent="tianhe_issue_library_menu_root_board"
name="议题审批"
action="yuthon_issue.issue_library_action"
sequence="9"/>
parent="tianhe_issue_library_menu_root_board"
name="议题审批"
action="yuthon_issue.issue_library_action"
sequence="9"/>
<menuitem id="issue_approval_party_menu_board"
parent="issue_approval_menu_board"
name="党总支议题审批"
action="yuthon_issue.issue_approval_party_action"
sequence="1"/>
parent="issue_approval_menu_board"
name="党总支议题审批"
action="yuthon_issue.issue_approval_party_action"
sequence="1"/>
<menuitem id="issue_approval_class_menu_board"
parent="issue_approval_menu_board"
name="领导班子议题审批"
action="yuthon_issue.issue_approval_class_action"
sequence="3"/>
parent="issue_approval_menu_board"
name="领导班子议题审批"
action="yuthon_issue.issue_approval_class_action"
sequence="3"/>
<menuitem id="issue_approval_boss_menu_board"
parent="issue_approval_menu_board"
name="董事会议题审批"
action="yuthon_issue.issue_approval_boss_action"
sequence="5"/>
parent="issue_approval_menu_board"
name="董事会议题审批"
action="yuthon_issue.issue_approval_boss_action"
sequence="5"/>
<!-- 会议室 -->
<menuitem id="room_menu_root_board"
name="会议室"
parent="spreadsheet_dashboard.spreadsheet_dashboard_menu_root"
sequence="9"/>
name="会议室"
parent="spreadsheet_dashboard.spreadsheet_dashboard_menu_root"
sequence="9"/>
<menuitem id="room_booking_menu_board"
name="预定"
action="room.room_booking_action"
parent="room_menu_root_board"
sequence="1"/>
name="预定"
action="room.room_booking_action"
parent="room_menu_root_board"
sequence="1"/>
<menuitem id="room_room_menu_board"
name="房间"
action="room.room_room_action"
parent="room_menu_root_board"
sequence="2"/>
name="房间"
action="room.room_room_action"
parent="room_menu_root_board"
sequence="2"/>
</odoo>