-
-
Notifications
You must be signed in to change notification settings - Fork 247
Expand file tree
/
Copy pathdms_field_template.py
More file actions
240 lines (225 loc) · 9.3 KB
/
Copy pathdms_field_template.py
File metadata and controls
240 lines (225 loc) · 9.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
# Copyright 2024 Tecnativa - Víctor Martínez
# Copyright 2025 Simone Rubino - PyTech
# 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":
existing_directory = directory_model.search(
[
("storage_id", "=", record.storage_id.id),
("res_id", "=", record.id),
("res_model", "=", record._name),
("is_root_directory", "=", True),
],
limit=1,
)
if existing_directory:
missing_groups = record.group_ids - existing_directory.group_ids
if missing_groups:
existing_directory.write(
{
"group_ids": [
fields.Command.link(group.id)
for group in missing_groups
],
}
)
return existing_directory
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": [
fields.Command.link(group.id) for group in record.group_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),
("storage_id", "=", template.storage_id.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": f"{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 _prepare_child_directory_vals(self, parent, template_child_directory):
"""Values to create child directories on the record.
:param parent: Directory already created from the template for the record
:param template_child_directory: Directory in the template directories structure
"""
return {
"name": template_child_directory.name,
"is_root_directory": False,
"parent_id": parent.id,
"inherit_group_ids": template_child_directory.inherit_group_ids,
"group_ids": [
fields.Command.link(group.id)
for group in template_child_directory.group_ids
],
}
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(
self._prepare_child_directory_vals(parent, child_directory)
)
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.")
)