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
@@ -1,5 +1,8 @@
1
1
  # Copyright 2020-2021 Tecnativa - Víctor Martínez
2
+ # Copyright 2024 Subteno - Timothée VANNIER (https://www.subteno.com).
3
+ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
2
4
  import base64
5
+ from typing import Optional # noqa # pylint: disable=unused-import
3
6
 
4
7
  from odoo import _, http
5
8
  from odoo.http import content_disposition, request
@@ -11,6 +14,15 @@ from odoo.addons.web.controllers.utils import ensure_db
11
14
 
12
15
  class CustomerPortal(CustomerPortal):
13
16
  def _dms_check_access(self, model, res_id, access_token=None):
17
+ """
18
+ Check access to the record.
19
+
20
+ :param str model: model
21
+ :param int res_id: res_id
22
+ :param Optional[str] access_token: access_token
23
+
24
+ :return: item
25
+ """
14
26
  item = request.env[model].browse(res_id)
15
27
  if access_token:
16
28
  item = item.sudo()
@@ -32,34 +44,34 @@ class CustomerPortal(CustomerPortal):
32
44
  def portal_my_dms(
33
45
  self, sortby=None, filterby=None, search=None, search_in="name", **kw
34
46
  ):
47
+ """
48
+ Display the main page for the DMS module.
49
+
50
+ :param Optional[str] sortby: The field to sort by
51
+ :param Optional[str] filterby: The field to filter by
52
+ :param Optional[str] search: The search term
53
+ :param Optional[str] search_in: The field to search in
54
+
55
+ :return: response
56
+ :rtype: odoo.http.Response
57
+ """
35
58
  values = self._prepare_portal_layout_values()
36
- searchbar_sortings = {"name": {"label": _("Name"), "order": "name asc"}}
37
- # default sortby br
38
- if not sortby:
39
- sortby = "name"
40
- sort_br = searchbar_sortings[sortby]["order"]
41
- # search
42
- searchbar_inputs = {
43
- "name": {"input": "name", "label": _("Name")},
44
- }
45
- if not filterby:
46
- filterby = "name"
59
+ (
60
+ filterby,
61
+ searchbar_inputs,
62
+ searchbar_sortings,
63
+ sort_order,
64
+ sortby,
65
+ ) = self._searchbar_data(filterby, sortby)
47
66
  # domain
48
67
  domain = [
49
- (
50
- "id",
51
- "in",
52
- request.env["dms.directory"]._get_own_root_directories(),
53
- )
68
+ ("id", "in", request.env["dms.directory"]._get_own_root_directories()),
54
69
  ]
55
70
  # search
56
- if search and search_in:
57
- search_domain = []
58
- if search_in == "name":
59
- search_domain = OR([search_domain, [("name", "ilike", search)]])
60
- domain += search_domain
71
+ if search and search_in == "name":
72
+ domain += OR([[], [("name", "ilike", search)]])
61
73
  # content according to pager and archive selected
62
- items = request.env["dms.directory"].search(domain, order=sort_br)
74
+ items = request.env["dms.directory"].search(domain, order=sort_order)
63
75
  request.session["my_dms_folder_history"] = items.ids
64
76
  # values
65
77
  values.update(
@@ -91,65 +103,42 @@ class CustomerPortal(CustomerPortal):
91
103
  search=None,
92
104
  search_in="name",
93
105
  access_token=None,
94
- **kw
106
+ **kw,
95
107
  ):
108
+ """
109
+ Display the content of a directory.
110
+
111
+ :param Optional[int] dms_directory_id: dms_directory_id
112
+ :param Optional[str] sortby: sortby
113
+ :param Optional[str] filterby: filterby
114
+ :param Optional[str] search: search
115
+ :param Optional[str] search_in: search_in
116
+ :param Optional[str] access_token: access_token
117
+
118
+ :return: response
119
+ :rtype: odoo.http.Response
120
+ """
96
121
  ensure_db()
97
122
  # operations
98
- searchbar_sortings = {"name": {"label": _("Name"), "order": "name asc"}}
99
- # default sortby br
100
- if not sortby:
101
- sortby = "name"
102
- sort_br = searchbar_sortings[sortby]["order"]
103
- # search
104
- searchbar_inputs = {
105
- "name": {"input": "name", "label": _("Name")},
106
- }
107
- if not filterby:
108
- filterby = "name"
109
- # domain
110
- domain = [("is_hidden", "=", False), ("parent_id", "=", dms_directory_id)]
111
- # search
112
- if search and search_in:
113
- search_domain = []
114
- if search_in == "name":
115
- search_domain = OR([search_domain, [("name", "ilike", search)]])
116
- domain += search_domain
117
- # content according to pager and archive selected
118
- if access_token:
119
- dms_directory_items = (
120
- request.env["dms.directory"].sudo().search(domain, order=sort_br)
121
- )
122
- else:
123
- dms_directory_items = request.env["dms.directory"].search(
124
- domain, order=sort_br
125
- )
126
- request.session["my_dms_folder_history"] = dms_directory_items.ids
127
- res = self._dms_check_access("dms.directory", dms_directory_id, access_token)
123
+ (
124
+ filterby,
125
+ searchbar_inputs,
126
+ searchbar_sortings,
127
+ sort_order,
128
+ sortby,
129
+ ) = self._searchbar_data(filterby, sortby)
130
+ dms_directory_items, res = self._get_directories(
131
+ access_token, dms_directory_id, search, search_in, sort_order
132
+ )
128
133
  if not res:
129
- if access_token:
130
- return request.redirect("/")
131
- else:
132
- return request.redirect("/my")
134
+ return request.redirect("/" if access_token else "/my")
135
+
133
136
  dms_directory_sudo = res
134
137
  # dms_files_count
135
- domain = [
136
- ("is_hidden", "=", False),
137
- ("directory_id", "=", dms_directory_id),
138
- ]
139
- # search
140
- if search and search_in:
141
- search_domain = []
142
- if search_in == "name":
143
- search_domain = OR([search_domain, [("name", "ilike", search)]])
144
- domain += search_domain
145
- # items
146
- if access_token:
147
- dms_file_items = (
148
- request.env["dms.file"].sudo().search(domain, order=sort_br)
149
- )
150
- else:
151
- dms_file_items = request.env["dms.file"].search(domain, order=sort_br)
152
- request.session["my_dms_file_history"] = dms_file_items.ids
138
+ dms_file_items = self._get_files(
139
+ access_token, dms_directory_id, search, search_in, sort_order
140
+ )
141
+
153
142
  dms_parent_categories = dms_directory_sudo.sudo()._get_parent_categories(
154
143
  access_token
155
144
  )
@@ -170,6 +159,101 @@ class CustomerPortal(CustomerPortal):
170
159
  }
171
160
  return request.render("dms.portal_my_dms", values)
172
161
 
162
+ def _get_files(self, access_token, dms_directory_id, search, search_in, sort_br):
163
+ """
164
+ Get files from dms_directory_id
165
+
166
+ :param Optional[str] access_token: access_token
167
+ :param int dms_directory_id: dms_directory_id
168
+ :param Optional[str] search: search
169
+ :param Optional[str] search_in: search_in
170
+ :param str sort_br: sort_br
171
+
172
+ :return: dms_file_items
173
+ :rtype: odoo.model.dms_file
174
+ """
175
+ if not dms_directory_id:
176
+ return request.env["dms.file"]
177
+ file_domain = [
178
+ ("is_hidden", "=", False),
179
+ ("directory_id", "=", dms_directory_id),
180
+ ]
181
+ # search
182
+ if search and search_in == "name":
183
+ file_domain.append(("name", "ilike", search))
184
+
185
+ # items
186
+ file_model = request.env["dms.file"]
187
+ is_access_token_valid = file_model.check_access_token(access_token)
188
+ file_model = file_model.sudo() if is_access_token_valid else file_model
189
+ dms_file_items = file_model.search(file_domain, order=sort_br)
190
+ request.session["my_dms_file_history"] = dms_file_items.ids
191
+ return dms_file_items
192
+
193
+ def _get_directories(
194
+ self, access_token, dms_directory_id, search, search_in, sort_order
195
+ ):
196
+ """
197
+ Get directories from dms_directory_id
198
+
199
+ :param Optional[str] access_token: access_token
200
+ :param int dms_directory_id: dms_directory_id
201
+ :param Optional[str] search: search
202
+ :param Optional[str] search_in: search_in
203
+ :param str sort_order: sort_br
204
+
205
+ :return: dms_directory_items, res
206
+ :rtype: tuple[odoo.model.dms_directory, bool|odoo.model.dms_directory]
207
+ """
208
+ # domain
209
+ domain = [("is_hidden", "=", False), ("parent_id", "=", dms_directory_id)]
210
+ # search
211
+ if search and search_in:
212
+ domain.append(("name", "ilike", search))
213
+
214
+ # content according to pager and archive selected
215
+ directory_model = request.env["dms.directory"]
216
+ directory_to_check = directory_model.browse(dms_directory_id)
217
+ is_access_token_valid = directory_to_check.check_access_token(access_token)
218
+ directory_model = (
219
+ directory_model.sudo() if is_access_token_valid else directory_model
220
+ )
221
+ dms_directory_items = directory_model.search(domain, order=sort_order)
222
+
223
+ request.session["my_dms_folder_history"] = dms_directory_items.ids
224
+ res = self._dms_check_access("dms.directory", dms_directory_id, access_token)
225
+ return dms_directory_items, res
226
+
227
+ def _searchbar_data(self, filterby, sortby):
228
+ """
229
+ Prepare searchbar data for portal.
230
+
231
+ :param str filterby: filterby
232
+ :param str sortby: sortby
233
+
234
+ :return: filterby, searchbar_inputs, searchbar_sortings, sort_order,
235
+ sortby
236
+ :rtype: tuple[str, dict, dict, str, str]
237
+ """
238
+ searchbar_sortings = {"name": {"label": _("Name"), "order": "name asc"}}
239
+ # default sortby
240
+ if not sortby:
241
+ sortby = "name"
242
+ sort_order = searchbar_sortings[sortby]["order"]
243
+ # search
244
+ searchbar_inputs = {
245
+ "name": {"input": "name", "label": _("Name")},
246
+ }
247
+ if not filterby:
248
+ filterby = "name"
249
+ return (
250
+ filterby,
251
+ searchbar_inputs,
252
+ searchbar_sortings,
253
+ sort_order,
254
+ sortby,
255
+ )
256
+
173
257
  @http.route(
174
258
  ["/my/dms/file/<int:dms_file_id>/download"],
175
259
  type="http",
@@ -177,26 +261,28 @@ class CustomerPortal(CustomerPortal):
177
261
  website=True,
178
262
  )
179
263
  def portal_my_dms_file_download(self, dms_file_id, access_token=None, **kw):
180
- """Process user's consent acceptance or rejection."""
264
+ """
265
+ Download a file.
266
+
267
+ :param int dms_file_id: dms_file_id
268
+ :param Optional[str] access_token: access_token
269
+
270
+ :return: response
271
+ :rtype: odoo.http.Response
272
+ """
181
273
  ensure_db()
182
- # operations
183
274
  res = self._dms_check_access("dms.file", dms_file_id, access_token)
184
275
  if not res:
185
276
  if access_token:
186
277
  return request.redirect("/")
187
- else:
188
- return request.redirect("/my")
189
-
190
- dms_file_sudo = res
191
- # It's necessary to prevent AccessError in ir_attachment .check() function
192
- if dms_file_sudo.attachment_id and request.env.user.has_group(
193
- "base.group_portal"
194
- ):
195
- dms_file_sudo = dms_file_sudo.sudo()
196
- filecontent = base64.b64decode(dms_file_sudo.content)
197
- content_type = ["Content-Type", "application/octet-stream"]
198
- disposition_content = [
278
+ return request.redirect("/my")
279
+
280
+ if res.attachment_id and request.env.user.has_group("base.group_portal"):
281
+ res = res.sudo()
282
+ file_content = base64.b64decode(res.content)
283
+ content_type = ("Content-Type", "application/octet-stream")
284
+ disposition_content = (
199
285
  "Content-Disposition",
200
- content_disposition(dms_file_sudo.name),
201
- ]
202
- return request.make_response(filecontent, [content_type, disposition_content])
286
+ content_disposition(res.name),
287
+ )
288
+ return request.make_response(file_content, [content_type, disposition_content])
@@ -0,0 +1,77 @@
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
+ -->
6
+ <odoo noupdate="1">
7
+
8
+ <!-- Steps (has to be fist so that onboarding panel can access it) -->
9
+ <record id="onboarding_step_document_storage" model="onboarding.onboarding.step">
10
+ <field name="title">Storage</field>
11
+ <field name="description">Create a new Document Storage.</field>
12
+ <field name="button_text">Create Storage</field>
13
+ <field name="done_text">Document Storage Created!</field>
14
+ <field
15
+ name="panel_step_open_action_name"
16
+ >action_open_documents_onboarding_storage</field>
17
+ <field
18
+ name="step_image"
19
+ type="base64"
20
+ file="base/static/img/onboarding_default.png"
21
+ />
22
+ <field name="step_image_filename">onboarding_default.png</field>
23
+ <field name="step_image_alt">Onboarding Storage</field>
24
+ <field name="sequence">1</field>
25
+ </record>
26
+
27
+ <record id="onboarding_step_create_directory" model="onboarding.onboarding.step">
28
+ <field name="title">Directory</field>
29
+ <field name="description">Create a new Root Directory.</field>
30
+ <field name="button_text">Create Directory</field>
31
+ <field name="done_text">Root Directory Created!</field>
32
+ <field
33
+ name="panel_step_open_action_name"
34
+ >action_open_documents_onboarding_directory</field>
35
+ <field
36
+ name="step_image"
37
+ type="base64"
38
+ file="base/static/img/onboarding_default.png"
39
+ />
40
+ <field name="step_image_filename">onboarding_default.png</field>
41
+ <field name="step_image_alt">Onboarding Directory</field>
42
+ <field name="sequence">2</field>
43
+ </record>
44
+
45
+ <record id="onboarding_step_upload_file" model="onboarding.onboarding.step">
46
+ <field name="title">File</field>
47
+ <field name="description">Upload your first File.</field>
48
+ <field name="button_text">Upload File</field>
49
+ <field name="done_text">First File Uploaded!</field>
50
+ <field
51
+ name="panel_step_open_action_name"
52
+ >action_open_documents_onboarding_file</field>
53
+ <field
54
+ name="step_image"
55
+ type="base64"
56
+ file="base/static/img/onboarding_default.png"
57
+ />
58
+ <field name="step_image_filename">onboarding_default.png</field>
59
+ <field name="step_image_alt">Onboarding File</field>
60
+ <field name="sequence">3</field>
61
+ </record>
62
+
63
+ <!-- File Onboarding Panel -->
64
+ <record id="onboarding_onboarding_dms_file" model="onboarding.onboarding">
65
+ <field name="name">File Onboarding</field>
66
+ <field
67
+ name="step_ids"
68
+ eval="[
69
+ Command.link(ref('dms.onboarding_step_document_storage')),
70
+ Command.link(ref('dms.onboarding_step_create_directory')),
71
+ Command.link(ref('dms.onboarding_step_upload_file'))
72
+ ]"
73
+ />
74
+ <field name="route_name">document_onboarding_file</field>
75
+ <field name="panel_close_action_name">action_close_panel_dms_file</field>
76
+ </record>
77
+ </odoo>
@@ -5,20 +5,14 @@
5
5
  <field name="perm_create">True</field>
6
6
  <field name="perm_write">True</field>
7
7
  <field name="perm_unlink">True</field>
8
- <field
9
- name="explicit_user_ids"
10
- eval="[(6, 0, [ref('base.user_admin'), ref('base.user_demo')])]"
11
- />
8
+ <field name="explicit_user_ids" eval="[(6, 0, [ref('base.user_admin')])]" />
12
9
  </record>
13
10
  <record id="access_group_02_demo" model="dms.access.group">
14
11
  <field name="name">Portal</field>
15
12
  <field name="group_ids" eval="[(6, 0, [ref('base.group_portal')])]" />
16
13
  </record>
17
14
  <record id="access_group_03_demo" model="dms.access.group">
18
- <field name="name">Only admin user</field>
19
- <field name="perm_create">True</field>
20
- <field name="perm_write">True</field>
21
- <field name="perm_unlink">True</field>
22
- <field name="explicit_user_ids" eval="[(6, 0, [ref('base.user_admin')])]" />
15
+ <field name="name">User</field>
16
+ <field name="explicit_user_ids" eval="[(6, 0, [ref('base.user_demo')])]" />
23
17
  </record>
24
18
  </odoo>