From 3368aa9bac821e27dcb95ff96cfb3485df904380 Mon Sep 17 00:00:00 2001 From: Akim Juillerat Date: Mon, 6 Jan 2020 14:56:34 +0100 Subject: [PATCH 1/3] [FIX] partner_ref_unique: Trigger check on company update Before this commit, the partner_ref_unique could be changed on the company even if existing partners share the same internal ref. Therefore, errors will appear afterwards as DB already contains duplicates although the policy shouldn't allow it. With this change, the error will appear as soon as the policy is changed, so that the data must be fixed before activating the constraint. --- partner_ref_unique/__manifest__.py | 2 +- partner_ref_unique/models/res_partner.py | 12 +++++++++--- partner_ref_unique/tests/test_res_partner_ref.py | 7 ++++++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/partner_ref_unique/__manifest__.py b/partner_ref_unique/__manifest__.py index 87f9ae2fa..672969662 100644 --- a/partner_ref_unique/__manifest__.py +++ b/partner_ref_unique/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Partner unique reference", "summary": "Add an unique constraint to partner ref field", - "version": "12.0.1.0.0", + "version": "12.0.1.0.1", "category": "Customer Relationship Management", "website": "https://github.com/OCA/partner-contact/", "author": "Tecnativa, " diff --git a/partner_ref_unique/models/res_partner.py b/partner_ref_unique/models/res_partner.py index c7fc7af23..0b45a7ca0 100644 --- a/partner_ref_unique/models/res_partner.py +++ b/partner_ref_unique/models/res_partner.py @@ -1,18 +1,24 @@ # Copyright 2016 Antonio Espinosa # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from odoo import _, api, models +from odoo import _, api, fields, models from odoo.exceptions import ValidationError class ResPartner(models.Model): _inherit = "res.partner" + # This related is needed in order to trigger the check when changing the + # value on res.company + partner_ref_unique = fields.Selection( + related='company_id.partner_ref_unique', + ) + @api.multi - @api.constrains('ref', 'is_company', 'company_id') + @api.constrains('ref', 'is_company', 'company_id', 'partner_ref_unique') def _check_ref(self): for partner in self: - mode = partner.company_id.partner_ref_unique + mode = partner.partner_ref_unique if (partner.ref and ( mode == 'all' or (mode == 'companies' and partner.is_company))): diff --git a/partner_ref_unique/tests/test_res_partner_ref.py b/partner_ref_unique/tests/test_res_partner_ref.py index bd97bda3b..39509fa42 100644 --- a/partner_ref_unique/tests/test_res_partner_ref.py +++ b/partner_ref_unique/tests/test_res_partner_ref.py @@ -18,7 +18,7 @@ class TestResPartnerRefUnique(common.SavepointCase): 'name': 'Partner2', }) - def test_check_ref(self): + def test_check_ref_company(self): # Test can create/modify partners with same ref self.company.partner_ref_unique = 'none' self.partner1.ref = 'same_ref' @@ -30,6 +30,11 @@ class TestResPartnerRefUnique(common.SavepointCase): 'ref': 'same_ref', }) self.partner2.ref = False + with self.assertRaises(ValidationError): + self.company.partner_ref_unique = 'all' + + def test_check_ref(self): + self.partner1.ref = 'same_ref' # Test can't create/modify partner with same ref self.company.partner_ref_unique = 'all' with self.assertRaises(ValidationError): From ac22a5810493fdc994be7713bf90923c957fff35 Mon Sep 17 00:00:00 2001 From: Akim Juillerat Date: Wed, 8 Jan 2020 13:59:59 +0100 Subject: [PATCH 2/3] Store partner_ref_unique to allow triggering the error updating res.company Add pre_init_hook to speed up module installation --- partner_ref_unique/__init__.py | 1 + partner_ref_unique/__manifest__.py | 1 + partner_ref_unique/hooks.py | 27 ++++++++++++++++++++++++ partner_ref_unique/models/res_partner.py | 2 +- 4 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 partner_ref_unique/hooks.py diff --git a/partner_ref_unique/__init__.py b/partner_ref_unique/__init__.py index 83e553ac4..01aac13a6 100644 --- a/partner_ref_unique/__init__.py +++ b/partner_ref_unique/__init__.py @@ -1,3 +1,4 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from . import models +from .hooks import pre_init_hook diff --git a/partner_ref_unique/__manifest__.py b/partner_ref_unique/__manifest__.py index 672969662..9b58a6323 100644 --- a/partner_ref_unique/__manifest__.py +++ b/partner_ref_unique/__manifest__.py @@ -13,6 +13,7 @@ "license": "AGPL-3", "application": False, "installable": True, + "pre_init_hook": "pre_init_hook", "depends": [ "base", ], diff --git a/partner_ref_unique/hooks.py b/partner_ref_unique/hooks.py new file mode 100644 index 000000000..8de3c4283 --- /dev/null +++ b/partner_ref_unique/hooks.py @@ -0,0 +1,27 @@ +# Copyright 2019 Camptocamp SA +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +import logging + +_logger = logging.getLogger(__name__) + + +def pre_init_hook(cr): + """Create column using SQL to avoid auto-init updating the table row by row + :param odoo.sql_db.Cursor cr: + Database cursor. + """ + _logger.info( + "Creating res.partner.partner_ref_unique column with value from " + "res.company" + ) + cr.execute("ALTER TABLE res_partner ADD partner_ref_unique varchar NULL;") + cr.execute( + "COMMENT ON COLUMN res_partner.partner_ref_unique " + "IS 'Unique partner reference for';" + ) + cr.execute( + "UPDATE res_partner rp " + "SET partner_ref_unique = rc.partner_ref_unique " + "FROM res_company rc " + "WHERE rc.id = rp.company_id;" + ) diff --git a/partner_ref_unique/models/res_partner.py b/partner_ref_unique/models/res_partner.py index 0b45a7ca0..c248c4196 100644 --- a/partner_ref_unique/models/res_partner.py +++ b/partner_ref_unique/models/res_partner.py @@ -11,7 +11,7 @@ class ResPartner(models.Model): # This related is needed in order to trigger the check when changing the # value on res.company partner_ref_unique = fields.Selection( - related='company_id.partner_ref_unique', + related='company_id.partner_ref_unique', store=True, ) @api.multi From d9da8510a360169c2e9f1275716144aa04730b84 Mon Sep 17 00:00:00 2001 From: Akim Juillerat Date: Wed, 8 Jan 2020 15:56:23 +0100 Subject: [PATCH 3/3] fixup! Store partner_ref_unique to allow triggering the error updating res.company --- partner_ref_unique/hooks.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/partner_ref_unique/hooks.py b/partner_ref_unique/hooks.py index 8de3c4283..2a51c94f5 100644 --- a/partner_ref_unique/hooks.py +++ b/partner_ref_unique/hooks.py @@ -1,4 +1,4 @@ -# Copyright 2019 Camptocamp SA +# Copyright 2020 Camptocamp SA # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) import logging @@ -10,6 +10,15 @@ def pre_init_hook(cr): :param odoo.sql_db.Cursor cr: Database cursor. """ + _logger.info("Creating res.company.partner_ref_unique column") + cr.execute("ALTER TABLE res_company ADD partner_ref_unique varchar NULL;") + cr.execute( + "COMMENT ON COLUMN public.res_company.partner_ref_unique " + "IS 'Unique partner reference for';" + ) + cr.execute( + "UPDATE res_company SET partner_ref_unique = 'none';" + ) _logger.info( "Creating res.partner.partner_ref_unique column with value from " "res.company"