Skip to content

Commit

Permalink
Merge 503e12a into 6b80913
Browse files Browse the repository at this point in the history
  • Loading branch information
ivantodorovich committed Sep 15, 2018
2 parents 6b80913 + 503e12a commit 8bd148a
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 76 deletions.
2 changes: 1 addition & 1 deletion document_page_approval/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

{
'name': 'Document Page Approval',
'version': '11.0.1.0.0',
'version': '11.0.2.0.0',
"author": "Savoir-faire Linux, Odoo Community Association (OCA)",
"website": "http://www.savoirfairelinux.com",
"license": "AGPL-3",
Expand Down
2 changes: 1 addition & 1 deletion document_page_approval/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from . import document_page_approval, document_page_history_workflow
from . import document_page, document_page_history
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from ast import literal_eval


class DocumentPageApproval(models.Model):
class DocumentPage(models.Model):
"""Useful to know the state of a document."""

_inherit = 'document.page'
Expand Down Expand Up @@ -66,6 +66,11 @@ class DocumentPageApproval(models.Model):
string='Has changes pending approval'
)

user_has_drafts = fields.Boolean(
compute='_compute_user_has_drafts',
string='User has drafts?',
)

@api.multi
@api.depends('approval_required', 'parent_id.is_approval_required')
def _compute_is_approval_required(self):
Expand Down Expand Up @@ -100,14 +105,17 @@ def can_user_approve_this_page(self, user):
# if it's not required, anyone can approve
if not self.is_approval_required:
return True
# to approve, you must have approver rights
approver_group_id = self.env.ref(
'document_page_approval.group_document_approver_user')
if approver_group_id not in user.groups_id:
# if user belongs to 'Knowledge / Manager', he can approve anything
if user.has_group('document_page.group_document_manager'):
return True
# to approve, user must have approver rights
if not user.has_group(
'document_page_approval.group_document_approver_user'):
return False
# and belong to at least one of the approver_groups (if any is set)
# if there aren't any approver_groups_defined, user can approve
if not self.approver_group_ids:
return True
# to approve, user must belong to any of the approver groups
return len(user.groups_id & self.approver_group_ids) > 0

@api.multi
Expand All @@ -119,10 +127,19 @@ def _compute_has_changes_pending_approval(self):
('state', '=', 'to approve')])
rec.has_changes_pending_approval = (changes > 0)

@api.multi
def _compute_user_has_drafts(self):
history = self.env['document.page.history']
for rec in self:
changes = history.search_count([
('page_id', '=', rec.id),
('state', '=', 'draft')])
rec.user_has_drafts = (changes > 0)

@api.multi
def _create_history(self, vals):
res = super(DocumentPageApproval, self)._create_history(vals)
res.document_page_auto_confirm()
res = super(DocumentPage, self)._create_history(vals)
res.action_to_approve()

@api.multi
def action_changes_pending_approval(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from datetime import datetime
from odoo.tools.translate import _
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
from odoo import api, fields, models
from odoo.exceptions import UserError


class DocumentPageHistoryWorkflow(models.Model):
class DocumentPageHistory(models.Model):
"""Useful to manage edition's workflow on a document."""

_name = 'document.page.history'
Expand All @@ -20,8 +18,8 @@ class DocumentPageHistoryWorkflow(models.Model):
('approved', 'Approved'),
('cancelled', 'Cancelled')],
'Status',
default='draft',
readonly=True,
default='draft'
)

approved_date = fields.Datetime(
Expand All @@ -43,7 +41,8 @@ class DocumentPageHistoryWorkflow(models.Model):
)

am_i_approver = fields.Boolean(
compute='_compute_am_i_approver'
related='page_id.am_i_approver',
related_sudo=False,
)

page_url = fields.Text(
Expand All @@ -52,56 +51,66 @@ class DocumentPageHistoryWorkflow(models.Model):
)

@api.multi
def page_approval_draft(self):
def action_draft(self):
"""Set a change request as draft"""
if self.filtered(lambda r: r.state not in [
'cancelled', 'approved']):
raise UserError(_("It's not cancelled or approved"))
if self.filtered(lambda r:
r.state == 'approved' and not self.am_i_approver):
raise UserError(_("You are not an appover to reset to draft"))
self.write({'state': 'draft'})

@api.multi
def document_page_auto_confirm(self):
"""Automatic Transitions for change requests created directly from
documents
"""
if self.filtered(lambda r: r.state != 'draft'):
raise UserError(_("It's not in draft state"))
to_approve = self.filtered(lambda r: r.is_approval_required)
to_approve.write({'state': 'to approve'})
approved = (self - to_approve)
approved.write({'state': 'approved'})
approved.mapped('page_id')._compute_history_head()
for rec in self:
if not rec.state == 'cancelled':
raise UserError(
_('You need to cancel it before reopening.'))
if not (rec.am_i_owner or rec.am_i_approver):
raise UserError(
_('You are not authorized to do this.\r\n'
'Only owners or approvers can reopen Change Requests.'))
rec.write({'state': 'draft'})

@api.multi
def page_approval_to_approve(self):
def action_to_approve(self):
"""Set a change request as to approve"""
self.write({'state': 'to approve'})
template = self.env.ref(
'document_page_approval.email_template_new_draft_need_approval')
approver_gid = self.env.ref(
'document_page_approval.group_document_approver_user')
for rec in self:
if rec.state != 'draft':
raise UserError(
_("Can't approve pages in '%s' state.") % rec.state)
if not (rec.am_i_owner or rec.am_i_approver):
raise UserError(
_('You are not authorized to do this.\r\n'
'Only owners or approvers can request approval.'))
# request approval
if rec.is_approval_required:
rec.write({'state': 'to approve'})
guids = [g.id for g in rec.page_id.approver_group_ids]
users = self.env['res.users'].search([
('groups_id', 'in', guids),
('groups_id', 'in', approver_gid.id)])
rec.message_subscribe_users([u.id for u in users])
rec.message_post_with_template(template.id)
else:
# auto-approve if approval is not required
rec.action_approve()

@api.multi
def page_approval_approved(self):
def action_approve(self):
"""Set a change request as approved."""
self.write({
'state': 'approved',
'approved_date': datetime.now().strftime(
DEFAULT_SERVER_DATETIME_FORMAT),
'approved_uid': self.env.uid
})
for rec in self:
if rec.state not in ['draft', 'to approve']:
raise UserError(
_("Can't approve page in '%s' state.") % rec.state)
if not rec.am_i_approver:
raise UserError(_(
'You are not authorized to do this.\r\n'
'Only approvers with these groups can approve this: '
) % ', '.join(
[g.display_name
for g in rec.page_id.approver_group_ids]))
# Update state
rec.write({
'state': 'approved',
'approved_date': fields.datetime.now(),
'approved_uid': self.env.uid,
})
# Trigger computed field update
rec.page_id._compute_history_head()
# Notify state change
Expand All @@ -120,7 +129,7 @@ def page_approval_approved(self):
)

@api.multi
def page_approval_cancelled(self):
def action_cancel(self):
"""Set a change request as cancelled."""
self.write({'state': 'cancelled'})
for rec in self:
Expand All @@ -131,19 +140,18 @@ def page_approval_cancelled(self):
) % (rec.display_name, self.env.user.name)
)

@api.multi
def action_cancel_and_draft(self):
"""Set a change request as draft, cancelling it first"""
self.action_cancel()
self.action_draft()

@api.multi
def _compute_am_i_owner(self):
"""Check if current user is the owner"""
for rec in self:
rec.am_i_owner = (rec.create_uid == self.env.user)

@api.multi
def _compute_am_i_approver(self):
"""check if current user is a approver"""
for rec in self:
rec.am_i_approver = rec.page_id.can_user_approve_this_page(
self.env.user)

@api.multi
def _compute_page_url(self):
"""Compute the page url."""
Expand Down
21 changes: 21 additions & 0 deletions document_page_approval/security/document_page_security.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,25 @@
<field name="implied_ids" eval="[(4, ref('group_document_approver_user'))]"/>
</record>

<record model="ir.rule" id="rule_change_request_global">
<field name="name">Change Request Global</field>
<field name="model_id" ref="model_document_page_history"/>
<field name="domain_force">['|',('state','=','approved'),('create_uid','=',user.id)]</field>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_unlink" eval="True"/>
<field name="perm_create" eval="True"/>
</record>

<record model="ir.rule" id="rule_change_request_approver">
<field name="name">Change Request Approver</field>
<field name="model_id" ref="model_document_page_history"/>
<field name="groups" eval="[(6, 0, [ref('group_document_approver_user')])]"/>
<field name="domain_force">[('state','!=','draft')]</field>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_unlink" eval="True"/>
<field name="perm_create" eval="True"/>
</record>

</odoo>
14 changes: 7 additions & 7 deletions document_page_approval/tests/test_document_page_approval.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def test_change_request_approve(self):
self.assertTrue(chreq.am_i_approver)

# approve
chreq.page_approval_approved()
chreq.action_approve()
self.assertEqual(chreq.state, 'approved')
self.assertEqual(chreq.content, page.content)

Expand All @@ -58,7 +58,7 @@ def test_change_request_approve(self):
('page_id', '=', page.id),
('state', '!=', 'approved')
])[0]
chreq.page_approval_approved()
chreq.action_approve()
self.assertEqual(page.content, 'New content')

def test_change_request_auto_approve(self):
Expand All @@ -74,7 +74,7 @@ def test_change_request_from_scratch(self):
self.history_obj.search([
('page_id', '=', page.id),
('state', '!=', 'approved')
]).page_approval_approved()
]).action_approve()

# new change request from scrath
chreq = self.history_obj.create({
Expand All @@ -88,25 +88,25 @@ def test_change_request_from_scratch(self):
self.assertNotEqual(page.approved_date, chreq.approved_date)
self.assertNotEqual(page.approved_uid, chreq.approved_uid)

chreq.page_approval_to_approve()
chreq.action_to_approve()
self.assertEqual(chreq.state, 'to approve')
self.assertNotEqual(page.content, chreq.content)
self.assertNotEqual(page.approved_date, chreq.approved_date)
self.assertNotEqual(page.approved_uid, chreq.approved_uid)

chreq.page_approval_cancelled()
chreq.action_cancel()
self.assertEqual(chreq.state, 'cancelled')
self.assertNotEqual(page.content, chreq.content)
self.assertNotEqual(page.approved_date, chreq.approved_date)
self.assertNotEqual(page.approved_uid, chreq.approved_uid)

chreq.page_approval_draft()
chreq.action_draft()
self.assertEqual(chreq.state, 'draft')
self.assertNotEqual(page.content, chreq.content)
self.assertNotEqual(page.approved_date, chreq.approved_date)
self.assertNotEqual(page.approved_uid, chreq.approved_uid)

chreq.page_approval_approved()
chreq.action_approve()
self.assertEqual(chreq.state, 'approved')
self.assertEqual(page.content, chreq.content)
self.assertEqual(page.approved_date, chreq.approved_date)
Expand Down
Loading

0 comments on commit 8bd148a

Please sign in to comment.