mirror of
https://github.com/OCA/knowledge.git
synced 2025-07-16 04:02:56 -06:00
[IMP] document_page_approval: black, isort
This commit is contained in:
parent
e1727575df
commit
8d8c8ac32a
@ -2,28 +2,25 @@
|
|||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Document Page Approval',
|
"name": "Document Page Approval",
|
||||||
'version': '12.0.1.0.0',
|
"version": "12.0.1.0.0",
|
||||||
"author": "Savoir-faire Linux, Odoo Community Association (OCA)",
|
"author": "Savoir-faire Linux, Odoo Community Association (OCA)",
|
||||||
"website": "http://www.savoirfairelinux.com",
|
"website": "http://www.savoirfairelinux.com",
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
'category': 'Knowledge Management',
|
"category": "Knowledge Management",
|
||||||
'depends': [
|
"depends": ["document_page", "mail",],
|
||||||
'document_page',
|
"data": [
|
||||||
'mail',
|
"data/email_template.xml",
|
||||||
|
"views/document_page_approval.xml",
|
||||||
|
"security/document_page_security.xml",
|
||||||
|
"security/ir.model.access.csv",
|
||||||
],
|
],
|
||||||
'data': [
|
"images": [
|
||||||
'data/email_template.xml',
|
"images/category.png",
|
||||||
'views/document_page_approval.xml',
|
"images/page_history_list.png",
|
||||||
'security/document_page_security.xml',
|
"images/page_history.png",
|
||||||
'security/ir.model.access.csv',
|
|
||||||
],
|
],
|
||||||
'images': [
|
"post_init_hook": "post_init_hook",
|
||||||
'images/category.png',
|
"uninstall_hook": "uninstall_hook",
|
||||||
'images/page_history_list.png',
|
"installable": True,
|
||||||
'images/page_history.png',
|
|
||||||
],
|
|
||||||
'post_init_hook': 'post_init_hook',
|
|
||||||
'uninstall_hook': 'uninstall_hook',
|
|
||||||
'installable': True,
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<!-- If user wants to make upgrade-proof customizations to email templates, he should edit ir.model.data and check noupdate himself -->
|
<!-- If user wants to make upgrade-proof customizations to email templates, he should edit ir.model.data and check noupdate himself -->
|
||||||
<record id="email_template_new_draft_need_approval" model="mail.template">
|
<record id="email_template_new_draft_need_approval" model="mail.template">
|
||||||
<field name="name">Automated new draft need approval Notification Mail</field>
|
<field name="name">Automated new draft need approval Notification Mail</field>
|
||||||
<field name="email_from">${object.create_uid.company_id.email or 'noreply@localhost.com'}</field>
|
<field
|
||||||
<field name="subject">New version of ${object.display_name} needs your approval</field>
|
name="email_from"
|
||||||
<field name="model_id" ref="model_document_page_history"/>
|
>${object.create_uid.company_id.email or 'noreply@localhost.com'}</field>
|
||||||
<field name="auto_delete" eval="True"/>
|
<field
|
||||||
|
name="subject"
|
||||||
|
>New version of ${object.display_name} needs your approval</field>
|
||||||
|
<field name="model_id" ref="model_document_page_history" />
|
||||||
|
<field name="auto_delete" eval="True" />
|
||||||
<field name="lang">${object.create_uid.partner_id.lang}</field>
|
<field name="lang">${object.create_uid.partner_id.lang}</field>
|
||||||
<field name="body_html">
|
<field name="body_html">
|
||||||
<![CDATA[
|
<![CDATA[
|
||||||
@ -39,5 +42,4 @@ ${object.diff|safe}
|
|||||||
]]>
|
]]>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
# Copyright 2018 Ivan Todorovich (<ivan.todorovich@gmail.com>)
|
# Copyright 2018 Ivan Todorovich (<ivan.todorovich@gmail.com>)
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def post_init_hook(cr, registry): # pragma: no cover
|
def post_init_hook(cr, registry): # pragma: no cover
|
||||||
# Set all pre-existing pages history to approved
|
# Set all pre-existing pages history to approved
|
||||||
_logger.info('Setting history to approved.')
|
_logger.info("Setting history to approved.")
|
||||||
cr.execute("""
|
cr.execute(
|
||||||
|
"""
|
||||||
UPDATE document_page_history
|
UPDATE document_page_history
|
||||||
SET state='approved',
|
SET state='approved',
|
||||||
approved_uid=create_uid,
|
approved_uid=create_uid,
|
||||||
approved_date=create_date
|
approved_date=create_date
|
||||||
WHERE state IS NULL OR state = 'draft'
|
WHERE state IS NULL OR state = 'draft'
|
||||||
""")
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def uninstall_hook(cr, registry): # pragma: no cover
|
def uninstall_hook(cr, registry): # pragma: no cover
|
||||||
# Remove unapproved pages
|
# Remove unapproved pages
|
||||||
_logger.info('Deleting unapproved Change Requests.')
|
_logger.info("Deleting unapproved Change Requests.")
|
||||||
cr.execute(
|
cr.execute("DELETE FROM document_page_history " "WHERE state != 'approved'")
|
||||||
"DELETE FROM document_page_history "
|
|
||||||
"WHERE state != 'approved'"
|
|
||||||
)
|
|
||||||
|
@ -262,21 +262,24 @@ msgstr ""
|
|||||||
#. module: document_page_approval
|
#. module: document_page_approval
|
||||||
#: code:addons/document_page_approval/models/document_page_history.py:102
|
#: code:addons/document_page_approval/models/document_page_history.py:102
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You are not authorized to do this.
\n"
|
msgid "You are not authorized to do this.
|
||||||
|
\n"
|
||||||
"Only approvers with these groups can approve this: "
|
"Only approvers with these groups can approve this: "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. module: document_page_approval
|
#. module: document_page_approval
|
||||||
#: code:addons/document_page_approval/models/document_page_history.py:62
|
#: code:addons/document_page_approval/models/document_page_history.py:62
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You are not authorized to do this.
\n"
|
msgid "You are not authorized to do this.
|
||||||
|
\n"
|
||||||
"Only owners or approvers can reopen Change Requests."
|
"Only owners or approvers can reopen Change Requests."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. module: document_page_approval
|
#. module: document_page_approval
|
||||||
#: code:addons/document_page_approval/models/document_page_history.py:79
|
#: code:addons/document_page_approval/models/document_page_history.py:79
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You are not authorized to do this.
\n"
|
msgid "You are not authorized to do this.
|
||||||
|
\n"
|
||||||
"Only owners or approvers can request approval."
|
"Only owners or approvers can request approval."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2,77 +2,74 @@
|
|||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
|
||||||
from odoo import api, fields, models
|
|
||||||
from ast import literal_eval
|
from ast import literal_eval
|
||||||
|
|
||||||
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
class DocumentPage(models.Model):
|
class DocumentPage(models.Model):
|
||||||
"""Useful to know the state of a document."""
|
"""Useful to know the state of a document."""
|
||||||
|
|
||||||
_inherit = 'document.page'
|
_inherit = "document.page"
|
||||||
|
|
||||||
history_ids = fields.One2many(
|
history_ids = fields.One2many(
|
||||||
order='approved_date DESC',
|
order="approved_date DESC", domain=[("state", "=", "approved")],
|
||||||
domain=[('state', '=', 'approved')],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
approved_date = fields.Datetime(
|
approved_date = fields.Datetime(
|
||||||
'Approved Date',
|
"Approved Date",
|
||||||
related='history_head.approved_date',
|
related="history_head.approved_date",
|
||||||
store=True,
|
store=True,
|
||||||
index=True,
|
index=True,
|
||||||
readonly=True,
|
readonly=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
approved_uid = fields.Many2one(
|
approved_uid = fields.Many2one(
|
||||||
'res.users',
|
"res.users",
|
||||||
'Approved by',
|
"Approved by",
|
||||||
related='history_head.approved_uid',
|
related="history_head.approved_uid",
|
||||||
store=True,
|
store=True,
|
||||||
index=True,
|
index=True,
|
||||||
readonly=True,
|
readonly=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
approval_required = fields.Boolean(
|
approval_required = fields.Boolean(
|
||||||
'Require approval',
|
"Require approval",
|
||||||
help='Require approval for changes on this page or its child pages.',
|
help="Require approval for changes on this page or its child pages.",
|
||||||
)
|
)
|
||||||
|
|
||||||
approver_gid = fields.Many2one(
|
approver_gid = fields.Many2one(
|
||||||
"res.groups",
|
"res.groups",
|
||||||
"Approver group",
|
"Approver group",
|
||||||
help='Users must also belong to the Approvers group',
|
help="Users must also belong to the Approvers group",
|
||||||
)
|
)
|
||||||
|
|
||||||
is_approval_required = fields.Boolean(
|
is_approval_required = fields.Boolean(
|
||||||
'Approval required',
|
"Approval required",
|
||||||
help='If true, changes of this page require approval',
|
help="If true, changes of this page require approval",
|
||||||
compute='_compute_is_approval_required',
|
compute="_compute_is_approval_required",
|
||||||
)
|
)
|
||||||
|
|
||||||
am_i_approver = fields.Boolean(
|
am_i_approver = fields.Boolean(compute="_compute_am_i_approver")
|
||||||
compute='_compute_am_i_approver'
|
|
||||||
)
|
|
||||||
|
|
||||||
approver_group_ids = fields.Many2many(
|
approver_group_ids = fields.Many2many(
|
||||||
'res.groups',
|
"res.groups",
|
||||||
string='Approver groups',
|
string="Approver groups",
|
||||||
help='Groups that can approve changes to this document',
|
help="Groups that can approve changes to this document",
|
||||||
compute='_compute_approver_group_ids',
|
compute="_compute_approver_group_ids",
|
||||||
)
|
)
|
||||||
|
|
||||||
has_changes_pending_approval = fields.Boolean(
|
has_changes_pending_approval = fields.Boolean(
|
||||||
compute='_compute_has_changes_pending_approval',
|
compute="_compute_has_changes_pending_approval",
|
||||||
string='Has changes pending approval'
|
string="Has changes pending approval",
|
||||||
)
|
)
|
||||||
|
|
||||||
user_has_drafts = fields.Boolean(
|
user_has_drafts = fields.Boolean(
|
||||||
compute='_compute_user_has_drafts',
|
compute="_compute_user_has_drafts", string="User has drafts?",
|
||||||
string='User has drafts?',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@api.depends('approval_required', 'parent_id.is_approval_required')
|
@api.depends("approval_required", "parent_id.is_approval_required")
|
||||||
def _compute_is_approval_required(self):
|
def _compute_is_approval_required(self):
|
||||||
"""Check if the document required approval based on his parents."""
|
"""Check if the document required approval based on his parents."""
|
||||||
for page in self:
|
for page in self:
|
||||||
@ -82,7 +79,7 @@ class DocumentPage(models.Model):
|
|||||||
page.is_approval_required = res
|
page.is_approval_required = res
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@api.depends('approver_gid', 'parent_id.approver_group_ids')
|
@api.depends("approver_gid", "parent_id.approver_group_ids")
|
||||||
def _compute_approver_group_ids(self):
|
def _compute_approver_group_ids(self):
|
||||||
"""Compute the approver groups based on his parents."""
|
"""Compute the approver groups based on his parents."""
|
||||||
for page in self:
|
for page in self:
|
||||||
@ -92,7 +89,7 @@ class DocumentPage(models.Model):
|
|||||||
page.approver_group_ids = res
|
page.approver_group_ids = res
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@api.depends('is_approval_required', 'approver_group_ids')
|
@api.depends("is_approval_required", "approver_group_ids")
|
||||||
def _compute_am_i_approver(self):
|
def _compute_am_i_approver(self):
|
||||||
"""Check if the current user can approve changes to this page."""
|
"""Check if the current user can approve changes to this page."""
|
||||||
for rec in self:
|
for rec in self:
|
||||||
@ -106,11 +103,10 @@ class DocumentPage(models.Model):
|
|||||||
if not self.is_approval_required:
|
if not self.is_approval_required:
|
||||||
return True
|
return True
|
||||||
# if user belongs to 'Knowledge / Manager', he can approve anything
|
# if user belongs to 'Knowledge / Manager', he can approve anything
|
||||||
if user.has_group('document_page.group_document_manager'):
|
if user.has_group("document_page.group_document_manager"):
|
||||||
return True
|
return True
|
||||||
# to approve, user must have approver rights
|
# to approve, user must have approver rights
|
||||||
if not user.has_group(
|
if not user.has_group("document_page_approval.group_document_approver_user"):
|
||||||
'document_page_approval.group_document_approver_user'):
|
|
||||||
return False
|
return False
|
||||||
# if there aren't any approver_groups_defined, user can approve
|
# if there aren't any approver_groups_defined, user can approve
|
||||||
if not self.approver_group_ids:
|
if not self.approver_group_ids:
|
||||||
@ -120,21 +116,21 @@ class DocumentPage(models.Model):
|
|||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _compute_has_changes_pending_approval(self):
|
def _compute_has_changes_pending_approval(self):
|
||||||
history = self.env['document.page.history']
|
history = self.env["document.page.history"]
|
||||||
for rec in self:
|
for rec in self:
|
||||||
changes = history.search_count([
|
changes = history.search_count(
|
||||||
('page_id', '=', rec.id),
|
[("page_id", "=", rec.id), ("state", "=", "to approve")]
|
||||||
('state', '=', 'to approve')])
|
)
|
||||||
rec.has_changes_pending_approval = (changes > 0)
|
rec.has_changes_pending_approval = changes > 0
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _compute_user_has_drafts(self):
|
def _compute_user_has_drafts(self):
|
||||||
history = self.env['document.page.history']
|
history = self.env["document.page.history"]
|
||||||
for rec in self:
|
for rec in self:
|
||||||
changes = history.search_count([
|
changes = history.search_count(
|
||||||
('page_id', '=', rec.id),
|
[("page_id", "=", rec.id), ("state", "=", "draft")]
|
||||||
('state', '=', 'draft')])
|
)
|
||||||
rec.user_has_drafts = (changes > 0)
|
rec.user_has_drafts = changes > 0
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _create_history(self, vals):
|
def _create_history(self, vals):
|
||||||
@ -144,10 +140,10 @@ class DocumentPage(models.Model):
|
|||||||
@api.multi
|
@api.multi
|
||||||
def action_changes_pending_approval(self):
|
def action_changes_pending_approval(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
action = self.env.ref('document_page_approval.action_change_requests')
|
action = self.env.ref("document_page_approval.action_change_requests")
|
||||||
action = action.read()[0]
|
action = action.read()[0]
|
||||||
context = literal_eval(action['context'])
|
context = literal_eval(action["context"])
|
||||||
context['search_default_page_id'] = self.id
|
context["search_default_page_id"] = self.id
|
||||||
context['default_page_id'] = self.id
|
context["default_page_id"] = self.id
|
||||||
action['context'] = context
|
action["context"] = context
|
||||||
return action
|
return action
|
||||||
|
@ -1,90 +1,84 @@
|
|||||||
# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
|
# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from odoo.tools.translate import _
|
|
||||||
from odoo import api, fields, models
|
from odoo import api, fields, models
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
|
from odoo.tools.translate import _
|
||||||
|
|
||||||
|
|
||||||
class DocumentPageHistory(models.Model):
|
class DocumentPageHistory(models.Model):
|
||||||
"""Useful to manage edition's workflow on a document."""
|
"""Useful to manage edition's workflow on a document."""
|
||||||
|
|
||||||
_name = 'document.page.history'
|
_name = "document.page.history"
|
||||||
_inherit = ['document.page.history', 'mail.thread']
|
_inherit = ["document.page.history", "mail.thread"]
|
||||||
|
|
||||||
state = fields.Selection([
|
state = fields.Selection(
|
||||||
('draft', 'Draft'),
|
[
|
||||||
('to approve', 'Pending Approval'),
|
("draft", "Draft"),
|
||||||
('approved', 'Approved'),
|
("to approve", "Pending Approval"),
|
||||||
('cancelled', 'Cancelled')],
|
("approved", "Approved"),
|
||||||
'Status',
|
("cancelled", "Cancelled"),
|
||||||
default='draft',
|
],
|
||||||
|
"Status",
|
||||||
|
default="draft",
|
||||||
readonly=True,
|
readonly=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
approved_date = fields.Datetime(
|
approved_date = fields.Datetime("Approved Date",)
|
||||||
'Approved Date',
|
|
||||||
)
|
|
||||||
|
|
||||||
approved_uid = fields.Many2one(
|
approved_uid = fields.Many2one("res.users", "Approved by",)
|
||||||
'res.users',
|
|
||||||
'Approved by',
|
|
||||||
)
|
|
||||||
|
|
||||||
is_approval_required = fields.Boolean(
|
is_approval_required = fields.Boolean(
|
||||||
related='page_id.is_approval_required',
|
related="page_id.is_approval_required", string="Approval required",
|
||||||
string="Approval required",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
am_i_owner = fields.Boolean(
|
am_i_owner = fields.Boolean(compute="_compute_am_i_owner")
|
||||||
compute='_compute_am_i_owner'
|
|
||||||
)
|
|
||||||
|
|
||||||
am_i_approver = fields.Boolean(
|
am_i_approver = fields.Boolean(related="page_id.am_i_approver", related_sudo=False,)
|
||||||
related='page_id.am_i_approver',
|
|
||||||
related_sudo=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
page_url = fields.Text(
|
page_url = fields.Text(compute="_compute_page_url", string="URL",)
|
||||||
compute='_compute_page_url',
|
|
||||||
string="URL",
|
|
||||||
)
|
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_draft(self):
|
def action_draft(self):
|
||||||
"""Set a change request as draft"""
|
"""Set a change request as draft"""
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if not rec.state == 'cancelled':
|
if not rec.state == "cancelled":
|
||||||
raise UserError(
|
raise UserError(_("You need to cancel it before reopening."))
|
||||||
_('You need to cancel it before reopening.'))
|
|
||||||
if not (rec.am_i_owner or rec.am_i_approver):
|
if not (rec.am_i_owner or rec.am_i_approver):
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_('You are not authorized to do this.\r\n'
|
_(
|
||||||
'Only owners or approvers can reopen Change Requests.'))
|
"You are not authorized to do this.\r\n"
|
||||||
rec.write({'state': 'draft'})
|
"Only owners or approvers can reopen Change Requests."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
rec.write({"state": "draft"})
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_to_approve(self):
|
def action_to_approve(self):
|
||||||
"""Set a change request as to approve"""
|
"""Set a change request as to approve"""
|
||||||
template = self.env.ref(
|
template = self.env.ref(
|
||||||
'document_page_approval.email_template_new_draft_need_approval')
|
"document_page_approval.email_template_new_draft_need_approval"
|
||||||
|
)
|
||||||
approver_gid = self.env.ref(
|
approver_gid = self.env.ref(
|
||||||
'document_page_approval.group_document_approver_user')
|
"document_page_approval.group_document_approver_user"
|
||||||
|
)
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if rec.state != 'draft':
|
if rec.state != "draft":
|
||||||
raise UserError(
|
raise UserError(_("Can't approve pages in '%s' state.") % rec.state)
|
||||||
_("Can't approve pages in '%s' state.") % rec.state)
|
|
||||||
if not (rec.am_i_owner or rec.am_i_approver):
|
if not (rec.am_i_owner or rec.am_i_approver):
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_('You are not authorized to do this.\r\n'
|
_(
|
||||||
'Only owners or approvers can request approval.'))
|
"You are not authorized to do this.\r\n"
|
||||||
|
"Only owners or approvers can request approval."
|
||||||
|
)
|
||||||
|
)
|
||||||
# request approval
|
# request approval
|
||||||
if rec.is_approval_required:
|
if rec.is_approval_required:
|
||||||
rec.write({'state': 'to approve'})
|
rec.write({"state": "to approve"})
|
||||||
guids = [g.id for g in rec.page_id.approver_group_ids]
|
guids = [g.id for g in rec.page_id.approver_group_ids]
|
||||||
users = self.env['res.users'].search([
|
users = self.env["res.users"].search(
|
||||||
('groups_id', 'in', guids),
|
[("groups_id", "in", guids), ("groups_id", "in", approver_gid.id)]
|
||||||
('groups_id', 'in', approver_gid.id)])
|
)
|
||||||
rec.message_subscribe([u.id for u in users])
|
rec.message_subscribe([u.id for u in users])
|
||||||
rec.message_post_with_template(template.id)
|
rec.message_post_with_template(template.id)
|
||||||
else:
|
else:
|
||||||
@ -95,49 +89,49 @@ class DocumentPageHistory(models.Model):
|
|||||||
def action_approve(self):
|
def action_approve(self):
|
||||||
"""Set a change request as approved."""
|
"""Set a change request as approved."""
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if rec.state not in ['draft', 'to approve']:
|
if rec.state not in ["draft", "to approve"]:
|
||||||
raise UserError(
|
raise UserError(_("Can't approve page in '%s' state.") % rec.state)
|
||||||
_("Can't approve page in '%s' state.") % rec.state)
|
|
||||||
if not rec.am_i_approver:
|
if not rec.am_i_approver:
|
||||||
raise UserError(_(
|
raise UserError(
|
||||||
'You are not authorized to do this.\r\n'
|
_(
|
||||||
'Only approvers with these groups can approve this: '
|
"You are not authorized to do this.\r\n"
|
||||||
) % ', '.join(
|
"Only approvers with these groups can approve this: "
|
||||||
[g.display_name
|
)
|
||||||
for g in rec.page_id.approver_group_ids]))
|
% ", ".join(
|
||||||
|
[g.display_name for g in rec.page_id.approver_group_ids]
|
||||||
|
)
|
||||||
|
)
|
||||||
# Update state
|
# Update state
|
||||||
rec.write({
|
rec.write(
|
||||||
'state': 'approved',
|
{
|
||||||
'approved_date': fields.datetime.now(),
|
"state": "approved",
|
||||||
'approved_uid': self.env.uid,
|
"approved_date": fields.datetime.now(),
|
||||||
})
|
"approved_uid": self.env.uid,
|
||||||
|
}
|
||||||
|
)
|
||||||
# Trigger computed field update
|
# Trigger computed field update
|
||||||
rec.page_id._compute_history_head()
|
rec.page_id._compute_history_head()
|
||||||
# Notify state change
|
# Notify state change
|
||||||
rec.message_post(
|
rec.message_post(
|
||||||
subtype='mt_comment',
|
subtype="mt_comment",
|
||||||
body=_(
|
body=_("Change request has been approved by %s.")
|
||||||
'Change request has been approved by %s.'
|
% (self.env.user.name),
|
||||||
) % (self.env.user.name)
|
|
||||||
)
|
)
|
||||||
# Notify followers a new version is available
|
# Notify followers a new version is available
|
||||||
rec.page_id.message_post(
|
rec.page_id.message_post(
|
||||||
subtype='mt_comment',
|
subtype="mt_comment",
|
||||||
body=_(
|
body=_("New version of the document %s approved.") % (rec.page_id.name),
|
||||||
'New version of the document %s approved.'
|
|
||||||
) % (rec.page_id.name)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_cancel(self):
|
def action_cancel(self):
|
||||||
"""Set a change request as cancelled."""
|
"""Set a change request as cancelled."""
|
||||||
self.write({'state': 'cancelled'})
|
self.write({"state": "cancelled"})
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.message_post(
|
rec.message_post(
|
||||||
subtype='mt_comment',
|
subtype="mt_comment",
|
||||||
body=_(
|
body=_("Change request <b>%s</b> has been cancelled by %s.")
|
||||||
'Change request <b>%s</b> has been cancelled by %s.'
|
% (rec.display_name, self.env.user.name),
|
||||||
) % (rec.display_name, self.env.user.name)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@ -150,36 +144,31 @@ class DocumentPageHistory(models.Model):
|
|||||||
def _compute_am_i_owner(self):
|
def _compute_am_i_owner(self):
|
||||||
"""Check if current user is the owner"""
|
"""Check if current user is the owner"""
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.am_i_owner = (rec.create_uid == self.env.user)
|
rec.am_i_owner = rec.create_uid == self.env.user
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _compute_page_url(self):
|
def _compute_page_url(self):
|
||||||
"""Compute the page url."""
|
"""Compute the page url."""
|
||||||
for page in self:
|
for page in self:
|
||||||
base_url = self.env['ir.config_parameter'].sudo().get_param(
|
base_url = (
|
||||||
'web.base.url',
|
self.env["ir.config_parameter"]
|
||||||
default='http://localhost:8069'
|
.sudo()
|
||||||
|
.get_param("web.base.url", default="http://localhost:8069")
|
||||||
)
|
)
|
||||||
|
|
||||||
page.page_url = (
|
page.page_url = (
|
||||||
'{}/web#db={}&id={}&view_type=form&'
|
"{}/web#db={}&id={}&view_type=form&" "model=document.page.history"
|
||||||
'model=document.page.history').format(
|
).format(base_url, self.env.cr.dbname, page.id)
|
||||||
base_url,
|
|
||||||
self.env.cr.dbname,
|
|
||||||
page.id
|
|
||||||
)
|
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _compute_diff(self):
|
def _compute_diff(self):
|
||||||
"""Shows a diff between this version and the previous version"""
|
"""Shows a diff between this version and the previous version"""
|
||||||
history = self.env['document.page.history']
|
history = self.env["document.page.history"]
|
||||||
for rec in self:
|
for rec in self:
|
||||||
domain = [
|
domain = [("page_id", "=", rec.page_id.id), ("state", "=", "approved")]
|
||||||
('page_id', '=', rec.page_id.id),
|
|
||||||
('state', '=', 'approved')]
|
|
||||||
if rec.approved_date:
|
if rec.approved_date:
|
||||||
domain.append(('approved_date', '<', rec.approved_date))
|
domain.append(("approved_date", "<", rec.approved_date))
|
||||||
prev = history.search(domain, limit=1, order='approved_date DESC')
|
prev = history.search(domain, limit=1, order="approved_date DESC")
|
||||||
if prev:
|
if prev:
|
||||||
rec.diff = self._get_diff(prev.id, rec.id)
|
rec.diff = self._get_diff(prev.id, rec.id)
|
||||||
else:
|
else:
|
||||||
|
@ -1,36 +1,36 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<record id="group_document_approver_user" model="res.groups">
|
<record id="group_document_approver_user" model="res.groups">
|
||||||
<field name="name">Approver</field>
|
<field name="name">Approver</field>
|
||||||
<field name="category_id" ref="knowledge.module_category_knowledge"/>
|
<field name="category_id" ref="knowledge.module_category_knowledge" />
|
||||||
<field name="implied_ids" eval="[(4, ref('document_page.group_document_editor'))]"/>
|
<field
|
||||||
|
name="implied_ids"
|
||||||
|
eval="[(4, ref('document_page.group_document_editor'))]"
|
||||||
|
/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record id="document_page.group_document_manager" model="res.groups">
|
<record id="document_page.group_document_manager" model="res.groups">
|
||||||
<field name="implied_ids" eval="[(4, ref('group_document_approver_user'))]"/>
|
<field name="implied_ids" eval="[(4, ref('group_document_approver_user'))]" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.rule" id="rule_change_request_global">
|
<record model="ir.rule" id="rule_change_request_global">
|
||||||
<field name="name">Change Request Global</field>
|
<field name="name">Change Request Global</field>
|
||||||
<field name="model_id" ref="model_document_page_history"/>
|
<field name="model_id" ref="model_document_page_history" />
|
||||||
<field name="groups" eval="[(6, 0, [ref('knowledge.group_document_user')])]"/>
|
<field name="groups" eval="[(6, 0, [ref('knowledge.group_document_user')])]" />
|
||||||
<field name="domain_force">['|',('state','=','approved'),('create_uid','=',user.id)]</field>
|
<field
|
||||||
<field name="perm_read" eval="True"/>
|
name="domain_force"
|
||||||
<field name="perm_write" eval="True"/>
|
>['|',('state','=','approved'),('create_uid','=',user.id)]</field>
|
||||||
<field name="perm_unlink" eval="True"/>
|
<field name="perm_read" eval="True" />
|
||||||
<field name="perm_create" eval="True"/>
|
<field name="perm_write" eval="True" />
|
||||||
|
<field name="perm_unlink" eval="True" />
|
||||||
|
<field name="perm_create" eval="True" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<record model="ir.rule" id="rule_change_request_approver">
|
<record model="ir.rule" id="rule_change_request_approver">
|
||||||
<field name="name">Change Request Approver</field>
|
<field name="name">Change Request Approver</field>
|
||||||
<field name="model_id" ref="model_document_page_history"/>
|
<field name="model_id" ref="model_document_page_history" />
|
||||||
<field name="groups" eval="[(6, 0, [ref('group_document_approver_user')])]"/>
|
<field name="groups" eval="[(6, 0, [ref('group_document_approver_user')])]" />
|
||||||
<field name="domain_force">[('state','!=','draft')]</field>
|
<field name="domain_force">[('state','!=','draft')]</field>
|
||||||
<field name="perm_read" eval="True"/>
|
<field name="perm_read" eval="True" />
|
||||||
<field name="perm_write" eval="True"/>
|
<field name="perm_write" eval="True" />
|
||||||
<field name="perm_unlink" eval="True"/>
|
<field name="perm_unlink" eval="True" />
|
||||||
<field name="perm_create" eval="True"/>
|
<field name="perm_create" eval="True" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
@ -2,31 +2,35 @@ from odoo.tests import common
|
|||||||
|
|
||||||
|
|
||||||
class TestDocumentPageApproval(common.TransactionCase):
|
class TestDocumentPageApproval(common.TransactionCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestDocumentPageApproval, self).setUp()
|
super(TestDocumentPageApproval, self).setUp()
|
||||||
self.page_obj = self.env['document.page']
|
self.page_obj = self.env["document.page"]
|
||||||
self.history_obj = self.env['document.page.history']
|
self.history_obj = self.env["document.page.history"]
|
||||||
# demo
|
# demo
|
||||||
self.category1 = self.env.ref('document_page.demo_category1')
|
self.category1 = self.env.ref("document_page.demo_category1")
|
||||||
self.page1 = self.env.ref('document_page.demo_page1')
|
self.page1 = self.env.ref("document_page.demo_page1")
|
||||||
self.approver_gid = self.env.ref(
|
self.approver_gid = self.env.ref(
|
||||||
'document_page_approval.group_document_approver_user')
|
"document_page_approval.group_document_approver_user"
|
||||||
self.env.ref('base.user_root').write({
|
)
|
||||||
'groups_id': [(4, self.approver_gid.id)],
|
self.env.ref("base.user_root").write(
|
||||||
})
|
{"groups_id": [(4, self.approver_gid.id)],}
|
||||||
|
)
|
||||||
# demo_approval
|
# demo_approval
|
||||||
self.category2 = self.page_obj.create({
|
self.category2 = self.page_obj.create(
|
||||||
'name': 'This category requires approval',
|
{
|
||||||
'type': 'category',
|
"name": "This category requires approval",
|
||||||
'approval_required': True,
|
"type": "category",
|
||||||
'approver_gid': self.approver_gid.id,
|
"approval_required": True,
|
||||||
})
|
"approver_gid": self.approver_gid.id,
|
||||||
self.page2 = self.page_obj.create({
|
}
|
||||||
'name': 'This page requires approval',
|
)
|
||||||
'parent_id': self.category2.id,
|
self.page2 = self.page_obj.create(
|
||||||
'content': 'This content will require approval',
|
{
|
||||||
})
|
"name": "This page requires approval",
|
||||||
|
"parent_id": self.category2.id,
|
||||||
|
"content": "This content will require approval",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def test_approval_required(self):
|
def test_approval_required(self):
|
||||||
page = self.page2
|
page = self.page2
|
||||||
@ -36,13 +40,12 @@ class TestDocumentPageApproval(common.TransactionCase):
|
|||||||
|
|
||||||
def test_change_request_approve(self):
|
def test_change_request_approve(self):
|
||||||
page = self.page2
|
page = self.page2
|
||||||
chreq = self.history_obj.search([
|
chreq = self.history_obj.search(
|
||||||
('page_id', '=', page.id),
|
[("page_id", "=", page.id), ("state", "!=", "approved")]
|
||||||
('state', '!=', 'approved')
|
)[0]
|
||||||
])[0]
|
|
||||||
|
|
||||||
# It should automatically be in 'to approve' state
|
# It should automatically be in 'to approve' state
|
||||||
self.assertEqual(chreq.state, 'to approve')
|
self.assertEqual(chreq.state, "to approve")
|
||||||
self.assertNotEqual(chreq.content, page.content)
|
self.assertNotEqual(chreq.content, page.content)
|
||||||
|
|
||||||
# who_am_i
|
# who_am_i
|
||||||
@ -51,66 +54,66 @@ class TestDocumentPageApproval(common.TransactionCase):
|
|||||||
|
|
||||||
# approve
|
# approve
|
||||||
chreq.action_approve()
|
chreq.action_approve()
|
||||||
self.assertEqual(chreq.state, 'approved')
|
self.assertEqual(chreq.state, "approved")
|
||||||
self.assertEqual(chreq.content, page.content)
|
self.assertEqual(chreq.content, page.content)
|
||||||
|
|
||||||
# new changes should create change requests
|
# new changes should create change requests
|
||||||
page.write({'content': 'New content'})
|
page.write({"content": "New content"})
|
||||||
self.assertNotEqual(page.content, 'New content')
|
self.assertNotEqual(page.content, "New content")
|
||||||
chreq = self.history_obj.search([
|
chreq = self.history_obj.search(
|
||||||
('page_id', '=', page.id),
|
[("page_id", "=", page.id), ("state", "!=", "approved")]
|
||||||
('state', '!=', 'approved')
|
)[0]
|
||||||
])[0]
|
|
||||||
chreq.action_approve()
|
chreq.action_approve()
|
||||||
self.assertEqual(page.content, 'New content')
|
self.assertEqual(page.content, "New content")
|
||||||
|
|
||||||
def test_change_request_auto_approve(self):
|
def test_change_request_auto_approve(self):
|
||||||
page = self.page1
|
page = self.page1
|
||||||
self.assertFalse(page.is_approval_required)
|
self.assertFalse(page.is_approval_required)
|
||||||
page.write({'content': 'New content'})
|
page.write({"content": "New content"})
|
||||||
self.assertEqual(page.content, 'New content')
|
self.assertEqual(page.content, "New content")
|
||||||
|
|
||||||
def test_change_request_from_scratch(self):
|
def test_change_request_from_scratch(self):
|
||||||
page = self.page2
|
page = self.page2
|
||||||
|
|
||||||
# aprove everything
|
# aprove everything
|
||||||
self.history_obj.search([
|
self.history_obj.search(
|
||||||
('page_id', '=', page.id),
|
[("page_id", "=", page.id), ("state", "!=", "approved")]
|
||||||
('state', '!=', 'approved')
|
).action_approve()
|
||||||
]).action_approve()
|
|
||||||
|
|
||||||
# new change request from scrath
|
# new change request from scrath
|
||||||
chreq = self.history_obj.create({
|
chreq = self.history_obj.create(
|
||||||
'page_id': page.id,
|
{
|
||||||
'summary': 'Changed something',
|
"page_id": page.id,
|
||||||
'content': 'New content',
|
"summary": "Changed something",
|
||||||
})
|
"content": "New content",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(chreq.state, 'draft')
|
self.assertEqual(chreq.state, "draft")
|
||||||
self.assertNotEqual(page.content, chreq.content)
|
self.assertNotEqual(page.content, chreq.content)
|
||||||
self.assertNotEqual(page.approved_date, chreq.approved_date)
|
self.assertNotEqual(page.approved_date, chreq.approved_date)
|
||||||
self.assertNotEqual(page.approved_uid, chreq.approved_uid)
|
self.assertNotEqual(page.approved_uid, chreq.approved_uid)
|
||||||
|
|
||||||
chreq.action_to_approve()
|
chreq.action_to_approve()
|
||||||
self.assertEqual(chreq.state, 'to approve')
|
self.assertEqual(chreq.state, "to approve")
|
||||||
self.assertNotEqual(page.content, chreq.content)
|
self.assertNotEqual(page.content, chreq.content)
|
||||||
self.assertNotEqual(page.approved_date, chreq.approved_date)
|
self.assertNotEqual(page.approved_date, chreq.approved_date)
|
||||||
self.assertNotEqual(page.approved_uid, chreq.approved_uid)
|
self.assertNotEqual(page.approved_uid, chreq.approved_uid)
|
||||||
|
|
||||||
chreq.action_cancel()
|
chreq.action_cancel()
|
||||||
self.assertEqual(chreq.state, 'cancelled')
|
self.assertEqual(chreq.state, "cancelled")
|
||||||
self.assertNotEqual(page.content, chreq.content)
|
self.assertNotEqual(page.content, chreq.content)
|
||||||
self.assertNotEqual(page.approved_date, chreq.approved_date)
|
self.assertNotEqual(page.approved_date, chreq.approved_date)
|
||||||
self.assertNotEqual(page.approved_uid, chreq.approved_uid)
|
self.assertNotEqual(page.approved_uid, chreq.approved_uid)
|
||||||
|
|
||||||
chreq.action_draft()
|
chreq.action_draft()
|
||||||
self.assertEqual(chreq.state, 'draft')
|
self.assertEqual(chreq.state, "draft")
|
||||||
self.assertNotEqual(page.content, chreq.content)
|
self.assertNotEqual(page.content, chreq.content)
|
||||||
self.assertNotEqual(page.approved_date, chreq.approved_date)
|
self.assertNotEqual(page.approved_date, chreq.approved_date)
|
||||||
self.assertNotEqual(page.approved_uid, chreq.approved_uid)
|
self.assertNotEqual(page.approved_uid, chreq.approved_uid)
|
||||||
|
|
||||||
chreq.action_approve()
|
chreq.action_approve()
|
||||||
self.assertEqual(chreq.state, 'approved')
|
self.assertEqual(chreq.state, "approved")
|
||||||
self.assertEqual(page.content, chreq.content)
|
self.assertEqual(page.content, chreq.content)
|
||||||
self.assertEqual(page.approved_date, chreq.approved_date)
|
self.assertEqual(page.approved_date, chreq.approved_date)
|
||||||
self.assertEqual(page.approved_uid, chreq.approved_uid)
|
self.assertEqual(page.approved_uid, chreq.approved_uid)
|
||||||
@ -122,6 +125,6 @@ class TestDocumentPageApproval(common.TransactionCase):
|
|||||||
|
|
||||||
def test_get_page_url(self):
|
def test_get_page_url(self):
|
||||||
"""Test if page url exist."""
|
"""Test if page url exist."""
|
||||||
pages = self.env['document.page.history'].search([])
|
pages = self.env["document.page.history"].search([])
|
||||||
page = pages[0]
|
page = pages[0]
|
||||||
self.assertIsNotNone(page.page_url)
|
self.assertIsNotNone(page.page_url)
|
||||||
|
@ -1,124 +1,196 @@
|
|||||||
<?xml version="1.0"?>
|
<?xml version="1.0" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
|
||||||
<!-- History Form View -->
|
<!-- History Form View -->
|
||||||
<record id="wiki_history_form_inherit" model="ir.ui.view">
|
<record id="wiki_history_form_inherit" model="ir.ui.view">
|
||||||
<field name="name">document.page.history.form</field>
|
<field name="name">document.page.history.form</field>
|
||||||
<field name="model">document.page.history</field>
|
<field name="model">document.page.history</field>
|
||||||
<field name="inherit_id" ref="document_page.wiki_history_form"/>
|
<field name="inherit_id" ref="document_page.wiki_history_form" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<sheet position="before">
|
<sheet position="before">
|
||||||
<header>
|
<header>
|
||||||
<!-- draft -> to approve -->
|
<!-- draft -> to approve -->
|
||||||
<button name="action_to_approve" type="object" string="Send to Review" class="oe_highlight"
|
<button
|
||||||
attrs="{'invisible':['|','|',('is_approval_required','=',False),('am_i_owner','=',False),('state', 'not in', ['draft'])]}"/>
|
name="action_to_approve"
|
||||||
|
type="object"
|
||||||
|
string="Send to Review"
|
||||||
|
class="oe_highlight"
|
||||||
|
attrs="{'invisible':['|','|',('is_approval_required','=',False),('am_i_owner','=',False),('state', 'not in', ['draft'])]}"
|
||||||
|
/>
|
||||||
<!-- approve if i am approver -->
|
<!-- approve if i am approver -->
|
||||||
<button name="action_approve" type="object" string="Approve" class="oe_highlight"
|
<button
|
||||||
attrs="{'invisible':['|','|',('is_approval_required','=',False),('am_i_approver','=',False),('state','not in',['draft','to approve'])]}"/>
|
name="action_approve"
|
||||||
|
type="object"
|
||||||
|
string="Approve"
|
||||||
|
class="oe_highlight"
|
||||||
|
attrs="{'invisible':['|','|',('is_approval_required','=',False),('am_i_approver','=',False),('state','not in',['draft','to approve'])]}"
|
||||||
|
/>
|
||||||
<!-- approve if it's not required and i am owner -->
|
<!-- approve if it's not required and i am owner -->
|
||||||
<button name="action_approve" type="object" string="Approve" class="oe_highlight"
|
<button
|
||||||
attrs="{'invisible':['|','|',('is_approval_required','=',True),('am_i_owner','=',False),('state','not in',['draft', 'to approve'])]}"/>
|
name="action_approve"
|
||||||
|
type="object"
|
||||||
|
string="Approve"
|
||||||
|
class="oe_highlight"
|
||||||
|
attrs="{'invisible':['|','|',('is_approval_required','=',True),('am_i_owner','=',False),('state','not in',['draft', 'to approve'])]}"
|
||||||
|
/>
|
||||||
<!-- cancel if i am owner or approver -->
|
<!-- cancel if i am owner or approver -->
|
||||||
<button name="action_cancel" type="object" string="Cancel"
|
<button
|
||||||
attrs="{'invisible':['|','&',('am_i_owner','=',False),('am_i_approver','=',False),('state','not in',['draft','to approve'])]}"/>
|
name="action_cancel"
|
||||||
|
type="object"
|
||||||
|
string="Cancel"
|
||||||
|
attrs="{'invisible':['|','&',('am_i_owner','=',False),('am_i_approver','=',False),('state','not in',['draft','to approve'])]}"
|
||||||
|
/>
|
||||||
<!-- reopen if i am owner or approver -->
|
<!-- reopen if i am owner or approver -->
|
||||||
<button name="action_draft" type="object" string="Back to draft"
|
<button
|
||||||
attrs="{'invisible':['|','&',('am_i_owner','=',False),('am_i_approver','=',False),('state','not in',['cancelled'])]}"/>
|
name="action_draft"
|
||||||
|
type="object"
|
||||||
|
string="Back to draft"
|
||||||
|
attrs="{'invisible':['|','&',('am_i_owner','=',False),('am_i_approver','=',False),('state','not in',['cancelled'])]}"
|
||||||
|
/>
|
||||||
<!-- cancel & reopen, if i am owner or approver -->
|
<!-- cancel & reopen, if i am owner or approver -->
|
||||||
<button name="action_draft" type="object" string="Back to draft"
|
<button
|
||||||
attrs="{'invisible':['|','&',('am_i_owner','=',False),('am_i_approver','=',False),('state','not in',['to approve'])]}"/>
|
name="action_draft"
|
||||||
<field name="am_i_owner" invisible="1"/>
|
type="object"
|
||||||
<field name="am_i_approver" invisible="1"/>
|
string="Back to draft"
|
||||||
<field name="is_approval_required" invisible="1"/>
|
attrs="{'invisible':['|','&',('am_i_owner','=',False),('am_i_approver','=',False),('state','not in',['to approve'])]}"
|
||||||
<field name="state" widget="statusbar" statusbar_visible="draft,approved" />
|
/>
|
||||||
|
<field name="am_i_owner" invisible="1" />
|
||||||
|
<field name="am_i_approver" invisible="1" />
|
||||||
|
<field name="is_approval_required" invisible="1" />
|
||||||
|
<field
|
||||||
|
name="state"
|
||||||
|
widget="statusbar"
|
||||||
|
statusbar_visible="draft,approved"
|
||||||
|
/>
|
||||||
</header>
|
</header>
|
||||||
</sheet>
|
</sheet>
|
||||||
<xpath expr="//field[@name='create_uid']/parent::group" position="after">
|
<xpath expr="//field[@name='create_uid']/parent::group" position="after">
|
||||||
<group>
|
<group>
|
||||||
<field name="approved_uid" readonly="1" attrs="{'invisible':[('state','not in',['approved'])]}"/>
|
<field
|
||||||
<field name="approved_date" readonly="1" attrs="{'invisible':[('state','not in',['approved'])]}"/>
|
name="approved_uid"
|
||||||
|
readonly="1"
|
||||||
|
attrs="{'invisible':[('state','not in',['approved'])]}"
|
||||||
|
/>
|
||||||
|
<field
|
||||||
|
name="approved_date"
|
||||||
|
readonly="1"
|
||||||
|
attrs="{'invisible':[('state','not in',['approved'])]}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
</xpath>
|
</xpath>
|
||||||
<!-- Readonly fields -->
|
<!-- Readonly fields -->
|
||||||
<field name="content" position="attributes"><attribute name="attrs">{'readonly': [('state', 'not in', ['draft'])]}</attribute></field>
|
<field name="content" position="attributes">
|
||||||
<field name="page_id" position="attributes"><attribute name="attrs">{'readonly': [('state', 'not in', ['draft'])]}</attribute></field>
|
<attribute
|
||||||
<field name="name" position="attributes"><attribute name="attrs">{'readonly': [('state', 'not in', ['draft'])]}</attribute></field>
|
name="attrs"
|
||||||
<field name="summary" position="attributes"><attribute name="attrs">{'readonly': [('state', 'not in', ['draft'])]}</attribute></field>
|
>{'readonly': [('state', 'not in', ['draft'])]}</attribute>
|
||||||
|
</field>
|
||||||
|
<field name="page_id" position="attributes">
|
||||||
|
<attribute
|
||||||
|
name="attrs"
|
||||||
|
>{'readonly': [('state', 'not in', ['draft'])]}</attribute>
|
||||||
|
</field>
|
||||||
|
<field name="name" position="attributes">
|
||||||
|
<attribute
|
||||||
|
name="attrs"
|
||||||
|
>{'readonly': [('state', 'not in', ['draft'])]}</attribute>
|
||||||
|
</field>
|
||||||
|
<field name="summary" position="attributes">
|
||||||
|
<attribute
|
||||||
|
name="attrs"
|
||||||
|
>{'readonly': [('state', 'not in', ['draft'])]}</attribute>
|
||||||
|
</field>
|
||||||
<!-- Chatter -->
|
<!-- Chatter -->
|
||||||
<sheet position="after">
|
<sheet position="after">
|
||||||
<div class="oe_chatter">
|
<div class="oe_chatter">
|
||||||
<field name="message_follower_ids" widget="mail_followers"/>
|
<field name="message_follower_ids" widget="mail_followers" />
|
||||||
<field name="message_ids" widget="mail_thread"/>
|
<field name="message_ids" widget="mail_thread" />
|
||||||
</div>
|
</div>
|
||||||
</sheet>
|
</sheet>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- History Form View Manager Rights -->
|
<!-- History Form View Manager Rights -->
|
||||||
<record id="wiki_history_form_inherit_manager" model="ir.ui.view">
|
<record id="wiki_history_form_inherit_manager" model="ir.ui.view">
|
||||||
<field name="name">document.page.history.form</field>
|
<field name="name">document.page.history.form</field>
|
||||||
<field name="model">document.page.history</field>
|
<field name="model">document.page.history</field>
|
||||||
<field name="inherit_id" ref="wiki_history_form_inherit"/>
|
<field name="inherit_id" ref="wiki_history_form_inherit" />
|
||||||
<field name="groups_id" eval="[(6, 0, [ref('document_page.group_document_manager')])]"/>
|
<field
|
||||||
|
name="groups_id"
|
||||||
|
eval="[(6, 0, [ref('document_page.group_document_manager')])]"
|
||||||
|
/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<!-- Readonly fields -->
|
<!-- Readonly fields -->
|
||||||
<field name="name" position="attributes"><attribute name="attrs">{'readonly': False}</attribute></field>
|
<field name="name" position="attributes">
|
||||||
<field name="summary" position="attributes"><attribute name="attrs">{'readonly': False}</attribute></field>
|
<attribute name="attrs">{'readonly': False}</attribute>
|
||||||
|
</field>
|
||||||
|
<field name="summary" position="attributes">
|
||||||
|
<attribute name="attrs">{'readonly': False}</attribute>
|
||||||
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- Page Form View -->
|
<!-- Page Form View -->
|
||||||
<record id="wiki_form_inherit" model="ir.ui.view">
|
<record id="wiki_form_inherit" model="ir.ui.view">
|
||||||
<field name="name">document.page.form</field>
|
<field name="name">document.page.form</field>
|
||||||
<field name="model">document.page</field>
|
<field name="model">document.page</field>
|
||||||
<field name="inherit_id" ref="document_page.view_wiki_form" />
|
<field name="inherit_id" ref="document_page.view_wiki_form" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
|
|
||||||
<sheet position="before">
|
<sheet position="before">
|
||||||
<div class="alert alert-info" role="alert" style="margin-bottom:0px;"
|
<div
|
||||||
attrs="{'invisible': [('has_changes_pending_approval','=',False)]}">
|
class="alert alert-info"
|
||||||
This document has <b>Changes Pending Approval</b>. You are viewing the last approved content.
|
role="alert"
|
||||||
|
style="margin-bottom:0px;"
|
||||||
|
attrs="{'invisible': [('has_changes_pending_approval','=',False)]}"
|
||||||
|
>
|
||||||
|
This document has <b
|
||||||
|
>Changes Pending Approval</b>. You are viewing the last approved content.
|
||||||
</div>
|
</div>
|
||||||
<div class="alert alert-warning oe_edit_only" role="alert" style="margin-bottom:0px;"
|
<div
|
||||||
attrs="{'invisible': [('is_approval_required','=',False)]}">
|
class="alert alert-warning oe_edit_only"
|
||||||
This document requires approval. If edited, you will create a new <b>Change Request</b>.
|
role="alert"
|
||||||
|
style="margin-bottom:0px;"
|
||||||
|
attrs="{'invisible': [('is_approval_required','=',False)]}"
|
||||||
|
>
|
||||||
|
This document requires approval. If edited, you will create a new <b
|
||||||
|
>Change Request</b>.
|
||||||
</div>
|
</div>
|
||||||
<div class="alert alert-warning oe_edit_only" role="alert" style="margin-bottom:0px;"
|
<div
|
||||||
attrs="{'invisible': [('user_has_drafts','=',False)]}">
|
class="alert alert-warning oe_edit_only"
|
||||||
|
role="alert"
|
||||||
|
style="margin-bottom:0px;"
|
||||||
|
attrs="{'invisible': [('user_has_drafts','=',False)]}"
|
||||||
|
>
|
||||||
<b>You already have a Draft Change Request for this page.</b>
|
<b>You already have a Draft Change Request for this page.</b>
|
||||||
It is highly recommended that you edit that one instead of creating a new one.
|
It is highly recommended that you edit that one instead of creating a new one.
|
||||||
</div>
|
</div>
|
||||||
<field name="is_approval_required" invisible="1"/>
|
<field name="is_approval_required" invisible="1" />
|
||||||
<field name="has_changes_pending_approval" invisible="1"/>
|
<field name="has_changes_pending_approval" invisible="1" />
|
||||||
<field name="user_has_drafts" invisible="1"/>
|
<field name="user_has_drafts" invisible="1" />
|
||||||
</sheet>
|
</sheet>
|
||||||
|
|
||||||
<button name="toggle_active" position="after">
|
<button name="toggle_active" position="after">
|
||||||
<button class="oe_stat_button" name="action_changes_pending_approval" string="Change Requests" type="object"
|
<button
|
||||||
attrs="{'invisible':[('has_changes_pending_approval','=',False),('user_has_drafts','=',False)]}" icon="fa-edit"/>
|
class="oe_stat_button"
|
||||||
|
name="action_changes_pending_approval"
|
||||||
|
string="Change Requests"
|
||||||
|
type="object"
|
||||||
|
attrs="{'invisible':[('has_changes_pending_approval','=',False),('user_has_drafts','=',False)]}"
|
||||||
|
icon="fa-edit"
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<field name="content_uid" position="after">
|
<field name="content_uid" position="after">
|
||||||
<field name="approved_uid"/>
|
<field name="approved_uid" />
|
||||||
</field>
|
</field>
|
||||||
|
|
||||||
<field name="content_date" position="replace">
|
<field name="content_date" position="replace">
|
||||||
<field name="approved_date"/>
|
<field name="approved_date" />
|
||||||
</field>
|
</field>
|
||||||
|
|
||||||
<field name="history_ids" position="inside">
|
<field name="history_ids" position="inside">
|
||||||
<tree>
|
<tree>
|
||||||
<field name="id"/>
|
<field name="id" />
|
||||||
<field name="approved_date"/>
|
<field name="approved_date" />
|
||||||
<field name="summary"/>
|
<field name="summary" />
|
||||||
<field name="create_uid"/>
|
<field name="create_uid" />
|
||||||
<field name="approved_uid"/>
|
<field name="approved_uid" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
|
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- Page Menu Form View -->
|
<!-- Page Menu Form View -->
|
||||||
<record id="view_wiki_menu_form_inherit" model="ir.ui.view">
|
<record id="view_wiki_menu_form_inherit" model="ir.ui.view">
|
||||||
<field name="name">document.page.form</field>
|
<field name="name">document.page.form</field>
|
||||||
@ -126,14 +198,16 @@
|
|||||||
<field name="inherit_id" ref="document_page.view_wiki_menu_form" />
|
<field name="inherit_id" ref="document_page.view_wiki_menu_form" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="content" position="before">
|
<field name="content" position="before">
|
||||||
<group class="oe_read_only" attrs="{'invisible':[('type','!=','content')]}">
|
<group
|
||||||
|
class="oe_read_only"
|
||||||
|
attrs="{'invisible':[('type','!=','content')]}"
|
||||||
|
>
|
||||||
<field name="approved_date" />
|
<field name="approved_date" />
|
||||||
<field name="approved_uid" />
|
<field name="approved_uid" />
|
||||||
</group>
|
</group>
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- Catgory Form View -->
|
<!-- Catgory Form View -->
|
||||||
<record id="view_category_form_inherit" model="ir.ui.view">
|
<record id="view_category_form_inherit" model="ir.ui.view">
|
||||||
<field name="name">document.page.category.form</field>
|
<field name="name">document.page.category.form</field>
|
||||||
@ -141,18 +215,19 @@
|
|||||||
<field name="inherit_id" ref="document_page.view_category_form" />
|
<field name="inherit_id" ref="document_page.view_category_form" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="parent_id" position="after">
|
<field name="parent_id" position="after">
|
||||||
<field name="approval_required"/>
|
<field name="approval_required" />
|
||||||
<field name="approver_gid"
|
<field
|
||||||
attrs="{'invisible':[('approval_required','!=', True)], 'required':[('approval_required','=', True)]}"/>
|
name="approver_gid"
|
||||||
|
attrs="{'invisible':[('approval_required','!=', True)], 'required':[('approval_required','=', True)]}"
|
||||||
|
/>
|
||||||
</field>
|
</field>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- History Tree view -->
|
<!-- History Tree view -->
|
||||||
<record id="view_wiki_history_tree_inherit" model="ir.ui.view">
|
<record id="view_wiki_history_tree_inherit" model="ir.ui.view">
|
||||||
<field name="name">document.page.history.tree</field>
|
<field name="name">document.page.history.tree</field>
|
||||||
<field name="model">document.page.history</field>
|
<field name="model">document.page.history</field>
|
||||||
<field name="inherit_id" ref="document_page.view_wiki_history_tree"/>
|
<field name="inherit_id" ref="document_page.view_wiki_history_tree" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree position="attributes">
|
<tree position="attributes">
|
||||||
<attribute name="decoration-info">state=='draft'</attribute>
|
<attribute name="decoration-info">state=='draft'</attribute>
|
||||||
@ -160,52 +235,71 @@
|
|||||||
<attribute name="decoration-muted">state=='cancelled'</attribute>
|
<attribute name="decoration-muted">state=='cancelled'</attribute>
|
||||||
</tree>
|
</tree>
|
||||||
<tree position="inside">
|
<tree position="inside">
|
||||||
<field name="state"/>
|
<field name="state" />
|
||||||
<field name="approved_uid"/>
|
<field name="approved_uid" />
|
||||||
<field name="approved_date"/>
|
<field name="approved_date" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<!-- History Search view -->
|
<!-- History Search view -->
|
||||||
<record id="view_wiki_history_filter" model="ir.ui.view">
|
<record id="view_wiki_history_filter" model="ir.ui.view">
|
||||||
<field name="name">document.page.history.search</field>
|
<field name="name">document.page.history.search</field>
|
||||||
<field name="model">document.page.history</field>
|
<field name="model">document.page.history</field>
|
||||||
<field name="inherit_id" ref="document_page.view_wiki_history_filter"/>
|
<field name="inherit_id" ref="document_page.view_wiki_history_filter" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="page_id" position="before">
|
<field name="page_id" position="before">
|
||||||
<field name="state"/>
|
<field name="state" />
|
||||||
</field>
|
</field>
|
||||||
<field name="create_uid" position="after">
|
<field name="create_uid" position="after">
|
||||||
<filter name="draft" string="Draft" domain="[('state','=','draft')]"/>
|
<filter name="draft" string="Draft" domain="[('state','=','draft')]" />
|
||||||
<filter name="pending" string="Pending Approval" domain="[('state','=','to approve')]"/>
|
<filter
|
||||||
<filter name="approved" string="Approved" domain="[('state','=','approved')]"/>
|
name="pending"
|
||||||
<filter name="cancelled" string="Cancelled" domain="[('state','=','cancelled')]"/>
|
string="Pending Approval"
|
||||||
|
domain="[('state','=','to approve')]"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
|
name="approved"
|
||||||
|
string="Approved"
|
||||||
|
domain="[('state','=','approved')]"
|
||||||
|
/>
|
||||||
|
<filter
|
||||||
|
name="cancelled"
|
||||||
|
string="Cancelled"
|
||||||
|
domain="[('state','=','cancelled')]"
|
||||||
|
/>
|
||||||
</field>
|
</field>
|
||||||
<filter name="group_by_author" position="before">
|
<filter name="group_by_author" position="before">
|
||||||
<filter name="group_state" string="State" context="{'group_by':'state'}" />
|
<filter
|
||||||
|
name="group_state"
|
||||||
|
string="State"
|
||||||
|
context="{'group_by':'state'}"
|
||||||
|
/>
|
||||||
</filter>
|
</filter>
|
||||||
<filter name="group_by_author" position="after">
|
<filter name="group_by_author" position="after">
|
||||||
<filter name="group_approver" string="Approver" context="{'group_by':'approved_uid'}" />
|
<filter
|
||||||
|
name="group_approver"
|
||||||
|
string="Approver"
|
||||||
|
context="{'group_by':'approved_uid'}"
|
||||||
|
/>
|
||||||
</filter>
|
</filter>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- Change Requests Action -->
|
<!-- Change Requests Action -->
|
||||||
<record model="ir.actions.act_window" id="action_change_requests">
|
<record model="ir.actions.act_window" id="action_change_requests">
|
||||||
<field name="name">Change Requests</field>
|
<field name="name">Change Requests</field>
|
||||||
<field name="res_model">document.page.history</field>
|
<field name="res_model">document.page.history</field>
|
||||||
<field name="view_type">form</field>
|
<field name="view_type">form</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
<field name="context">{'search_default_draft': 1, 'search_default_pending': 1}</field>
|
<field
|
||||||
|
name="context"
|
||||||
|
>{'search_default_draft': 1, 'search_default_pending': 1}</field>
|
||||||
</record>
|
</record>
|
||||||
|
<menuitem
|
||||||
<menuitem id="menu_page_change_requests"
|
id="menu_page_change_requests"
|
||||||
name="Change Requests"
|
name="Change Requests"
|
||||||
parent="document_page.menu_wiki"
|
parent="document_page.menu_wiki"
|
||||||
action="action_change_requests"
|
action="action_change_requests"
|
||||||
sequence="25"
|
sequence="25"
|
||||||
groups="document_page.group_document_editor" />
|
groups="document_page.group_document_editor"
|
||||||
|
/>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
Loading…
Reference in New Issue
Block a user