Browse Source

Merge PR #1233 into 14.0

Signed-off-by dreispt
14.0
OCA-git-bot 2 years ago
parent
commit
fe9817d1cb
  1. 48
      partner_tier_validation/models/res_partner.py
  2. 22
      partner_tier_validation/readme/CONFIGURATION.rst
  3. 5
      partner_tier_validation/readme/USAGE.rst
  4. 68
      partner_tier_validation/tests/test_tier_validation.py

48
partner_tier_validation/models/res_partner.py

@ -15,40 +15,36 @@ class ResPartner(models.Model):
_tier_validation_manual_config = False
@api.model
def _tier_revalidation_fields(self, values):
def _partner_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 extending this method.
"""
return ["is_company", "parent_id"]
@api.model
def _get_confirmed_stage(self):
return self.env["res.partner.stage"].search(
[("state", "in", self._state_to)], limit=1
)
@api.model
def create(self, vals):
new = super().create(vals)
# Contact not requiring validation
# are created in confirmed state
if not new.need_validation:
confirmed_stage = self._get_confirmed_stage()
new.stage_id = confirmed_stage
return new
# IDEA: make it a System Parameter?
return [
"company_type",
"parent_id",
"vat",
"state_id",
"country_id",
"property_account_position_id",
"property_account_receivable_id",
"property_account_payable_id",
]
def write(self, vals):
# Signal state transition by adding to vals
# Changing certain fields requires a new validation process
revalidate_fields = self._partner_tier_revalidation_fields(vals)
if any(x in revalidate_fields for x in vals.keys()):
vals["stage_id"] = self._get_default_stage_id().id
# Tier Validation does not work with Stages, only States :-(
# Workaround is to signal state transition adding it to the write values
if "stage_id" in vals:
stage_id = vals.get("stage_id")
stage = self.env["res.partner.stage"].browse(stage_id)
vals["state"] = stage.state
# 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"
self.request_validation()
return super().write(vals)
res = super().write(vals)
if "stage_id" in vals:
self.restart_validation()
return res

22
partner_tier_validation/readme/CONFIGURATION.rst

@ -3,8 +3,22 @@ A default validation rule is provided out of the box,
that can be used as a starting point fot this configuration.
This configuration is done at
*Settings > Technical > Tier Validations > Tier Definition*.
*Settings / Technical / Tier Validations / Tier Definition*.
Note that, since Contacts start as archived records,
the *Definition Domain* must include ``"|",["active","=",True],["active","=",False]``.
Otherwise the validation rule won't apply correctly in new records.
Also relevant is the configuration on the default Stage
for new Contacts/Partners.
This can be set at *Contacts / Configuration / Contact Stage*,
setting the "Default Sate" field on the appropriate Stage record.
Changing some fields will trigger a new request for validation.
This list of fields can be customized extending ``_partner_tier_revalidation_fields``.
By default these fields are:
- Company Type (Individual or Company)
- Parent Company
- Tax ID
- State
- Country
- Fiscal Position
- Account Receivable
- Account Payable

5
partner_tier_validation/readme/USAGE.rst

@ -1,3 +1,8 @@
Before using, check Contact Stages configuration,
to ensure that the default stage has the "Related State" field
set to "To Approve".
For example, having the "Draft" stage the default ensures this.
A regular user creates a new Contact and sends it for approval:
#. Create a Contact triggering at least one "Tier Definition".

68
partner_tier_validation/tests/test_tier_validation.py

@ -10,18 +10,25 @@ 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(
group_user = cls.env.ref("base.group_user")
group_contacts = cls.env.ref("base.group_partner_manager")
group_approver = cls.env.ref("base.group_no_one")
User = cls.env["res.users"]
cls.user_employee = User.create(
{
"name": "Employee",
"login": "empl1",
"email": "empl1@example.com",
"groups_id": (group_user | group_contacts).ids,
}
)
cls.user_approver = User.create(
{
"name": "John",
"login": "test1",
"groups_id": [(6, 0, group_ids)],
"email": "test@example.com",
"name": "Approver",
"login": "aprov1",
"email": "approv1@example.com",
"groups_id": (group_user | group_contacts | group_approver).ids,
}
)
@ -29,13 +36,20 @@ class TestPartnerTierValidation(common.SavepointCase):
cls.TierDefinition = cls.env["tier.definition"]
cls.TierDefinition.create(
{
"model_id": cls.partner_model.id,
"model_id": cls.env.ref("base.model_res_partner").id,
"review_type": "individual",
"reviewer_id": cls.test_user_1.id,
"reviewer_id": cls.user_approver.id,
"definition_domain": "[('is_company','=',True)]",
}
)
# Setup Contact Stages: draft is the default
Stage = cls.env["res.partner.stage"]
Stage.search([("is_default", "=", True)]).write({"is_default": False})
cls.stage_draft = Stage.search([("state", "=", "draft")], limit=1)
cls.stage_draft.is_default = True
cls.stage_confirmed = Stage.search([("state", "=", "confirmed")], limit=1)
def test_tier_validation_model_name(self):
self.assertIn(
"res.partner", self.TierDefinition._get_tier_validation_model_names()
@ -45,31 +59,37 @@ class TestPartnerTierValidation(common.SavepointCase):
"""
Case where new Contact requires validation
"""
contact = self.env["res.partner"].create(
{"name": "Company for test", "company_type": "company"}
)
# Since contact need validation, it should be inactive
Partner = self.env["res.partner"]
contact_vals = {"name": "Company for test", "company_type": "company"}
contact = Partner.with_user(self.user_employee).create(contact_vals)
self.assertEqual(contact.state, "draft")
# Assert an error shows if trying to make it active
with self.assertRaises(ValidationError):
contact.write({"state": "confirmed"})
contact.write({"stage_id": self.stage_confirmed.id})
# Request and validate partner
contact.request_validation()
contact.with_user(self.test_user_1).validate_tier()
contact.with_user(self.test_user_1).write({"state": "confirmed"})
contact.with_user(self.user_approver).validate_tier()
contact.with_user(self.user_approver).write(
{"stage_id": self.stage_confirmed.id}
)
self.assertEqual(contact.state, "confirmed")
# Change company type to retrigger validation
contact.write({"company_type": "person", "is_company": False})
self.assertEqual(contact.state, "draft")
contact.write({"company_type": "person"})
self.assertEqual(
contact.state, "draft", "Change company type sets back to draft"
)
def test_no_validation_res_partner(self):
"""
Case where new Contact does not require validation
"""
contact = self.env["res.partner"].create(
{"name": "Person for test", "company_type": "person"}
)
Partner = self.env["res.partner"]
contact_vals = {"name": "Company for test", "company_type": "person"}
contact = Partner.with_user(self.user_employee).create(contact_vals)
self.assertEqual(contact.state, "draft")
# Can move to confirmed state without approval
contact.write({"stage_id": self.stage_confirmed.id})
self.assertEqual(contact.state, "confirmed")
Loading…
Cancel
Save