From 946b69e72210bd49a83e13be399ec9d55e0dddde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Sainl=C3=A9ger?= Date: Fri, 6 Mar 2026 10:24:51 +0100 Subject: [PATCH] [FIX] partner_phone_country_validation: correct overall fragile process --- .../models/res_partner.py | 93 ++++++++----------- .../tools/get_country_from_phone_number.py | 4 +- 2 files changed, 39 insertions(+), 58 deletions(-) diff --git a/partner_phone_country_validation/models/res_partner.py b/partner_phone_country_validation/models/res_partner.py index 7a35660..daffa7b 100644 --- a/partner_phone_country_validation/models/res_partner.py +++ b/partner_phone_country_validation/models/res_partner.py @@ -1,73 +1,54 @@ from odoo import api, models, _ -from odoo.addons.partner_phone_country_validation.tools.get_country_from_phone_number import get_country_from_phone_number +from odoo.addons.partner_phone_country_validation.tools.get_country_from_phone_number import ( + get_country_from_phone_number, +) from odoo.exceptions import ValidationError -import logging -_logger = logging.getLogger(__name__) class Partner(models.Model): - _name = 'res.partner' - _inherit = ['res.partner', 'phone.validation.mixin'] + _name = "res.partner" + _inherit = ["res.partner", "phone.validation.mixin"] - @api.constrains('country_id','phone','mobile') + @api.constrains("country_id", "phone", "mobile") def _check_country_id(self): - if not self.country_id and (self.phone or self.mobile): - raise ValidationError(_('You must set a country for the phone number')) - - @api.onchange('country_id') - def _onchange_country(self): - self.format_mobile_from_country() - self.format_phone_from_country() + for partner in self: + if not partner.country_id and (partner.phone or partner.mobile): + raise ValidationError(_("You must set a country for the phone number")) - def format_number_zerozero(self, number): - if number.startswith("00"): - number = "+"+number[2:] + def _normalize_phone_number(self, number): + """Convert 00xx format to +xx international format.""" + if number and number.startswith("00"): + return "+" + number[2:] return number - def format_phone_from_country(self): - if self.phone: - country = None - if self.phone.startswith('+'): - country = self.env['res.country'].search( - [('code', '=', get_country_from_phone_number(self.phone))], limit=1 - ) - if self.country_id: - country = self.country_id + def _set_country_from_phone_number(self, phone_number): + """Auto-detect and set country from phone number prefix if not already set.""" + if not phone_number or self.country_id: + return + country_code = get_country_from_phone_number(phone_number) + if country_code: + country = self.env["res.country"].search( + [("code", "=", country_code)], limit=1 + ) if country: - self.phone = self.phone_format(self.phone, country=country) + self.country_id = country - def format_mobile_from_country(self): - if self.mobile: - country = None - if self.mobile.startswith('+'): - country = self.env['res.country'].search( - [('code', '=', get_country_from_phone_number(self.mobile))], limit=1 - ) - if self.country_id: - country = self.country_id - if country: - self.mobile = self.phone_format(self.mobile, country=country) - - def set_country_from_phone_number(self, phone_number): - country = self.env['res.country'].search( - [('code', '=', get_country_from_phone_number(phone_number))], limit=1 - ) - if country and not self.country_id: - self.country_id = country - - @api.onchange('phone') + @api.onchange("phone", "country_id", "company_id") def _onchange_phone_validation(self): - # If no country is found, we define the country based on the beginning of the number + # Normalize 00xx → +xx before standard processing if self.phone: - self.phone = self.format_number_zerozero(self.phone) - self.set_country_from_phone_number(self.phone) - self.format_phone_from_country() - + self.phone = self._normalize_phone_number(self.phone) + # Auto-detect country if not set + self._set_country_from_phone_number(self.phone) + # Let standard module do the formatting + super()._onchange_phone_validation() - @api.onchange('mobile') + @api.onchange("mobile", "country_id", "company_id") def _onchange_mobile_validation(self): - # If no country is found, we define the country based on the beginning of the number + # Normalize 00xx → +xx before standard processing if self.mobile: - self.mobile = self.format_number_zerozero(self.mobile) - self.set_country_from_phone_number(self.mobile) - self.format_mobile_from_country() \ No newline at end of file + self.mobile = self._normalize_phone_number(self.mobile) + # Auto-detect country if not set + self._set_country_from_phone_number(self.mobile) + # Let standard module do the formatting + super()._onchange_mobile_validation() diff --git a/partner_phone_country_validation/tools/get_country_from_phone_number.py b/partner_phone_country_validation/tools/get_country_from_phone_number.py index ad9c012..79a8cf3 100644 --- a/partner_phone_country_validation/tools/get_country_from_phone_number.py +++ b/partner_phone_country_validation/tools/get_country_from_phone_number.py @@ -7,7 +7,7 @@ try: def get_country_from_phone_number(number): try: - number = phonenumbers.parse(number) + number = phonenumbers.parse(number) return phonenumbers.region_code_for_number(number) except phonenumbers.phonenumberutil.NumberParseException: return False @@ -22,4 +22,4 @@ except ImportError: "verified. Please install the `phonenumbers` Python module." ) _phonenumbers_lib_warning = True - return number \ No newline at end of file + return number