odoo-addon-base-tier-validation 17.0.1.5.1.3__py3-none-any.whl → 17.0.2.0.0__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 (19) hide show
  1. odoo/addons/base_tier_validation/README.rst +2 -1
  2. odoo/addons/base_tier_validation/__manifest__.py +2 -1
  3. odoo/addons/base_tier_validation/i18n/base_tier_validation.pot +117 -2
  4. odoo/addons/base_tier_validation/i18n/it.po +2 -2
  5. odoo/addons/base_tier_validation/models/__init__.py +1 -0
  6. odoo/addons/base_tier_validation/models/tier_definition.py +4 -2
  7. odoo/addons/base_tier_validation/models/tier_validation.py +129 -4
  8. odoo/addons/base_tier_validation/models/tier_validation_exception.py +95 -0
  9. odoo/addons/base_tier_validation/readme/CONTRIBUTORS.md +1 -0
  10. odoo/addons/base_tier_validation/security/ir.model.access.csv +2 -0
  11. odoo/addons/base_tier_validation/static/description/index.html +9 -5
  12. odoo/addons/base_tier_validation/tests/test_tier_validation.py +59 -2
  13. odoo/addons/base_tier_validation/tests/tier_validation_tester.py +2 -0
  14. odoo/addons/base_tier_validation/views/tier_definition_view.xml +1 -0
  15. odoo/addons/base_tier_validation/views/tier_validation_exception_view.xml +112 -0
  16. {odoo_addon_base_tier_validation-17.0.1.5.1.3.dist-info → odoo_addon_base_tier_validation-17.0.2.0.0.dist-info}/METADATA +3 -2
  17. {odoo_addon_base_tier_validation-17.0.1.5.1.3.dist-info → odoo_addon_base_tier_validation-17.0.2.0.0.dist-info}/RECORD +19 -17
  18. {odoo_addon_base_tier_validation-17.0.1.5.1.3.dist-info → odoo_addon_base_tier_validation-17.0.2.0.0.dist-info}/WHEEL +0 -0
  19. {odoo_addon_base_tier_validation-17.0.1.5.1.3.dist-info → odoo_addon_base_tier_validation-17.0.2.0.0.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,7 @@ Base Tier Validation
7
7
  !! This file is generated by oca-gen-addon-readme !!
8
8
  !! changes will be overwritten. !!
9
9
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10
- !! source digest: sha256:985b9816d91b596431cb157813581e485b5dee02ac1d0625e208d1516f970a34
10
+ !! source digest: sha256:c6317aa94557d07370f45bb16d3bb54ddbd9f037937958680816482aba127ff2
11
11
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12
12
 
13
13
  .. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png
@@ -235,6 +235,7 @@ Contributors
235
235
  - bosd
236
236
  - Evan Soh <evan.soh@omnisoftsolution.com>
237
237
  - Manuel Regidor <manuel.regidor@sygel.es>
238
+ - Eduardo de Miguel <edu@moduon.team>
238
239
 
239
240
  Maintainers
240
241
  -----------
@@ -3,7 +3,7 @@
3
3
  {
4
4
  "name": "Base Tier Validation",
5
5
  "summary": "Implement a validation process based on tiers.",
6
- "version": "17.0.1.5.1",
6
+ "version": "17.0.2.0.0",
7
7
  "development_status": "Mature",
8
8
  "maintainers": ["LoisRForgeFlow"],
9
9
  "category": "Tools",
@@ -20,6 +20,7 @@
20
20
  "views/res_config_settings_views.xml",
21
21
  "views/tier_definition_view.xml",
22
22
  "views/tier_review_view.xml",
23
+ "views/tier_validation_exception_view.xml",
23
24
  "wizard/comment_wizard_view.xml",
24
25
  "templates/tier_validation_templates.xml",
25
26
  ],
@@ -39,6 +39,11 @@ msgid ""
39
39
  " !"
40
40
  msgstr ""
41
41
 
42
+ #. module: base_tier_validation
43
+ #: model_terms:ir.ui.view,arch_db:base_tier_validation.tier_validation_exception_form
44
+ msgid "<span class=\"oe_edit_only\">Model</span>"
45
+ msgstr ""
46
+
42
47
  #. module: base_tier_validation
43
48
  #: model_terms:ir.ui.view,arch_db:base_tier_validation.tier_definition_view_form
44
49
  msgid "<span class=\"oe_edit_only\">Name</span>"
@@ -153,6 +158,15 @@ msgstr ""
153
158
  msgid "Archived"
154
159
  msgstr ""
155
160
 
161
+ #. module: base_tier_validation
162
+ #. odoo-python
163
+ #: code:addons/base_tier_validation/models/tier_validation_exception.py:0
164
+ #, python-format
165
+ msgid ""
166
+ "At least one of these fields must be checked! Write under Validation, Write "
167
+ "after Validation"
168
+ msgstr ""
169
+
156
170
  #. module: base_tier_validation
157
171
  #: model:ir.model.fields,help:base_tier_validation.field_tier_definition__approve_sequence_bypass
158
172
  #: model:ir.model.fields,help:base_tier_validation.field_tier_review__approve_sequence_bypass
@@ -204,6 +218,8 @@ msgstr ""
204
218
  #. module: base_tier_validation
205
219
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_definition__company_id
206
220
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_review__company_id
221
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__company_id
222
+ #: model_terms:ir.ui.view,arch_db:base_tier_validation.tier_validation_exception_search
207
223
  msgid "Company"
208
224
  msgstr ""
209
225
 
@@ -212,10 +228,16 @@ msgstr ""
212
228
  msgid "Config Settings"
213
229
  msgstr ""
214
230
 
231
+ #. module: base_tier_validation
232
+ #: model_terms:ir.actions.act_window,help:base_tier_validation.tier_validation_exception_action
233
+ msgid "Create a new Validation Exception!"
234
+ msgstr ""
235
+
215
236
  #. module: base_tier_validation
216
237
  #: model:ir.model.fields,field_description:base_tier_validation.field_comment_wizard__create_uid
217
238
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_definition__create_uid
218
239
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_review__create_uid
240
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__create_uid
219
241
  msgid "Created by"
220
242
  msgstr ""
221
243
 
@@ -223,6 +245,7 @@ msgstr ""
223
245
  #: model:ir.model.fields,field_description:base_tier_validation.field_comment_wizard__create_date
224
246
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_definition__create_date
225
247
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_review__create_date
248
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__create_date
226
249
  msgid "Created on"
227
250
  msgstr ""
228
251
 
@@ -250,6 +273,7 @@ msgstr ""
250
273
  #: model:ir.model.fields,field_description:base_tier_validation.field_comment_wizard__display_name
251
274
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_definition__display_name
252
275
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_review__display_name
276
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__display_name
253
277
  msgid "Display Name"
254
278
  msgstr ""
255
279
 
@@ -280,6 +304,11 @@ msgstr ""
280
304
  msgid "Field in related record"
281
305
  msgstr ""
282
306
 
307
+ #. module: base_tier_validation
308
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__field_ids
309
+ msgid "Fields"
310
+ msgstr ""
311
+
283
312
  #. module: base_tier_validation
284
313
  #. odoo-python
285
314
  #: code:addons/base_tier_validation/models/tier_review.py:0
@@ -306,6 +335,7 @@ msgstr ""
306
335
  #: model:ir.model.fields,field_description:base_tier_validation.field_comment_wizard__id
307
336
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_definition__id
308
337
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_review__id
338
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__id
309
339
  msgid "ID"
310
340
  msgstr ""
311
341
 
@@ -350,10 +380,21 @@ msgid ""
350
380
  "definition are restarted."
351
381
  msgstr ""
352
382
 
383
+ #. module: base_tier_validation
384
+ #: model_terms:ir.actions.act_window,help:base_tier_validation.tier_validation_exception_action
385
+ msgid "It's fully validated"
386
+ msgstr ""
387
+
388
+ #. module: base_tier_validation
389
+ #: model_terms:ir.actions.act_window,help:base_tier_validation.tier_validation_exception_action
390
+ msgid "It's in the validation process"
391
+ msgstr ""
392
+
353
393
  #. module: base_tier_validation
354
394
  #: model:ir.model.fields,field_description:base_tier_validation.field_comment_wizard__write_uid
355
395
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_definition__write_uid
356
396
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_review__write_uid
397
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__write_uid
357
398
  msgid "Last Updated by"
358
399
  msgstr ""
359
400
 
@@ -361,11 +402,14 @@ msgstr ""
361
402
  #: model:ir.model.fields,field_description:base_tier_validation.field_comment_wizard__write_date
362
403
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_definition__write_date
363
404
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_review__write_date
405
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__write_date
364
406
  msgid "Last Updated on"
365
407
  msgstr ""
366
408
 
367
409
  #. module: base_tier_validation
368
410
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_definition__model
411
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__model_id
412
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__model_name
369
413
  #: model_terms:ir.ui.view,arch_db:base_tier_validation.tier_definition_view_search
370
414
  msgid "Model"
371
415
  msgstr ""
@@ -431,6 +475,13 @@ msgstr ""
431
475
  msgid "Notify Reviewers on reaching Pending"
432
476
  msgstr ""
433
477
 
478
+ #. module: base_tier_validation
479
+ #: model_terms:ir.actions.act_window,help:base_tier_validation.tier_validation_exception_action
480
+ msgid ""
481
+ "Once created, you can decide which fields you want to be editable when the "
482
+ "record:"
483
+ msgstr ""
484
+
434
485
  #. module: base_tier_validation
435
486
  #. odoo-python
436
487
  #: code:addons/base_tier_validation/models/tier_validation.py:0
@@ -584,9 +635,12 @@ msgstr ""
584
635
 
585
636
  #. module: base_tier_validation
586
637
  #. odoo-python
587
- #: code:addons/base_tier_validation/models/tier_validation.py:0
638
+ #: code:addons/base_tier_validation/models/tier_validation_exception.py:0
639
+ #: model:ir.model.constraint,message:base_tier_validation.constraint_tier_validation_exception_model_company_under_after_unique
588
640
  #, python-format
589
- msgid "The operation is under validation."
641
+ msgid ""
642
+ "The model already exists for this company with this Write Validation "
643
+ "configuration!"
590
644
  msgstr ""
591
645
 
592
646
  #. module: base_tier_validation
@@ -657,6 +711,18 @@ msgstr ""
657
711
  msgid "Tier Validation Accepted Notification"
658
712
  msgstr ""
659
713
 
714
+ #. module: base_tier_validation
715
+ #: model:ir.actions.act_window,name:base_tier_validation.tier_validation_exception_action
716
+ #: model:ir.ui.menu,name:base_tier_validation.menu_tier_validation_exception
717
+ #: model_terms:ir.ui.view,arch_db:base_tier_validation.tier_validation_exception_form
718
+ msgid "Tier Validation Exception"
719
+ msgstr ""
720
+
721
+ #. module: base_tier_validation
722
+ #: model:ir.model,name:base_tier_validation.model_tier_validation_exception
723
+ msgid "Tier Validation Exceptions"
724
+ msgstr ""
725
+
660
726
  #. module: base_tier_validation
661
727
  #: model:mail.message.subtype,name:base_tier_validation.mt_tier_validation_rejected
662
728
  msgid "Tier Validation Rejected Notification"
@@ -699,6 +765,11 @@ msgstr ""
699
765
  msgid "User"
700
766
  msgstr ""
701
767
 
768
+ #. module: base_tier_validation
769
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__valid_model_field_ids
770
+ msgid "Valid Model Field"
771
+ msgstr ""
772
+
702
773
  #. module: base_tier_validation
703
774
  #: model:ir.model.fields,field_description:base_tier_validation.field_tier_definition__valid_reviewer_field_ids
704
775
  msgid "Valid Reviewer Field"
@@ -765,6 +836,50 @@ msgstr ""
765
836
  msgid "Without validation"
766
837
  msgstr ""
767
838
 
839
+ #. module: base_tier_validation
840
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__allowed_to_write_after_validation
841
+ msgid "Write after Validation"
842
+ msgstr ""
843
+
844
+ #. module: base_tier_validation
845
+ #: model_terms:ir.ui.view,arch_db:base_tier_validation.tier_validation_exception_search
846
+ msgid "Write after validation"
847
+ msgstr ""
848
+
849
+ #. module: base_tier_validation
850
+ #: model:ir.model.fields,field_description:base_tier_validation.field_tier_validation_exception__allowed_to_write_under_validation
851
+ msgid "Write under Validation"
852
+ msgstr ""
853
+
854
+ #. module: base_tier_validation
855
+ #: model_terms:ir.ui.view,arch_db:base_tier_validation.tier_validation_exception_search
856
+ msgid "Write under validation"
857
+ msgstr ""
858
+
859
+ #. module: base_tier_validation
860
+ #. odoo-python
861
+ #: code:addons/base_tier_validation/models/tier_validation.py:0
862
+ #, python-format
863
+ msgid ""
864
+ "You are not allowed to write those fields after validation.\n"
865
+ "- %(not_allowed_fields)s\n"
866
+ "\n"
867
+ "Only those fields can be modified:\n"
868
+ "- %(allowed_fields)s"
869
+ msgstr ""
870
+
871
+ #. module: base_tier_validation
872
+ #. odoo-python
873
+ #: code:addons/base_tier_validation/models/tier_validation.py:0
874
+ #, python-format
875
+ msgid ""
876
+ "You are not allowed to write those fields under validation.\n"
877
+ "- %(not_allowed_fields)s\n"
878
+ "\n"
879
+ "Only those fields can be modified:\n"
880
+ "- %(allowed_fields)s"
881
+ msgstr ""
882
+
768
883
  #. module: base_tier_validation
769
884
  #: model_terms:ir.ui.view,arch_db:base_tier_validation.tier_definition_view_form
770
885
  msgid "e.g. Tier Validation for..."
@@ -6,7 +6,7 @@ msgid ""
6
6
  msgstr ""
7
7
  "Project-Id-Version: Odoo Server 14.0\n"
8
8
  "Report-Msgid-Bugs-To: \n"
9
- "PO-Revision-Date: 2024-05-02 13:41+0000\n"
9
+ "PO-Revision-Date: 2024-06-26 11:27+0000\n"
10
10
  "Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
11
11
  "Language-Team: none\n"
12
12
  "Language: it\n"
@@ -676,7 +676,7 @@ msgstr "Formula livello"
676
676
  #. module: base_tier_validation
677
677
  #: model:ir.model,name:base_tier_validation.model_tier_review
678
678
  msgid "Tier Review"
679
- msgstr "Livello Approvazione"
679
+ msgstr "Revisione livello"
680
680
 
681
681
  #. module: base_tier_validation
682
682
  #: model_terms:ir.ui.view,arch_db:base_tier_validation.res_config_settings_view_form_budget
@@ -1,6 +1,7 @@
1
1
  # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
2
2
 
3
3
  from . import tier_definition
4
+ from . import tier_validation_exception
4
5
  from . import tier_review
5
6
  from . import tier_validation
6
7
  from . import res_users
@@ -108,6 +108,8 @@ class TierDefinition(models.Model):
108
108
  @api.depends("review_type", "model_id")
109
109
  def _compute_domain_reviewer_field(self):
110
110
  for rec in self:
111
- rec.valid_reviewer_field_ids = self.env["ir.model.fields"].search(
112
- [("model", "=", rec.model), ("relation", "=", "res.users")]
111
+ rec.valid_reviewer_field_ids = (
112
+ self.env["ir.model.fields"]
113
+ .sudo()
114
+ .search([("model", "=", rec.model), ("relation", "=", "res.users")])
113
115
  )
@@ -1,4 +1,5 @@
1
1
  # Copyright 2017-19 ForgeFlow S.L. (https://www.forgeflow.com)
2
+ # Copyright 2024 Moduon Team (https://www.moduon.team)
2
3
  # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3
4
 
4
5
  from ast import literal_eval
@@ -9,6 +10,8 @@ from odoo import _, api, fields, models
9
10
  from odoo.exceptions import ValidationError
10
11
  from odoo.tools.misc import frozendict
11
12
 
13
+ BASE_EXCEPTION_FIELDS = ["message_follower_ids", "access_token"]
14
+
12
15
 
13
16
  class TierValidation(models.AbstractModel):
14
17
  _name = "tier.validation"
@@ -251,10 +254,43 @@ class TierValidation(models.AbstractModel):
251
254
  else:
252
255
  return self
253
256
 
257
+ @api.model
258
+ def _get_validation_exceptions(self, extra_domain=None, add_base_exceptions=True):
259
+ """Return Tier Validation Exception field names that matchs custom domain."""
260
+ exception_fields = (
261
+ self.env["tier.validation.exception"]
262
+ .search(
263
+ [
264
+ ("model_name", "=", self._name),
265
+ ("company_id", "in", [False] + self.env.company.ids),
266
+ *(extra_domain or []),
267
+ ]
268
+ )
269
+ .mapped("field_ids.name")
270
+ )
271
+ if add_base_exceptions:
272
+ exception_fields = list(set(exception_fields + BASE_EXCEPTION_FIELDS))
273
+ return exception_fields
274
+
275
+ @api.model
276
+ def _get_all_validation_exceptions(self):
277
+ """Extend for more field exceptions to be written when on the entire
278
+ validation process."""
279
+ return self._get_validation_exceptions()
280
+
254
281
  @api.model
255
282
  def _get_under_validation_exceptions(self):
256
- """Extend for more field exceptions."""
257
- return ["message_follower_ids", "access_token"]
283
+ """Extend for more field exceptions to be written under validation."""
284
+ return self._get_validation_exceptions(
285
+ extra_domain=[("allowed_to_write_under_validation", "=", True)]
286
+ )
287
+
288
+ @api.model
289
+ def _get_after_validation_exceptions(self):
290
+ """Extend for more field exceptions to be written after validation."""
291
+ return self._get_validation_exceptions(
292
+ extra_domain=[("allowed_to_write_after_validation", "=", True)]
293
+ )
258
294
 
259
295
  def _check_allow_write_under_validation(self, vals):
260
296
  """Allow to add exceptions for fields that are allowed to be written
@@ -265,6 +301,36 @@ class TierValidation(models.AbstractModel):
265
301
  return False
266
302
  return True
267
303
 
304
+ def _check_allow_write_after_validation(self, vals):
305
+ """Allow to add exceptions for fields that are allowed to be written
306
+ even when the record is after validation."""
307
+ exceptions = self._get_after_validation_exceptions()
308
+ for val in vals:
309
+ if val not in exceptions:
310
+ return False
311
+ return True
312
+
313
+ def _get_fields_to_write_validation(self, vals, records_exception_function):
314
+ """Not allowed fields to write when validation depending
315
+ on the given function."""
316
+ exceptions = records_exception_function()
317
+ not_allowed_fields = []
318
+ for val in vals:
319
+ if val not in exceptions:
320
+ not_allowed_fields.append(val)
321
+ if not not_allowed_fields:
322
+ return []
323
+
324
+ not_allowed_field_names, allowed_field_names = [], []
325
+ for fld_name, fld_data in self.fields_get(
326
+ not_allowed_fields + exceptions
327
+ ).items():
328
+ if fld_name in not_allowed_fields:
329
+ not_allowed_field_names.append(fld_data["string"])
330
+ else:
331
+ allowed_field_names.append(fld_data["string"])
332
+ return allowed_field_names, not_allowed_field_names
333
+
268
334
  def write(self, vals):
269
335
  for rec in self:
270
336
  if rec._check_state_conditions(vals):
@@ -286,6 +352,7 @@ class TierValidation(models.AbstractModel):
286
352
  "one record."
287
353
  )
288
354
  )
355
+ # Write under validation
289
356
  if (
290
357
  rec.review_ids
291
358
  and getattr(rec, self._state_field) in self._state_from
@@ -294,7 +361,50 @@ class TierValidation(models.AbstractModel):
294
361
  and not rec._check_allow_write_under_validation(vals)
295
362
  and not rec._context.get("skip_validation_check")
296
363
  ):
297
- raise ValidationError(_("The operation is under validation."))
364
+ (
365
+ allowed_fields,
366
+ not_allowed_fields,
367
+ ) = rec._get_fields_to_write_validation(
368
+ vals, rec._get_under_validation_exceptions
369
+ )
370
+ raise ValidationError(
371
+ _(
372
+ "You are not allowed to write those fields under validation.\n"
373
+ "- %(not_allowed_fields)s\n\n"
374
+ "Only those fields can be modified:\n- %(allowed_fields)s"
375
+ )
376
+ % {
377
+ "not_allowed_fields": "\n- ".join(not_allowed_fields),
378
+ "allowed_fields": "\n- ".join(allowed_fields),
379
+ }
380
+ )
381
+
382
+ # Write after validation. Check only if Tier Validation Exception is created
383
+ if (
384
+ rec._get_validation_exceptions(add_base_exceptions=False)
385
+ and rec.validation_status == "validated"
386
+ and getattr(rec, self._state_field)
387
+ in (self._state_to + [self._cancel_state])
388
+ and not rec._check_allow_write_after_validation(vals)
389
+ and not rec._context.get("skip_validation_check")
390
+ ):
391
+ (
392
+ allowed_fields,
393
+ not_allowed_fields,
394
+ ) = rec._get_fields_to_write_validation(
395
+ vals, rec._get_after_validation_exceptions
396
+ )
397
+ raise ValidationError(
398
+ _(
399
+ "You are not allowed to write those fields after validation.\n"
400
+ "- %(not_allowed_fields)s\n\n"
401
+ "Only those fields can be modified:\n- %(allowed_fields)s"
402
+ )
403
+ % {
404
+ "not_allowed_fields": "\n- ".join(not_allowed_fields),
405
+ "allowed_fields": "\n- ".join(allowed_fields),
406
+ }
407
+ )
298
408
  if rec._allow_to_remove_reviews(vals):
299
409
  rec.mapped("review_ids").unlink()
300
410
  return super().write(vals)
@@ -422,7 +532,10 @@ class TierValidation(models.AbstractModel):
422
532
  lambda x: x.sequence in sequences or x.approve_sequence_bypass
423
533
  )
424
534
  if self.has_comment:
425
- return self._add_comment("validate", reviews)
535
+ user_reviews = reviews.filtered(
536
+ lambda r: r.status == "pending" and (self.env.user in r.reviewer_ids)
537
+ )
538
+ return self._add_comment("validate", user_reviews)
426
539
  self._validate_tier(reviews)
427
540
  self._update_counter({"review_deleted": True})
428
541
 
@@ -622,6 +735,9 @@ class TierValidation(models.AbstractModel):
622
735
  new_node = etree.fromstring(str_element)
623
736
  return new_node
624
737
 
738
+ def _get_tier_validation_readonly_domain(self):
739
+ return "bool(review_ids)"
740
+
625
741
  @api.model
626
742
  def get_view(self, view_id=None, view_type="form", **options):
627
743
  res = super().get_view(view_id=view_id, view_type=view_type, **options)
@@ -662,6 +778,15 @@ class TierValidation(models.AbstractModel):
662
778
  all_models[model] = res["models"][model]
663
779
  new_node = etree.fromstring(new_arch)
664
780
  node.append(new_node)
781
+ excepted_fields = self._get_all_validation_exceptions()
782
+ for node in doc.xpath("//field[@name][not(ancestor::field)]"):
783
+ if node.attrib.get("name") in excepted_fields:
784
+ continue
785
+ new_r_modifier = self._get_tier_validation_readonly_domain()
786
+ old_r_modifier = node.attrib.get("readonly")
787
+ if old_r_modifier:
788
+ new_r_modifier = f"({old_r_modifier}) or ({new_r_modifier})"
789
+ node.attrib["readonly"] = new_r_modifier
665
790
  res["arch"] = etree.tostring(doc)
666
791
  res["models"] = frozendict(all_models)
667
792
  return res
@@ -0,0 +1,95 @@
1
+ # Copyright 2024 Moduon Team (https://www.moduon.team)
2
+ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
3
+
4
+ from odoo import _, api, exceptions, fields, models
5
+
6
+ from .tier_validation import BASE_EXCEPTION_FIELDS
7
+
8
+
9
+ class TierValidationException(models.Model):
10
+ _name = "tier.validation.exception"
11
+ _description = "Tier Validation Exceptions"
12
+ _rec_name = "model_name"
13
+
14
+ @api.model
15
+ def _get_tier_validation_model_names(self):
16
+ return self.env["tier.definition"]._get_tier_validation_model_names()
17
+
18
+ model_id = fields.Many2one(
19
+ comodel_name="ir.model",
20
+ string="Model",
21
+ required=True,
22
+ ondelete="cascade",
23
+ domain=lambda self: [("model", "in", self._get_tier_validation_model_names())],
24
+ )
25
+ model_name = fields.Char(
26
+ related="model_id.model",
27
+ string="Model",
28
+ store=True,
29
+ readonly=True,
30
+ index=True,
31
+ )
32
+ field_ids = fields.Many2many(
33
+ comodel_name="ir.model.fields",
34
+ string="Fields",
35
+ domain="[('id', 'in', valid_model_field_ids)]",
36
+ required=True,
37
+ )
38
+ valid_model_field_ids = fields.One2many(
39
+ comodel_name="ir.model.fields",
40
+ compute="_compute_valid_model_field_ids",
41
+ )
42
+ company_id = fields.Many2one(
43
+ comodel_name="res.company",
44
+ string="Company",
45
+ default=lambda self: self.env.company,
46
+ )
47
+ allowed_to_write_under_validation = fields.Boolean(
48
+ string="Write under Validation",
49
+ default=True,
50
+ )
51
+ allowed_to_write_after_validation = fields.Boolean(
52
+ string="Write after Validation",
53
+ default=True,
54
+ )
55
+
56
+ @api.depends("model_id")
57
+ def _compute_valid_model_field_ids(self):
58
+ for record in self:
59
+ record.valid_model_field_ids = (
60
+ self.env["ir.model.fields"]
61
+ .sudo()
62
+ .search(
63
+ [
64
+ ("model", "=", record.model_name),
65
+ ("name", "not in", BASE_EXCEPTION_FIELDS),
66
+ ]
67
+ )
68
+ )
69
+
70
+ @api.constrains(
71
+ "allowed_to_write_under_validation", "allowed_to_write_after_validation"
72
+ )
73
+ def _check_allowed_to_write(self):
74
+ if (
75
+ not self.allowed_to_write_under_validation
76
+ and not self.allowed_to_write_after_validation
77
+ ):
78
+ raise exceptions.ValidationError(
79
+ _(
80
+ "At least one of these fields must be checked! "
81
+ "Write under Validation, Write after Validation"
82
+ )
83
+ )
84
+
85
+ _sql_constraints = [
86
+ (
87
+ "model_company_under_after_unique",
88
+ "unique(model_id, company_id, "
89
+ "allowed_to_write_under_validation, allowed_to_write_after_validation)",
90
+ _(
91
+ "The model already exists for this company with this "
92
+ "Write Validation configuration!"
93
+ ),
94
+ )
95
+ ]
@@ -10,3 +10,4 @@
10
10
  - bosd
11
11
  - Evan Soh \<<evan.soh@omnisoftsolution.com>\>
12
12
  - Manuel Regidor \<<manuel.regidor@sygel.es>\>
13
+ - Eduardo de Miguel \<<edu@moduon.team>\>
@@ -7,3 +7,5 @@ access_tier_review,access.tier.review,model_tier_review,base.group_user,1,1,1,1
7
7
  access_tier_definition_all,tier.definition.all,model_tier_definition,base.group_user,1,0,0,0
8
8
  access_tier_definition_settings,tier.definition.settings,model_tier_definition,base.group_system,1,1,1,1
9
9
  access_comment_wizard,access.comment.wizard,model_comment_wizard,base.group_user,1,1,1,1
10
+ access_tier_validation_exceptions_all,tier.validation.exceptions,model_tier_validation_exception,,1,0,0,0
11
+ access_tier_validation_exceptions_settings,tier.validation.exceptions,model_tier_validation_exception,base.group_system,1,1,1,1
@@ -8,10 +8,11 @@
8
8
 
9
9
  /*
10
10
  :Author: David Goodger (goodger@python.org)
11
- :Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
11
+ :Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
12
12
  :Copyright: This stylesheet has been placed in the public domain.
13
13
 
14
14
  Default cascading style sheet for the HTML output of Docutils.
15
+ Despite the name, some widely supported CSS2 features are used.
15
16
 
16
17
  See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
17
18
  customize this style sheet.
@@ -274,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
274
275
  margin-left: 2em ;
275
276
  margin-right: 2em }
276
277
 
277
- pre.code .ln { color: grey; } /* line numbers */
278
+ pre.code .ln { color: gray; } /* line numbers */
278
279
  pre.code, code { background-color: #eeeeee }
279
280
  pre.code .comment, code .comment { color: #5C6576 }
280
281
  pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -300,7 +301,7 @@ span.option {
300
301
  span.pre {
301
302
  white-space: pre }
302
303
 
303
- span.problematic {
304
+ span.problematic, pre.problematic {
304
305
  color: red }
305
306
 
306
307
  span.section-subtitle {
@@ -366,7 +367,7 @@ ul.auto-toc {
366
367
  !! This file is generated by oca-gen-addon-readme !!
367
368
  !! changes will be overwritten. !!
368
369
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
369
- !! source digest: sha256:985b9816d91b596431cb157813581e485b5dee02ac1d0625e208d1516f970a34
370
+ !! source digest: sha256:c6317aa94557d07370f45bb16d3bb54ddbd9f037937958680816482aba127ff2
370
371
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
371
372
  <p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Mature" src="https://img.shields.io/badge/maturity-Mature-brightgreen.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/server-ux/tree/17.0/base_tier_validation"><img alt="OCA/server-ux" src="https://img.shields.io/badge/github-OCA%2Fserver--ux-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/server-ux-17-0/server-ux-17-0-base_tier_validation"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/server-ux&amp;target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
372
373
  <p>Validating some operations is a common need across different areas in a
@@ -588,12 +589,15 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
588
589
  <li>bosd</li>
589
590
  <li>Evan Soh &lt;<a class="reference external" href="mailto:evan.soh&#64;omnisoftsolution.com">evan.soh&#64;omnisoftsolution.com</a>&gt;</li>
590
591
  <li>Manuel Regidor &lt;<a class="reference external" href="mailto:manuel.regidor&#64;sygel.es">manuel.regidor&#64;sygel.es</a>&gt;</li>
592
+ <li>Eduardo de Miguel &lt;<a class="reference external" href="mailto:edu&#64;moduon.team">edu&#64;moduon.team</a>&gt;</li>
591
593
  </ul>
592
594
  </div>
593
595
  <div class="section" id="maintainers">
594
596
  <h2><a class="toc-backref" href="#toc-entry-23">Maintainers</a></h2>
595
597
  <p>This module is maintained by the OCA.</p>
596
- <a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
598
+ <a class="reference external image-reference" href="https://odoo-community.org">
599
+ <img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
600
+ </a>
597
601
  <p>OCA, or the Odoo Community Association, is a nonprofit organization whose
598
602
  mission is to support the collaborative development of Odoo features and
599
603
  promote its widespread use.</p>
@@ -2,12 +2,16 @@
2
2
  # Copyright (c) 2022 brain-tec AG (https://braintec.com)
3
3
  # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html).
4
4
 
5
+ from unittest import mock
6
+
5
7
  from lxml import etree
6
8
 
7
9
  from odoo.exceptions import ValidationError
8
10
  from odoo.tests import Form
9
11
  from odoo.tests.common import tagged
10
12
 
13
+ from ..models.tier_validation import BASE_EXCEPTION_FIELDS as BEF
14
+ from ..models.tier_validation import TierValidation as TV
11
15
  from .common import CommonTierValidation
12
16
 
13
17
 
@@ -158,13 +162,14 @@ class TierTierValidation(CommonTierValidation):
158
162
  self.assertTrue(review)
159
163
  record = test_record.with_user(self.test_user_1.id)
160
164
  record.invalidate_model()
165
+ review.invalidate_model()
161
166
  res = record.validate_tier()
162
167
  ctx = res.get("context")
163
168
  wizard = Form(self.env["comment.wizard"].with_context(**ctx))
164
169
  wizard.comment = "Test Comment"
165
170
  wiz = wizard.save()
166
171
  wiz.add_comment()
167
- self.assertTrue(test_record.review_ids.mapped("comment"))
172
+ self.assertTrue(test_record.review_ids.filtered("comment"))
168
173
  # Check notify
169
174
  comment = test_record.with_user(
170
175
  self.test_user_1.id
@@ -193,13 +198,14 @@ class TierTierValidation(CommonTierValidation):
193
198
  self.assertTrue(review)
194
199
  record = test_record.with_user(self.test_user_1.id)
195
200
  record.invalidate_model()
201
+ review.invalidate_model()
196
202
  res = record.reject_tier() # Rejection
197
203
  ctx = res.get("context")
198
204
  wizard = Form(self.env["comment.wizard"].with_context(**ctx))
199
205
  wizard.comment = "Test Comment"
200
206
  wiz = wizard.save()
201
207
  wiz.add_comment()
202
- self.assertTrue(test_record.review_ids.mapped("comment"))
208
+ self.assertTrue(test_record.review_ids.filtered("comment"))
203
209
  # Check notify
204
210
  comment = test_record.with_user(
205
211
  self.test_user_1.id
@@ -917,6 +923,57 @@ class TierTierValidation(CommonTierValidation):
917
923
  )
918
924
  self.assertEqual(notifications_no_2, notifications_no_1)
919
925
 
926
+ def test_25_change_field_exception_validation(self):
927
+ """Test under and after validations"""
928
+ # Cannot create `tier.validation.exception` records because
929
+ # `tier.validation.tester` are fake model and its fields are
930
+ # not propagated to the DDBB and cannot read from `ir.model.fields`.
931
+ # We will use the mock.patch instead.
932
+ _tvf = ["test_validation_field"]
933
+ _rv = _tvf + BEF
934
+ self.assertEqual(self.test_record.test_validation_field, 0)
935
+ self.assertFalse(self.test_record.review_ids)
936
+ reviews = self.test_record.with_user(self.test_user_2.id).request_validation()
937
+ self.assertTrue(reviews)
938
+ self.test_record.invalidate_model()
939
+ self.assertTrue(self.test_record.review_ids)
940
+ # Unable to write test_validation_field under validation
941
+ with self.assertRaises(ValidationError):
942
+ self.test_record.with_user(self.test_user_2.id).write(
943
+ {"test_validation_field": 1}
944
+ )
945
+ # Able to write test_validation_field under validation
946
+ with mock.patch.object(
947
+ TV, "_get_under_validation_exceptions", return_value=_rv
948
+ ):
949
+ self.test_record.with_user(self.test_user_2.id).write(
950
+ {"test_validation_field": 2}
951
+ )
952
+ self.assertEqual(self.test_record.test_validation_field, 2)
953
+ # Validate record
954
+ record = self.test_record.with_user(self.test_user_1.id)
955
+ record.invalidate_model()
956
+ record.validate_tier()
957
+ record.action_confirm()
958
+ self.assertTrue(record.validated)
959
+ # Unable to write test_validation_field after validation
960
+ with self.assertRaises(ValidationError):
961
+ # Simulate there are fields, but not test_validation_field
962
+ with mock.patch.object(TV, "_get_validation_exceptions", return_value=BEF):
963
+ self.test_record.with_user(self.test_user_2.id).write(
964
+ {"test_validation_field": 3}
965
+ )
966
+ # Able to write test_validation_field after validation
967
+ with mock.patch.multiple(
968
+ TV,
969
+ _get_validation_exceptions=mock.MagicMock(return_value=_tvf),
970
+ _get_after_validation_exceptions=mock.MagicMock(return_value=_rv),
971
+ ):
972
+ self.test_record.with_user(self.test_user_2.id).write(
973
+ {"test_validation_field": 4}
974
+ )
975
+ self.assertEqual(self.test_record.test_validation_field, 4)
976
+
920
977
 
921
978
  @tagged("at_install")
922
979
  class TierTierValidationView(CommonTierValidation):
@@ -18,6 +18,7 @@ class TierValidationTester(models.Model):
18
18
  ],
19
19
  default="draft",
20
20
  )
21
+ test_validation_field = fields.Integer(default=0)
21
22
  test_field = fields.Float()
22
23
  user_id = fields.Many2one(string="Assigned to:", comodel_name="res.users")
23
24
 
@@ -40,6 +41,7 @@ class TierValidationTester2(models.Model):
40
41
  default="draft",
41
42
  )
42
43
  test_field = fields.Float()
44
+ test_validation_field = fields.Float()
43
45
  user_id = fields.Many2one(string="Assigned to:", comodel_name="res.users")
44
46
 
45
47
  def action_confirm(self):
@@ -168,5 +168,6 @@
168
168
  id="menu_tier_definition"
169
169
  parent="menu_tier_confirmation"
170
170
  action="tier_definition_action"
171
+ sequence="10"
171
172
  />
172
173
  </odoo>
@@ -0,0 +1,112 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <!-- Copyright 2024 Moduon Team (https://www.moduon.team)
3
+ License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
4
+ <odoo>
5
+ <record id="tier_validation_exception_tree" model="ir.ui.view">
6
+ <field name="name">tier.validation.exception.tree</field>
7
+ <field name="model">tier.validation.exception</field>
8
+ <field name="arch" type="xml">
9
+ <tree>
10
+ <field name="model_id" />
11
+ <field name="field_ids" widget="many2many_tags" optional="show" />
12
+ <field name="company_id" groups="base.group_multi_company" />
13
+ <field name="allowed_to_write_under_validation" />
14
+ <field name="allowed_to_write_after_validation" />
15
+ </tree>
16
+ </field>
17
+ </record>
18
+
19
+ <record id="tier_validation_exception_form" model="ir.ui.view">
20
+ <field name="name">tier.validation.exception.form</field>
21
+ <field name="model">tier.validation.exception</field>
22
+ <field name="arch" type="xml">
23
+ <form string="Tier Validation Exception">
24
+ <sheet>
25
+ <div class="oe_title">
26
+ <span class="oe_edit_only">Model</span>
27
+ <h1>
28
+ <field
29
+ name="model_id"
30
+ options="{'no_create': True, 'no_open': True}"
31
+ />
32
+ </h1>
33
+ </div>
34
+ <group>
35
+ <group name="left">
36
+ <field name="valid_model_field_ids" invisible="1" />
37
+ <field
38
+ name="field_ids"
39
+ widget="many2many_tags"
40
+ options="{'no_create': True}"
41
+ />
42
+ <field
43
+ name="company_id"
44
+ groups="base.group_multi_company"
45
+ />
46
+ </group>
47
+ <group name="right">
48
+ <field name="allowed_to_write_under_validation" />
49
+ <field name="allowed_to_write_after_validation" />
50
+ </group>
51
+ </group>
52
+ </sheet>
53
+ </form>
54
+ </field>
55
+ </record>
56
+
57
+ <record id="tier_validation_exception_search" model="ir.ui.view">
58
+ <field name="name">tier.validation.exception.search</field>
59
+ <field name="model">tier.validation.exception</field>
60
+ <field name="arch" type="xml">
61
+ <search>
62
+ <field name="model_id" />
63
+ <field name="field_ids" />
64
+ <field name="company_id" groups="base.group_multi_company" />
65
+ <separator />
66
+ <filter
67
+ string="Write under validation"
68
+ name="flt_allowed_to_write_under_validation_true"
69
+ domain="[('allowed_to_write_under_validation', '=', True)]"
70
+ />
71
+ <filter
72
+ string="Write after validation"
73
+ name="flt_allowed_to_write_after_validation_true"
74
+ domain="[('allowed_to_write_after_validation', '=', True)]"
75
+ />
76
+ <group>
77
+ <filter
78
+ string="Company"
79
+ name="grp_company"
80
+ domain="[]"
81
+ context="{'group_by': 'company_id'}"
82
+ />
83
+ </group>
84
+ </search>
85
+ </field>
86
+ </record>
87
+
88
+ <record id="tier_validation_exception_action" model="ir.actions.act_window">
89
+ <field name="name">Tier Validation Exception</field>
90
+ <field name="type">ir.actions.act_window</field>
91
+ <field name="res_model">tier.validation.exception</field>
92
+ <field name="view_mode">tree,form</field>
93
+ <field name="help" type="html">
94
+ <p
95
+ class="o_view_nocontent_smiling_face"
96
+ >Create a new Validation Exception!</p>
97
+ <p
98
+ >Once created, you can decide which fields you want to be editable when the record:</p>
99
+ <ul>
100
+ <li>It's in the validation process</li>
101
+ <li>It's fully validated</li>
102
+ </ul>
103
+ </field>
104
+ </record>
105
+
106
+ <menuitem
107
+ id="menu_tier_validation_exception"
108
+ parent="menu_tier_confirmation"
109
+ action="tier_validation_exception_action"
110
+ sequence="20"
111
+ />
112
+ </odoo>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: odoo-addon-base_tier_validation
3
- Version: 17.0.1.5.1.3
3
+ Version: 17.0.2.0.0
4
4
  Requires-Python: >=3.10
5
5
  Requires-Dist: odoo>=17.0a,<17.1dev
6
6
  Summary: Implement a validation process based on tiers.
@@ -23,7 +23,7 @@ Base Tier Validation
23
23
  !! This file is generated by oca-gen-addon-readme !!
24
24
  !! changes will be overwritten. !!
25
25
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
26
- !! source digest: sha256:985b9816d91b596431cb157813581e485b5dee02ac1d0625e208d1516f970a34
26
+ !! source digest: sha256:c6317aa94557d07370f45bb16d3bb54ddbd9f037937958680816482aba127ff2
27
27
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
28
28
 
29
29
  .. |badge1| image:: https://img.shields.io/badge/maturity-Mature-brightgreen.png
@@ -251,6 +251,7 @@ Contributors
251
251
  - bosd
252
252
  - Evan Soh <evan.soh@omnisoftsolution.com>
253
253
  - Manuel Regidor <manuel.regidor@sygel.es>
254
+ - Eduardo de Miguel <edu@moduon.team>
254
255
 
255
256
  Maintainers
256
257
  -----------
@@ -1,31 +1,32 @@
1
- odoo/addons/base_tier_validation/README.rst,sha256=9rsIQR1_-kthmYgfGqRZ_3ecDq1twhLHjE1gsUTwMak,7527
1
+ odoo/addons/base_tier_validation/README.rst,sha256=_rWFCAo-c-7hzpvRCmjzhlBM2l6Sb4y1d9-b2z-_Hgo,7566
2
2
  odoo/addons/base_tier_validation/__init__.py,sha256=rKfzYX9RhkkCxgh2f0PJLYN45Kw8T8-fwxw1pbjLuug,108
3
- odoo/addons/base_tier_validation/__manifest__.py,sha256=hF3vB__WhQDiptSIhmHpoyJsv6ENK0oI66NlmwbsyGk,1606
3
+ odoo/addons/base_tier_validation/__manifest__.py,sha256=ucZRGbnNu0J2mV4NgQDs7WpsRlGE59h8AEna26rdoFQ,1658
4
4
  odoo/addons/base_tier_validation/data/mail_data.xml,sha256=UKzkLT8rYrFuThdp43v7nLW5SOco4vvIIAhbB_IAQZs,1414
5
- odoo/addons/base_tier_validation/i18n/base_tier_validation.pot,sha256=kLaZk1QzRvPUFTxYyATaYg7Xtqj6ZqKT8j4V6Lwh_jQ,26806
5
+ odoo/addons/base_tier_validation/i18n/base_tier_validation.pot,sha256=8v7x8P7bvRckBkHImSDiOALz-5viZ1Lq2Rkd_tkdsIA,31437
6
6
  odoo/addons/base_tier_validation/i18n/es.po,sha256=1mrTc0uRWxDdBlub8QIZwsKoE6t28vT_YniNN1gnlr0,32571
7
7
  odoo/addons/base_tier_validation/i18n/es_MX.po,sha256=jZqztOsZHTRMOY9d2iK1OG0HYCufAhuFK9cGoXvJ2KE,30201
8
8
  odoo/addons/base_tier_validation/i18n/fr.po,sha256=nxS-gcZ8rtqdX6IJbIDRpj6tWw2s-d3GQTJ0IjFzZaA,31207
9
- odoo/addons/base_tier_validation/i18n/it.po,sha256=zBhKFb-_p157-IZzJcHFCEaBqVKHpCqpZV7y1vZ4uVw,32122
9
+ odoo/addons/base_tier_validation/i18n/it.po,sha256=4IqjboE5CTUuD7XDM_7zX1fcKtJ1Els3laTg8QfDEwM,32119
10
10
  odoo/addons/base_tier_validation/i18n/nl_NL.po,sha256=8-gfWvAqGgFjX5EE9FMeypSFsAp_mSX6McCIdBFE5h0,30500
11
11
  odoo/addons/base_tier_validation/i18n/sv.po,sha256=b9nhAtjUwRplMD4yygEQejqyFDK9X1PjBC5KOnS1hC8,32686
12
12
  odoo/addons/base_tier_validation/i18n/tr.po,sha256=kJCCMKVkULuJjhh5SHf2SK7Pu03fmMaBuoNckKd2MSY,30073
13
13
  odoo/addons/base_tier_validation/i18n/zh_CN.po,sha256=0gJMwbLvUSNpV64Yl9S49sr5Mb9mHeuPyFN9yE2lnQ4,28624
14
- odoo/addons/base_tier_validation/models/__init__.py,sha256=mLFF29I3WBYA2Qwlf9NU4pP2KwDKn5JpbZRzwe9-9pg,210
14
+ odoo/addons/base_tier_validation/models/__init__.py,sha256=X8c8CFM5eOXyIErFr7xsaGDBPZMBSKE2v4W-_2h9B2s,250
15
15
  odoo/addons/base_tier_validation/models/res_config_settings.py,sha256=xMdQiCfU5p7Z5puKcSRvJihLpI9ulyVFUd_QJjAOuwc,619
16
16
  odoo/addons/base_tier_validation/models/res_users.py,sha256=JhUZ0NxJ9EPwpkJ-mvsNTrE1avQncGNKqAF-xFxokEo,2638
17
- odoo/addons/base_tier_validation/models/tier_definition.py,sha256=yHFe4atrr-zHUPAfmxB1BYyWK8oC172JTLPnEbCoanI,4125
17
+ odoo/addons/base_tier_validation/models/tier_definition.py,sha256=I-HeOZopA1n-bISs28XDeAosUrTnhL_mp_TB3awb2w0,4168
18
18
  odoo/addons/base_tier_validation/models/tier_review.py,sha256=vuR832VVM-ZUDm-4j9zK1BSNnL0JfesxBSLyhW4Zia8,6754
19
- odoo/addons/base_tier_validation/models/tier_validation.py,sha256=QdE966M-46aTix_rlIuKiH28pYrduf8jsjK2PHir61Q,27196
19
+ odoo/addons/base_tier_validation/models/tier_validation.py,sha256=I-I5q68QdDAALJeUzgN-xSj-UQN7sOk0cx5QFdz-qOI,32602
20
+ odoo/addons/base_tier_validation/models/tier_validation_exception.py,sha256=wlzi9q3oS5YwYdJed6CqO9CRdj9MQWr5-Y0GIZnZkJE,2992
20
21
  odoo/addons/base_tier_validation/readme/CONFIGURE.md,sha256=95NOZLcm0wpb4a8gC89YlSibj7GZ1kz5IbDsuqaaNII,752
21
- odoo/addons/base_tier_validation/readme/CONTRIBUTORS.md,sha256=_JIIvdWdZ7iVO1dpyq9XJ1UtytA1gowJ9L0y0LABJuo,504
22
+ odoo/addons/base_tier_validation/readme/CONTRIBUTORS.md,sha256=J7LBj933qFHjWwQrkaxWQUhFE-O3rqObqyRw96H5dpc,545
22
23
  odoo/addons/base_tier_validation/readme/DESCRIPTION.md,sha256=nFbYOx89EsI26v6NJF9d-Wm-X2YtHduSRlV5Euk3WWc,651
23
24
  odoo/addons/base_tier_validation/readme/HISTORY.md,sha256=P8GfoUhYG7QGIpa8Z0L67E3YEeZBFQCwpDXnt5WG-DY,1332
24
25
  odoo/addons/base_tier_validation/readme/ROADMAP.md,sha256=HRRQQuOlSeOF5yfqG0KuANnvrde8y6Suz2pbrXB1OyU,864
25
- odoo/addons/base_tier_validation/security/ir.model.access.csv,sha256=BuwLCexKbuj-5uOaxK8STRW1UMAhFJVaZj9Kto4iBp8,900
26
+ odoo/addons/base_tier_validation/security/ir.model.access.csv,sha256=g6B58IuYYqxD54e9I9vyre7mD74tkpauqTqMAH4Oey0,1134
26
27
  odoo/addons/base_tier_validation/security/tier_validation_security.xml,sha256=eWFwz-osHgYFmVoEVzOSboO9oqUMtQ8oygyaz0os50Y,806
27
28
  odoo/addons/base_tier_validation/static/description/icon.png,sha256=6xBPJauaFOF0KDHfHgQopSc28kKvxMaeoQFQWZtfZDo,9455
28
- odoo/addons/base_tier_validation/static/description/index.html,sha256=YytZbh7jIMWxDd_BbOmrva_hVwBXdLEcHlOVEh1haEQ,21686
29
+ odoo/addons/base_tier_validation/static/description/index.html,sha256=IpKrO7kJcxmH9DDFqbPtiR0Nxo_xUiAILXHRqeIskSw,21892
29
30
  odoo/addons/base_tier_validation/static/src/components/tier_review_menu/tier_review_menu.esm.js,sha256=MNfjKSg-9h3JfeXiYlf15SAdVHjj3aUvedj0BqVvJrk,2254
30
31
  odoo/addons/base_tier_validation/static/src/components/tier_review_menu/tier_review_menu.xml,sha256=_wIy5Gv2VUJEXD5_FGphx1J19-Y8uzFlWryuPqlIh8c,2798
31
32
  odoo/addons/base_tier_validation/static/src/components/tier_review_widget/tier_review_widget.esm.js,sha256=MDWUp2ozeRdBoLeCfTcOnD-bKnk3yF6pHwtTAnsLZmg,1090
@@ -35,15 +36,16 @@ odoo/addons/base_tier_validation/static/src/js/services/tier_review_service.esm.
35
36
  odoo/addons/base_tier_validation/templates/tier_validation_templates.xml,sha256=VI6kY0V6nVSz6KQ9GRxY_9TZkRrJgzBzsl9xFKtA__Y,3620
36
37
  odoo/addons/base_tier_validation/tests/__init__.py,sha256=3z2_lQ9JiDSFDam4p24qDw5j02iaPb4m2naxv9DkbGA,122
37
38
  odoo/addons/base_tier_validation/tests/common.py,sha256=Q0g3zv6cYrSPx8QHwsikFxRmi7TtmuUr4ID_9WvImd8,4504
38
- odoo/addons/base_tier_validation/tests/test_tier_validation.py,sha256=jSjddl2waQQzOMLGlAAuqKQrItlEeZodA7yMnasgE6g,38852
39
- odoo/addons/base_tier_validation/tests/tier_validation_tester.py,sha256=sUN-BRUHDDQ8t1Dze5c6H_2XQqop7c5cEsA4vJksEpA,1660
39
+ odoo/addons/base_tier_validation/tests/test_tier_validation.py,sha256=7l1kfCv31dqzNgAirZMaQM5OVvaA2OvJ7uAc0O7PLYw,41566
40
+ odoo/addons/base_tier_validation/tests/tier_validation_tester.py,sha256=3usFbhfDhlKIWbVu--3qsbsm52B6RwTP4zy244dY1yk,1757
40
41
  odoo/addons/base_tier_validation/views/res_config_settings_views.xml,sha256=5HbrsAVaXRoQNX7utIQ_EzZrqzKnwBrV9uHsi-PHb9M,2640
41
- odoo/addons/base_tier_validation/views/tier_definition_view.xml,sha256=u0n0iMvMxECxoduao9IpYf1f0LG-sH7QXqIj1mKB1o4,7613
42
+ odoo/addons/base_tier_validation/views/tier_definition_view.xml,sha256=FHpO2tW8FYKQffayERVlQEJH_ip8baZ7nC1NcFDsP7Y,7635
42
43
  odoo/addons/base_tier_validation/views/tier_review_view.xml,sha256=tPzmpz-kbQwOOtJrAcsTJEP9bJLcfzWAITCpI86kZU4,966
44
+ odoo/addons/base_tier_validation/views/tier_validation_exception_view.xml,sha256=aLh_jOIpEl4ScujerORyc2e4ANNVce3GVVf7Jo3waPg,4685
43
45
  odoo/addons/base_tier_validation/wizard/__init__.py,sha256=52q6-LAjYeJ1Vu5ahon_jnhds9VsoJvYaQCiZc82WKw,95
44
46
  odoo/addons/base_tier_validation/wizard/comment_wizard.py,sha256=gj7zCcpe47-2ifxSRlE6okQ1wtq5Ok3JBVg2CtN0ZIU,879
45
47
  odoo/addons/base_tier_validation/wizard/comment_wizard_view.xml,sha256=9XFTqrNwDCZH2IEX3HutaznSkBYk-6RERXzUDwObz4I,979
46
- odoo_addon_base_tier_validation-17.0.1.5.1.3.dist-info/METADATA,sha256=OP-NEiWLhF8pxPrpBoHPPAzpjvFAbIzMOcDjdA3qxDM,8125
47
- odoo_addon_base_tier_validation-17.0.1.5.1.3.dist-info/WHEEL,sha256=8Rd4enx1PCuyDWP4SABqO5Fv8rpaknqp3VzjoFFLa6c,83
48
- odoo_addon_base_tier_validation-17.0.1.5.1.3.dist-info/top_level.txt,sha256=QE6RBQ0QX5f4eFuUcGgU5Kbq1A_qJcDs-e_vpr6pmfU,4
49
- odoo_addon_base_tier_validation-17.0.1.5.1.3.dist-info/RECORD,,
48
+ odoo_addon_base_tier_validation-17.0.2.0.0.dist-info/METADATA,sha256=aeKefD3we4EbPnj3PBs4Fm05tiFqOZiBOVq3KgE5e40,8162
49
+ odoo_addon_base_tier_validation-17.0.2.0.0.dist-info/WHEEL,sha256=8Rd4enx1PCuyDWP4SABqO5Fv8rpaknqp3VzjoFFLa6c,83
50
+ odoo_addon_base_tier_validation-17.0.2.0.0.dist-info/top_level.txt,sha256=QE6RBQ0QX5f4eFuUcGgU5Kbq1A_qJcDs-e_vpr6pmfU,4
51
+ odoo_addon_base_tier_validation-17.0.2.0.0.dist-info/RECORD,,