From 1c1c55ba3d4818e48e35f11455b73e6695a1aba6 Mon Sep 17 00:00:00 2001 From: Gervais Naoussi Date: Wed, 28 Oct 2015 10:55:22 -0400 Subject: [PATCH] [MIG] document_page_approval: Migration to 9.0 * Lint error corrected * test improved * lint error corrected in test file * readme corrected * test improved * test of document page history workflow added * CI error corrected * dreipst comment * Migration to new api improved in model's file and data tag remove in xml file * code totally migrate to odoo 9.0 api * test bug fixed * test error fixed * Lint error improved --- document_page_approval/README.rst | 88 ++++++++++ document_page_approval/__init__.py | 4 +- document_page_approval/__openerp__.py | 26 +-- .../data/email_template.xml | 10 +- document_page_approval/models/__init__.py | 2 + .../models/document_page_approval.py | 130 ++++++++++++++ .../document_page_history_workflow.py} | 158 ++++-------------- .../security/document_page_security.xml | 6 +- .../security/ir.model.access.csv | 2 +- document_page_approval/tests/__init__.py | 2 + .../tests/test_document_page_approval.py | 37 ++++ .../test_document_page_history_workflow.py | 67 ++++++++ .../document_page_approval.xml} | 6 +- .../document_page_approval.xml} | 9 +- 14 files changed, 379 insertions(+), 168 deletions(-) create mode 100644 document_page_approval/README.rst create mode 100644 document_page_approval/models/__init__.py create mode 100644 document_page_approval/models/document_page_approval.py rename document_page_approval/{document_page_approval.py => models/document_page_history_workflow.py} (53%) create mode 100644 document_page_approval/tests/__init__.py create mode 100644 document_page_approval/tests/test_document_page_approval.py create mode 100644 document_page_approval/tests/test_document_page_history_workflow.py rename document_page_approval/{document_page_view.xml => views/document_page_approval.xml} (98%) rename document_page_approval/{document_page_wkfl.xml => workflows/document_page_approval.xml} (97%) diff --git a/document_page_approval/README.rst b/document_page_approval/README.rst new file mode 100644 index 00000000..affff9ce --- /dev/null +++ b/document_page_approval/README.rst @@ -0,0 +1,88 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +====================== +Document Page Approval +====================== + +This module adds a workflow to approve page modification and show the approved +version by default. + +Installation +============ + +Makes the document page approval available from where some users can approved the modifications +made by others users in documents that required approvement. + +Configuration +============= + +No configuration required + +Usage +===== + +To use this module, you need to: + +* Set a valid email address on the company settings. +* go to knowledge > Categories. +* Create a new page category and set an approver group. Make sure users + belonging to that group have valid email addresses. +* go to knowledge > Pages +* Create a new page and choose the previously created category. +* A notification is sent to the group with a link to the page history to + review. +* Depending on the review, the page history is approved or not. +* Users reading the page see the last approved version. + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.odoo-community.org/runbot/118/9.0 + +Known issues / Roadmap +====================== + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed feedback `here `_. + + +Credits +======= + +Contributors +------------ + +* Odoo SA +* Savoir-faire Linux +* Gervais Naoussi + +Maintainer +---------- + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +This module is maintained by the OCA. + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +To contribute to this module, please visit http://odoo-community.org. + +Changelog +--------- + +v9.0.1.0.0 + +Here are the modification that have been done: + +* The module does no depends anymore on email_template but on mail module diff --git a/document_page_approval/__init__.py b/document_page_approval/__init__.py index d2b3bb9e..7f626589 100644 --- a/document_page_approval/__init__.py +++ b/document_page_approval/__init__.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # OpenERP, Open Source Management Solution @@ -18,4 +18,4 @@ # along with this program. If not, see . # ############################################################################## -from . import document_page_approval +from . import models diff --git a/document_page_approval/__openerp__.py b/document_page_approval/__openerp__.py index a60b5a0c..1e95feb3 100644 --- a/document_page_approval/__openerp__.py +++ b/document_page_approval/__openerp__.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # OpenERP, Open Source Management Solution @@ -21,36 +21,20 @@ { 'name': 'Document Page Approval', - 'version': '8.0.1.0.0', + 'version': '9.0.1.0.0', "author": "Savoir-faire Linux,Odoo Community Association (OCA)", "website": "http://www.savoirfairelinux.com", "license": "AGPL-3", 'category': 'Knowledge Management', - 'description': """ -This module adds a workflow to approve page modification and show the approved -version by default. - -Scenario -======== - -* Set a valid email address on the company settings. -* Create a new page category and set an approver group. Make sure users - belonging to that group have valid email addresses. -* Create a new page and choose the previously created category. -* A notification is sent to the group with a link to the page history to - review. -* Depending on the review, the page history is approved or not. -* Users reading the page see the last approved version. - """, 'depends': [ 'knowledge', 'document_page', - 'email_template', + 'mail', ], 'data': [ 'data/email_template.xml', - 'document_page_wkfl.xml', - 'document_page_view.xml', + 'workflows/document_page_approval.xml', + 'views/document_page_approval.xml', 'security/document_page_security.xml', 'security/ir.model.access.csv', ], diff --git a/document_page_approval/data/email_template.xml b/document_page_approval/data/email_template.xml index 00a9734a..e31c8bcb 100644 --- a/document_page_approval/data/email_template.xml +++ b/document_page_approval/data/email_template.xml @@ -1,12 +1,11 @@ - + - + Automated new draft need approval Notification Mail ${object.create_uid.company_id.email or 'noreply@localhost.com'} New version of "${object.page_id.name}" to approve @@ -14,7 +13,8 @@ ${object.create_uid.partner_id.lang} - + Hello,

The page "${object.page_id.name}" has been modified and need your approval.

@@ -28,4 +28,4 @@ Odoo

]]>
-
+ diff --git a/document_page_approval/models/__init__.py b/document_page_approval/models/__init__.py new file mode 100644 index 00000000..91075fe8 --- /dev/null +++ b/document_page_approval/models/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import document_page_approval, document_page_history_workflow diff --git a/document_page_approval/models/document_page_approval.py b/document_page_approval/models/document_page_approval.py new file mode 100644 index 00000000..278f5227 --- /dev/null +++ b/document_page_approval/models/document_page_approval.py @@ -0,0 +1,130 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2013 Savoir-faire Linux (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields, api + + +class DocumentPageApproval(models.Model): + """Useful to know the state of a document.""" + + _inherit = 'document.page' + + @api.multi + def _get_display_content(self): + """Display the content of document.""" + for page in self: + content = "" + if page.type == "category": + content = self._get_page_index(page, link=False) + else: + history = self.env['document.page.history'] + if self.is_approval_required(page): + history_ids = history.search( + [ + ('page_id', '=', page.id), + ('state', '=', 'approved') + ], + limit=1, + order='create_date DESC' + ) + content = history_ids.content + else: + content = page.content + page.display_content = content + + @api.multi + def _get_approved_date(self): + """Return the approved date of a document.""" + for page in self: + approved_date = False + if self.is_approval_required(page): + history = self.env['document.page.history'] + history_ids = history.search( + [ + ('page_id', '=', page.id), + ('state', '=', 'approved') + ], + limit=1, + order='create_date DESC' + ) + approved_date = history_ids.approved_date + page.approved_date = approved_date + + @api.multi + def _get_approved_uid(self): + """Return the user's id of the approved user.""" + for page in self: + approved_uid = False + if self.is_approval_required(page): + history = self.env['document.page.history'] + history_ids = history.search( + [ + ('page_id', '=', page.id), + ('state', '=', 'approved') + ], + limit=1, + order='create_date DESC' + ) + approved_uid = history_ids.approved_uid.id + page.approved_uid = approved_uid + + @api.multi + def _is_parent_approval_required(self): + """Check if the document required approval base on his parrent.""" + for page in self: + page.is_parent_approval_required = self.is_approval_required(page) + + def is_approval_required(self, page): + """Check if a document required approval.""" + if page: + res = page.approval_required + res = res or self.is_approval_required(page.parent_id) + else: + res = False + return res + + display_content = fields.Text( + compute=_get_display_content, + string='Displayed Content' + ) + + approved_date = fields.Datetime( + compute=_get_approved_date, + string="Approved Date" + ) + + approved_uid = fields.Many2one( + 'res.users', + compute=_get_approved_uid, + string="Approved By", + ) + + approval_required = fields.Boolean("Require approval") + + is_parent_approval_required = fields.Boolean( + compute=_is_parent_approval_required, + string="parent approval" + ) + + approver_gid = fields.Many2one( + "res.groups", + "Approver group" + ) diff --git a/document_page_approval/document_page_approval.py b/document_page_approval/models/document_page_history_workflow.py similarity index 53% rename from document_page_approval/document_page_approval.py rename to document_page_approval/models/document_page_history_workflow.py index 8f11e5f7..2eeb7e91 100644 --- a/document_page_approval/document_page_approval.py +++ b/document_page_approval/models/document_page_history_workflow.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- coding: utf-8 -*- ############################################################################## # # OpenERP, Open Source Management Solution @@ -22,54 +22,51 @@ from datetime import datetime from openerp.tools.translate import _ from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT -from openerp import models, fields, SUPERUSER_ID +from openerp import models, fields, api -class document_page_history_wkfl(models.Model): +class DocumentPageHistoryWorkflow(models.Model): + """Useful to manage edition's workflow on a document.""" + _inherit = 'document.page.history' - def page_approval_draft(self, cr, uid, ids, context=None): - self.write(cr, uid, ids, {'state': 'draft'}) - template_id = self.pool.get('ir.model.data').get_object_reference( - cr, uid, - 'document_page_approval', - 'email_template_new_draft_need_approval')[1] - for page in self.browse(cr, uid, ids, context=context): + @api.multi + def page_approval_draft(self): + """Set a document state as draft and notified the reviewers.""" + self.write({'state': 'draft'}) + template = self.env.ref( + 'document_page_approval.email_template_new_draft_need_approval') + for page in self: if page.is_parent_approval_required: - self.pool.get('email.template').send_mail( - cr, - uid, - template_id, - page.id, - force_send=True - ) + template.send_mail(page.id, force_send=True) return True - def page_approval_approved(self, cr, uid, ids, context=None): - model_data_obj = self.pool.get('ir.model.data') - message_obj = self.pool.get('mail.message') - self.write(cr, uid, ids, { + @api.multi + def page_approval_approved(self): + """Set a document state as approve.""" + message_obj = self.env['mail.message'] + self.write({ 'state': 'approved', 'approved_date': datetime.now().strftime( DEFAULT_SERVER_DATETIME_FORMAT), - 'approved_uid': uid - }, context=context) + 'approved_uid': self.env.uid + }) # Notify followers a new version is available - for page_history in self.browse(cr, uid, ids, context=context): - subtype_id = model_data_obj.get_object_reference( - cr, SUPERUSER_ID, 'mail', 'mt_comment')[1] + for page_history in self: + subtype = self.env.ref('mail.mt_comment') message_obj.create( - cr, uid, {'res_id': page_history.page_id.id, 'model': 'document.page', - 'subtype_id': subtype_id, + 'subtype_id': subtype.id, 'body': _('New version of the document %s' ' approved.') % page_history.page_id.name } ) return True + @api.multi def _can_user_approve_page(self): + """Check if a user cas approve the page.""" user = self.env.user for page in self: page.can_user_approve_page = page.can_user_approve_this_page( @@ -78,6 +75,7 @@ class document_page_history_wkfl(models.Model): ) def can_user_approve_this_page(self, page, user): + """Check if a user can approved the page.""" if page: res = page.approver_gid in user.groups_id res = res or self.can_user_approve_this_page(page.parent_id, user) @@ -85,13 +83,16 @@ class document_page_history_wkfl(models.Model): res = False return res + @api.multi def get_approvers_guids(self): + """Return the approvers group.""" res = {} for page in self: res[page.id] = self.get_approvers_guids_for_page(page.page_id) return res def get_approvers_guids_for_page(self, page): + """Return the approvers group for a page.""" if page: if page.approver_gid: res = [page.approver_gid.id] @@ -103,7 +104,9 @@ class document_page_history_wkfl(models.Model): return res + @api.multi def _get_approvers_email(self): + """Get the approvers email.""" for page in self: emails = '' guids = self.get_approvers_guids() @@ -126,7 +129,9 @@ class document_page_history_wkfl(models.Model): page.get_approvers_email = emails[:-1] + @api.multi def _get_page_url(self): + """Get the page url.""" for page in self: base_url = self.env['ir.config_parameter'].get_param( 'web.base.url', @@ -175,100 +180,3 @@ class document_page_history_wkfl(models.Model): string="URL", store=False ) - - -class document_page_approval(models.Model): - _inherit = 'document.page' - - def _get_display_content(self): - for page in self: - content = "" - if page.type == "category": - content = self._get_page_index(page, link=False) - else: - history = self.env['document.page.history'] - if self.is_approval_required(page): - history_ids = history.search( - [ - ('page_id', '=', page.id), - ('state', '=', 'approved') - ], - limit=1, - order='create_date DESC' - ) - content = history_ids.content - else: - content = page.content - page.display_content = content - - def _get_approved_date(self): - for page in self: - approved_date = False - if self.is_approval_required(page): - history = self.env['document.page.history'] - history_ids = history.search( - [ - ('page_id', '=', page.id), - ('state', '=', 'approved') - ], - limit=1, - order='create_date DESC' - ) - approved_date = history_ids.approved_date - page.approved_date = approved_date - - def _get_approved_uid(self): - for page in self: - approved_uid = False - if self.is_approval_required(page): - history = self.env['document.page.history'] - history_ids = history.search( - [ - ('page_id', '=', page.id), - ('state', '=', 'approved') - ], - limit=1, - order='create_date DESC' - ) - approved_uid = history_ids.approved_uid.id - page.approved_uid = approved_uid - - def _is_parent_approval_required(self): - for page in self: - page.is_parent_approval_required = self.is_approval_required(page) - - def is_approval_required(self, page): - if page: - res = page.approval_required - res = res or self.is_approval_required(page.parent_id) - else: - res = False - return res - - display_content = fields.Text( - compute=_get_display_content, - string='Displayed Content' - ) - - approved_date = fields.Datetime( - compute=_get_approved_date, - string="Approved Date" - ) - - approved_uid = fields.Many2one( - 'res.users', - compute=_get_approved_uid, - string="Approved By", - ) - - approval_required = fields.Boolean("Require approval") - - is_parent_approval_required = fields.Boolean( - compute=_is_parent_approval_required, - string="parent approval" - ) - - approver_gid = fields.Many2one( - "res.groups", - "Approver group" - ) diff --git a/document_page_approval/security/document_page_security.xml b/document_page_approval/security/document_page_security.xml index 7192d3f8..d41d96f8 100644 --- a/document_page_approval/security/document_page_security.xml +++ b/document_page_approval/security/document_page_security.xml @@ -1,9 +1,9 @@ - + - + Document approver - + diff --git a/document_page_approval/security/ir.model.access.csv b/document_page_approval/security/ir.model.access.csv index e4835836..f8e75f15 100644 --- a/document_page_approval/security/ir.model.access.csv +++ b/document_page_approval/security/ir.model.access.csv @@ -1,2 +1,2 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -document_page_history,document.page.history,model_document_page_history,base.group_document_approver_user,1,1,1,0 \ No newline at end of file +document_page_history,document.page.history,model_document_page_history,group_document_approver_user,1,1,1,0 diff --git a/document_page_approval/tests/__init__.py b/document_page_approval/tests/__init__.py new file mode 100644 index 00000000..2413da81 --- /dev/null +++ b/document_page_approval/tests/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import test_document_page_approval, test_document_page_history_workflow diff --git a/document_page_approval/tests/test_document_page_approval.py b/document_page_approval/tests/test_document_page_approval.py new file mode 100644 index 00000000..4c0e8457 --- /dev/null +++ b/document_page_approval/tests/test_document_page_approval.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +from openerp.tests import common + + +class TestDocumentPageApproval(common.TransactionCase): + """Test document page approval model.""" + + def test_get_display_content(self): + """Test page display content.""" + # Check content of a category + category = self.env['document.page'].search([ + ('name', '=', 'OpenERP Features') + ]) + + self.assertIsNotNone(category.display_content, 'a category') + + # Check content of a page + pages = self.env['document.page'].search([ + ('parent_id', '=', category.id) + ]) + page = pages[0] + self.assertIsNotNone(page.display_content, 'Page content') + + # Check if approval is required + self.assertTrue(page.is_approval_required(page) == + category.approval_required) + + # Check content of an approval page + page.approval_required = True + + self.assertIsNotNone(page.display_content, 'Page content') + + # Check if approval is required + self.assertTrue(page.is_approval_required(page)) + + # Check if parent approval is required + self.assertTrue(page.is_parent_approval_required) diff --git a/document_page_approval/tests/test_document_page_history_workflow.py b/document_page_approval/tests/test_document_page_history_workflow.py new file mode 100644 index 00000000..508aff80 --- /dev/null +++ b/document_page_approval/tests/test_document_page_history_workflow.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +from openerp.tests import common +# Import logger +import logging + +# Get the logger +_logger = logging.getLogger(__name__) + + +class TestDocumentPageHistoryWorkflow(common.TransactionCase): + """Test document page history workflow.""" + + def test_can_user_approve_this_page(self): + """Test if a user can approve this page.""" + category = self.env.ref('document_page.demo_category1') + category.approval_required = True + category.approver_gid = self.env.ref( + 'document_page_approval.group_document_approver_user') + + page = self.env['document.page'].create({ + 'name': 'Test Page10', + 'content': 'A difficult test', + 'parent_id': category.id + }) + + history = self.env['document.page.history'].search( + [ + ('page_id', '=', page.id) + ], + limit=1, + order='create_date DESC' + ) + + self.assertTrue(history.can_user_approve_page) + + def test_get_approvers_guids(self): + """Get approver guids.""" + category = self.env.ref('document_page.demo_category1') + category.approval_required = True + pages = self.env['document.page.history'].search([ + ('page_id', '=', category.id) + ]) + page = pages[0] + approvers_guid = page.get_approvers_guids() + self.assertTrue(len(approvers_guid) > 0) + + def test_get_approvers_email(self): + """Get approver email.""" + category = self.env.ref('document_page.demo_category1') + category.approval_required = True + pages = self.env['document.page.history'].search([ + ('page_id', '=', category.id) + ]) + page = pages[0] + _logger.info("Email: " + str(page.get_approvers_email)) + self.assertIsNotNone(page.get_approvers_email) + + def test_get_page_url(self): + """Test if page url exist.""" + category = self.env.ref('document_page.demo_category1') + category.approval_required = True + pages = self.env['document.page.history'].search([ + ('page_id', '=', category.id) + ]) + page = pages[0] + _logger.info("Page: " + str(page.get_page_url)) + self.assertIsNotNone(page.get_page_url) diff --git a/document_page_approval/document_page_view.xml b/document_page_approval/views/document_page_approval.xml similarity index 98% rename from document_page_approval/document_page_view.xml rename to document_page_approval/views/document_page_approval.xml index e12885fa..6b0e5c91 100644 --- a/document_page_approval/document_page_view.xml +++ b/document_page_approval/views/document_page_approval.xml @@ -1,6 +1,5 @@ - - + document.page.history.form document.page.history @@ -89,5 +88,4 @@ - - + diff --git a/document_page_approval/document_page_wkfl.xml b/document_page_approval/workflows/document_page_approval.xml similarity index 97% rename from document_page_approval/document_page_wkfl.xml rename to document_page_approval/workflows/document_page_approval.xml index 7dc85019..ea8a254b 100644 --- a/document_page_approval/document_page_wkfl.xml +++ b/document_page_approval/workflows/document_page_approval.xml @@ -1,7 +1,5 @@ - - - + document.page.history.aproval.wkf document.page.history @@ -37,7 +35,4 @@ edit - - - - +