diff --git a/partner_tier_validation/data/tier_definition.xml b/partner_tier_validation/data/tier_definition.xml index 9d328db91..4a5436fa0 100644 --- a/partner_tier_validation/data/tier_definition.xml +++ b/partner_tier_validation/data/tier_definition.xml @@ -1,12 +1,12 @@ - - Partner Validation + + Partner Validation (Company) group domain ["&",["parent_id","=",False],"|",["active","=",True],["active","=",False]] + >["&",["is_company","=",True],"|",["active","=",True],["active","=",False]] diff --git a/partner_tier_validation/models/res_partner.py b/partner_tier_validation/models/res_partner.py index 79464e016..34e78d17e 100644 --- a/partner_tier_validation/models/res_partner.py +++ b/partner_tier_validation/models/res_partner.py @@ -15,18 +15,33 @@ class ResPartner(models.Model): default="draft", ) + @api.model + def _tier_revalidation_fields(self, values): + """ + Changing some Partner fields forces Tier Validation to be reevaluated. + Out of the box these are is_company and parent_id. + Other can be added extenting this method. + """ + return ["is_company", "parent_id"] + @api.model def create(self, vals): new = super().create(vals) if new.need_validation and new.state != "confirmed": new.active = False + else: + new.active = True + new.state = "confirmed" return new def write(self, vals): - """ - Default `active` is False. - It is set to True when State changes to confirmed. - """ + # Changing certain fields required new validation process + revalidate_fields = self._tier_revalidation_fields(vals) + if any(x in revalidate_fields for x in vals.keys()): + self.mapped("review_ids").unlink() + vals["state"] = "draft" + + # Automatically update active flag depending on state if "state" in vals: vals["active"] = vals["state"] == "confirmed" return super().write(vals) diff --git a/partner_tier_validation/readme/DESCRIPTION.rst b/partner_tier_validation/readme/DESCRIPTION.rst index 3e383aee8..fe2b83fe6 100644 --- a/partner_tier_validation/readme/DESCRIPTION.rst +++ b/partner_tier_validation/readme/DESCRIPTION.rst @@ -1,5 +1,12 @@ Adds an approval workflow to Partners. -The default rule requires new parent Contacts to be approved +The default rule requires new company Contacts to be approved before they can be used. +The rule can be extended to new non-company contact, +but beware that may cause issues with automatically created new contacts, +such as the ones generated when processing incoming emails. + +If the 'Is Company' or 'Parent' field changes then the contact is Request +for approval. + For this, the new Contact record is kept as "Archived" until it is approved. diff --git a/partner_tier_validation/tests/__init__.py b/partner_tier_validation/tests/__init__.py new file mode 100644 index 000000000..f39596410 --- /dev/null +++ b/partner_tier_validation/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import test_tier_validation diff --git a/partner_tier_validation/tests/test_tier_validation.py b/partner_tier_validation/tests/test_tier_validation.py new file mode 100644 index 000000000..f4fe3d221 --- /dev/null +++ b/partner_tier_validation/tests/test_tier_validation.py @@ -0,0 +1,68 @@ +# Copyright 2021 Patrick Wilson +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl.html). + +from odoo.exceptions import ValidationError +from odoo.tests import common, tagged + + +@tagged("-at_install", "post_install") +class TestPartnerTierValidation(common.SavepointCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + # Get res partner model + cls.partner_model = cls.env.ref("base.model_res_partner") + + # Create users + group_ids = cls.env.ref("base.group_system").ids + group_ids.append(cls.env.ref("base.group_partner_manager").id) + cls.test_user_1 = cls.env["res.users"].create( + { + "name": "John", + "login": "test1", + "groups_id": [(6, 0, group_ids)], + "email": "test@examlple.com", + } + ) + + # Create tier definitions: + cls.tier_def_obj = cls.env["tier.definition"] + cls.tier_def_obj.create( + { + "model_id": cls.partner_model.id, + "review_type": "individual", + "reviewer_id": cls.test_user_1.id, + "definition_domain": "['&',('is_company','=',True),'|', \ + ('active','=',True),('active','=',False)]", + } + ) + + def test_tier_validation_model_name(self): + self.assertIn( + "res.partner", self.tier_def_obj._get_tier_validation_model_names() + ) + + def test_validation_res_partner(self): + company = self.env["res.partner"].create( + {"name": "Company for test", "company_type": "company"} + ) + # Since company need validation, it should be inactive + self.assertEqual(company.active, False) + + # Assert an error shows if trying to make it active + with self.assertRaises(ValidationError): + company.write({"state": "confirmed"}) + + # Request and validate partner + company.request_validation() + company.with_user(self.test_user_1).validate_tier() + company.with_user(self.test_user_1).write({"state": "confirmed"}) + self.assertEqual(company.state, "confirmed") + + # Change company type to retrigger validation + company.write({"company_type": "person", "is_company": False}) + self.assertEqual(company.state, "draft") + + # Test partner creation that doesn't need validation + customer = self.env["res.partner"].create({"name": "Partner for test"}) + self.assertEqual(customer.active, True)