[IMP] base_vat,l10n_br: depend on l10n_latam_base to categorize id types
This adds the two main identification types we use in Brazil. CNPJ is used the standard VAT type. The custom check_vat logic was removed because stdnum supports this out of the box. Another non-VAT CPF type was added that is checked for validity using stdnum as well. task-3475609 closes odoo/odoo#132773 Related: odoo/enterprise#46127 Related: odoo/upgrade#5062 Signed-off-by: Josse Colpaert <jco@odoo.com>
This commit is contained in:
@@ -32,6 +32,7 @@ _ref_vat = {
|
||||
'au': '83 914 571 673',
|
||||
'be': 'BE0477472701',
|
||||
'bg': 'BG1234567892',
|
||||
'br': '48.906.308/0001-27',
|
||||
'ch': 'CHE-123.456.788 TVA or CHE-123.456.788 MWST or CHE-123.456.788 IVA', # Swiss by Yannick Vaucher @ Camptocamp
|
||||
'cl': 'CL76086428-5',
|
||||
'co': 'CO213123432-1 or CO213.123.432-1',
|
||||
|
||||
@@ -46,9 +46,11 @@ come with any additional paid permission for online use of 'private modules'.
|
||||
'depends': [
|
||||
'account',
|
||||
'base_vat',
|
||||
'l10n_latam_base',
|
||||
],
|
||||
'data': [
|
||||
'data/account_tax_report_data.xml',
|
||||
'data/l10n_latam.identification.type.csv',
|
||||
'views/account_view.xml',
|
||||
'views/account_fiscal_position_views.xml',
|
||||
'views/res_company_views.xml',
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
id,name,country_id:id,is_vat
|
||||
cnpj,CNPJ,base.br,True
|
||||
cpf,CPF,base.br,False
|
||||
|
@@ -243,14 +243,7 @@ msgstr ""
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_br/models/res_partner.py:0
|
||||
#, python-format
|
||||
msgid "Invalid CNPJ. Make sure that all the typs are entered correctly."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_br
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_br/models/res_partner.py:0
|
||||
#, python-format
|
||||
msgid "Invalid CNPJ. Make sure that the CNPJ is a 14 digits number."
|
||||
msgid "CPF number %s for %s is not valid."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_br
|
||||
|
||||
@@ -230,15 +230,8 @@ msgstr "Interstate Fiscal Position Type"
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_br/models/res_partner.py:0
|
||||
#, python-format
|
||||
msgid "Invalid CNPJ. Make sure that all the typs are entered correctly."
|
||||
msgstr "Invalid CNPJ. Make sure that all the digits are entered correctly."
|
||||
|
||||
#. module: l10n_br
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_br/models/res_partner.py:0
|
||||
#, python-format
|
||||
msgid "Invalid CNPJ. Make sure that the CNPJ is a 14 digits number."
|
||||
msgstr "Invalid CNPJ. Make sure that the CNPJ is a 14 digits number."
|
||||
msgid "CPF number %s for %s is not valid."
|
||||
msgstr "O número de CPF %s para %s não é válido."
|
||||
|
||||
#. module: l10n_br
|
||||
#: model:ir.model.fields,field_description:l10n_br.field_account_tax__amount_mva
|
||||
|
||||
@@ -1,45 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import stdnum.br.cpf
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
import re
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
l10n_br_cpf_code = fields.Char(string="CPF", help="Natural Persons Register.")
|
||||
l10n_br_ie_code = fields.Char(string="IE", help="State Tax Identification Number. Should contain 9-14 digits.")
|
||||
l10n_br_im_code = fields.Char(string="IM", help="Municipal Tax Identification Number")
|
||||
l10n_br_isuf_code = fields.Char(string="SUFRAMA code", help="SUFRAMA registration number.")
|
||||
|
||||
@api.constrains("vat")
|
||||
def check_vat(self):
|
||||
'''
|
||||
Example of a Brazilian CNPJ number: 76.634.583/0001-74.
|
||||
The 13th digit is the check digit of the previous 12 digits.
|
||||
The check digit is calculated by multiplying the first 12 digits by weights and calculate modulo 11 of the result.
|
||||
The 14th digit is the check digit of the previous 13 digits. Calculated the same way.
|
||||
Both remainders are appended to the first 12 digits.
|
||||
'''
|
||||
def _l10n_br_calculate_mod_11(check, weights):
|
||||
result = (sum([i*j for (i, j) in zip(check, weights)])) % 11
|
||||
if result <= 1:
|
||||
return 0
|
||||
return 11 - result
|
||||
|
||||
for partner in self:
|
||||
if not partner.vat:
|
||||
return
|
||||
if not partner.country_code == 'BR':
|
||||
return super().check_vat()
|
||||
weights = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
|
||||
vat_clean = list(map(int, re.sub("[^0-9]", "", partner.vat)))
|
||||
if len(vat_clean) != 14:
|
||||
raise ValidationError(_("Invalid CNPJ. Make sure that the CNPJ is a 14 digits number."))
|
||||
vat_check = vat_clean[:12]
|
||||
vat_check.append(_l10n_br_calculate_mod_11(vat_check, weights[1:]))
|
||||
vat_check.append(_l10n_br_calculate_mod_11(vat_check, weights))
|
||||
if vat_check != vat_clean:
|
||||
raise ValidationError(_("Invalid CNPJ. Make sure that all the digits are entered correctly."))
|
||||
@api.constrains('vat', 'l10n_latam_identification_type_id')
|
||||
def check_cpf(self):
|
||||
for partner in self.filtered(lambda partner: partner.l10n_latam_identification_type_id == self.env.ref('l10n_br.cpf')):
|
||||
if partner.vat and not stdnum.br.cpf.is_valid(partner.vat):
|
||||
raise ValidationError(_('CPF number %s for %s is not valid.') % (partner.vat, partner.display_name))
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
<field name="inherit_id" ref="account.view_partner_property_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='vat']" position="after">
|
||||
<field name="l10n_br_cpf_code" invisible="'BR'.lower() not in (fiscal_country_codes or '').lower()"/>
|
||||
<field name="l10n_br_ie_code" invisible="'BR'.lower() not in (fiscal_country_codes or '').lower()"/>
|
||||
<field name="l10n_br_im_code" invisible="'BR'.lower() not in (fiscal_country_codes or '').lower()"/>
|
||||
<field name="l10n_br_isuf_code" invisible="'BR'.lower() not in (fiscal_country_codes or '').lower()"/>
|
||||
|
||||
Reference in New Issue
Block a user