odoo-addon-dms 16.0.1.8.0.3__py3-none-any.whl → 17.0.1.0.0.2__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 (111) 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 +13 -117
  9. odoo/addons/dms/i18n/dms.pot +137 -174
  10. odoo/addons/dms/i18n/es.po +15 -58
  11. odoo/addons/dms/i18n/fr.po +296 -450
  12. odoo/addons/dms/i18n/he_IL.po +13 -117
  13. odoo/addons/dms/i18n/it.po +15 -131
  14. odoo/addons/dms/i18n/nl.po +13 -117
  15. odoo/addons/dms/i18n/pt.po +13 -121
  16. odoo/addons/dms/i18n/pt_BR.po +28 -147
  17. odoo/addons/dms/i18n/ru.po +13 -117
  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.2.dist-info/METADATA +257 -0
  91. {odoo_addon_dms-16.0.1.8.0.3.dist-info → odoo_addon_dms-17.0.1.0.0.2.dist-info}/RECORD +93 -93
  92. {odoo_addon_dms-16.0.1.8.0.3.dist-info → odoo_addon_dms-17.0.1.0.0.2.dist-info}/WHEEL +1 -1
  93. odoo_addon_dms-17.0.1.0.0.2.dist-info/top_level.txt +1 -0
  94. odoo/addons/dms/readme/CONFIGURE.rst +0 -40
  95. odoo/addons/dms/readme/CONTRIBUTORS.rst +0 -16
  96. odoo/addons/dms/readme/CREDITS.rst +0 -6
  97. odoo/addons/dms/readme/DESCRIPTION.rst +0 -6
  98. odoo/addons/dms/readme/INSTALL.rst +0 -9
  99. odoo/addons/dms/readme/ROADMAP.rst +0 -8
  100. odoo/addons/dms/readme/USAGE.rst +0 -8
  101. odoo/addons/dms/static/src/js/components/path/path.esm.js +0 -0
  102. odoo/addons/dms/static/src/js/dms_portal_tour.js +0 -57
  103. odoo/addons/dms/static/src/js/fields/path.js +0 -81
  104. odoo/addons/dms/static/src/js/views/fields/binary/preview_record.esm.js +0 -35
  105. odoo/addons/dms/static/src/js/views/many_drop_target.js +0 -98
  106. odoo/addons/dms/static/src/scss/variables.scss +0 -9
  107. odoo/addons/dms/static/src/xml/views.xml +0 -72
  108. odoo/addons/dms/template/assets.xml +0 -44
  109. odoo/addons/dms/template/onboarding.xml +0 -97
  110. odoo_addon_dms-16.0.1.8.0.3.dist-info/METADATA +0 -203
  111. odoo_addon_dms-16.0.1.8.0.3.dist-info/top_level.txt +0 -1
@@ -1,3 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+ <!--
3
+ Copyright 2024 Subteno - Timothée Vannier (https://www.subteno.com).
4
+ License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
5
+ -->
1
6
  <odoo>
2
7
  <template
3
8
  id="portal_my_home_dms"
@@ -5,10 +10,15 @@
5
10
  inherit_id="portal.portal_my_home"
6
11
  priority="20"
7
12
  >
8
- <xpath expr="//div[hasclass('o_portal_docs')]" position="inside">
13
+ <xpath expr="//div[hasclass('o_portal_docs')]" position="before">
14
+ <t t-set="portal_client_category_enable" t-value="True" />
15
+ </xpath>
16
+ <xpath expr="//div[@id='portal_client_category']" position="inside">
9
17
  <t t-call="portal.portal_docs_entry">
10
18
  <t t-set="title">Documents</t>
19
+ <t t-set="text" t-value="'Manage your documents'" />
11
20
  <t t-set="url" t-value="'/my/dms'" />
21
+ <t t-set="icon" t-value="'/dms/static/description/portal_icon.svg'" />
12
22
  <t t-set="placeholder_count" t-value="'dms_directory_count'" />
13
23
  </t>
14
24
  </xpath>
@@ -101,9 +111,9 @@
101
111
  >
102
112
  <img
103
113
  class="o_portal_contact_img"
104
- t-att-src="dms_file.icon_url"
114
+ t-att-src="dms_file.icon_url + (('&amp;access_token=' + access_token) if access_token else '')"
105
115
  />
106
- <span t-esc="dms_file.name" />
116
+ <span t-esc="dms_file.name" />
107
117
  </a>
108
118
  </td>
109
119
  <td>
@@ -1,6 +1,7 @@
1
1
  # Copyright 2017-2019 MuK IT GmbH.
2
2
  # Copyright 2020 Creu Blanca
3
3
  # Copyright 2021-2024 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
  import base64
6
7
  import functools
@@ -173,23 +174,38 @@ class StorageAttachmentBaseCase(DocumentsBaseCase):
173
174
  cls.partner_model_id = cls.env.ref("base.model_res_partner")
174
175
  cls.create_directory(storage=cls.storage, model_id=cls.partner_model_id)
175
176
  cls.partner = cls.partner_model.create({"name": "test partner"})
177
+ cls.other_partner = cls.partner_model.create({"name": "other partner"})
176
178
  cls.model_partner = cls.env.ref("base.model_res_partner")
177
179
 
178
180
  @classmethod
179
- def _create_attachment(cls, name):
181
+ def _create_attachment(cls, name, partner=None):
182
+ """
183
+ Create an attachment for the partner model.
184
+ If no partner is provided, the default partner is used.
185
+
186
+ :param str name: The name of the attachment.
187
+ :param odoo.model.res_partner partner: The partner to attach the document to.
188
+
189
+ :return: The created attachment.
190
+ :rtype: odoo.model.ir.attachment
191
+ """
192
+ if not partner:
193
+ partner = cls.partner
180
194
  return cls.create_attachment(
181
195
  name=name,
182
196
  res_model=cls.partner_model._name,
183
- res_id=cls.partner.id,
197
+ res_id=partner.id,
184
198
  )
185
199
 
186
200
  @classmethod
187
- def _get_partner_directory(cls):
201
+ def _get_partner_directory(cls, partner=False):
202
+ if not partner:
203
+ partner = cls.partner
188
204
  return cls.directory_model.search(
189
205
  [
190
206
  ("storage_id", "=", cls.storage.id),
191
207
  ("res_model", "=", cls.partner_model._name),
192
- ("res_id", "=", cls.partner.id),
208
+ ("res_id", "=", partner.id),
193
209
  ]
194
210
  )
195
211
 
@@ -1,5 +1,5 @@
1
1
  Return-Path: <123@acm.org>
2
- To: Manuel Lemos <directory+test@linux.local>
2
+ To: Manuel Lemos <directory+test@dmsTest.com>
3
3
  Subject: Testing Manuel Lemos' MIME E-mail composing and sending PHP class: HTML message
4
4
  From: mlemos <345@acm.org>
5
5
  Reply-To: mlemos <456@acm.org>
@@ -7,7 +7,7 @@ Sender: mlemos@acm.org
7
7
  X-Mailer: http://www.phpclasses.org/mimemessage $Revision: 1.63 $ (mail)
8
8
  MIME-Version: 1.0
9
9
  Content-Type: multipart/mixed; boundary="652b8c4dcb00cdcdda1e16af36781caf"
10
- Message-ID: <20050430192829.0489.mlemos@acm.org>
10
+ Message-ID: <20050430192829.0489.mlemos@dmsTest.com>
11
11
  Date: Sat, 30 Apr 2005 19:28:29 -0300
12
12
 
13
13
 
@@ -1,11 +1,11 @@
1
1
  MIME-Version: 1.0
2
2
  Received: by 10.220.191.194 with HTTP; Wed, 11 May 2011 12:27:12 -0700 (PDT)
3
3
  Date: Wed, 11 May 2011 13:27:12 -0600
4
- Delivered-To: jncjkq@gmail.com
4
+ Delivered-To: jncjkq@dmsTest.com
5
5
  Message-ID: <BANLkTi=JCQO1h3ET-pT_PLEHejhSSYxTZw@mail.jncjkq.com>
6
6
  Subject: Test
7
7
  From: Bill Jncjkq <jncjkq@gmail.com>
8
- To: directory+test@jncjkq.net
8
+ To: directory+test@dmsTest.com
9
9
  Content-Type: multipart/mixed; boundary=bcaec54eecc63acce904a3050f79
10
10
 
11
11
  --bcaec54eecc63acce904a3050f79
@@ -1,11 +1,12 @@
1
1
  # Copyright 2017-2019 MuK IT GmbH.
2
2
  # Copyright 2020 Creu Blanca
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
7
+ import os
6
8
  import unittest
7
9
 
8
- from odoo.modules.module import get_module_resource
9
10
  from odoo.tests import common, tagged
10
11
  from odoo.tools import convert_file
11
12
  from odoo.tools.misc import profile
@@ -26,23 +27,15 @@ class BenchmarkTestCase(common.TransactionCase):
26
27
 
27
28
  @classmethod
28
29
  def _clean_existing_records(cls):
29
- cls.env["dms.category"].search([]).unlink()
30
- cls.env["dms.directory"].search([]).unlink()
31
- cls.env["dms.storage"].search([]).unlink()
32
- cls.env["dms.tag"].search([]).unlink()
30
+ cls.env["dms.category"].search([]).sudo().unlink()
31
+ cls.env["dms.directory"].search([]).sudo().unlink()
32
+ cls.env["dms.storage"].search([]).sudo().unlink()
33
+ cls.env["dms.tag"].search([]).sudo().unlink()
33
34
 
34
35
  @classmethod
35
36
  def _load(cls, module, *args):
36
- convert_file(
37
- cls.cr,
38
- "dms",
39
- get_module_resource(module, *args),
40
- {},
41
- "init",
42
- False,
43
- "test",
44
- cls.registry._assertion_report,
45
- )
37
+ path = str(os.path.join(module, *args))
38
+ convert_file(cls.env, "dms", args[-1], {}, "init", False, "test", path)
46
39
 
47
40
  @classmethod
48
41
  def _setup_benchmark_data(cls):
@@ -57,7 +50,7 @@ class BenchmarkTestCase(common.TransactionCase):
57
50
  formt = "{:7}" + "| {:28}" * columns
58
51
 
59
52
  result = formt.format(*data[0]) + "\n"
60
- result += ("-" * 7) + (("+" + ("-") * 29) * columns) + "\n"
53
+ result += ("-" * 7) + (("+" + "-" * 29) * columns) + "\n"
61
54
  for row in data[1:]:
62
55
  result += formt.format(*row) + "\n"
63
56
  return result
@@ -66,12 +59,13 @@ class BenchmarkTestCase(common.TransactionCase):
66
59
  tfunc = track_function(return_tracking=True)(func)
67
60
  benchmark = []
68
61
  for item in args_list:
69
- self.registry.clear_caches()
62
+ self.registry.clear_all_caches()
70
63
  args = item[0] if len(item) > 0 else []
71
64
  kwargs = item[1] if len(item) > 1 else {}
72
65
  tracking = tuple(tfunc(*args, **kwargs)[1][1:])
73
66
  # pylint: disable=too-few-format-args
74
- benchmark.append("%sq %.3fs %.3fs %.3fs" % tracking)
67
+ # pyupgrade: disable=UP030
68
+ benchmark.append("{}sq {:.3f}s {:.3f}s {:.3f}s".format(*tracking))
75
69
  return benchmark
76
70
 
77
71
  # ----------------------------------------------------------
@@ -93,7 +87,6 @@ class BenchmarkTestCase(common.TransactionCase):
93
87
  "is_lock_editor",
94
88
  "permission_write",
95
89
  "permission_unlink",
96
- "__last_update",
97
90
  ]
98
91
 
99
92
  def test_file_search_benchmark(self):
@@ -177,7 +170,7 @@ class BenchmarkTestCase(common.TransactionCase):
177
170
  model = self.env["dms.file"].with_context(bin_size=True)
178
171
 
179
172
  def test_function(model, limit):
180
- return model.search([], limit=limit).name_get()
173
+ return model.search([], limit=limit).mapped("display_name")
181
174
 
182
175
  model_super = model.sudo()
183
176
  model_admin = model.with_user(admin_uid)
@@ -211,7 +204,9 @@ class BenchmarkTestCase(common.TransactionCase):
211
204
  test_function, args_demo
212
205
  )
213
206
 
214
- info_message = "\n\nSearching and 'name_get' function with bin_size = True | "
207
+ info_message = (
208
+ "\n\nSearching and 'display_name' function with bin_size = True | "
209
+ )
215
210
  info_message += "Benchmark with Limit 1 / 80 / 500 / None (1500)\n\n"
216
211
  info_message += self._benchmark_table(
217
212
  [
@@ -1,6 +1,7 @@
1
1
  # Copyright 2017-2019 MuK IT GmbH.
2
2
  # Copyright 2020 Creu Blanca
3
3
  # Copyright 2021-2022 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 os
@@ -26,50 +27,85 @@ class DirectoryTestCaseBase(StorageDatabaseBaseCase):
26
27
  def test_create_directory(self):
27
28
  root_directory = self.create_directory(storage=self.storage)
28
29
  sub_directory = self.create_directory(directory=root_directory)
29
- self.assertEqual(sub_directory.storage_id.id, self.storage.id)
30
- self.assertEqual(root_directory.count_directories, 1)
30
+ self.assertEqual(
31
+ sub_directory.storage_id.id,
32
+ self.storage.id,
33
+ msg="The storage of the subdirectory should be the same as "
34
+ "the root directory",
35
+ )
36
+ self.assertEqual(
37
+ root_directory.count_directories,
38
+ 1,
39
+ msg="The root directory should have one subdirectory",
40
+ )
31
41
 
32
42
  @users("dms-manager", "dms-user")
33
43
  def test_copy_root_directory(self):
34
44
  copy_root_directory = self.directory.copy()
35
45
  copy_root_directory.flush_recordset()
36
46
  self.assertEqual(
37
- self.directory.storage_id.id, copy_root_directory.storage_id.id
47
+ self.directory.storage_id.id,
48
+ copy_root_directory.storage_id.id,
49
+ msg="The storage of the copied root directory should be the same as the "
50
+ "original root directory",
38
51
  )
39
52
  self.assertEqual(
40
53
  self.directory.count_directories,
41
54
  copy_root_directory.count_directories,
55
+ msg="The copied root directory should have the same number of "
56
+ "subdirectories as the original root directory",
57
+ )
58
+ self.assertEqual(
59
+ self.directory.count_files,
60
+ copy_root_directory.count_files,
61
+ msg="The copied root directory should have the same number of "
62
+ "files as the original root directory",
42
63
  )
43
- self.assertEqual(self.directory.count_files, copy_root_directory.count_files)
44
64
 
45
65
  @users("dms-manager", "dms-user")
46
66
  def test_copy_sub_directory(self):
47
67
  copy_sub_directory = self.subdirectory.copy()
48
68
  self.assertEqual(
49
- self.subdirectory.storage_id.id, copy_sub_directory.storage_id.id
69
+ self.subdirectory.storage_id.id,
70
+ copy_sub_directory.storage_id.id,
71
+ msg="The storage of the copied subdirectory should be the same as the "
72
+ "original subdirectory",
50
73
  )
51
74
  self.assertEqual(
52
75
  self.subdirectory.count_directories,
53
76
  copy_sub_directory.count_directories,
77
+ msg="The copied subdirectory should have the same number of subdirectories "
78
+ "as the original subdirectory",
79
+ )
80
+ self.assertEqual(
81
+ self.subdirectory.count_files,
82
+ copy_sub_directory.count_files,
83
+ msg="The copied subdirectory should have the same number of "
84
+ "files as the original subdirectory",
54
85
  )
55
- self.assertEqual(self.subdirectory.count_files, copy_sub_directory.count_files)
56
86
 
57
87
  @users("dms-manager", "dms-user")
58
88
  def test_rename_directory(self):
59
89
  path_names = self.subdirectory.complete_name
60
90
  self.directory.write({"name": "New Test Name %s" % self.env.user.login})
61
- self.assertNotEqual(path_names, self.subdirectory.complete_name)
91
+ self.assertNotEqual(
92
+ path_names,
93
+ self.subdirectory.complete_name,
94
+ msg="The path name of the subdirectory should have changed",
95
+ )
62
96
 
63
97
  @users("dms-manager", "dms-user")
64
98
  def test_move_directory(self):
65
- with self.assertRaises(UserError):
99
+ with self.assertRaises(UserError, msg="The root directory should not be moved"):
66
100
  self.directory.write(
67
101
  {
68
102
  "is_root_directory": False,
69
103
  "parent_id": self.subdirectory.id,
70
104
  }
71
105
  )
72
- with self.assertRaises(UserError):
106
+ with self.assertRaises(
107
+ UserError, msg="The subdirectory storage should not be changed"
108
+ ):
73
109
  self.subdirectory.write(
74
110
  {
75
111
  "is_root_directory": True,
@@ -92,7 +128,7 @@ class DirectoryTestCaseBase(StorageDatabaseBaseCase):
92
128
  "parent_id": new_directory.id,
93
129
  }
94
130
  )
95
- with self.assertRaises(UserError):
131
+ with self.assertRaises(UserError, msg="The root directory should not be moved"):
96
132
  self.directory.storage_id = self.new_storage.id
97
133
  self.subdirectory.write(
98
134
  {
@@ -109,8 +145,12 @@ class DirectoryTestCaseBase(StorageDatabaseBaseCase):
109
145
  sub_directory = self.create_directory(directory=root_directory)
110
146
  sub_files = self.create_file(directory=sub_directory)
111
147
  root_directory.unlink()
112
- self.assertFalse(sub_directory.exists())
113
- self.assertFalse(sub_files.exists())
148
+ self.assertFalse(
149
+ sub_directory.exists(), msg="The subdirectory should not exist anymore"
150
+ )
151
+ self.assertFalse(
152
+ sub_files.exists(), msg="The subfiles should not exist anymore"
153
+ )
114
154
 
115
155
  @users("dms-manager", "dms-user")
116
156
  @mute_logger("odoo.models.unlink")
@@ -119,15 +159,27 @@ class DirectoryTestCaseBase(StorageDatabaseBaseCase):
119
159
  sub_directory = self.create_directory(directory=root_directory)
120
160
  sub_files = self.create_file(directory=sub_directory)
121
161
  sub_directory.unlink()
122
- self.assertTrue(root_directory.exists())
123
- self.assertFalse(sub_files.exists())
162
+ self.assertTrue(
163
+ root_directory.exists(), msg="The root directory should still exist"
164
+ )
165
+ self.assertFalse(
166
+ sub_files.exists(), msg="The subfiles should not exist anymore"
167
+ )
124
168
 
125
169
  @users("dms-manager", "dms-user")
126
170
  def test_storage(self):
127
171
  root_directory = self.create_directory(storage=self.storage)
128
172
  sub_directory = self.create_directory(directory=root_directory)
129
- self.assertEqual(sub_directory.storage_id.id, self.storage.id)
130
- with self.assertRaises(UserError):
173
+ self.assertEqual(
174
+ sub_directory.storage_id.id,
175
+ self.storage.id,
176
+ msg="The storage "
177
+ "of the subdirectory should be the same as the root "
178
+ "directory",
179
+ )
180
+ with self.assertRaises(
181
+ UserError, msg="The storage of the root directory should " "not be changed"
182
+ ):
131
183
  root_directory.write({"storage_id": self.new_storage.id})
132
184
 
133
185
  @users("dms-manager", "dms-user")
@@ -135,72 +187,111 @@ class DirectoryTestCaseBase(StorageDatabaseBaseCase):
135
187
  self.directory.toggle_starred()
136
188
  self.subdirectory.write({"starred": True})
137
189
  starred = self.directory_model.search([("starred", "=", True)])
138
- self.assertIn(self.directory.id, starred.ids)
139
- self.assertIn(self.subdirectory.id, starred.ids)
190
+ self.assertIn(
191
+ self.directory.id, starred.ids, msg="The directory should be starred"
192
+ )
193
+ self.assertIn(
194
+ self.subdirectory.id, starred.ids, msg="The subdirectory should be starred"
195
+ )
140
196
 
141
197
  @users("dms-manager", "dms-user")
142
198
  def test_count_directories(self):
143
- self.assertTrue(self.directory.count_directories)
199
+ self.assertTrue(
200
+ self.directory.count_directories,
201
+ msg="The directory should have subdirectories",
202
+ )
144
203
 
145
204
  @users("dms-manager", "dms-user")
146
205
  def test_count_files(self):
147
- self.assertTrue(self.subdirectory.count_files)
206
+ self.assertTrue(
207
+ self.subdirectory.count_files, msg="The subdirectory should have files"
208
+ )
148
209
 
149
210
  @users("dms-manager", "dms-user")
150
211
  def test_count_elements(self):
151
- self.assertTrue(self.directory.count_elements)
212
+ self.assertTrue(
213
+ self.directory.count_elements,
214
+ msg="The directory should have subdirectories and files",
215
+ )
152
216
 
153
217
  @users("dms-manager", "dms-user")
154
218
  def test_count_total_directories(self):
155
- self.assertTrue(self.directory.count_total_directories)
219
+ self.assertTrue(
220
+ self.directory.count_total_directories,
221
+ msg="The directory should have subdirectories",
222
+ )
156
223
 
157
224
  @users("dms-manager", "dms-user")
158
225
  def test_count_count_total_files(self):
159
- self.assertTrue(self.directory.count_total_files)
226
+ self.assertTrue(
227
+ self.directory.count_total_files, msg="The directory should have files"
228
+ )
160
229
 
161
230
  @users("dms-manager", "dms-user")
162
231
  def test_count_total_elements(self):
163
- self.assertTrue(self.directory.count_total_elements)
232
+ self.assertTrue(
233
+ self.directory.count_total_elements,
234
+ msg="The directory should have subdirectories and files",
235
+ )
164
236
 
165
237
  @users("dms-manager", "dms-user")
166
238
  def test_size(self):
167
- self.assertTrue(self.directory.size)
239
+ self.assertTrue(self.directory.size, msg="The directory should have a size")
168
240
 
169
241
  @users("dms-manager", "dms-user")
170
242
  def test_name_get(self):
171
243
  directory = self.subdirectory.with_context(dms_directory_show_path=True)
172
244
  self.assertTrue(
173
- "/" in directory.with_context(dms_directory_show_path=True).name_get()[0][1]
245
+ "/" in directory.with_context(dms_directory_show_path=True).display_name,
246
+ msg="The path should be displayed in the directory name",
174
247
  )
175
248
 
176
249
  @users("dms-manager", "dms-user")
177
250
  def test_name_search(self):
178
251
  directories = self.directory_model.name_search("/")
179
- self.assertTrue(len(directories))
252
+ self.assertTrue(len(directories), msg="The root directory should be found")
180
253
 
181
254
  @users("dms-manager", "dms-user")
182
255
  def test_search_panel(self):
183
256
  self.assertTrue(
184
- self.directory_model.search_panel_select_multi_range("parent_id")
257
+ self.directory_model.search_panel_select_multi_range("parent_id"),
258
+ msg="The parent_id field should be a multi range field",
185
259
  )
186
260
  self.assertTrue(
187
- self.directory_model.search_panel_select_multi_range("category_id")
261
+ self.directory_model.search_panel_select_multi_range("category_id"),
262
+ msg="The category_id field should be a multi range field",
263
+ )
264
+ self.assertTrue(
265
+ self.directory_model.search_panel_select_multi_range("tag_ids"),
266
+ msg="The tag_ids field should be a multi range field",
188
267
  )
189
- self.assertTrue(self.directory_model.search_panel_select_multi_range("tag_ids"))
190
268
 
191
269
 
192
270
  class DirectoryMailTestCase(StorageDatabaseBaseCase):
193
- def setUp(self):
194
- super().setUp()
195
- self.params = self.env["ir.config_parameter"].sudo()
196
- self.params.set_param("mail.catchall.domain", "mydomain.com")
271
+ @classmethod
272
+ def setUpClass(cls):
273
+ super().setUpClass()
274
+ cls.params = cls.env["ir.config_parameter"].sudo()
275
+ cls.params.set_param("mail.catchall.domain", "dmstest.com")
276
+ domain = cls.env["mail.alias.domain"].create({"name": "dmstest.com"})
277
+ cls.env["mail.alias"].create(
278
+ {
279
+ "alias_model_id": cls.env["ir.model"]
280
+ .search([("model", "=", "dms.directory")])
281
+ .id,
282
+ "alias_domain_id": domain.id,
283
+ }
284
+ )
197
285
 
198
286
  @mute_logger("odoo.addons.mail.mail_thread")
199
287
  def test_mail_alias_files(self):
200
288
  self.directory.write({"alias_process": "files", "alias_name": "directory+test"})
201
- with open(os.path.join(_path, "tests", "data", "mail01.eml"), "r") as file:
289
+ self._handle_mail_reception()
290
+
291
+ def _handle_mail_reception(self):
292
+ with open(os.path.join(_path, "tests", "data", "mail01.eml")) as file:
202
293
  self.env["mail.thread"].message_process(None, file.read())
203
- with open(os.path.join(_path, "tests", "data", "mail02.eml"), "r") as file:
294
+ with open(os.path.join(_path, "tests", "data", "mail02.eml")) as file:
204
295
  self.env["mail.thread"].message_process(None, file.read())
205
296
 
206
297
  @mute_logger("odoo.addons.mail.mail_thread")
@@ -208,7 +299,4 @@ class DirectoryMailTestCase(StorageDatabaseBaseCase):
208
299
  self.directory.write(
209
300
  {"alias_process": "directory", "alias_name": "directory+test"}
210
301
  )
211
- with open(os.path.join(_path, "tests", "data", "mail01.eml"), "r") as file:
212
- self.env["mail.thread"].message_process(None, file.read())
213
- with open(os.path.join(_path, "tests", "data", "mail02.eml"), "r") as file:
214
- self.env["mail.thread"].message_process(None, file.read())
302
+ self._handle_mail_reception()