收发文

This commit is contained in:
李鹏宇
2024-08-02 17:47:33 +08:00
parent a5d7c5978b
commit 78cde9a8b4
37 changed files with 587 additions and 264 deletions
+1
View File
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from . import models
from . import wizard
+2 -1
View File
@@ -17,7 +17,8 @@
"views/soong_workflow_node_views.xml",
"views/soong_workflow_link_views.xml",
"views/soong_workflow_views.xml",
'views/soong_workflow_record.xml'
'views/soong_workflow_record.xml',
'wizard/approval_notice_wizard_views.xml'
],
"installable": True,
"auto_install": False,
@@ -26,7 +26,7 @@ class SoongApprovalUsers(models.Model):
approval_user = fields.Many2one('soong.user.role', string='审批角色')
approval_user_datetime = fields.Datetime(string='审批时间')
approval_user_notice = fields.Char(string='审批意见')
approval_user_sign = fields.Char(string='审批签署')
approval_user_sign = fields.Binary(string='审批签署')
approval_user_state = fields.Selection([('will', '待审批')], string='状态')
@api.model_create_multi
+12 -12
View File
@@ -148,18 +148,18 @@ class SoongWorkflowMixin(models.AbstractModel):
@api.model
def get_view(self, view_id=None, view_type="form", **options):
res = super().get_view(view_id, view_type, **options)
if view_type in ["tree", "form"]:
if "field" in res["arch"]:
# res = self._remove_default_header(view_type, res)
res = self._remove_default_modifiers(view_type, res)
res = self._load_buttons_view(view_type, res)
res = self._load_button_box_view(view_type, res)
res = self._load_state_view(view_type, res)
res = self._load_one2many_views(view_type, res)
res = self._update_fields_view(view_type, res)
# 列表视图增加状态字段
# res = self._add_state_tree_view(view_type, res)
if 'create="false"' not in res['arch']: # 针对一个模型多个form临时做的区分
if view_type in ["tree", "form"]:
if "field" in res["arch"]:
# res = self._remove_default_header(view_type, res)
res = self._remove_default_modifiers(view_type, res)
res = self._load_buttons_view(view_type, res)
res = self._load_button_box_view(view_type, res)
res = self._load_state_view(view_type, res)
res = self._load_one2many_views(view_type, res)
res = self._update_fields_view(view_type, res)
# 列表视图增加状态字段
# res = self._add_state_tree_view(view_type, res)
return res
def _remove_default_header(self, view_type, res):
+3 -1
View File
@@ -17,4 +17,6 @@ access_soong_workflow_link_manager,soong_workflow_link_manager,model_soong_workf
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_user_role,soong_user_role,model_soong_user_role,soong_workflow.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
access_soong_note,soong_note,model_soong_note,soong_workflow.group_soong_workflow_user,1,1,1,1
access_soong_approval_notice_wizard,soong_approval_notice_wizard,model_soong_approval_notice_wizard,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
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_user_role soong_user_role model_soong_user_role soong_workflow.group_soong_workflow_user 1 1 1 1
19 access_soong_approval_users soong_approval_users model_soong_approval_users soong_workflow.group_soong_workflow_user 1 1 1 1
20 access_soong_note soong_note model_soong_note soong_workflow.group_soong_workflow_user 1 1 1 1
21 access_soong_approval_notice_wizard soong_approval_notice_wizard model_soong_approval_notice_wizard base.group_user 1 1 1 1
22
@@ -13,7 +13,7 @@
<field name="approval_user"/>
<field name="approval_user_datetime"/>
<field name="approval_user_notice"/>
<field name="approval_user_sign"/>
<field name="approval_user_sign" widget="image" options='{"size": [80, 40]}'/>
</tree>
</field>
</record>
+5
View File
@@ -0,0 +1,5 @@
#
from . import approval_notice_wizard
@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models, tools, _
class SoongApprovalNoticeWizard(models.TransientModel):
_name = 'soong.approval.notice.wizard'
_description = """ 审批意见弹窗 """
# approval_res_id = fields.Char(string="审批明细行")
# approval_res_model = fields.Char(string="审批明细行")
approval_user_notice = fields.Char(string='审批意见')
approval_user_sign = fields.Binary(string="审批签署", copy=False)
def confirm(self):
self.ensure_one()
active_model = self.env.context.get("active_model")
active_id = self.env.context.get("active_id")
self.env["soong.approval.users"].create({
'res_model_id': self.env['ir.model']._get(active_model).id,
'res_id': active_id,
'approval_user_notice': self.approval_user_notice,
'approval_user_id': self.env.user.id,
'approval_user_datetime': fields.datetime.now(),
'approval_user_sign': self.approval_user_sign,
})
@@ -0,0 +1,34 @@
<odoo>
<record id="soong_approval_notice_wizard_form" model="ir.ui.view">
<field name="name">审批意见弹窗</field>
<field name="model">soong.approval.notice.wizard</field>
<field name="arch" type="xml">
<form>
<!-- <field name="approval_res_id" invisible="1"/>-->
<!-- <field name="approval_res_model" invisible="1"/>-->
<group>
<field name="approval_user_notice"/>
</group>
<group>
<field name="approval_user_sign" widget="signature" options="{'size': ['',200]}"/>
</group>
<footer>
<button name="confirm" string="确认" type="object" class="oe_highlight"/>
<button string="返回" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="soong_approval_notice_wizard_action" model="ir.actions.act_window">
<field name="name">审批意见弹窗</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">soong.approval.notice.wizard</field>
<!-- <field name="context">{-->
<!-- 'default_approval_res_id': active_id,-->
<!-- 'default_approval_res_model': active_model,-->
<!-- }-->
<!-- </field>-->
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</odoo>
+19
View File
@@ -0,0 +1,19 @@
{
'name': 'TinyMCE Editor',
'summary': 'TinyMCE Editor for Html Field',
'author': 'Hoang Minh Hieu',
'version': '17.0.1.0.0',
'license': 'OPL-1',
'support ': 'hieuhoangminh1996@gmail.com',
'depends': ['web'],
'assets': {
'web.assets_backend': [
'web_editor_tinymce/static/src/field_tinymce/field_tinymce.scss',
'web_editor_tinymce/static/src/field_tinymce/field_tinymce.xml',
'web_editor_tinymce/static/src/field_tinymce/field_tinymce.js',
],
},
'images': ['static/description/main_screenshot.png'],
'price': 35,
'currency': 'USD',
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>This module replaces Odoo html editor with TinyMCE editor.</title>
</head>
<body>
<section class="mb64">
<h2 class="text-info">
This module replaces Odoo html editor with TinyMCE editor.
</h2>
</section>
<section class="mb64">
<h3>Screenshot</h3>
<img src="main_screenshot.png" class="w-75">
<h3>Usage</h3>
<img src="usage.png" class="w-50">
</section>
<section class="mb64">
<h2 class="">
Contact me
</h2>
<p>
Skype: <a href="skype:live:hieuhoangminh1996">live:hieuhoangminh1996</a>
<br>
Email: <a href="mailto:hieuhoangminh1996@gmail.com">hieuhoangminh1996@gmail.com</a>
<br>
<br>
Email subject should begin with
<span class="text-info font-weight-bold">[Odoo Module]</span>
</p>
</section>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

@@ -0,0 +1,130 @@
/** @odoo-module **/
import {_t} from '@web/core/l10n/translation';
import {Component, onWillStart, onMounted, onPatched, onWillUnmount, useEffect} from '@odoo/owl';
import {standardFieldProps} from '@web/views/fields/standard_field_props';
import {registry} from '@web/core/registry';
import {TranslationButton} from '@web/views/fields/translation_button';
import {loadJS} from '@web/core/assets';
import {cookie} from '@web/core/browser/cookie';
export class FieldTinyMCE extends Component {
static template = 'web_editor_tinymce.TinyMCE';
static components = {
TranslationButton,
};
static props = {
...standardFieldProps,
placeholder: {type: String, optional: true},
dynamicPlaceholder: {type: Boolean, optional: true},
dynamicPlaceholderModelReferenceField: {type: String, optional: true},
};
static defaultProps = {
dynamicPlaceholder: false,
};
setup() {
super.setup();
this.editorId = `tinymce_${this.props.name}`
const useDarkMode = this.theme === 'dark';
this.defaultTinymceConfig = {
selector: `#${this.editorId}`,
plugins: 'autoresize preview importcss searchreplace autolink directionality code visualblocks visualchars fullscreen image link media codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists wordcount help charmap quickbars emoticons accordion',
editimage_cors_hosts: ['picsum.photos'],
image_advtab: true,
importcss_append: true,
height: 'auto',
image_caption: true,
quickbars_selection_toolbar: 'bold italic | quicklink h2 h3 blockquote quickimage quicktable',
noneditable_class: 'mceNonEditable',
toolbar_mode: 'sliding',
contextmenu: 'link image table',
skin: useDarkMode ? 'oxide-dark' : 'oxide',
content_css: useDarkMode ? 'dark' : 'default',
content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }',
placeholder: this.props.placeholder,
}
onWillStart(async () => {
await loadJS('web_editor_tinymce/static/lib/tinymce/tinymce.min.js');
});
onMounted(async () => {
await this.initEditor();
})
useEffect(() => {
this.updateEditor();
})
onWillUnmount(async () => {
this.removeEditor()
})
}
get value() {
return this.props.record.data[this.props.name] || '';
}
get theme() {
return cookie.get('color_scheme');
}
get isTranslatable() {
return this.props.record.fields[this.props.name].translate;
}
get tinymceConfig() {
return {
...this.defaultTinymceConfig,
menubar: !this.props.readonly && 'file edit view insert format tools table help',
toolbar: !this.props.readonly && 'undo redo | accordion accordionremove | blocks fontfamily fontsize | bold italic underline strikethrough | align numlist bullist | link image | table media | lineheight outdent indent| forecolor backcolor removeformat | charmap emoticons | code fullscreen preview | save print | pagebreak anchor codesample | ltr rtl',
readonly: this.props.readonly,
setup: this.setupEditor.bind(this),
init_instance_callback: this.initCallback.bind(this),
}
}
setupEditor(editor) {
editor.on('change', e => {
const value = tinymce.activeEditor.getContent();
if (value !== this.value) {
this.props.record.update({[this.props.name]: value})
}
});
}
removeEditor() {
if (this.editor) {
this.editor.remove()
}
}
async initEditor() {
this.removeEditor()
const config = this.tinymceConfig;
this.editor = (await tinymce.init(config))[0];
}
initCallback(editor) {
editor.setContent(this.value);
}
updateEditor() {
if (!this.editor || this.props.record.dirty) {
return
}
this.editor.setContent(this.value);
}
}
export const fieldTinyMCE = {
component: FieldTinyMCE,
displayName: _t('TinyMCE'),
supportedTypes: ['html', 'text'],
extractProps: ({attrs, options}) => ({
placeholder: attrs.placeholder,
dynamicPlaceholder: options?.dynamic_placeholder || false,
dynamicPlaceholderModelReferenceField:
options?.dynamic_placeholder_model_reference_field || '',
}),
}
registry.category('fields').add('tinymce', fieldTinyMCE);
@@ -0,0 +1,3 @@
.o_field_tinymce {
width: 100%;
}
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<template xml:space="preserve">
<t t-name="web_editor_tinymce.TinyMCE" owl="1">
<div class="tinymce_editor_container w-100 position-relative"
t-att-class="{'o_field_translate': isTranslatable}"
>
<textarea t-att-id="editorId" t-ref="input"/>
<span t-if="isTranslatable and !props.readonly"
class="position-absolute top-0 end-0 p-2"
style="z-index: 2;"
>
<TranslationButton
fieldName="props.name"
record="props.record"
/>
</span>
</div>
</t>
</template>
+18 -32
View File
@@ -21,18 +21,19 @@ class YuthonNotice(models.Model):
start_date = fields.Date(string="生效日期")
end_date = fields.Date(string="终止日期")
sequence = fields.Integer(string="顺序", default=1)
statu = fields.Selection([('new', '草稿'), ('approval', '审批中'), ('no', '未发布'), ('done', '已发布')], default='new', string="公告状态")
# pub_range = fields.Char(string="发布范围")
statu = fields.Selection(
[('new', '草稿'), ('approval', '审批中'), ('no', '未发布'), ('done', '已发布'), ('stop', '已终止')],
default='new', string="公告状态")
notice_documents_ids = fields.Many2many('documents.document', string="通知公告文件")
# is_confirm = fields.Boolean(string="是否需要人员确认")
is_notice_roger = fields.Boolean(string="已读")
is_notice_roger = fields.Selection([('yes', '已读'), ('no', '未读')], default='no', string="确认状态")
notice_text = fields.Html(string="正文")
@api.onchange('is_notice_roger')
def onchange_is_notice_roger(self):
roger_id = self.env['yuthon.confirm.users'].search([('notice_id', '=', self.id), ('user_id', '=', self.env.user.id)])
roger_id = self.env['yuthon.confirm.users'].search(
[('notice_id', '=', self.id), ('user_id', '=', self.env.user.id)])
if not roger_id:
self.is_notice_roger = False
self.is_notice_roger = 'yes'
def on_sequence(self):
self.sequence = 1
@@ -40,28 +41,6 @@ class YuthonNotice(models.Model):
def no_sequence(self):
self.sequence = 0
# @api.onchange('department_ids', 'employee_ids')
# def onchange_pub_range(self):
# for pub in self:
# data_str = ''
# de_str = [de.name for de in pub.department_ids] if pub.department_ids else data_str
# if len(de_str) == 1:
# de_str = de_str[0]
# else:
# de_str = ','.join(de_str)
# em_str = [em.name for em in pub.employee_ids] if pub.employee_ids else data_str
# if len(em_str) == 1:
# em_str = em_str[0]
# else:
# em_str = ','.join(em_str)
# if de_str and em_str:
# pub.pub_range = '部门:' + de_str + ' 人员:' + em_str
# elif de_str and not em_str:
# pub.pub_range = '部门:' + de_str
# elif em_str and not de_str:
# pub.pub_range = '人员:' + em_str
# else:
# pub.pub_range = data_str
def notice_publish(self):
users_role_list = department_users_list = []
for depart in self.department_ids:
@@ -82,13 +61,14 @@ class YuthonNotice(models.Model):
'state': 'yes',
})
# todo 普通用户权限是否打开,可能需要配置权限
partner_ids = self.sudo().env['res.users'].search([('id', 'in', publish_user_list)]).mapped('partner_id').ids
self.sudo().with_context(lang=self.env.lang)._message_auto_subscribe_notify(partner_ids, 'yuthon_notice.message_yuthon_confirm_users_data')
partner_ids = self.sudo().env['res.users'].search([('id', 'in', publish_user_list)]).mapped(
'partner_id').ids
self.sudo().with_context(lang=self.env.lang)._message_auto_subscribe_notify(partner_ids,
'yuthon_notice.message_yuthon_confirm_users_data')
self.write({"statu": 'done'})
def confirm_notice(self):
self.write({'is_notice_roger': True})
# 用write
self.write({'is_notice_roger': 'yes'})
def look_up_notice_users(self):
return {
@@ -101,3 +81,9 @@ class YuthonNotice(models.Model):
"search_default_group_state": True,
},
}
def stop_notice(self):
self.write({
'statu': 'stop',
'end_date': fields.Datetime.now(),
})
+5
View File
@@ -21,6 +21,11 @@
</storng>
</h2>
</div>
<table width="100%" style="table-layout:fixed;">
<tr colspan="7" rowspan="2">
<t t-esc="doc.notice_text"/>
</tr>
</table>
</t>
</template>
</odoo>
+91 -6
View File
@@ -10,7 +10,6 @@
<field name="department_ids" optional="hidden"/>
<field name="employee_ids" optional="hidden"/>
<field name="users_role_ids" optional="hidden"/>
<!-- <field name="pub_range"/>-->
<field name="notice_type_id"/>
<field name="create_date"/>
<field name="start_date"/>
@@ -18,6 +17,7 @@
<field name="statu"/>
<button name="on_sequence" string="置顶" invisible="sequence != 0" type="object" class="btn-primary"/>
<button name="no_sequence" string="取消置顶" invisible="sequence != 1" type="object" class="btn-primary"/>
<button name="stop_notice" string="终止" type="object" class="btn-primary"/>
<field name="sequence" column_invisible="1"/>
</tree>
</field>
@@ -32,8 +32,6 @@
<button name="look_up_notice_users" string="查看确认信息" invisible="statu != 'done'" type="object" class="btn-primary"/>
<button name="confirm_notice" string="确认收到" invisible="statu != 'done'" type="object" class="btn-primary"/>
<button name="notice_publish" string="发布" invisible="statu != 'no'" type="object" class="btn-primary"/>
<!-- <button name="on_sequence" string="置顶" invisible="sequence != 0" type="object" class="btn-primary"/>-->
<!-- <button name="no_sequence" string="取消置顶" invisible="sequence != 1" type="object" class="btn-primary"/>-->
<field name="statu" widget="statusbar"/>
</header>
<sheet>
@@ -50,9 +48,7 @@
<field name="department_ids" widget="many2many_tags"/>
<field name="employee_ids" widget="many2many_tags"/>
<field name="users_role_ids" widget="many2many_tags"/>
<!-- <field name="pub_range" invisible="1"/>-->
<field name="notice_type_id"/>
<!-- <field name="is_confirm"/>-->
<field name="is_notice_roger"/>
</group>
<group>
@@ -67,7 +63,7 @@
</group>
</group>
<group>
<field name="notice_text"/>
<field name="notice_text" widget="tinymce"/>
<field name="sequence" invisible="1"/>
</group>
</sheet>
@@ -107,12 +103,101 @@
<field name="search_view_id" ref="view_yuthon_notice_filter"/>
</record>
<record id="view_yuthon_notice_tree2" model="ir.ui.view">
<field name="name">yuthon.notice.tree</field>
<field name="model">yuthon.notice</field>
<field name="arch" type="xml">
<tree string="公告管理">
<field name="name"/>
<field name="user_id"/>
<field name="department_ids" optional="hidden"/>
<field name="employee_ids" optional="hidden"/>
<field name="users_role_ids" optional="hidden"/>
<field name="notice_type_id"/>
<field name="create_date"/>
<field name="start_date"/>
<field name="end_date"/>
<field name="statu"/>
<field name="is_notice_roger"/>
</tree>
</field>
</record>
<record id="view_yuthon_notice_form2" model="ir.ui.view">
<field name="name">yuthon.notice.form2</field>
<field name="model">yuthon.notice</field>
<field name="arch" type="xml">
<form create="false" edit="false" string="公告管理">
<div class="col-12 text-center">
<h1>
<field name="name" required="1"/>
</h1>
</div>
<group>
<group>
<field name="code"/>
<field name="user_id"/>
<field name="department_ids" widget="many2many_tags"/>
<field name="employee_ids" widget="many2many_tags"/>
<field name="users_role_ids" widget="many2many_tags"/>
<field name="notice_type_id"/>
<field name="is_notice_roger"/>
</group>
<group>
<field name="create_date"/>
<field name="start_date"/>
<field name="end_date"/>
<field name="notice_documents_ids">
<tree>
<field name="name"/>
</tree>
</field>
</group>
</group>
<group>
<field name="notice_text" widget="html"/>
<field name="sequence" invisible="1"/>
</group>
</form>
</field>
</record>
<record id="view_yuthon_notice_filter2" model="ir.ui.view">
<field name="name">yuthon.notice.search</field>
<field name="model">yuthon.notice</field>
<field name="arch" type="xml">
<search string="公告查询">
<group expand="0">
<filter name="group_by_is_notice_roger" string="已读" context="{'group_by': 'is_notice_roger'}"/>
</group>
</search>
</field>
</record>
<record id="approval_notice_action2" model="ir.actions.act_window">
<field name="name">我的通知公告</field>
<field name="res_model">yuthon.notice</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="view_yuthon_notice_filter2"/>
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'tree', 'view_id': ref('yuthon_notice.view_yuthon_notice_tree2')}),
(0, 0, {'view_mode': 'form', 'view_id': ref('yuthon_notice.view_yuthon_notice_form2')})]"/>
<field name="context">{'search_default_group_by_is_notice_roger': True,}</field>
</record>
<menuitem
id="yuthon_notice_menu_config_root"
name="通知公告"
web_icon="yuthon_notice,static/description/icon.png"
sequence="1"/>
<menuitem
id="yuthon_notice_my_menu"
parent="yuthon_notice_menu_config_root"
name="我的通知公告"
action="approval_notice_action2"
sequence="2"/>
<menuitem
id="yuthon_notice_menu"
parent="yuthon_notice_menu_config_root"
+12 -8
View File
@@ -10,21 +10,25 @@
'category': 'Human Resources/Attendances',
'version': '0.1',
'license': 'LGPL-3',
'depends': ['mail','hr'],
'depends': ['mail', 'hr', 'soong_workflow'],
'data': [
'data/official_type_data.xml',
'security/ir.model.access.csv',
'views/yuthon_official_views.xml',
'views/official_partner_views.xml',
'views/official_type_views.xml',
'views/yuthon_official_labor_views.xml',
'views/yuthon_official_party_views.xml',
'views/yuthon_official_normal_views.xml',
'views/yuthon_official_incoming_party_views.xml',
'views/yuthon_official_incoming_labor_views.xml',
'views/yuthon_official_views.xml',
'views/yuthon_official_incoming_normal_views.xml',
'views/yuthon_official_labor_views.xml',
'views/yuthon_official_incoming_labor_views.xml',
'views/yuthon_official_party_views.xml',
'views/yuthon_official_incoming_party_views.xml',
'views/official_menus.xml',
],
'installable': True,
'application': True,
}
+26 -4
View File
@@ -14,11 +14,13 @@
</record>
<record id="official_type_2" model="official.type">
<field name="name">决定</field>
<field name="note">适用于对重要事项作出决策和部署、奖惩有关单位和人员、变更或者撤销下级机关不适当的决定事项</field>
<field name="note">适用于对重要事项作出决策和部署、奖惩有关单位和人员、变更或者撤销下级机关不适当的决定事项
</field>
</record>
<record id="official_type_3" model="official.type">
<field name="name">命令(令)</field>
<field name="note">适用于公布行政法规和规章、宣布施行重大强制性措施、批准授予和晋升衔级、嘉奖有关单位和人员。</field>
<field name="note">适用于公布行政法规和规章、宣布施行重大强制性措施、批准授予和晋升衔级、嘉奖有关单位和人员。
</field>
</record>
<record id="official_type_4" model="official.type">
<field name="name">公报</field>
@@ -58,7 +60,8 @@
</record>
<record id="official_type_13" model="official.type">
<field name="name">议案</field>
<field name="note">适用于各级人民政府按照法律程序向同级人民代表大会或者人民代表大会常务委员会提请审议事项</field>
<field name="note">适用于各级人民政府按照法律程序向同级人民代表大会或者人民代表大会常务委员会提请审议事项
</field>
</record>
<record id="official_type_14" model="official.type">
<field name="name">函</field>
@@ -70,7 +73,26 @@
</record>
<record id="official_type_16" model="official.type">
<field name="name">公示</field>
<field name="note">党政机关、企事业单位、社会团体等事先预告群众周知,用以征询意见、改善工作的一种应用文文体</field>
<field name="note">党政机关、企事业单位、社会团体等事先预告群众周知,用以征询意见、改善工作的一种应用文文体
</field>
</record>
<template id="message_yuthon_official_confirm_users_data">
<p style="margin: 0px;">
<span>尊敬的用户,</span>
<br/>
<span style="margin-top: 8px;">您有一条新的收文
<t t-esc="object.name"/>
请登录系统查看详情。
</span>
</p>
<p style="margin-top: 24px; margin-bottom: 16px;">
<a t-att-href="access_link" t-att-data-oe-model="object._name" t-att-data-oe-id="object.id"
style="background-color:#2C65F7; padding: 10px; text-decoration: none; color: #fff; border-radius: 5px;">
查看
<t t-esc="model_description or 'document'"/>
</a>
</p>
</template>
</data>
</odoo>
-1
View File
@@ -5,7 +5,6 @@ from . import official_partner
from . import officical_type
from . import yuthon_official_labor
from . import yuthon_official_party
from . import yuthon_official_normal
from . import yuthon_offficial_incoming_party
from . import yuthon_official_incoming_labor
from . import yuthon_official_incoming_normal
+22 -2
View File
@@ -6,7 +6,7 @@ from odoo.exceptions import ValidationError, UserError
class YuthonOfficial(models.Model):
_name = 'yuthon.official'
_description = '收发文管理'
_inherit = ['mail.thread.main.attachment', 'mail.activity.mixin']
_inherit = ['mail.thread.main.attachment', 'mail.activity.mixin', 'soong.workflow.mixin']
_rec_name = 'name'
name = fields.Char(string="名称")
@@ -23,11 +23,31 @@ class YuthonOfficial(models.Model):
incoming_file_id = fields.Char(string="收文编号")
main_flats = fields.Char(string="主送")
copy_flats = fields.Char(string="抄送")
department_ids = fields.Many2many('hr.department', string='部门范围')
employee_ids = fields.Many2many('hr.employee', string='人员范围')
users_role_ids = fields.Many2many('soong.user.role', string='角色范围')
servings_number = fields.Integer(string="份数")
urgency = fields.Selection([('normal', '一般'), ('urgent', '紧急'), ('extra_urgent', '特急')], string="紧急程度")
secret_level = fields.Selection([('normal', '一般'), ('urgent', '秘密'), ('secret', '机密'), ('so_secret', '绝密')], string="密级")
date = fields.Datetime(string="日期", default=fields.Datetime.now)
department_id = fields.Many2one('hr.department', string="申请人部门")
statu = fields.Selection([('drft', '草稿'), ('going', '执行中'), ('cancel', '已取消'), ('done', '已完成')], string="状态", default='drft')
statu = fields.Selection([('drft', '草稿'), ('going', '审批中'), ('cancel', '已取消'), ('no', '未发布'), ('done', '已发布')], string="状态", default='drft')
deadline = fields.Date(string="办理期限")
red_suit = fields.Char(string="套红")
def cancel_official(self):
self.write({'statu': '已取消'})
def done_publish(self):
users_role_list = department_users_list = []
for depart in self.department_ids:
department_users_data = self.env['hr.employee'].search([('department_id', '=', depart.id)])
department_users_list = [de.id for de in department_users_data]
employee_users_list = [em.user_id.id for em in self.employee_ids]
for user_id in self.users_role_ids:
department_users_data = self.env['soong.user.role'].search([('user_role_id', '=', user_id.id)])
users_role_list = [ro.id for ro in department_users_data]
publish_user_list = list(set(department_users_list + employee_users_list + users_role_list))
partner_ids = self.sudo().env['res.users'].search([('id', 'in', publish_user_list)]).mapped('partner_id').ids
self.sudo().with_context(lang=self.env.lang)._message_auto_subscribe_notify(partner_ids, 'yuthon_official.message_yuthon_official_confirm_users_data')
self.write({"statu": 'done'})
@@ -12,7 +12,6 @@ class YuthonOfficialIncomingNormal(models.Model):
name = fields.Char(string="名称")
code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('official_code'))
official_type_id = fields.Many2one('official.type', string="公文种类")
# official_type = fields.Selection([('go', '发文'), ('come', '收文')], string="公文类型")
reference_cold = fields.Integer(string="公文字号")
major_event_category = fields.Integer(string="重大事项所属类别")
official_partner_id = fields.Many2one('official.partner', string="来文单位")
@@ -1,31 +0,0 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models, tools
from odoo.exceptions import ValidationError, UserError
class YuthonOfficialNormal(models.Model):
_name = 'yuthon.official.normal'
_description = '行政发文'
_inherit = ['mail.thread.main.attachment', 'mail.activity.mixin']
_rec_name = 'name'
name = fields.Char(string="名称")
code = fields.Char(string="编号", default=lambda self: self.env['ir.sequence'].next_by_code('official_code'))
official_type_id = fields.Many2one('official.type', string="公文种类")
# official_type = fields.Selection([('go', '发文'), ('come', '收文')], string="公文类型")
reference_cold = fields.Integer(string="公文字号")
major_event_category = fields.Integer(string="重大事项所属类别")
remarks = fields.Char(string="备注事项")
main_text = fields.Html(string='正文')
main_flats = fields.Char(string="主送")
copy_flats = fields.Char(string="抄送")
servings_number = fields.Integer(string="份数")
urgency = fields.Selection([('normal', '一般'), ('urgent', '紧急'), ('extra_urgent', '特急')], string="紧急程度")
secret_level = fields.Selection([('normal', '一般'), ('urgent', '秘密'), ('secret', '机密'), ('so_secret', '绝密')],
string="密级")
date = fields.Datetime(string="日期", default=fields.Datetime.now)
department_id = fields.Many2one('hr.department', string="申请人部门")
statu = fields.Selection([('drft', '草稿'), ('going', '执行中'), ('cancel', '已取消'), ('done', '已完成')],
string="状态", default='drft')
deadline = fields.Date(string="办理期限")
red_suit = fields.Char(string="套红")
@@ -4,7 +4,6 @@ access_official_partner,official_partner,model_official_partner,base.group_user,
access_official_type,official_type,model_official_type,base.group_user,1,1,1,1
access_yuthon_official_labor,yuthon_official_labor,model_yuthon_official_labor,base.group_user,1,1,1,1
access_yuthon_official_party,yuthon_official_party,model_yuthon_official_party,base.group_user,1,1,1,1
access_yuthon_official_normal,yuthon_official_normal,model_yuthon_official_normal,base.group_user,1,1,1,1
access_yuthon_official_incoming_party,yuthon_official_incoming_party,model_yuthon_official_incoming_party,base.group_user,1,1,1,1
access_yuthon_official_incoming_labor,yuthon_official_incoming_labor,model_yuthon_official_incoming_labor,base.group_user,1,1,1,1
access_yuthon_official_incoming_normal,yuthon_official_incoming_normal,model_yuthon_official_incoming_normal,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
4 access_official_type official_type model_official_type base.group_user 1 1 1 1
5 access_yuthon_official_labor yuthon_official_labor model_yuthon_official_labor base.group_user 1 1 1 1
6 access_yuthon_official_party yuthon_official_party model_yuthon_official_party base.group_user 1 1 1 1
access_yuthon_official_normal yuthon_official_normal model_yuthon_official_normal base.group_user 1 1 1 1
7 access_yuthon_official_incoming_party yuthon_official_incoming_party model_yuthon_official_incoming_party base.group_user 1 1 1 1
8 access_yuthon_official_incoming_labor yuthon_official_incoming_labor model_yuthon_official_incoming_labor base.group_user 1 1 1 1
9 access_yuthon_official_incoming_normal yuthon_official_incoming_normal model_yuthon_official_incoming_normal base.group_user 1 1 1 1
+105
View File
@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<menuitem
id="official_management_menu_root"
name="公文管理"
web_icon="yuthon_official,static/description/icon.png"
action="send_receive_messages_management_action"/>
<menuitem
id="yuthon_official_my_menu"
parent="official_management_menu_root"
name="我的公文"
sequence="2"/>
<menuitem
id="yuthon_official_my_admin"
parent="yuthon_official_my_menu"
name="行政收文"
action="yuthon_official_incoming_labor_action"
sequence="5"/>
<menuitem
id="yuthon_official_my_labor"
parent="yuthon_official_my_menu"
name="工会收文"
action="yuthon_official_incoming_labor_action"
sequence="6"/>
<menuitem
id="yuthon_official_my_party"
parent="yuthon_official_my_menu"
name="党总支收文"
action="yuthon_official_incoming_labor_action"
sequence="7"/>
<menuitem
id="yuthon_official_normal_management_menu"
parent="official_management_menu_root"
name="行政公文管理"
sequence="5"/>
<menuitem
id="yuthon_official_normal"
parent="yuthon_official_normal_management_menu"
name="行政发文"
action="send_receive_messages_management_action"
sequence="8"/>
<menuitem
id="yuthon_official_incoming_normal"
parent="yuthon_official_normal_management_menu"
name="行政收文"
action="yuthon_official_incoming_normal_action"
sequence="10"/>
<menuitem
id="yuthon_official_party_management_menu"
parent="official_management_menu_root"
name="党总支公文管理"
sequence="7"/>
<menuitem
id="yuthon_official_incoming_party"
parent="yuthon_official_party_management_menu"
name="党总支收文"
action="yuthon_official_incoming_party_action"
sequence="10"/>
<menuitem
id="yuthon_official_party"
parent="yuthon_official_party_management_menu"
name="党总支发文"
action="yuthon_official_party_action"
sequence="20"/>
<menuitem
id="yuthon_official_labor_management_menu"
parent="official_management_menu_root"
name="工会公文管理"
sequence="9"/>
<menuitem
id="yuthon_official_incoming_labor"
parent="yuthon_official_labor_management_menu"
name="工会收文"
action="yuthon_official_incoming_labor_action"
sequence="5"/>
<menuitem
id="yuthon_official_labor"
parent="yuthon_official_labor_management_menu"
name="工会发文"
action="yuthon_official_labor_action"
sequence="10"/>
<menuitem
id="official_management_partner_menu"
parent="official_management_menu_root"
name="发文单位管理"
action="official_partner_action"
sequence="10"/>
<menuitem
id="official_management_type_menu"
parent="official_management_menu_root"
name="公文类型管理"
action="official_type_action"
sequence="15"/>
</odoo>
@@ -18,10 +18,5 @@
<field name="view_mode">tree</field>
</record>
<menuitem
id="official_management_partner_menu"
parent="official_management_menu_root"
name="发文单位管理"
action="official_partner_action"
sequence="10"/>
</odoo>
@@ -18,10 +18,5 @@
<field name="view_mode">tree</field>
</record>
<menuitem
id="official_management_type_menu"
parent="official_management_menu_root"
name="公文类型管理"
action="official_type_action"
sequence="10"/>
</odoo>
@@ -81,11 +81,6 @@
</record>
<menuitem
id="yuthon_official_incoming_labor"
parent="yuthon_official_labor_management_menu"
name="工会收文"
action="yuthon_official_incoming_labor_action"
sequence="5"/>
</odoo>
@@ -81,11 +81,6 @@
</record>
<menuitem
id="yuthon_official_incoming_normal"
parent="yuthon_official_normal_management_menu"
name="行政收文"
action="yuthon_official_incoming_normal_action"
sequence="10"/>
</odoo>
@@ -81,11 +81,6 @@
</record>
<menuitem
id="yuthon_official_incoming_party"
parent="yuthon_official_party_management_menu"
name="党总支收文"
action="yuthon_official_incoming_party_action"
sequence="10"/>
</odoo>
@@ -79,11 +79,6 @@
</record>
<menuitem
id="yuthon_official_labor"
parent="yuthon_official_labor_management_menu"
name="工会发文"
action="yuthon_official_labor_action"
sequence="10"/>
</odoo>
@@ -1,91 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="yuthon_official_normal_tree" model="ir.ui.view">
<field name="name">yuthon.official.normal.tree</field>
<field name="model">yuthon.official.normal</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="department_id"/>
<field name="date"/>
<field name="statu"/>
</tree>
</field>
</record>
<record id="yuthon_official_normal_form" model="ir.ui.view">
<field name="name">yuthon.official.normal.form</field>
<field name="model">yuthon.official.normal</field>
<field name="arch" type="xml">
<form>
<header>
<field name="statu" widget="statusbar"/>
</header>
<sheet>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name" required="1"/>
</h1>
</div>
<group>
<group>
<field name="code"/>
<field name="reference_cold"/>
<field name="major_event_category"/>
<field name="urgency"/>
<field name="secret_level"/>
<field name="date"/>
</group>
<group>
<field name="department_id"/>
<field name="main_flats"/>
<field name="copy_flats"/>
<field name="servings_number"/>
<field name="deadline"/>
</group>
</group>
<group>
<field name="main_text"/>
<field name="remarks"/>
</group>
</sheet>
<div class="o_attachment_preview"/>
<div class="oe_chatter">
<field name="message_follower_ids" groups="base.group_user"/>
<field name="activity_ids"/>
<field name="message_ids"/>
<field name="red_suit"/>
</div>
</form>
</field>
</record>
<record id="yuthon_official_normal_search" model="ir.ui.view">
<field name="name">yuthon.official.normal.search</field>
<field name="model">yuthon.official.normal</field>
<field name="arch" type="xml">
<search string="考勤审批状态">
<filter string="草稿" name="Drft " domain="[('statu', '=', 'drft')]"/>
<filter string="执行中" name="Going " domain="[('statu', '=', 'going')]"/>
<filter string="已取消" name="Cancel " domain="[('statu', '=', 'cancel')]"/>
<filter string="已完成" name="Done " domain="[('statu', '=', 'done')]"/>
</search>
</field>
</record>
<record id="yuthon_official_normal_action" model="ir.actions.act_window">
<field name="name">行政发文</field>
<field name="res_model">yuthon.official.normal</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem
id="yuthon_official_normal_menu"
parent="yuthon_official_normal_management_menu"
name="行政发文"
action="yuthon_official_normal_action"
sequence="30"/>
</odoo>
@@ -81,11 +81,6 @@
</record>
<menuitem
id="yuthon_official_party"
parent="yuthon_official_party_management_menu"
name="党总支发文"
action="yuthon_official_party_action"
sequence="20"/>
</odoo>
@@ -20,6 +20,10 @@
<field name="arch" type="xml">
<form>
<header>
<button name="cancel_official" string="取消" invisible="statu != 'done'" type="object"
class="btn-primary"/>
<button name="done_publish" string="发布" invisible="statu != 'no'" type="object"
class="btn-primary"/>
<field name="statu" widget="statusbar"/>
</header>
<sheet>
@@ -48,6 +52,9 @@
<field name="main_flats"/>
<field name="copy_flats"/>
<field name="servings_number"/>
<field name="department_ids" widget="many2many_tags"/>
<field name="employee_ids" widget="many2many_tags"/>
<field name="users_role_ids" widget="many2many_tags"/>
</group>
</group>
<group>
@@ -85,34 +92,5 @@
<field name="view_mode">tree,form</field>
</record>
<menuitem
id="official_management_menu_root"
name="公文管理"
web_icon="yuthon_official,static/description/icon.png"
action="send_receive_messages_management_action"/>
<menuitem
id="official_management_menu"
parent="official_management_menu_root"
name="公文管理"
action="send_receive_messages_management_action"
sequence="8"/>
<menuitem
id="yuthon_official_normal_management_menu"
parent="official_management_menu_root"
name="行政公文管理"
action="send_receive_messages_management_action"
sequence="15"/>
<menuitem
id="yuthon_official_party_management_menu"
parent="official_management_menu_root"
name="党总支公文管理"
action="send_receive_messages_management_action"
sequence="20"/>
<menuitem
id="yuthon_official_labor_management_menu"
parent="official_management_menu_root"
name="工会公文管理"
action="send_receive_messages_management_action"
sequence="30"/>
</odoo>