From cb8dd2f5c84df1fb4494d5851254926a987d2658 Mon Sep 17 00:00:00 2001 From: Holger Brunn Date: Wed, 19 Apr 2023 18:50:52 +0200 Subject: [PATCH] [ADD] base_tier_validation: compute validation flag dynamically --- .../models/tier_definition.py | 29 +++++++++++++++++ .../models/tier_validation.py | 32 +++++++++++++++++-- .../tests/test_tier_validation.py | 16 ++++++++++ 3 files changed, 74 insertions(+), 3 deletions(-) diff --git a/base_tier_validation/models/tier_definition.py b/base_tier_validation/models/tier_definition.py index ec40bc60af..57300aa8eb 100644 --- a/base_tier_validation/models/tier_definition.py +++ b/base_tier_validation/models/tier_definition.py @@ -103,3 +103,32 @@ def _compute_domain_reviewer_field(self): rec.valid_reviewer_field_ids = self.env["ir.model.fields"].search( [("model", "=", rec.model), ("relation", "=", "res.users")] ) + + @api.model_create_multi + def create(self, vals_list): + result = super().create(vals_list) + result._update_registry() + return result + + def write(self, vals): + result = super().write(vals) + if "definition_domain" in vals: + self._update_registry() + return result + + def unlink(self): + models = set(self.mapped("model")) + result = super().unlink() + self._update_registry(models) + return result + + def _update_registry(self, models=None): + """Update dependencies of validation flag""" + for model in models or set(self.mapped("model")): + depends = self.env[model]._compute_need_validation._depends + if not callable(depends): # pragma: no cover + continue + self.pool.field_depends[ + self.env[model]._fields["need_validation"] + ] = depends(self.env[model]) + self.pool.registry_invalidated = True diff --git a/base_tier_validation/models/tier_validation.py b/base_tier_validation/models/tier_validation.py index 547a1f948a..09b4ebb390 100644 --- a/base_tier_validation/models/tier_validation.py +++ b/base_tier_validation/models/tier_validation.py @@ -7,6 +7,7 @@ from odoo import _, api, fields, models from odoo.exceptions import ValidationError +from odoo.osv.expression import is_leaf from odoo.tools.misc import frozendict @@ -213,11 +214,9 @@ def _calc_reviews_rejected(self, reviews): """Override for different rejection policy.""" return any([s == "rejected" for s in reviews.mapped("status")]) + @api.depends(lambda self: self._compute_need_validation_dependencies()) def _compute_need_validation(self): for rec in self: - if isinstance(rec.id, models.NewId): - rec.need_validation = False - continue tiers = self.env["tier.definition"].search( [ ("model", "=", self._name), @@ -229,6 +228,33 @@ def _compute_need_validation(self): not rec.review_ids and valid_tiers and rec._check_state_from_condition() ) + def _compute_need_validation_dependencies(self): + """Return the fields the validation flag depends on""" + if self._abstract: + return [] + tiers = self.env["tier.definition"].search([("model", "=", self._name)]) + tier_domains = sum( + # we can't browse because this is called during updates too + ( + literal_eval( + tier.read(["definition_domain"])[0]["definition_domain"] or "[]" + ) + for tier in tiers + ), + [], + ) + dependencies = [] + for leaf in tier_domains: + if not is_leaf(leaf): + continue + field_name = leaf[0] + if "." in field_name: + field_name = field_name.split(".", 1)[0] + if field_name in self._fields: + dependencies.append(leaf[0]) + + return dependencies + def evaluate_tier(self, tier): if tier.definition_domain: domain = literal_eval(tier.definition_domain) diff --git a/base_tier_validation/tests/test_tier_validation.py b/base_tier_validation/tests/test_tier_validation.py index 0f62ed12bb..a2dc870ef9 100644 --- a/base_tier_validation/tests/test_tier_validation.py +++ b/base_tier_validation/tests/test_tier_validation.py @@ -851,6 +851,22 @@ def test_24_no_notification(self): ) self.assertEqual(notifications_no_2, notifications_no_1) + def test_25_update_registry(self): + """Test that changes to the tier definition reloads the registry""" + tier = self.env["tier.definition"].search( + [ + ("model_id", "=", self.tester_model.id), + ] + ) + field = self.env[self.test_model._name]._fields["need_validation"] + self.assertIn("test_field", self.env.registry.field_depends[field]) + tier.write({"definition_domain": "[('user_id.name', '=', 'test')]"}) + self.assertNotIn("test_field", self.env.registry.field_depends[field]) + tier.unlink() + self.assertNotIn("test_field", self.env.registry.field_depends[field]) + self.assertTrue(self.env.registry.registry_invalidated) + self.env.registry.registry_invalidated = False + @tagged("at_install") class TierTierValidationView(CommonTierValidation):