From 6e85c8655fa1f10659ec507eb02fc8708b5c3b90 Mon Sep 17 00:00:00 2001 From: Marc Durepos Date: Wed, 18 Oct 2023 08:57:01 -0400 Subject: [PATCH] Further work on sequences and wizard. --- bemade_document_versions/models/document.py | 37 +++++++++++++++++-- .../models/document_revision.py | 2 - .../models/document_revision_sequence.py | 12 +++++- .../wizard/document_revision_wizard.py | 32 +++++++++------- bemade_documents_portal/models/documents.py | 2 +- 5 files changed, 62 insertions(+), 23 deletions(-) diff --git a/bemade_document_versions/models/document.py b/bemade_document_versions/models/document.py index 8ee2940..8742590 100644 --- a/bemade_document_versions/models/document.py +++ b/bemade_document_versions/models/document.py @@ -5,11 +5,37 @@ from odoo.exceptions import ValidationError class Document(models.Model): _inherit = 'documents.document' + """ In order to implement named revisions, we hook into the already-existing version + tracking that documents.document records implement. The field previous_attachmen_ids + is already used to contain ir.attachment records that have been replaced after a + write call. What we are adding here is the concept of tying a revision number/name + to the current revision and keeping track of the same thing for previous revisions. + + This is implemented in the documents.revision record. + """ + current_revision_id = fields.Many2one('documents.revision', 'Current Revision') revision_ids = fields.One2many('documents.revision', 'document_id') revision_sequence = fields.Many2one('ir.sequence', 'Revision Sequence', ) + def write(self, vals): + # When a document already has an attachment and we are passed a new + # attachment_id in vals, we need to update the revision at least for the + # current revision and maybe for the one that was superseded. + recs_to_update = self.filtered(lambda r: r.attachment_id) + super().write(vals) + if 'attachment_id' in vals: + recs_to_update.update_revision() + + + def update_revision(self): + for rec in self: + if not rec.revision_sequence: + rec.set_up_revisions() + + # TODO : finish writing this method + def set_up_revisions(self, initial_revision_name: str = None, sequence_prefix: str = None, sequence_suffix: str = None, sequence_padding: int = None): @@ -25,7 +51,8 @@ class Document(models.Model): self.revision_sequence = self.revision_sequence or self._create_rev_sequence( sequence_prefix, sequence_suffix, sequence_padding) self.revision_ids = self.revision_ids or [Command.set( - [self._create_first_revision(initial_revision_name).id])] + [self._create_first_revision().id])] + def _create_rev_sequence(self, sequence_prefix: str = None, sequence_suffix: str = None, sequence_padding: int = None): @@ -47,7 +74,8 @@ class Document(models.Model): 'implementation': 'standard', }) - def _create_first_revision(self, name: str = None): + + def _create_first_revision(self): """ Creates a new documents.revision record to associate to this Document @@ -55,16 +83,17 @@ class Document(models.Model): :return: a single, new documents.revision record """ self.ensure_one() - name = name or self.revision_sequence.get_next_char(0) + name = self.revision_sequence.next_by_id() return self.env['documents.revision'].create({ 'document_id': self.id, 'name': name, 'attachment_id': self.attachment_id.id, }) + def get_next_revision_name(self): """ :return str: The name of the next revision in the sequence or None if revision tracking is not yet set up. """ - return self.revision_sequence.get_next_char(self.revision_sequence._next()) + return self.revision_sequence.predict_next_id() diff --git a/bemade_document_versions/models/document_revision.py b/bemade_document_versions/models/document_revision.py index 240d82f..6878660 100644 --- a/bemade_document_versions/models/document_revision.py +++ b/bemade_document_versions/models/document_revision.py @@ -11,8 +11,6 @@ class DocumentRevision(models.Model): name = fields.Char() 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): diff --git a/bemade_document_versions/models/document_revision_sequence.py b/bemade_document_versions/models/document_revision_sequence.py index dee825d..aa7703c 100644 --- a/bemade_document_versions/models/document_revision_sequence.py +++ b/bemade_document_versions/models/document_revision_sequence.py @@ -1,6 +1,4 @@ from odoo import models, fields, api, _ -from odoo.exceptions import UserError - class DocumentRevisionSequence(models.Model): _inherit = 'ir.sequence' @@ -10,3 +8,13 @@ class DocumentRevisionSequence(models.Model): document_id = fields.Many2one('documents.document', 'Document', ondelete='cascade') + + def predict_next_id(self, sequence_date=None): + self.check_access_rights('read') + return self._predict_next(sequence_date=sequence_date) + + def _predict_next(self, sequence_date=None): + if not self.use_date_range: + return self.get_next_char(self.number_next_actual) + raise NotImplementedError( + _('_predict_next is not implemented for date sequences.')) diff --git a/bemade_document_versions/wizard/document_revision_wizard.py b/bemade_document_versions/wizard/document_revision_wizard.py index e117594..ac042fd 100644 --- a/bemade_document_versions/wizard/document_revision_wizard.py +++ b/bemade_document_versions/wizard/document_revision_wizard.py @@ -9,14 +9,14 @@ class DocumentRevisionWizard(models.TransientModel): document_id = fields.Many2one('documents.document', 'Document') document_name = fields.Char() file = fields.Binary('File to upload') - revision_name = fields.Char(required=True) - revision_sequence_prefix = fields.Char(string='Sequence Prefix') - revision_sequence_suffix = fields.Char(string='Sequence Suffix') - revision_sequence_padding = fields.Integer(string='Sequence Padding', - help="Number of digits to show in the" - " sequence number. A value of 2 will" - " generate sequence numbers like 01," - " 02, 03, etc.") + revision_name = fields.Char(required=True, readonly=True) + revision_sequence = fields.Many2one('ir.sequence', required=True) + revision_sequence_prefix = fields.Char(related='revision_sequence.prefix', + readonly=False) + revision_sequence_suffix = fields.Char(related='revision_sequence.suffix', + readonly=False) + revision_sequence_padding = fields.Integer(related='revision_sequence.padding', + readonly=False) def default_get(self, fields_list): ctx = self._context @@ -30,7 +30,7 @@ class DocumentRevisionWizard(models.TransientModel): sequence = document.revision_sequence or self.env.ref( 'bemade_document_versions.document_revision_sequence_default') if document.revision_sequence: - vals['revision_name'] = self.document_id.get_next_revision_name() + vals['revision_name'] = document.get_next_revision_name() else: vals['revision_name'] = sequence.get_next_char(0) vals['revision_sequence_prefix'] = sequence.prefix @@ -38,12 +38,17 @@ class DocumentRevisionWizard(models.TransientModel): vals['revision_sequence_padding'] = sequence.padding return vals + @api.depends('document_id', 'document_id.revision_sequence', + 'revision_sequence') def action_upload_revision(self): for wizard in self: if not wizard.file: raise UserError(_('You must upload a file.')) - if not wizard.revision_name: - raise UserError(_('Revision name cannot be empty.')) + wizard.revision_sequence.write({ + 'prefix': wizard.revision_sequence_prefix, + 'suffix': wizard.revision_sequence_suffix, + 'padding': wizard.revision_sequence_padding, + }) prev_attachment = wizard.document_id.attachment_id attachment = self.env['ir.attachment'].with_context( {'no_document': True}).create({ @@ -55,14 +60,13 @@ class DocumentRevisionWizard(models.TransientModel): 'public': prev_attachment.public, }) if not wizard.document_id.revision_sequence: - wizard.document_id.set_up_revisions(wizard.revision_name, - wizard.revision_sequence_prefix, + wizard.document_id.set_up_revisions(wizard.revision_sequence_prefix, wizard.revision_sequence_suffix, wizard.revision_sequence_padding) else: self.env['documents.revision'].create({ 'document_id': wizard.document_id.id, 'attachment_id': attachment.id, - 'name': wizard.revision_name, + 'name': wizard.document_id.revision_sequence.next_by_id(), 'attachment_id': attachment.id, }) diff --git a/bemade_documents_portal/models/documents.py b/bemade_documents_portal/models/documents.py index adcef6a..25f1cae 100644 --- a/bemade_documents_portal/models/documents.py +++ b/bemade_documents_portal/models/documents.py @@ -14,4 +14,4 @@ class Document(models.Model): """ Return the action used to display documents when returning from customer portal.""" self.ensure_one() - return self.env.ref('documents.document_action') \ No newline at end of file + return self.env.ref('documents.document_action')