diff --git a/partner_vat_manual_check_vies/README.rst b/partner_vat_manual_check_vies/README.rst new file mode 100644 index 00000000000..31c41d30954 --- /dev/null +++ b/partner_vat_manual_check_vies/README.rst @@ -0,0 +1,136 @@ +======================================== +Manual validation of European VAT number +======================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:b5c065825fe93d47826c9c18e6210074880e19010f97c405b3cbcca60f7fc298 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--financial--tools-lightgray.png?logo=github + :target: https://github.com/OCA/account-financial-tools/tree/18.0/partner_vat_manual_check_vies + :alt: OCA/account-financial-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/account-financial-tools-18-0/account-financial-tools-18-0-partner_vat_manual_check_vies + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/account-financial-tools&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module extends the functionality of base_vat module to display +validation status of VAT number for EU partners using VIES validation +service. It allows to request a new validation in case validation failed +when first entering VAT number. + +**Table of contents** + +.. contents:: + :local: + +Use Cases / Context +=================== + +This module is an extension of Odoo base_vat module which allows to +display VAT validation status. This module is only useful for EU +partners if you would use VAT validation using EU VIES service. + +Quite often, VIES validation service responds with a timeout or a +MS_MAX_CONCURRENT_REQ error. In this case, there is no way to request +new validation to VIES service. + +This module adds validation status next to VAT and a button to request +validation in case it is not yet validated. + +Usage +===== + +To use this module, you need to: + +- Go to *Invoicing* / Configuration / Settings menu + +- Check **Verify VAT Numbers** + +- Go to *Contacts* + +- In “Contact” form for an EU based partner, next to VAT number you get + either a check sign (if validated) of question mark (if validation + failed) or cross sign (if invalid) |image1| + +- If validation failed, you get a new button **Validate with VIES** + which allows you to request a new validation from VIES |image2| + +- You can check chatter looking for error messages related to VIES + validation + +- If VAT number is invalid, you should correct if or remove it, you get + a new button **Clear invalid VAT** that would remove VAT and replace + by "/" |image3| + +You also get 2 planned action (cron job), disabled by default that will +try to request new validation for the first 20 partners with failed +validation, and another one that would clear VAT from all partners with +invalid VAT. + +.. |image1| image:: https://raw.githubusercontent.com/OCA/account-financial-tools/18.0/partner_vat_manual_check_vies/static/description/valid.png +.. |image2| image:: https://raw.githubusercontent.com/OCA/account-financial-tools/18.0/partner_vat_manual_check_vies/static/description/validation_failed.png +.. |image3| image:: https://raw.githubusercontent.com/OCA/account-financial-tools/18.0/partner_vat_manual_check_vies/static/description/invalid.png + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Le Filament +* Odoo S.A. + +Contributors +------------ + +- Rémi Cazeanave (https://le-filament.com) + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +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-remi-filament| image:: https://github.com/remi-filament.png?size=40px + :target: https://github.com/remi-filament + :alt: remi-filament + +Current `maintainer `__: + +|maintainer-remi-filament| + +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/partner_vat_manual_check_vies/__init__.py b/partner_vat_manual_check_vies/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/partner_vat_manual_check_vies/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/partner_vat_manual_check_vies/__manifest__.py b/partner_vat_manual_check_vies/__manifest__.py new file mode 100644 index 00000000000..88b8f8b7802 --- /dev/null +++ b/partner_vat_manual_check_vies/__manifest__.py @@ -0,0 +1,20 @@ +{ + "name": "Manual validation of European VAT number", + "version": "18.0.1.0.0", + "development_status": "Beta", + "category": "Accounting/Accounting", + "website": "https://github.com/OCA/account-financial-tools", + "author": "Le Filament, Odoo S.A., Odoo Community Association (OCA)", + "maintainers": ["remi-filament"], + "license": "LGPL-3", + "application": False, + "installable": True, + "preloadable": True, + "depends": [ + "base_vat", + ], + "data": [ + "data/ir_cron_data.xml", + "views/res_partner_view.xml", + ], +} diff --git a/partner_vat_manual_check_vies/data/ir_cron_data.xml b/partner_vat_manual_check_vies/data/ir_cron_data.xml new file mode 100644 index 00000000000..121f0bae6c8 --- /dev/null +++ b/partner_vat_manual_check_vies/data/ir_cron_data.xml @@ -0,0 +1,28 @@ + + + + + + + Partner: Validate VAT with EU VIES + 1 + days + + + model._cron_check_vies() + code + + + + Partner: Replace VAT by "/" on partners with invalid VAT (according to EU VIES validation) + 1 + days + + + model._cron_clear_vat() + code + + + + diff --git a/partner_vat_manual_check_vies/models/__init__.py b/partner_vat_manual_check_vies/models/__init__.py new file mode 100644 index 00000000000..91fed54d404 --- /dev/null +++ b/partner_vat_manual_check_vies/models/__init__.py @@ -0,0 +1 @@ +from . import res_partner diff --git a/partner_vat_manual_check_vies/models/res_partner.py b/partner_vat_manual_check_vies/models/res_partner.py new file mode 100644 index 00000000000..a848ad25b41 --- /dev/null +++ b/partner_vat_manual_check_vies/models/res_partner.py @@ -0,0 +1,132 @@ +# Copyright 2025 Le Filament (https://le-filament.com) +# Copyright (c) 2004-2015 Odoo S.A. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import logging + +from stdnum.eu.vat import check_vies +from stdnum.exceptions import InvalidComponent + +from odoo import _, api, fields, models +from odoo.tools import zeep + +_logger = logging.getLogger(__name__) + + +class ResPartner(models.Model): + _inherit = "res.partner" + + # Field representing whether VIES validation should be requested + request_vies_validation = fields.Boolean(compute="_compute_request_vies_validation") + vies_invalid = fields.Boolean() + + @api.depends_context("company") + def _compute_request_vies_validation(self): + self.request_vies_validation = self.env.company.vat_check_vies + + def action_check_vies(self): + self._compute_vies_valid() + + def action_clear_vat(self): + for partner in self.filtered("vies_invalid"): + partner.vat = "/" + partner.vies_invalid = False + + def _cron_check_vies(self, limit=20): + # Nothing to do if no company uses VIES validation + if ( + not self.env["res.company"] + .sudo() + .search_count([("vat_check_vies", "=", True)]) + ): + return False + partners = self.search( + [("vies_valid", "!=", True), ("vies_invalid", "!=", True)], limit=limit + ) + for partner in partners.filtered("vies_vat_to_check"): + # Avoid pre-fetching after each cache invalidation due to committing. + partner = partner[0] + partner._compute_vies_valid() + + def _cron_clear_vat(self): + # Nothing to do if no company uses VIES validation + if ( + not self.env["res.company"] + .sudo() + .search_count([("vat_check_vies", "=", True)]) + ): + return False + partners = self.search( + [ + ("vies_valid", "!=", True), + ("vies_invalid", "=", True), + ("vat", "not in", [False, "/"]), + ] + ) + partners.action_clear_vat() + + @api.depends("vies_vat_to_check") + def _compute_vies_valid(self): + """ + This function is rewritten from base_vat module (from Odoo v18 CE module) + Check the VAT number with VIES, if enabled. + There are 2 changes with respect to Odoo code : + - sync vies_invalid with parent_id + - set vies_invalid to True in case VIES reports an invalid VAT ID + """ + if ( + not self.env["res.company"] + .sudo() + .search_count([("vat_check_vies", "=", True)]) + ): + self.vies_valid = False + return + + for partner in self: + if not partner.vies_vat_to_check: + partner.vies_valid = False + continue + if ( + partner.parent_id + and partner.parent_id.vies_vat_to_check == partner.vies_vat_to_check + ): + partner.vies_valid = partner.parent_id.vies_valid + # Added sync of vies_invalid with parent + partner.vies_invalid = partner.parent_id.vies_invalid + continue + try: + _logger.info( + "Calling VIES service to check VAT for validation: %s", + partner.vies_vat_to_check, + ) + vies_valid = check_vies(partner.vies_vat_to_check, timeout=10) + partner.vies_valid = vies_valid["valid"] + # Added set vies_invalid in case VIES reports invalid VAT id + if not vies_valid["valid"]: + partner.vies_invalid = True + except (OSError, InvalidComponent, zeep.exceptions.Fault) as e: + if partner._origin.id: + msg = "" + if isinstance(e, OSError): + msg = _( + "Connection with the VIES server failed. The VAT number %s " + "could not be validated.", + partner.vies_vat_to_check, + ) + elif isinstance(e, InvalidComponent): + msg = _( + "The VAT number %s could not be interpreted by the VIES " + "server.", + partner.vies_vat_to_check, + ) + elif isinstance(e, zeep.exceptions.Fault): + msg = _( + "The request for VAT validation was not processed. VIES " + "service has responded with the following error: %s", + e.message, + ) + partner._origin.message_post(body=msg) + _logger.warning( + "The VAT number %s failed VIES check.", partner.vies_vat_to_check + ) + partner.vies_valid = False diff --git a/partner_vat_manual_check_vies/pyproject.toml b/partner_vat_manual_check_vies/pyproject.toml new file mode 100644 index 00000000000..4231d0cccb3 --- /dev/null +++ b/partner_vat_manual_check_vies/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/partner_vat_manual_check_vies/readme/CONTEXT.md b/partner_vat_manual_check_vies/readme/CONTEXT.md new file mode 100644 index 00000000000..0d772a09f7e --- /dev/null +++ b/partner_vat_manual_check_vies/readme/CONTEXT.md @@ -0,0 +1,7 @@ +This module is an extension of Odoo base_vat module which allows to display VAT validation status. +This module is only useful for EU partners if you would use VAT validation using EU VIES service. + +Quite often, VIES validation service responds with a timeout or a MS_MAX_CONCURRENT_REQ error. +In this case, there is no way to request new validation to VIES service. + +This module adds validation status next to VAT and a button to request validation in case it is not yet validated. diff --git a/partner_vat_manual_check_vies/readme/CONTRIBUTORS.md b/partner_vat_manual_check_vies/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..b3d1f671ee8 --- /dev/null +++ b/partner_vat_manual_check_vies/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- Rémi Cazeanave (https://le-filament.com) diff --git a/partner_vat_manual_check_vies/readme/DESCRIPTION.md b/partner_vat_manual_check_vies/readme/DESCRIPTION.md new file mode 100644 index 00000000000..a7cadb39532 --- /dev/null +++ b/partner_vat_manual_check_vies/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +This module extends the functionality of base_vat module to display validation status of VAT number for EU partners using VIES validation service. +It allows to request a new validation in case validation failed when first entering VAT number. diff --git a/partner_vat_manual_check_vies/readme/USAGE.md b/partner_vat_manual_check_vies/readme/USAGE.md new file mode 100644 index 00000000000..b7a2f6b1cf0 --- /dev/null +++ b/partner_vat_manual_check_vies/readme/USAGE.md @@ -0,0 +1,15 @@ +To use this module, you need to: + +- Go to *Invoicing* / Configuration / Settings menu +- Check **Verify VAT Numbers** +- Go to *Contacts* +- In “Contact” form for an EU based partner, next to VAT number you get either a check sign (if validated) of question mark (if validation failed) or cross sign (if invalid) +![](static/description/valid.png) + +- If validation failed, you get a new button **Validate with VIES** which allows you to request a new validation from VIES +![](static/description/validation_failed.png) +- You can check chatter looking for error messages related to VIES validation +- If VAT number is invalid, you should correct if or remove it, you get a new button **Clear invalid VAT** that would remove VAT and replace by "/" +![](static/description/invalid.png) + +You also get 2 planned action (cron job), disabled by default that will try to request new validation for the first 20 partners with failed validation, and another one that would clear VAT from all partners with invalid VAT. diff --git a/partner_vat_manual_check_vies/static/description/icon.png b/partner_vat_manual_check_vies/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/partner_vat_manual_check_vies/static/description/icon.png differ diff --git a/partner_vat_manual_check_vies/static/description/icon.svg b/partner_vat_manual_check_vies/static/description/icon.svg new file mode 100644 index 00000000000..a7a26d0932a --- /dev/null +++ b/partner_vat_manual_check_vies/static/description/icon.svg @@ -0,0 +1,79 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/partner_vat_manual_check_vies/static/description/index.html b/partner_vat_manual_check_vies/static/description/index.html new file mode 100644 index 00000000000..f92d18ab8d6 --- /dev/null +++ b/partner_vat_manual_check_vies/static/description/index.html @@ -0,0 +1,124 @@ +
+
+
+

Module name

+

This module was written to extend the functionality of ... to support ... and allow you to ...

+
+
+
+ +
+
+
+

Installation

+
+
+

To install this module, you need to: +

    +
  • ...
  • +
+

+
+
+
+ + + +
+
+
+
+ +
+
+
+

Configuration

+
+
+

To configure this module, you need to: +

    +
  • ...
  • +
+

+
+
+
+ + + +
+
+
+
+ +
+
+
+

Usage

+
+
+

To use this module, you need to: +

    +
  • ...
  • +
+

+

For further information, please visit: +

+

+
+
+
+ + + +
+
+
+
+ +
+
+
+

Known issues / Roadmap

+
+
+

+

    +
  • ...
  • +
+

+
+
+
+ + + +
+
+
+
+ +
+
+
+

Credits

+
+
+

Contributors

+ +
+
+

Maintainer

+

+ 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.
+ To contribute to this module, please visit http://odoo-community.org.
+ +

+
+
+
diff --git a/partner_vat_manual_check_vies/static/description/invalid.png b/partner_vat_manual_check_vies/static/description/invalid.png new file mode 100644 index 00000000000..f1ef0d42568 Binary files /dev/null and b/partner_vat_manual_check_vies/static/description/invalid.png differ diff --git a/partner_vat_manual_check_vies/static/description/valid.png b/partner_vat_manual_check_vies/static/description/valid.png new file mode 100644 index 00000000000..516bb22e745 Binary files /dev/null and b/partner_vat_manual_check_vies/static/description/valid.png differ diff --git a/partner_vat_manual_check_vies/static/description/validation_failed.png b/partner_vat_manual_check_vies/static/description/validation_failed.png new file mode 100644 index 00000000000..e274c1ce3fe Binary files /dev/null and b/partner_vat_manual_check_vies/static/description/validation_failed.png differ diff --git a/partner_vat_manual_check_vies/views/res_partner_view.xml b/partner_vat_manual_check_vies/views/res_partner_view.xml new file mode 100644 index 00000000000..7c9b67284c5 --- /dev/null +++ b/partner_vat_manual_check_vies/views/res_partner_view.xml @@ -0,0 +1,22 @@ + + + + + + + view.partner.vat.manual.check.form + res.partner + + + + + + +