144 lines
6.2 KiB
Python
144 lines
6.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import Command, models
|
|
|
|
|
|
class DocumentMixin(models.AbstractModel):
|
|
"""
|
|
Inherit this mixin to automatically create a `documents.document` when
|
|
an `ir.attachment` is linked to a record and add the default values when
|
|
creating a document related to the model that inherits from this mixin.
|
|
|
|
Override this mixin's methods to specify an owner, a folder, tags or
|
|
access_rights for the document.
|
|
|
|
Note: this mixin can be disabled with the context variable "no_document=True".
|
|
"""
|
|
_name = 'documents.mixin'
|
|
_inherit = 'documents.unlink.mixin'
|
|
_description = "Documents creation mixin"
|
|
|
|
def _get_document_vals(self, attachment):
|
|
"""
|
|
Return values used to create a `documents.document`
|
|
"""
|
|
self.ensure_one()
|
|
document_vals = {}
|
|
if self._check_create_documents():
|
|
access_rights_vals = self._get_document_vals_access_rights()
|
|
if set(access_rights_vals) - {'access_via_link', 'access_internal', 'is_access_via_link_hidden'}:
|
|
raise ValueError("Invalid access right values")
|
|
document_vals = {
|
|
'attachment_id': attachment.id,
|
|
'name': attachment.name or self.display_name,
|
|
'folder_id': self._get_document_folder().id,
|
|
'owner_id': self._get_document_owner().id,
|
|
'partner_id': self._get_document_partner().id,
|
|
'tag_ids': [(6, 0, self._get_document_tags().ids)],
|
|
} | access_rights_vals
|
|
return document_vals
|
|
|
|
def _get_document_vals_access_rights(self):
|
|
""" Return access rights values to create a `documents.document`
|
|
|
|
In the default implementation, we give the minimal permission and rely on the propagation of the folder
|
|
permission but this method can be overridden to set more open rights.
|
|
|
|
Authorized fields: access_via_link, access_internal, is_access_via_link_hidden.
|
|
Note: access_ids are handled differently because when set, it prevents inheritance from the parent folder
|
|
(see specific document override).
|
|
"""
|
|
return {
|
|
'access_via_link': 'none',
|
|
'access_internal': 'none',
|
|
'is_access_via_link_hidden': True,
|
|
}
|
|
|
|
def _get_document_owner(self):
|
|
""" Return the owner value to create a `documents.document`
|
|
|
|
In the default implementation, we return OdooBot as owner to avoid giving full access to a user and to rely
|
|
instead on explicit access managed via `document.access` or via parent folder access inheritance but this
|
|
method can be overridden to for example give the ownership to the current user.
|
|
"""
|
|
return self.env.ref('base.user_root')
|
|
|
|
def _get_document_tags(self):
|
|
return self.env['documents.tag']
|
|
|
|
def _get_document_folder(self):
|
|
return self.env['documents.document']
|
|
|
|
def _get_document_partner(self):
|
|
return self.env['res.partner']
|
|
|
|
def _get_document_access_ids(self):
|
|
""" Add or remove members
|
|
|
|
:return boolean|list: list of tuple (partner, (role, expiration_date)) or False to avoid
|
|
inheriting members from parent folder.
|
|
"""
|
|
return []
|
|
|
|
def _check_create_documents(self):
|
|
return bool(self and self._get_document_folder())
|
|
|
|
def _prepare_document_create_values_for_linked_records(
|
|
self, res_model, vals_list, pre_vals_list):
|
|
""" Set default value defined on the document mixin implementation of the related record if there are not
|
|
explicitly set.
|
|
|
|
:param str res_model: model referenced by the documents to consider
|
|
:param list[dict] vals_list: list of values
|
|
:param list[dict] pre_vals_list: list of values before _prepare_create_values (no permission inherited yet)
|
|
|
|
Note:
|
|
- This method doesn't override existing values (permission, owner, ...).
|
|
- The related record res_model must inherit from DocumentMixin
|
|
"""
|
|
if self._name != res_model:
|
|
raise ValueError(f'Invalid model {res_model} (expected {self._name})')
|
|
|
|
related_record_by_id = self.env[res_model].browse([
|
|
res_id for vals in vals_list if (res_id := vals.get('res_id'))]).grouped('id')
|
|
for vals, pre_vals in zip(vals_list, pre_vals_list):
|
|
if not vals.get('res_id'):
|
|
continue
|
|
related_record = related_record_by_id.get(vals['res_id'])
|
|
vals.update(
|
|
{
|
|
'owner_id': pre_vals.get('owner_id', related_record._get_document_owner().id),
|
|
'partner_id': pre_vals.get('partner_id', related_record._get_document_partner().id),
|
|
'tag_ids': pre_vals.get('tag_ids', [(6, 0, related_record._get_document_tags().ids)]),
|
|
} | {
|
|
key: value
|
|
for key, value in related_record._get_document_vals_access_rights().items()
|
|
if key not in pre_vals
|
|
})
|
|
if 'access_ids' in pre_vals:
|
|
continue
|
|
access_ids = vals.get('access_ids') or []
|
|
partner_with_access = {access[2]['partner_id'] for access in access_ids} # list of Command.create tuples
|
|
related_document_access = related_record._get_document_access_ids()
|
|
if related_document_access is False:
|
|
# Keep logs but remove members
|
|
access_ids = [a for a in access_ids if not a[2].get('role')]
|
|
else:
|
|
accesses_to_add = [
|
|
(partner, access)
|
|
for partner, access in related_record._get_document_access_ids()
|
|
if partner.id not in partner_with_access
|
|
]
|
|
if accesses_to_add:
|
|
access_ids.extend(
|
|
Command.create({
|
|
'partner_id': partner.id,
|
|
'role': role,
|
|
'expiration_date': expiration_date,
|
|
})
|
|
for partner, (role, expiration_date) in accesses_to_add
|
|
)
|
|
vals['access_ids'] = access_ids
|
|
return vals_list
|