bemade_document_versions: successfully uploading a new revision via the Kanban view.
This commit is contained in:
parent
f0f92cf483
commit
a987afd5d3
13 changed files with 221 additions and 66 deletions
|
|
@ -1,2 +1,3 @@
|
|||
from . import models
|
||||
from . import wizard
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,11 @@
|
|||
'website': 'https://www.bemade.org',
|
||||
'license': 'OPL-1',
|
||||
'depends': ['documents', 'mail'],
|
||||
'data': [],
|
||||
'data': ['security/ir.model.access.csv',
|
||||
'data/document_revision_data.xml',
|
||||
'views/document_views.xml',
|
||||
'wizard/document_revision_wizard.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,18 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record model="documents.revision.sequence" id="document_revision_sequence_default">
|
||||
<record model="ir.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>
|
||||
<record id="document_revision_workflow_rule" model="documents.workflow.rule">
|
||||
<field name="sequence">0</field>
|
||||
<field name="name">Revise</field>
|
||||
<field name="domain_folder_id" ref="documents.documents_internal_folder"/>
|
||||
<field name="create_model">documents.revision</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
from . import document_revision
|
||||
from . import document
|
||||
from . import document_sequence
|
||||
from . import document_revision
|
||||
from . import document_revision_sequence
|
||||
from . import workflow
|
||||
|
|
|
|||
|
|
@ -3,68 +3,68 @@ from odoo.exceptions import ValidationError
|
|||
|
||||
|
||||
class Document(models.Model):
|
||||
_inherit = ['documents.document']
|
||||
_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 = fields.Many2one('ir.sequence',
|
||||
'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):
|
||||
def set_up_revisions(self, initial_revision_name: str = None,
|
||||
sequence_prefix: str = None,
|
||||
sequence_suffix: str = None, sequence_padding: int = None):
|
||||
"""
|
||||
Helper method to set up revisions, no matter how we got into tracking them.
|
||||
:return: None
|
||||
:param initial_revision_name str: The name to give to the initial revision. By
|
||||
default, this will be the next name from the sequence.
|
||||
:param sequence_prefix: The prefix to use for the new revision sequence.
|
||||
:param sequence_suffix: The suffix to use for the new revision sequence.
|
||||
: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()])
|
||||
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])]
|
||||
|
||||
def _create_first_revision(self):
|
||||
def _create_rev_sequence(self, sequence_prefix: str = None,
|
||||
sequence_suffix: str = None, sequence_padding: int = None):
|
||||
"""
|
||||
Helper method to create a new sequence for a document that we are just starting
|
||||
to track revisions for.
|
||||
|
||||
:param sequence_prefix: The prefix to use for the sequence.
|
||||
:param sequence_suffix: The suffix to use for the sequence.
|
||||
:param sequence_padding: The padding to use for the sequence.
|
||||
:return: The created ir.sequence record.
|
||||
"""
|
||||
return self.env['ir.sequence'].create({
|
||||
'document_id': self.id,
|
||||
'name': f'sequence_doc{self.id}',
|
||||
'prefix': sequence_prefix,
|
||||
'suffix': sequence_suffix,
|
||||
'padding': sequence_padding,
|
||||
'implementation': 'standard',
|
||||
})
|
||||
|
||||
def _create_first_revision(self, name: str = None):
|
||||
"""
|
||||
Creates a new documents.revision record to associate to this Document
|
||||
|
||||
:param name: Optional name to use for the newly created revision.
|
||||
:return: a single, new documents.revision record
|
||||
"""
|
||||
self.ensure_one()
|
||||
return self.env['documents.revision'].create({'document_id': self.id, })
|
||||
name = name or self.revision_sequence.get_next_char(0)
|
||||
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())
|
||||
|
|
|
|||
|
|
@ -4,7 +4,11 @@ from odoo import models, fields, _, api
|
|||
class DocumentRevision(models.Model):
|
||||
_name = "documents.revision"
|
||||
_description = "Document Revision"
|
||||
_sql_constraints = [
|
||||
('name_document_id_unique', 'unique (name,document_id)',
|
||||
'The revision name must be unique for each document.')]
|
||||
|
||||
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')
|
||||
|
|
@ -12,6 +16,16 @@ class DocumentRevision(models.Model):
|
|||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
"""
|
||||
Creates one or more new document revisions. Each revision created replaces the
|
||||
ir.attachment tied to the document with the one provided in this revision. It
|
||||
also supersedes the previous revision, updating the document's
|
||||
current_revision_id and carrying a link to the previous revision in
|
||||
previous_revision_id.
|
||||
|
||||
:param vals_list: Dictionary or list of dictionaries
|
||||
:return:
|
||||
"""
|
||||
res = super().create(vals_list)
|
||||
for rec in res:
|
||||
# When we create a new revision, we need to replace the attachment linked
|
||||
|
|
@ -21,3 +35,4 @@ class DocumentRevision(models.Model):
|
|||
# back to the previous revisions
|
||||
rec.previous_revision_id = rec.document_id.current_revision_id
|
||||
rec.document_id.current_revision_id = rec
|
||||
return res
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
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'
|
||||
# Would prefer to inherit and make a new model, but the way ir.sequence is
|
||||
# implemented has a lot of hard coded references to "ir.sequence" for all the
|
||||
# database operations.
|
||||
|
||||
document_id = fields.Many2one('documents.document', 'Document', ondelete='cascade')
|
||||
document_id = fields.Many2one('documents.document', 'Document',
|
||||
ondelete='cascade')
|
||||
|
|
|
|||
28
bemade_document_versions/models/workflow.py
Normal file
28
bemade_document_versions/models/workflow.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
from odoo import models, fields, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class WorkflowActionRuleRevision(models.Model):
|
||||
_inherit = ['documents.workflow.rule']
|
||||
|
||||
create_model = fields.Selection(selection_add=[('documents.revision', "Revision")])
|
||||
|
||||
def create_record(self, documents=None):
|
||||
rv = super().create_record(documents=documents)
|
||||
if self.create_model == 'documents.revision':
|
||||
if len(documents) != 1:
|
||||
raise UserError(_('Document revisions must be added for one and '
|
||||
'only one document at a time.'))
|
||||
ctx = {'document_id': documents[0].id}
|
||||
ctx.update(self._context)
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'documents.revision.wizard',
|
||||
'name': 'New Revision',
|
||||
'target': 'new',
|
||||
'context': ctx,
|
||||
'views': [(self.env.ref(
|
||||
'bemade_document_versions.document_revision_wizard_view_form').id,
|
||||
'form')],
|
||||
'view_mode': 'form',
|
||||
}
|
||||
5
bemade_document_versions/security/ir.model.access.csv
Normal file
5
bemade_document_versions/security/ir.model.access.csv
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_document_revision_user,Document Revision Access,model_documents_revision,documents.group_documents_user,1,1,1,1
|
||||
access_document_revision_manager,Document Revision Manager Access,model_documents_revision,documents.group_documents_manager,1,1,1,1
|
||||
access_document_revision_wizard_user,Document Revision Wizard Access,model_documents_revision_wizard,documents.group_documents_user,1,1,1,1
|
||||
access_document_revision_wizard_manager,Document Revision Wizard Manager Access,model_documents_revision_wizard,documents.group_documents_manager,1,1,1,1
|
||||
|
12
bemade_document_versions/views/document_views.xml
Normal file
12
bemade_document_versions/views/document_views.xml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="action_upload_revision" model="ir.actions.act_window">
|
||||
<field name="name">Upload Document Revision</field>
|
||||
<field name="res_model">documents.revision.wizard</field>
|
||||
<field name="binding_model_id" ref="documents.model_documents_document"/>
|
||||
<field name="binding_type">action</field>
|
||||
<field name="binding_view_types">list,form,kanban</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
</odoo>
|
||||
1
bemade_document_versions/wizard/__init__.py
Normal file
1
bemade_document_versions/wizard/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from . import document_revision_wizard
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from odoo import models, fields, _
|
||||
from odoo import models, fields, _, api
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
|
|
@ -7,13 +7,62 @@ class DocumentRevisionWizard(models.TransientModel):
|
|||
_description = 'Allows the creation of new document revisions'
|
||||
|
||||
document_id = fields.Many2one('documents.document', 'Document')
|
||||
document_name = fields.Char()
|
||||
file = fields.Binary('File to upload')
|
||||
revision_name = fields.Char()
|
||||
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.")
|
||||
|
||||
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'))
|
||||
vals = {}
|
||||
if 'document_id' not in ctx:
|
||||
raise UserError(
|
||||
_('You must select a document for which you are creating a revision.'))
|
||||
document = self.env['documents.document'].browse(ctx.get('document_id'))
|
||||
vals['document_name'] = document.name
|
||||
vals['document_id'] = document.id
|
||||
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()
|
||||
else:
|
||||
vals['revision_name'] = sequence.get_next_char(0)
|
||||
vals['revision_sequence_prefix'] = sequence.prefix
|
||||
vals['revision_sequence_suffix'] = sequence.suffix
|
||||
vals['revision_sequence_padding'] = sequence.padding
|
||||
return vals
|
||||
|
||||
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.'))
|
||||
prev_attachment = wizard.document_id.attachment_id
|
||||
attachment = self.env['ir.attachment'].with_context(
|
||||
{'no_document': True}).create({
|
||||
'name': prev_attachment.name,
|
||||
'datas': wizard.file,
|
||||
'res_model': prev_attachment.res_model,
|
||||
'res_id': prev_attachment.res_id,
|
||||
'company_id': prev_attachment.company_id.id,
|
||||
'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.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,
|
||||
'attachment_id': attachment.id,
|
||||
})
|
||||
|
|
|
|||
32
bemade_document_versions/wizard/document_revision_wizard.xml
Normal file
32
bemade_document_versions/wizard/document_revision_wizard.xml
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<record id="document_revision_wizard_view_form" model="ir.ui.view">
|
||||
<field name="name">bemade_document_versions.document.revision.wizard.form</field>
|
||||
<field name="model">documents.revision.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<header>
|
||||
<field name="document_id" invisible="1"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<group>
|
||||
<group string="File">
|
||||
<field name="file"/>
|
||||
<field name="revision_name"/>
|
||||
</group>
|
||||
<group string="Sequence Numbering Setup">
|
||||
<field name="revision_sequence_prefix"/>
|
||||
<field name="revision_sequence_suffix"/>
|
||||
<field name="revision_sequence_padding"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<footer>
|
||||
<button string="Upload" name="action_upload_revision" type="object"
|
||||
class="btn-primary"/>
|
||||
<button special="cancel" string="Cancel" class="btn-secondary"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Loading…
Reference in a new issue