started on module bemade_document_versions.

This commit is contained in:
Marc Durepos 2023-09-28 16:44:08 -04:00
parent 1379fe609d
commit f0f92cf483
12 changed files with 207 additions and 12 deletions

View file

@ -0,0 +1,2 @@
from . import models

View file

@ -0,0 +1,31 @@
#
# Bemade Inc.
#
# Copyright (C) September 2023 Bemade Inc. (<https://www.bemade.org>).
# Author: Marc Durepos (Contact : marc@bemade.org)
#
# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1)
# It is forbidden to publish, distribute, sublicense, or sell copies of the Software
# or modified copies of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
{
'name': 'Document Versions',
'version': '15.0.1.0.0',
'summary': 'Adds document revisions alongside Documents',
'category': 'Document Management',
'author': 'Bemade Inc.',
'website': 'https://www.bemade.org',
'license': 'OPL-1',
'depends': ['documents', 'mail'],
'data': [],
'installable': True,
'auto_install': False,
}

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<record model="documents.revision.sequence" id="document_revision_sequence_default">
<field name="name">Default Document Revision Sequence</field>
<field name="code">document.revision</field>
<field name="implementation">standard</field>
<field name="prefix">DOC/</field>
<field name="padding">2</field>
</record>
</data>
</odoo>

View file

@ -0,0 +1,3 @@
from . import document_revision
from . import document
from . import document_sequence

View file

@ -0,0 +1,70 @@
from odoo import models, fields, _, api, Command
from odoo.exceptions import ValidationError
class Document(models.Model):
_inherit = ['documents.document']
current_revision_id = fields.Many2one('documents.revision', 'Current Revision')
revision_ids = fields.One2many('documents.revision', 'document_id')
revision_sequence = fields.Many2one('documents.revision.sequence', 'document_id',
'Revision Sequence', )
track_revisions = fields.Boolean(default=False)
# set copy=False for number_next
number_next = fields.Integer(string='Next Number', required=True, default=1,
copy=False, help="Next number of this sequence")
@api.constrains('revision_ids', 'revision_sequence', 'track_revisions')
def constrain_revisions(self):
for rec in self:
revision_fields = [rec.revision_ids, rec.revision_sequence,
rec.track_revisions]
if any(revision_fields) and not all(revision_fields):
raise ValidationError(_('A revision sequence must be selected to track'
' revisions.'))
def write(self, vals):
super().write(vals)
if self.track_revisions and 'track_revisions' in vals \
and not vals['track_revisions']:
raise ValidationError(_('Revision tracking cannot be disabled after it has'
'been turned on for a document.'))
self._check_revision_fields()
@api.model_create_multi
def create(self, vals):
res = super().create(vals)
for rec in res:
rec._check_revision_fields()
return res
def _check_revision_fields(self):
""" Helper method to check that all three fields `track_revisions`,
`revisions_sequence` and `revision_ids` are properly set if any one of them is set.
:return: None
"""
self.ensure_one()
revision_fields = [self.revision_ids, self.revision_sequence,
self.track_revisions]
if any(revision_fields) and not all(revision_fields):
self._set_up_revisions()
def _set_up_revisions(self):
"""
Helper method to set up revisions, no matter how we got into tracking them.
:return: None
"""
self.ensure_one()
self.track_revisions = True # may already be true, but no matter
self.revision_sequence = self.revision_sequence or self.env.ref(
'bemade_document_versions.document_revision_sequence_default')
self.revision_ids = self.revision_ids or Command.set(
[self._create_first_revision()])
def _create_first_revision(self):
"""
Creates a new documents.revision record to associate to this Document
:return: a single, new documents.revision record
"""
self.ensure_one()
return self.env['documents.revision'].create({'document_id': self.id, })

View file

@ -0,0 +1,23 @@
from odoo import models, fields, _, api
class DocumentRevision(models.Model):
_name = "documents.revision"
_description = "Document Revision"
document_id = fields.Many2one('documents.document', required=True)
attachment_id = fields.Many2one('ir.attachment', required=True)
previous_revision_id = fields.Many2one('documents.revision', 'Previous Revision')
next_revision_id = fields.One2many('documents.revision', 'previous_revision_id')
@api.model_create_multi
def create(self, vals_list):
res = super().create(vals_list)
for rec in res:
# When we create a new revision, we need to replace the attachment linked
# to the document to keep it on the latest version.
rec.document_id.attachment_id = rec.attachment_id
# Then we update the current revision to this new revision and link
# back to the previous revisions
rec.previous_revision_id = rec.document_id.current_revision_id
rec.document_id.current_revision_id = rec

View file

@ -0,0 +1,11 @@
from odoo import models, fields, api, _
class DocumentRevisionSequence(models.Model):
""" Creates an independent sequence for each Document when the document is set to
track
"""
_name = 'documents.revision.sequence'
_inherit = 'ir.sequence'
document_id = fields.Many2one('documents.document', 'Document', ondelete='cascade')

View file

@ -0,0 +1,19 @@
from odoo import models, fields, _
from odoo.exceptions import UserError
class DocumentRevisionWizard(models.TransientModel):
_name = 'documents.revision.wizard'
_description = 'Allows the creation of new document revisions'
document_id = fields.Many2one('documents.document', 'Document')
file = fields.Binary('File to upload')
revision_name = fields.Char()
def default_get(self, fields_list):
ctx = self._context
if 'active_ids' in ctx and len(ctx.get('active_ids')) > 1:
raise UserError(_('You can only create revisions for one document at a time.'))
if 'active_id' not in ctx:
raise UserError(_('You must select a document for which you are creating a revision.'))
self.document_id = self.env['documents.document'].browse(ctx.get('active_id'))

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<record id="mail_template_document_approval_request" model="mail.template">
<field name="name">Document Approval Request</field>
<field name="model_id" ref="model_documents_document"/>
<field name="subject">Document Approval Request {{ object.name != False and ': ' + object.name or '' }} </field>
<field name="email_to">{{ }}</field>
</record>
</data>
</odoo>

View file

@ -5,3 +5,4 @@ class Document(models.Model):
_inherit = 'documents.document'
external_approver_ids = fields.Many2many('res.partner')

View file

@ -1,11 +1,24 @@
from odoo import models, fields, api
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
class RequestDocumentApprovalsWizard(models.TransientModel):
_name = 'project_documents.approval.wizard'
document_ids = fields.Many2many('documents.document', string='Documents')
partner_ids = fields.Many2many('res.partner')
partner_ids = fields.Many2many('res.partner', string="Recipients",
help="""Contacts who will receive a request to
approve the document.""")
request_template = fields.Many2one('mail.template')
def default_get(self, fields_list):
if 'request_template' not in fields_list:
self.request_template = self.env.ref()
def request_approvals(self):
pass
self._validate_partners_have_emails()
def _validate_partners_have_emails(self):
for wizard in self:
if any([not p.email for p in wizard.partner_ids]):
raise ValidationError(_('Each partner must have an email address.'))

View file

@ -15,21 +15,17 @@
<field name="model">project_documents.approval.wizard</field>
<field name="arch" type="xml">
<form>
<!-- TODO: Add field labels -->
<sheet>
<field name="partner_ids" domain="[('is_company', '=', True)]">
<label for="partner_ids"/>
<field name="partner_ids" domain="[('is_company', '=', False)]">
<tree editable="bottom">
<field name="name" colspan="3"/>
<field name="email"/>
<field name="title"/>
</tree>
</field>
<field name="document_ids">
<!-- TODO: Add a domain to restrict to context domain -->
<tree>
<field name="name"/>
</tree>
</field>
<label for="document_ids"/>
<field name="document_ids" readonly="True"/>
<footer>
<button name="request_approvals" type="object"
string="Request" class="btn btn-primary"/>
@ -45,7 +41,10 @@
<field name="res_model">project_documents.approval.wizard</field>
<field name="view_mode">form</field>
<field name="context">{
'form_view_ref': 'bemade_project_documents.documents_request_approval_form_view'}</field>
'form_view_ref': 'bemade_project_documents.documents_request_approval_form_view',
'default_res_model': context.get('default_res_model', False),
'default_res_id': context.get('default_res_id', False)
}</field>
<field name="target">new</field>
</record>
</data>