# Copyright (C) 2013 Savoir-faire Linux (). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import api, fields, models from odoo.exceptions import UserError from odoo.tools.translate import _ class DocumentPageHistory(models.Model): """Useful to manage edition's workflow on a document.""" _name = "document.page.history" _inherit = ["document.page.history", "mail.thread"] state = fields.Selection( [ ("draft", "Draft"), ("to approve", "Pending Approval"), ("approved", "Approved"), ("cancelled", "Cancelled"), ], "Status", default="draft", readonly=True, ) approved_date = fields.Datetime("Approved Date",) approved_uid = fields.Many2one("res.users", "Approved by",) is_approval_required = fields.Boolean( related="page_id.is_approval_required", string="Approval required", ) am_i_owner = fields.Boolean(compute="_compute_am_i_owner") am_i_approver = fields.Boolean(related="page_id.am_i_approver", related_sudo=False,) page_url = fields.Text(compute="_compute_page_url", string="URL",) @api.multi def action_draft(self): """Set a change request as draft""" 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 action_to_approve(self): """Set a change request as 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([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 action_approve(self): """Set a change request as approved.""" 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 rec.message_post( subtype="mt_comment", body=_("Change request has been approved by %s.") % (self.env.user.name), ) # Notify followers a new version is available rec.page_id.message_post( subtype="mt_comment", body=_("New version of the document %s approved.") % (rec.page_id.name), ) @api.multi def action_cancel(self): """Set a change request as cancelled.""" self.write({"state": "cancelled"}) for rec in self: rec.message_post( subtype="mt_comment", body=_("Change request %s has been cancelled by %s.") % (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_page_url(self): """Compute the page url.""" for page in self: base_url = ( self.env["ir.config_parameter"] .sudo() .get_param("web.base.url", default="http://localhost:8069") ) page.page_url = ( "{}/web#db={}&id={}&view_type=form&" "model=document.page.history" ).format(base_url, self.env.cr.dbname, page.id) @api.multi def _compute_diff(self): """Shows a diff between this version and the previous version""" history = self.env["document.page.history"] for rec in self: domain = [("page_id", "=", rec.page_id.id), ("state", "=", "approved")] if rec.approved_date: domain.append(("approved_date", "<", rec.approved_date)) prev = history.search(domain, limit=1, order="approved_date DESC") if prev: rec.diff = self._get_diff(prev.id, rec.id) else: rec.diff = self._get_diff(False, rec.id)