From 8f225d8aa3879d4942f8e0b8a082454311ac7a8a Mon Sep 17 00:00:00 2001
From: Jairo Llopis
Date: Tue, 12 Nov 2024 11:34:16 +0000
Subject: [PATCH] [FIX] base_vat_optional_vies: don't block mass checks
The whole point of this module is to allow VIES failures. However, when running mass checks, if one single partner failed, the whole process had to start again.
FWIW that can be also problematic due to rate limits in VIES service. For that same reason, we now skip partners that are validated already, and those that are will inherit the status from their parent anyway.
Now, the process will just continue and report failures at the end.
It includes new tests, removes dead code, and reduces pre-existing tests verbosity.
@moduon MT-7763
---
base_vat_optional_vies/README.rst | 14 ++++-
base_vat_optional_vies/__manifest__.py | 1 +
.../models/res_config_settings.py | 29 ++++++++--
base_vat_optional_vies/models/res_partner.py | 16 +-----
.../readme/CONTRIBUTORS.rst | 1 +
base_vat_optional_vies/readme/DESCRIPTION.rst | 2 +-
.../static/description/index.html | 17 +++---
base_vat_optional_vies/tests/__init__.py | 1 +
.../tests/tes_config_settings.py | 44 ---------------
.../tests/test_config_settings.py | 54 +++++++++++++++++++
.../tests/test_res_partner.py | 4 ++
11 files changed, 112 insertions(+), 71 deletions(-)
delete mode 100644 base_vat_optional_vies/tests/tes_config_settings.py
create mode 100644 base_vat_optional_vies/tests/test_config_settings.py
diff --git a/base_vat_optional_vies/README.rst b/base_vat_optional_vies/README.rst
index 4a86b1e7d..2cec14f83 100644
--- a/base_vat_optional_vies/README.rst
+++ b/base_vat_optional_vies/README.rst
@@ -32,7 +32,7 @@ This module extends base_vat module features allowing to know if VIES
validation was passed or not.
Then you can use "VIES validation passed" field in order to show VAT ID with
-or without country preffix in invoices, for instance.
+or without country prefix in invoices, for instance.
*NOTE*: Although VIES validation is set in your company, this validation
will not block VAT ID write (main difference to Odoo standard behavior) if this
@@ -97,6 +97,7 @@ Contributors
* Harald Panten
* Eduardo de Miguel
* Emilio Pascual
+* Jairo Llopis (`Moduon `__)
Maintainers
~~~~~~~~~~~
@@ -111,6 +112,17 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
+.. |maintainer-yajo| image:: https://github.com/yajo.png?size=40px
+ :target: https://github.com/yajo
+ :alt: yajo
+.. |maintainer-rafaelbn| image:: https://github.com/rafaelbn.png?size=40px
+ :target: https://github.com/rafaelbn
+ :alt: rafaelbn
+
+Current `maintainers `__:
+
+|maintainer-yajo| |maintainer-rafaelbn|
+
This module is part of the `OCA/account-financial-tools `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/base_vat_optional_vies/__manifest__.py b/base_vat_optional_vies/__manifest__.py
index 280380bde..667a6a844 100644
--- a/base_vat_optional_vies/__manifest__.py
+++ b/base_vat_optional_vies/__manifest__.py
@@ -17,5 +17,6 @@
"author": "Tecnativa," "Odoo Community Association (OCA)",
"website": "https://github.com/OCA/account-financial-tools",
"license": "AGPL-3",
+ "maintainers": ["yajo", "rafaelbn"],
"installable": True,
}
diff --git a/base_vat_optional_vies/models/res_config_settings.py b/base_vat_optional_vies/models/res_config_settings.py
index 757d0bdf4..0da07c864 100644
--- a/base_vat_optional_vies/models/res_config_settings.py
+++ b/base_vat_optional_vies/models/res_config_settings.py
@@ -1,20 +1,41 @@
# Copyright 2022-2023 Moduon Team S.L.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from logging import getLogger
from odoo import _, models
+from odoo.exceptions import ValidationError
+
+_logger = getLogger(__name__)
class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"
def execute_update_check_vies(self):
- # Only parent partners, children are synced from parent
- count_partners = self.env["res.partner"].search_count([])
- self.env["res.partner"].search([]).check_vat()
+ """Bulk VAT check on company partners."""
+ partners = self.env["res.partner"].search(
+ [
+ ("is_company", "=", True),
+ ("parent_id", "=", False),
+ ("vat", "!=", False),
+ ("vies_passed", "=", False),
+ ]
+ )
+ failures = 0
+ for partner in partners:
+ try:
+ partner.check_vat()
+ except ValidationError:
+ _logger.warning("VAT check failed for %r", partner, exc_info=True)
+ failures += 1
return {
"effect": {
"fadeout": "slow",
- "message": _("Vies passed calculated in %s partners") % count_partners,
+ "message": _(
+ "Vies passed calculated in %(partners)d partners (%(failures)d failures)",
+ partners=len(partners),
+ failures=failures,
+ ),
"img_url": "/web/static/img/smile.svg",
"type": "rainbow_man",
}
diff --git a/base_vat_optional_vies/models/res_partner.py b/base_vat_optional_vies/models/res_partner.py
index b76b6c5f0..9c7d1a151 100644
--- a/base_vat_optional_vies/models/res_partner.py
+++ b/base_vat_optional_vies/models/res_partner.py
@@ -4,9 +4,7 @@
# Copyright 2022 Moduon - Eduardo de Miguel
# Copyright 2023 Moduon - Emilio Pascual
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
-from odoo import _, api, fields, models
-
-from odoo.addons.base_vat.models.res_partner import _ref_vat
+from odoo import api, fields, models
class ResPartner(models.Model):
@@ -61,15 +59,3 @@ class ResPartner(models.Model):
return super(
ResPartner, self.with_context(vat_partner=self)
)._onchange_check_vies()
-
- @api.model
- def _build_vat_error_message(self, country_code, wrong_vat, record_label):
- return "\n" + _(
- "The VAT number [%(wrong_vat)s] for %(record_label)s does not seem to be valid. "
- "\nNote: the expected format is %(expected_format)s",
- wrong_vat=wrong_vat,
- record_label=record_label,
- expected_format=_ref_vat.get(
- country_code, "'CC##' (CC=Country Code, ##=VAT Number)"
- ),
- )
diff --git a/base_vat_optional_vies/readme/CONTRIBUTORS.rst b/base_vat_optional_vies/readme/CONTRIBUTORS.rst
index c24f5cdc2..1edb0e39a 100644
--- a/base_vat_optional_vies/readme/CONTRIBUTORS.rst
+++ b/base_vat_optional_vies/readme/CONTRIBUTORS.rst
@@ -7,3 +7,4 @@
* Harald Panten
* Eduardo de Miguel
* Emilio Pascual
+* Jairo Llopis (`Moduon `__)
diff --git a/base_vat_optional_vies/readme/DESCRIPTION.rst b/base_vat_optional_vies/readme/DESCRIPTION.rst
index c430079de..618b114cc 100644
--- a/base_vat_optional_vies/readme/DESCRIPTION.rst
+++ b/base_vat_optional_vies/readme/DESCRIPTION.rst
@@ -2,7 +2,7 @@ This module extends base_vat module features allowing to know if VIES
validation was passed or not.
Then you can use "VIES validation passed" field in order to show VAT ID with
-or without country preffix in invoices, for instance.
+or without country prefix in invoices, for instance.
*NOTE*: Although VIES validation is set in your company, this validation
will not block VAT ID write (main difference to Odoo standard behavior) if this
diff --git a/base_vat_optional_vies/static/description/index.html b/base_vat_optional_vies/static/description/index.html
index 1129df23b..42a64b68e 100644
--- a/base_vat_optional_vies/static/description/index.html
+++ b/base_vat_optional_vies/static/description/index.html
@@ -1,4 +1,3 @@
-
@@ -9,10 +8,11 @@
/*
:Author: David Goodger (goodger@python.org)
-:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
+:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
+Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
@@ -275,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
-pre.code .ln { color: grey; } /* line numbers */
+pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -301,7 +301,7 @@ span.option {
span.pre {
white-space: pre }
-span.problematic {
+span.problematic, pre.problematic {
color: red }
span.section-subtitle {
@@ -373,7 +373,7 @@ ul.auto-toc {
This module extends base_vat module features allowing to know if VIES
validation was passed or not.
Then you can use “VIES validation passed” field in order to show VAT ID with
-or without country preffix in invoices, for instance.
+or without country prefix in invoices, for instance.
NOTE: Although VIES validation is set in your company, this validation
will not block VAT ID write (main difference to Odoo standard behavior) if this
VAT ID is valid in its country.
@@ -441,15 +441,20 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
Harald Panten <harald.panten@sygel.es>
Eduardo de Miguel <edu@moduon.team>
Emilio Pascual <emilio@moduon.team>
+Jairo Llopis (Moduon)
This module is maintained by the OCA.
-

+
+
+
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
+
Current maintainers:
+

This module is part of the OCA/account-financial-tools project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/base_vat_optional_vies/tests/__init__.py b/base_vat_optional_vies/tests/__init__.py
index d57d215f9..cea88474a 100644
--- a/base_vat_optional_vies/tests/__init__.py
+++ b/base_vat_optional_vies/tests/__init__.py
@@ -1 +1,2 @@
+from . import test_config_settings
from . import test_res_partner
diff --git a/base_vat_optional_vies/tests/tes_config_settings.py b/base_vat_optional_vies/tests/tes_config_settings.py
deleted file mode 100644
index 93cd36873..000000000
--- a/base_vat_optional_vies/tests/tes_config_settings.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2022-2023 Moduon Team S.L.
-# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-
-from unittest import mock
-
-from odoo.tests import common
-
-
-class TestConfigSettings(common.TransactionCase):
- def setUp(self):
- super(TestConfigSettings, self).setUp()
- self.company = self.env.user.company_id
- self.partner1_test = self.env["res.partner"].create(
- {
- "name": "Test partner",
- "is_company": True,
- "vat": "ESB87530432",
- "country_id": self.env.ref("base.be").id,
- }
- )
- self.partner2_test = self.env["res.partner"].create(
- {
- "name": "Test partner2",
- "is_company": True,
- "vat": "ESB87530432",
- }
- )
- self.vatnumber_path = "odoo.addons.base_vat.models.res_partner.check_vies"
-
- def test_execute_update_check_vies_validate(self):
- with mock.patch(self.vatnumber_path) as mock_vatnumber:
- self.company.vat_check_vies = True
- mock_vatnumber.check_vies.return_value = True
- self.env["res.config.settings"].execute_update_check_vies()
- self.assertTrue(self.partner1_test.vies_passed)
- self.assertFalse(self.partner2_test.vies_passed)
-
- def test_execute_update_check_vies_no_validate(self):
- with mock.patch(self.vatnumber_path) as mock_vatnumber:
- self.company.vat_check_vies = False
- mock_vatnumber.check_vies.return_value = False
- self.env["res.config.settings"].execute_update_check_vies()
- self.assertFalse(self.partner1_test.vies_passed)
- self.assertFalse(self.partner2_test.vies_passed)
diff --git a/base_vat_optional_vies/tests/test_config_settings.py b/base_vat_optional_vies/tests/test_config_settings.py
new file mode 100644
index 000000000..907052dec
--- /dev/null
+++ b/base_vat_optional_vies/tests/test_config_settings.py
@@ -0,0 +1,54 @@
+# Copyright 2024 Moduon Team S.L.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from unittest import mock
+
+from odoo.tests import common
+from odoo.tools import mute_logger
+
+
+class TestConfigSettings(common.TransactionCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ cls.partner1, cls.partner2 = (
+ cls.env["res.partner"]
+ .with_context(no_vat_validation=True)
+ .create(
+ [
+ {
+ "name": "Test partner",
+ "is_company": True,
+ "vat": "ESB87530432",
+ "country_id": cls.env.ref("base.es").id,
+ },
+ {
+ "name": "Test partner2",
+ "is_company": True,
+ "vat": "ES00000000T",
+ "country_id": cls.env.ref("base.es").id,
+ },
+ ]
+ )
+ )
+ cls.config = cls.env["res.config.settings"].create({"vat_check_vies": True})
+
+ def setUp(self):
+ super().setUp()
+ self.mock_check_vies = self.startPatcher(
+ mock.patch(
+ "odoo.addons.base_vat.models.res_partner.check_vies",
+ side_effect=(lambda vat: {"valid": vat == "ESB87530432"}),
+ )
+ )
+
+ @mute_logger(
+ "odoo.addons.base_vat_optional_vies.models.res_config_settings",
+ "odoo.addons.base_vat.models.res_partner",
+ )
+ def test_batch_checking(self):
+ self.config.execute_update_check_vies()
+ self.mock_check_vies.assert_any_call("ESB87530432")
+ self.mock_check_vies.assert_any_call("ES00000000T")
+ self.assertTrue(self.partner1.vies_passed)
+ self.assertFalse(self.partner2.vies_passed)
diff --git a/base_vat_optional_vies/tests/test_res_partner.py b/base_vat_optional_vies/tests/test_res_partner.py
index 770525686..f6ca96b06 100644
--- a/base_vat_optional_vies/tests/test_res_partner.py
+++ b/base_vat_optional_vies/tests/test_res_partner.py
@@ -8,6 +8,7 @@ from unittest.mock import patch
from odoo.exceptions import ValidationError
from odoo.tests import common
+from odoo.tools import mute_logger
class TestResPartner(common.TransactionCase):
@@ -26,6 +27,7 @@ class TestResPartner(common.TransactionCase):
cls._vies_check_func = check_vies
+ @mute_logger("odoo.addons.base_vat.models.res_partner")
def test_validate_vat_vies(self):
with patch(self.vatnumber_path, type(self)._vies_check_func):
values = {"vat": "ESB87530432", "country_id": self.env.ref("base.be").id}
@@ -40,6 +42,7 @@ class TestResPartner(common.TransactionCase):
self.partner.write(values)
self.assertEqual(self.partner.vies_passed, True)
+ @mute_logger("odoo.addons.base_vat.models.res_partner")
def test_exception_vat_vies(self):
with patch(self.vatnumber_path, side_effect=Exception()):
values = {"vat": "87530432", "country_id": self.env.ref("base.es").id}
@@ -69,6 +72,7 @@ class TestResPartner(common.TransactionCase):
self.partner.country_id = self.env.ref("base.mx")
self.assertEqual(self.partner.vies_passed, False)
+ @mute_logger("odoo.addons.base_vat.models.res_partner")
def test_validate_vies_passed_false_when_vat_set_to_false(self):
with patch(self.vatnumber_path) as mock_vatnumber:
mock_vatnumber.check_vies.return_value = True