odoo-addon-dms 16.0.1.8.0.5__py3-none-any.whl → 17.0.1.0.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. odoo/addons/dms/README.rst +132 -78
  2. odoo/addons/dms/__manifest__.py +34 -16
  3. odoo/addons/dms/actions/file.xml +1 -3
  4. odoo/addons/dms/controllers/main.py +0 -34
  5. odoo/addons/dms/controllers/portal.py +178 -92
  6. odoo/addons/dms/data/onboarding_data.xml +77 -0
  7. odoo/addons/dms/demo/access_group.xml +3 -9
  8. odoo/addons/dms/i18n/de.po +332 -221
  9. odoo/addons/dms/i18n/dms.pot +137 -174
  10. odoo/addons/dms/i18n/es.po +355 -226
  11. odoo/addons/dms/i18n/fr.po +256 -342
  12. odoo/addons/dms/i18n/he_IL.po +208 -181
  13. odoo/addons/dms/i18n/it.po +369 -248
  14. odoo/addons/dms/i18n/nl.po +140 -168
  15. odoo/addons/dms/i18n/pt.po +352 -223
  16. odoo/addons/dms/i18n/pt_BR.po +358 -256
  17. odoo/addons/dms/i18n/ru.po +138 -172
  18. odoo/addons/dms/models/__init__.py +7 -1
  19. odoo/addons/dms/models/abstract_dms_mixin.py +1 -1
  20. odoo/addons/dms/models/access_groups.py +18 -11
  21. odoo/addons/dms/models/base.py +10 -2
  22. odoo/addons/dms/models/directory.py +46 -75
  23. odoo/addons/dms/models/{category.py → dms_category.py} +10 -42
  24. odoo/addons/dms/models/dms_file.py +125 -147
  25. odoo/addons/dms/models/dms_security_mixin.py +26 -22
  26. odoo/addons/dms/models/ir_attachment.py +0 -1
  27. odoo/addons/dms/models/ir_binary.py +19 -0
  28. odoo/addons/dms/models/mail_thread.py +2 -4
  29. odoo/addons/dms/models/mixins_thumbnail.py +13 -8
  30. odoo/addons/dms/models/onboarding_onboarding.py +16 -0
  31. odoo/addons/dms/models/onboarding_onboarding_step.py +50 -0
  32. odoo/addons/dms/models/res_company.py +22 -47
  33. odoo/addons/dms/models/res_config_settings.py +0 -1
  34. odoo/addons/dms/models/storage.py +4 -24
  35. odoo/addons/dms/models/tag.py +1 -1
  36. odoo/addons/dms/readme/CONFIGURE.md +59 -0
  37. odoo/addons/dms/readme/CONTRIBUTORS.md +14 -0
  38. odoo/addons/dms/readme/CREDITS.md +6 -0
  39. odoo/addons/dms/readme/DESCRIPTION.md +9 -0
  40. odoo/addons/dms/readme/INSTALL.md +4 -0
  41. odoo/addons/dms/readme/ROADMAP.md +19 -0
  42. odoo/addons/dms/readme/USAGE.md +11 -0
  43. odoo/addons/dms/security/security.xml +1 -0
  44. odoo/addons/dms/static/description/icon.png +0 -0
  45. odoo/addons/dms/static/description/icon.svg +4 -1
  46. odoo/addons/dms/static/description/index.html +133 -88
  47. odoo/addons/dms/static/description/portal_icon.svg +12 -0
  48. odoo/addons/dms/static/src/js/fields/{path_owl.esm.js → path_json/path_owl.esm.js} +22 -4
  49. odoo/addons/dms/static/src/js/fields/{path_owl.xml → path_json/path_owl.xml} +7 -4
  50. odoo/addons/dms/static/src/js/fields/preview_binary/preview_record.esm.js +47 -0
  51. odoo/addons/dms/static/src/js/{views/fields/binary → fields/preview_binary}/preview_record.xml +5 -4
  52. odoo/addons/dms/static/src/js/views/dms_file_upload.esm.js +155 -148
  53. odoo/addons/dms/static/src/js/views/file_kanban_controller.xml +0 -1
  54. odoo/addons/dms/static/src/js/views/file_kanban_record.esm.js +26 -27
  55. odoo/addons/dms/static/src/js/views/file_kanban_renderer.esm.js +1 -2
  56. odoo/addons/dms/static/src/js/views/file_kanban_renderer.xml +12 -16
  57. odoo/addons/dms/static/src/js/views/file_kanban_view.esm.js +11 -9
  58. odoo/addons/dms/static/src/js/views/file_list_controller.esm.js +1 -1
  59. odoo/addons/dms/static/src/js/views/file_list_renderer.xml +1 -7
  60. odoo/addons/dms/static/src/js/views/file_list_view.esm.js +11 -9
  61. odoo/addons/dms/static/src/js/views/search_panel.esm.js +9 -10
  62. odoo/addons/dms/static/src/models/attachment.esm.js +83 -82
  63. odoo/addons/dms/static/src/models/attachment_image.esm.js +30 -28
  64. odoo/addons/dms/static/src/models/attachment_viewer_viewable.esm.js +27 -25
  65. odoo/addons/dms/static/src/scss/directory_kanban.scss +28 -73
  66. odoo/addons/dms/static/src/scss/dms_common.scss +69 -0
  67. odoo/addons/dms/static/src/scss/file_kanban.scss +22 -34
  68. odoo/addons/dms/static/src/scss/portal.scss +12 -0
  69. odoo/addons/dms/static/tests/tours/dms_portal_tour.esm.js +46 -0
  70. odoo/addons/dms/{views/dms_portal_templates.xml → template/portal.xml} +13 -3
  71. odoo/addons/dms/tests/common.py +20 -4
  72. odoo/addons/dms/tests/data/mail01.eml +2 -2
  73. odoo/addons/dms/tests/data/mail02.eml +2 -2
  74. odoo/addons/dms/tests/test_benchmark.py +16 -21
  75. odoo/addons/dms/tests/test_directory.py +128 -40
  76. odoo/addons/dms/tests/test_file.py +112 -30
  77. odoo/addons/dms/tests/test_file_database.py +50 -24
  78. odoo/addons/dms/tests/test_portal.py +50 -37
  79. odoo/addons/dms/tests/test_storage_attachment.py +85 -63
  80. odoo/addons/dms/tests/test_storage_database.py +89 -35
  81. odoo/addons/dms/tools/file.py +63 -11
  82. odoo/addons/dms/views/dms_access_groups_views.xml +2 -17
  83. odoo/addons/dms/views/{category.xml → dms_category.xml} +4 -9
  84. odoo/addons/dms/views/{directory.xml → dms_directory.xml} +168 -176
  85. odoo/addons/dms/views/dms_file.xml +170 -191
  86. odoo/addons/dms/views/{tag.xml → dms_tag.xml} +50 -53
  87. odoo/addons/dms/views/menu.xml +52 -21
  88. odoo/addons/dms/views/res_config_settings.xml +31 -82
  89. odoo/addons/dms/views/storage.xml +7 -13
  90. odoo_addon_dms-17.0.1.0.0.3.dist-info/METADATA +257 -0
  91. {odoo_addon_dms-16.0.1.8.0.5.dist-info → odoo_addon_dms-17.0.1.0.0.3.dist-info}/RECORD +93 -95
  92. {odoo_addon_dms-16.0.1.8.0.5.dist-info → odoo_addon_dms-17.0.1.0.0.3.dist-info}/WHEEL +1 -1
  93. odoo_addon_dms-17.0.1.0.0.3.dist-info/top_level.txt +1 -0
  94. odoo/addons/dms/i18n/fa.po +0 -2277
  95. odoo/addons/dms/i18n/fa_IR.po +0 -2277
  96. odoo/addons/dms/readme/CONFIGURE.rst +0 -40
  97. odoo/addons/dms/readme/CONTRIBUTORS.rst +0 -16
  98. odoo/addons/dms/readme/CREDITS.rst +0 -6
  99. odoo/addons/dms/readme/DESCRIPTION.rst +0 -6
  100. odoo/addons/dms/readme/INSTALL.rst +0 -9
  101. odoo/addons/dms/readme/ROADMAP.rst +0 -8
  102. odoo/addons/dms/readme/USAGE.rst +0 -8
  103. odoo/addons/dms/static/src/js/components/path/path.esm.js +0 -0
  104. odoo/addons/dms/static/src/js/dms_portal_tour.js +0 -57
  105. odoo/addons/dms/static/src/js/fields/path.js +0 -81
  106. odoo/addons/dms/static/src/js/views/fields/binary/preview_record.esm.js +0 -35
  107. odoo/addons/dms/static/src/js/views/many_drop_target.js +0 -98
  108. odoo/addons/dms/static/src/scss/variables.scss +0 -9
  109. odoo/addons/dms/static/src/xml/views.xml +0 -72
  110. odoo/addons/dms/template/assets.xml +0 -44
  111. odoo/addons/dms/template/onboarding.xml +0 -97
  112. odoo_addon_dms-16.0.1.8.0.5.dist-info/METADATA +0 -203
  113. odoo_addon_dms-16.0.1.8.0.5.dist-info/top_level.txt +0 -1
@@ -30,7 +30,7 @@ class AbstractDmsMixin(models.AbstractModel):
30
30
  color = fields.Integer(default=0)
31
31
  category_id = fields.Many2one(
32
32
  comodel_name="dms.category",
33
- context="{'dms_category_show_path': True}",
33
+ context={"dms_category_show_path": True},
34
34
  string="Category",
35
35
  )
36
36
 
@@ -1,5 +1,6 @@
1
1
  # Copyright 2017-2019 MuK IT GmbH
2
2
  # Copyright 2020 RGB Consulting
3
+ # Copyright 2024 Timothée Vannier - Subteno (https://www.subteno.com).
3
4
  # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
4
5
 
5
6
  from odoo import _, api, fields, models
@@ -121,8 +122,7 @@ class DmsAccessGroups(models.Model):
121
122
  for one in self:
122
123
  one.update(
123
124
  {
124
- "perm_inclusive_%s"
125
- % perm: (
125
+ "perm_inclusive_%s" % perm: (
126
126
  one["perm_%s" % perm]
127
127
  or one.parent_group_id["perm_inclusive_%s" % perm]
128
128
  )
@@ -132,8 +132,8 @@ class DmsAccessGroups(models.Model):
132
132
 
133
133
  @api.model
134
134
  def default_get(self, fields_list):
135
- res = super(DmsAccessGroups, self).default_get(fields_list)
136
- if "explicit_user_ids" in res and res["explicit_user_ids"]:
135
+ res = super().default_get(fields_list)
136
+ if res.get("explicit_user_ids"):
137
137
  res["explicit_user_ids"] = res["explicit_user_ids"] + [self.env.uid]
138
138
  else:
139
139
  res["explicit_user_ids"] = [(6, 0, [self.env.uid])]
@@ -148,17 +148,24 @@ class DmsAccessGroups(models.Model):
148
148
  )
149
149
  def _compute_users(self):
150
150
  for record in self:
151
- users = record.mapped("group_ids.users")
152
- users |= record.mapped("explicit_user_ids")
153
- users |= record.mapped("parent_group_id.users")
151
+ users = (
152
+ record.group_ids.users
153
+ | record.explicit_user_ids
154
+ | record.parent_group_id.users
155
+ )
154
156
  record.update({"users": users, "count_users": len(users)})
155
157
 
158
+ def copy(self, default=None):
159
+ default = dict(default or {})
160
+ default["name"] = _("%s (copy)") % self.name
161
+ return super().copy(default=default)
162
+
156
163
  @api.constrains("parent_path")
157
164
  def _check_parent_recursiveness(self):
158
- """Forbid recursive relationships."""
159
- for one in self:
160
- if not one.parent_group_id:
161
- continue
165
+ """
166
+ Forbid recursive relationships.
167
+ """
168
+ for one in self.filtered("parent_group_id"):
162
169
  if str(one.id) in one.parent_path.split("/"):
163
170
  raise ValidationError(
164
171
  _("Parent group '%(parent)s' is child of '%(current)s'.")
@@ -1,5 +1,6 @@
1
1
  # Copyright 2021 Tecnativa - Jairo Llopis
2
2
  # Copyright 2024 Tecnativa - Víctor Martínez
3
+ # Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
3
4
  # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
4
5
 
5
6
  from odoo import models
@@ -19,6 +20,13 @@ class Base(models.AbstractModel):
19
20
  and self._name not in ("dms.file", "dms.directory")
20
21
  ):
21
22
  domain = [("res_model", "=", self._name), ("res_id", "in", self.ids)]
22
- self.env["dms.file"].sudo().search(domain).unlink()
23
- self.env["dms.directory"].sudo().search(domain).unlink()
23
+ # Has to check if existing before unlinking, because even if the search
24
+ # returns an empty recordset, it will still call the unlink method on it.
25
+ # This can result in an infinite loop and a recursion depth error.
26
+ files = self.env["dms.file"].sudo().search(domain)
27
+ if files:
28
+ files.unlink()
29
+ directories = self.env["dms.directory"].sudo().search(domain)
30
+ if directories:
31
+ directories.unlink()
24
32
  return result
@@ -1,13 +1,16 @@
1
1
  # Copyright 2017-2019 MuK IT GmbH.
2
2
  # Copyright 2020 Creu Blanca
3
3
  # Copyright 2021 Tecnativa - Víctor Martínez
4
+ # Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
4
5
  # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
5
6
 
6
7
  import ast
7
8
  import base64
8
9
  import logging
10
+ import os
9
11
  from ast import literal_eval
10
12
  from collections import defaultdict
13
+ from typing import Literal # noqa # pylint: disable=unused-import
11
14
 
12
15
  from odoo import _, api, fields, models, tools
13
16
  from odoo.exceptions import UserError, ValidationError
@@ -19,6 +22,7 @@ from odoo.addons.http_routing.models.ir_http import slugify
19
22
  from ..tools.file import check_name, unique_name
20
23
 
21
24
  _logger = logging.getLogger(__name__)
25
+ _path = os.path.dirname(os.path.dirname(__file__))
22
26
 
23
27
 
24
28
  class DmsDirectory(models.Model):
@@ -115,7 +119,7 @@ class DmsDirectory(models.Model):
115
119
  inverse_name="parent_id",
116
120
  string="Subdirectories",
117
121
  auto_join=False,
118
- copy=False,
122
+ copy=True,
119
123
  )
120
124
 
121
125
  tag_ids = fields.Many2many(
@@ -152,7 +156,7 @@ class DmsDirectory(models.Model):
152
156
  inverse_name="directory_id",
153
157
  string="Files",
154
158
  auto_join=False,
155
- copy=False,
159
+ copy=True,
156
160
  )
157
161
 
158
162
  count_directories = fields.Integer(
@@ -248,15 +252,16 @@ class DmsDirectory(models.Model):
248
252
  item = items[0]
249
253
  if item.id == self.id:
250
254
  return True
251
- else:
252
- directory_item = self
253
- while directory_item.parent_id:
254
- if directory_item.id == item.id:
255
- return True
256
- directory_item = directory_item.parent_id
257
- # Fix last level
255
+ # sudo because the user might not usually have access to the record but
256
+ # now the token is valid.
257
+ directory_item = self.sudo()
258
+ while directory_item.parent_id:
258
259
  if directory_item.id == item.id:
259
260
  return True
261
+ directory_item = directory_item.parent_id
262
+ # Fix last level
263
+ if directory_item.id == item.id:
264
+ return True
260
265
  return res
261
266
 
262
267
  @api.model
@@ -332,28 +337,16 @@ class DmsDirectory(models.Model):
332
337
  for record in self:
333
338
  record.res_model = record.model_id.model
334
339
 
335
- def name_get(self):
336
- if not self.env.context.get("directory_short_name", False):
337
- return super().name_get()
338
- vals = []
339
- for record in self:
340
- vals.append(tuple([record.id, record.name]))
341
- return vals
342
-
343
340
  def toggle_starred(self):
344
341
  updates = defaultdict(set)
345
342
  for record in self:
346
343
  vals = {"starred": not record.starred}
347
344
  updates[tools.frozendict(vals)].add(record.id)
348
- with self.env.norecompute():
349
- for vals, ids in updates.items():
350
- self.browse(ids).write(dict(vals))
345
+ for vals, ids in updates.items():
346
+ self.browse(ids).write(dict(vals))
351
347
  self.flush_recordset()
352
348
 
353
- # ----------------------------------------------------------
354
349
  # SearchPanel
355
- # ----------------------------------------------------------
356
-
357
350
  @api.model
358
351
  def search_panel_select_range(self, field_name, **kwargs):
359
352
  context = {}
@@ -369,19 +362,13 @@ class DmsDirectory(models.Model):
369
362
  DmsDirectory, self.with_context(category_short_name=True)
370
363
  ).search_panel_select_multi_range(field_name, **kwargs)
371
364
 
372
- # ----------------------------------------------------------
373
365
  # Actions
374
- # ----------------------------------------------------------
375
-
376
366
  def action_save_onboarding_directory_step(self):
377
367
  self.env.user.company_id.set_onboarding_step_done(
378
368
  "documents_onboarding_directory_state"
379
369
  )
380
370
 
381
- # ----------------------------------------------------------
382
371
  # SearchPanel
383
- # ----------------------------------------------------------
384
-
385
372
  @api.model
386
373
  def _search_panel_directory(self, **kwargs):
387
374
  search_domain = (kwargs.get("search_domain", []),)
@@ -391,10 +378,7 @@ class DmsDirectory(models.Model):
391
378
  return domain[1], domain[2]
392
379
  return None, None
393
380
 
394
- # ----------------------------------------------------------
395
381
  # Search
396
- # ----------------------------------------------------------
397
-
398
382
  @api.model
399
383
  def _search_starred(self, operator, operand):
400
384
  if operator == "=" and operand:
@@ -443,9 +427,7 @@ class DmsDirectory(models.Model):
443
427
  @api.depends("child_directory_ids", "file_ids")
444
428
  def _compute_count_elements(self):
445
429
  for record in self:
446
- elements = record.count_files
447
- elements += record.count_directories
448
- record.count_elements = elements
430
+ record.count_elements = record.count_files + record.count_directories
449
431
 
450
432
  def _compute_count_total_directories(self):
451
433
  for record in self:
@@ -466,9 +448,9 @@ class DmsDirectory(models.Model):
466
448
 
467
449
  def _compute_count_total_elements(self):
468
450
  for record in self:
469
- total_elements = record.count_total_files
470
- total_elements += record.count_total_directories
471
- record.count_total_elements = total_elements
451
+ record.count_total_elements = (
452
+ record.count_total_files + record.count_total_directories
453
+ )
472
454
 
473
455
  def _compute_size(self):
474
456
  sudo_model = self.env["dms.file"].sudo()
@@ -502,10 +484,7 @@ class DmsDirectory(models.Model):
502
484
  groups |= one.parent_id.complete_group_ids
503
485
  self.complete_group_ids = groups
504
486
 
505
- # ----------------------------------------------------------
506
487
  # View
507
- # ----------------------------------------------------------
508
-
509
488
  @api.depends("is_root_directory")
510
489
  def _compute_parent_id(self):
511
490
  for record in self:
@@ -530,7 +509,8 @@ class DmsDirectory(models.Model):
530
509
  def _compute_tags(self):
531
510
  for record in self:
532
511
  tags = record.tag_ids.filtered(
533
- lambda rec: not rec.category_id or rec.category_id == record.category_id
512
+ lambda rec, record=record: not rec.category_id
513
+ or rec.category_id == record.category_id
534
514
  )
535
515
  record.tag_ids = tags
536
516
 
@@ -547,10 +527,7 @@ class DmsDirectory(models.Model):
547
527
  def _onchange_model_id(self):
548
528
  self._inverse_model_id()
549
529
 
550
- # ----------------------------------------------------------
551
530
  # Constrains
552
- # ----------------------------------------------------------
553
-
554
531
  @api.constrains("parent_id")
555
532
  def _check_directory_recursion(self):
556
533
  if not self._check_recursion():
@@ -559,9 +536,9 @@ class DmsDirectory(models.Model):
559
536
 
560
537
  @api.constrains("storage_id", "model_id")
561
538
  def _check_storage_id_attachment_model_id(self):
562
- for record in self:
563
- if record.storage_id.save_type != "attachment":
564
- continue
539
+ for record in self.filtered(
540
+ lambda directory: directory.storage_id.save_type == "attachment"
541
+ ):
565
542
  if not record.model_id:
566
543
  raise ValidationError(
567
544
  _("A directory has to have model in attachment storage.")
@@ -593,23 +570,19 @@ class DmsDirectory(models.Model):
593
570
  if self.env.context.get("check_name", True) and not check_name(record.name):
594
571
  raise ValidationError(_("The directory name is invalid."))
595
572
  if record.is_root_directory:
596
- childs = record.sudo().storage_id.root_directory_ids.name_get()
573
+ children = record.sudo().storage_id.root_directory_ids
597
574
  else:
598
- childs = record.sudo().parent_id.child_directory_ids.name_get()
599
- if list(
600
- filter(
601
- lambda child: child[1] == record.name and child[0] != record.id,
602
- childs,
603
- )
575
+ children = record.sudo().parent_id.child_directory_ids
576
+
577
+ if children.filtered(
578
+ lambda child, record=record: child.name == record.name
579
+ and child != record
604
580
  ):
605
581
  raise ValidationError(
606
582
  _("A directory with the same name already exists.")
607
583
  )
608
584
 
609
- # ----------------------------------------------------------
610
585
  # Create, Update, Delete
611
- # ----------------------------------------------------------
612
-
613
586
  def _inverse_starred(self):
614
587
  starred_records = self.env["dms.directory"].sudo()
615
588
  not_starred_records = self.env["dms.directory"].sudo()
@@ -625,19 +598,14 @@ class DmsDirectory(models.Model):
625
598
  self.ensure_one()
626
599
  default = dict(default or [])
627
600
  if "parent_id" in default:
628
- parent_directory = self.browse(default["parent_id"])
601
+ parent_directory = self.browse(default.get("parent_id"))
629
602
  names = parent_directory.sudo().child_directory_ids.mapped("name")
630
603
  elif self.is_root_directory:
631
604
  names = self.sudo().storage_id.root_directory_ids.mapped("name")
632
605
  else:
633
606
  names = self.sudo().parent_id.child_directory_ids.mapped("name")
634
607
  default.update({"name": unique_name(self.name, names)})
635
- new = super().copy(default)
636
- for record in self.file_ids:
637
- record.copy({"directory_id": new.id})
638
- for record in self.child_directory_ids:
639
- record.copy({"parent_id": new.id})
640
- return new
608
+ return super().copy(default)
641
609
 
642
610
  def _alias_get_creation_values(self):
643
611
  values = super()._alias_get_creation_values()
@@ -652,7 +620,7 @@ class DmsDirectory(models.Model):
652
620
  @api.model
653
621
  def message_new(self, msg_dict, custom_values=None):
654
622
  custom_values = custom_values if custom_values is not None else {}
655
- parent_directory_id = custom_values.get("parent_id", None)
623
+ parent_directory_id = custom_values.get("parent_id")
656
624
  parent_directory = self.sudo().browse(parent_directory_id)
657
625
  if not parent_directory_id or not parent_directory.exists():
658
626
  raise ValueError("No directory could be found!")
@@ -697,11 +665,12 @@ class DmsDirectory(models.Model):
697
665
  # Hack to prevent error related to mail_message parent not exists in some cases
698
666
  ctx = dict(self.env.context).copy()
699
667
  ctx.update({"default_parent_id": False})
668
+ self.env.registry.clear_cache()
700
669
  res = super(DmsDirectory, self.with_context(**ctx)).create(vals_list)
701
670
  return res
702
671
 
703
672
  def write(self, vals):
704
- if any([k in vals.keys() for k in ["storage_id", "parent_id"]]):
673
+ if any(k in vals.keys() for k in ["storage_id", "parent_id"]):
705
674
  for item in self:
706
675
  new_storage_id = vals.get("storage_id", item.storage_id.id)
707
676
  new_parent_id = vals.get("parent_id", item.parent_id.id)
@@ -711,17 +680,19 @@ class DmsDirectory(models.Model):
711
680
  if new_parent_id:
712
681
  if old_storage_id != self.browse(new_parent_id).storage_id.id:
713
682
  raise UserError(
714
- _("It is not possible to change parent to other storage.")
683
+ _(
684
+ "It is not possible to change to a parent "
685
+ "with other storage."
686
+ )
715
687
  )
716
688
  elif old_storage_id != new_storage_id:
717
689
  raise UserError(_("It is not possible to change the storage."))
718
690
  # Groups part
719
691
  if any(key in vals for key in ["group_ids", "inherit_group_ids"]):
720
- with self.env.norecompute():
721
- res = super(DmsDirectory, self).write(vals)
722
- domain = [("id", "child_of", self.ids)]
723
- records = self.sudo().search(domain)
724
- records.modified(["group_ids"])
692
+ res = super().write(vals)
693
+ domain = [("id", "child_of", self.ids)]
694
+ records = self.sudo().search(domain)
695
+ records.modified(["group_ids"])
725
696
  records.flush_recordset()
726
697
  else:
727
698
  res = super().write(vals)
@@ -736,14 +707,14 @@ class DmsDirectory(models.Model):
736
707
  self.file_ids.unlink()
737
708
  if self.child_directory_ids:
738
709
  self.child_directory_ids.unlink()
739
- return super().unlink()
710
+ return super(DmsDirectory, self.exists()).unlink()
740
711
 
741
712
  @api.model
742
713
  def _search_panel_domain_image(
743
714
  self, field_name, domain, set_count=False, limit=False
744
715
  ):
745
716
  """We need to overwrite function from directories because odoo only return
746
- records with childs (very weird for user perspective).
717
+ records with children (very weird for user perspective).
747
718
  All records are returned now.
748
719
  """
749
720
  if field_name == "parent_id":
@@ -1,5 +1,6 @@
1
1
  # Copyright 2020 Creu Blanca
2
2
  # Copyright 2017-2019 MuK IT GmbH
3
+ # Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
3
4
  # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
4
5
 
5
6
  import logging
@@ -10,7 +11,7 @@ from odoo.exceptions import ValidationError
10
11
  _logger = logging.getLogger(__name__)
11
12
 
12
13
 
13
- class Category(models.Model):
14
+ class DMSCategory(models.Model):
14
15
  _name = "dms.category"
15
16
  _description = "Document Category"
16
17
 
@@ -20,12 +21,7 @@ class Category(models.Model):
20
21
  _order = "complete_name asc"
21
22
  _rec_name = "complete_name"
22
23
 
23
- # ----------------------------------------------------------
24
- # Database
25
- # ----------------------------------------------------------
26
-
27
24
  name = fields.Char(required=True, translate=True)
28
-
29
25
  active = fields.Boolean(
30
26
  default=True,
31
27
  help="The active field allows you to hide the category without removing it.",
@@ -34,65 +30,49 @@ class Category(models.Model):
34
30
  compute="_compute_complete_name", store=True, recursive=True
35
31
  )
36
32
  parent_id = fields.Many2one(
37
- comodel_name="dms.category",
38
33
  string="Parent Category",
34
+ comodel_name="dms.category",
39
35
  ondelete="cascade",
40
36
  index="btree",
41
37
  )
42
-
43
38
  child_category_ids = fields.One2many(
39
+ string="Child Categories",
44
40
  comodel_name="dms.category",
45
41
  inverse_name="parent_id",
46
- string="Child Categories",
47
42
  )
48
-
49
43
  parent_path = fields.Char(index="btree", unaccent=False)
50
44
  tag_ids = fields.One2many(
51
- comodel_name="dms.tag", inverse_name="category_id", string="Tags"
45
+ string="Tags", comodel_name="dms.tag", inverse_name="category_id"
52
46
  )
53
47
  directory_ids = fields.One2many(
48
+ string="Directories",
54
49
  comodel_name="dms.directory",
55
50
  inverse_name="category_id",
56
- string="Directories",
57
51
  readonly=True,
58
52
  )
59
-
60
53
  file_ids = fields.One2many(
54
+ string="Files",
61
55
  comodel_name="dms.file",
62
56
  inverse_name="category_id",
63
- string="Files",
64
57
  readonly=True,
65
58
  )
66
-
67
59
  count_categories = fields.Integer(
68
- compute="_compute_count_categories", string="Count Subcategories"
60
+ string="Count Subcategories", compute="_compute_count_categories"
69
61
  )
70
-
71
62
  count_tags = fields.Integer(compute="_compute_count_tags")
72
-
73
63
  count_directories = fields.Integer(compute="_compute_count_directories")
74
-
75
64
  count_files = fields.Integer(compute="_compute_count_files")
76
65
 
77
- # ----------------------------------------------------------
78
- # Constrains
79
- # ----------------------------------------------------------
80
-
81
66
  _sql_constraints = [
82
67
  ("name_uniq", "unique (name)", "Category name already exists!"),
83
68
  ]
84
69
 
85
- # ----------------------------------------------------------
86
- # Read
87
- # ----------------------------------------------------------
88
-
89
70
  @api.depends("name", "parent_id.complete_name")
90
71
  def _compute_complete_name(self):
91
72
  for category in self:
92
73
  if category.parent_id:
93
- category.complete_name = "{} / {}".format(
94
- category.parent_id.complete_name,
95
- category.name,
74
+ category.complete_name = (
75
+ f"{category.parent_id.complete_name} / {category.name}"
96
76
  )
97
77
  else:
98
78
  category.complete_name = category.name
@@ -117,18 +97,6 @@ class Category(models.Model):
117
97
  for record in self:
118
98
  record.count_files = len(record.file_ids)
119
99
 
120
- def name_get(self):
121
- if not self.env.context.get("category_short_name", False):
122
- return super().name_get()
123
- vals = []
124
- for record in self:
125
- vals.append(tuple([record.id, record.name]))
126
- return vals
127
-
128
- # ----------------------------------------------------------
129
- # Create
130
- # ----------------------------------------------------------
131
-
132
100
  @api.constrains("parent_id")
133
101
  def _check_category_recursion(self):
134
102
  if not self._check_recursion():