oca-technical/odoo-bringout-oca-dms-dms_field/dms_field/models/dms_field_template.py
2025-08-29 15:43:03 +02:00

202 lines
7.7 KiB
Python

# Copyright 2024 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import UserError, ValidationError
class DmsFieldTemplate(models.Model):
_name = "dms.field.template"
_inherit = "dms.field.mixin"
_description = "Dms Field Template"
name = fields.Char(required=True)
company_id = fields.Many2one(
comodel_name="res.company",
string="Company",
store=True,
index=True,
)
storage_id = fields.Many2one(
comodel_name="dms.storage",
domain=[("save_type", "!=", "attachment")],
string="Storage",
)
parent_directory_id = fields.Many2one(
comodel_name="dms.directory",
domain="[('storage_id', '=', storage_id)]",
string="Parent directory",
)
model_id = fields.Many2one(
comodel_name="ir.model",
string="Model",
domain=[("transient", "=", False), ("model", "!=", "dms.field.template")],
index=True,
)
model = fields.Char(
compute="_compute_model", compute_sudo=True, store=True, string="Model name"
)
group_ids = fields.Many2many(
comodel_name="dms.access.group",
string="Groups",
)
user_field_id = fields.Many2one(
comodel_name="ir.model.fields",
domain="[('model_id', '=', model_id),('relation', '=', 'res.users')]",
string="User field",
)
directory_format_name = fields.Char(
string="Directory format name",
default="{{object.display_name}}",
help="""You can set expressions to be used for the directory name,
e.g.: {{object.name}}""",
)
@api.depends("model_id")
def _compute_model(self):
for item in self:
item.model = item.model_id.model
def _get_template_from_model(self, model):
return self.search([("model", "=", model)], limit=1)
@api.model_create_multi
def create(self, vals_list):
"""Create dms directory automatically in the creation in install mode."""
result = super().create(vals_list)
if self.env.context.get("install_mode"):
for item in result:
item_ctx = item.with_context(res_model=item._name, res_id=item.id)
item_ctx.create_dms_directory()
return result
@api.model
def create_dms_directory(self):
"""According to the model, create the directory linked to that record
and the subdirectories."""
res_model = self.env.context.get("res_model")
res_id = self.env.context.get("res_id")
record = self.env[res_model].browse(res_id)
directory_model = self.env["dms.directory"].sudo()
if res_model == "dms.field.template":
return directory_model.create(
{
"storage_id": record.storage_id.id,
"res_id": record.id,
"res_model": record._name,
"is_root_directory": True,
"name": record.display_name,
"group_ids": record.group_ids.ids,
}
)
template = self._get_template_from_model(res_model).sudo()
if not template:
raise ValidationError(_("There is no template linked to this model"))
total_directories = directory_model.search_count(
[
("parent_id", "=", self.parent_directory_id.id),
("res_model", "=", res_model),
("res_id", "=", res_id),
]
)
if total_directories > 0:
raise ValidationError(_("There is already a linked directory created."))
# Create root directory + files
dms_directory_ids = template.dms_directory_ids
new_directory = directory_model.create(
template._prepare_directory_vals(dms_directory_ids, record)
)
self._copy_files_from_directory(dms_directory_ids, new_directory)
# Create child directories
self._create_child_directories(new_directory, dms_directory_ids)
return new_directory
def _copy_files_from_directory(self, directory, new_directory):
for file in directory.file_ids:
file.copy({"directory_id": new_directory.id})
def _prepare_autogenerated_group(self, record):
group_name = _("Autogenerated group from %(model)s (%(name)s) #%(id)s") % {
"model": record._description,
"name": record.display_name,
"id": record.id,
}
vals = {
"name": group_name,
# We need to set all the permissions so that the user can manage their
# documents (directories and files)
"perm_create": True,
"perm_write": True,
"perm_unlink": True,
"dms_field_ref": "%s,%s" % (record._name, record.id),
"explicit_user_ids": [(5, 0)],
}
# Apply sudo() because the user may not have permissions to access
# ir.model.fields.
user_field = self.sudo().user_field_id
if user_field:
user = record[user_field.name]
if user:
vals["explicit_user_ids"] += [(4, user.id)]
return vals
def _get_autogenerated_group(self, record):
"""Get the existing auto-generated group or create a new one.
The permissions of the auto-generated group should be changed
to make sure you have the correct data.
"""
group_model = self.env["dms.access.group"]
group_ref = group_model._get_item_from_dms_field_ref(record)
if group_ref:
group_ref.write(self._prepare_autogenerated_group(record))
return group_ref
# Create the autogenerated group linked to the record
return group_model.create(self._prepare_autogenerated_group(record))
def _create_child_directories(self, parent, directory):
# Create child directories (all leves) + files
directory_model = self.env["dms.directory"].sudo()
for child_directory in directory.child_directory_ids:
child = directory_model.create(
{
"name": child_directory.name,
"is_root_directory": False,
"parent_id": parent.id,
}
)
self._copy_files_from_directory(child_directory, child)
self._create_child_directories(child, child_directory)
def _prepare_directory_vals(self, directory, record):
# Groups of the new directory will be those of the template + auto-generate
groups = directory.group_ids
groups += self._get_autogenerated_group(record)
directory_name = self.env["mail.render.mixin"]._render_template(
self.directory_format_name,
record._name,
record.ids,
engine="inline_template",
)[record.id]
vals = {
"storage_id": directory.storage_id.id,
"res_id": record.id,
"res_model": record._name,
"name": directory_name,
"group_ids": [(4, group.id) for group in groups],
}
if not self.parent_directory_id:
vals.update({"is_root_directory": True})
else:
vals.update(
{"parent_id": self.parent_directory_id.id, "inherit_group_ids": False}
)
return vals
@api.constrains("model_id")
def _check_model_id(self):
for template in self:
if self.env["dms.field.template"].search(
[("model_id", "=", template.model_id.id), ("id", "!=", template.id)]
):
raise UserError(
_("There is already a template created for this model.")
)