[FIX] l1n_pe: forward-port of fixes to l10n_pe
base_vat: Correct management of the check of peruvian VAT without prefix. l10n_pe: Correct income account the last one is not correct. l10n_pe: Forced Round globally for peruvian companies once l10n_pe is installed, and with the onchange. l10n_pe: For peruvian companies it does not make sense a sequence per year and the year in the prefix is incorrect, we must force XXX- as a sequence prefix. closes odoo/odoo#38854 Forward-port-of: #38764 Signed-off-by: Josse Colpaert <jco@openerp.com>
This commit is contained in:
@@ -95,7 +95,7 @@ _ref_vat = {
|
||||
'mx': 'ABC123456T1B',
|
||||
'nl': 'NL123456782B90',
|
||||
'no': 'NO123456785',
|
||||
'pe': 'PER10254824220 or PED10254824220',
|
||||
'pe': '10XXXXXXXXY or 20XXXXXXXXY or 15XXXXXXXXY or 16XXXXXXXXY or 17XXXXXXXXY',
|
||||
'pl': 'PL1234567883',
|
||||
'pt': 'PT123456789',
|
||||
'ro': 'RO1234567897',
|
||||
@@ -325,38 +325,14 @@ class ResPartner(models.Model):
|
||||
|
||||
# Peruvian VAT validation, contributed by Vauxoo
|
||||
def check_vat_pe(self, vat):
|
||||
|
||||
vat_type, vat = vat and len(vat) >= 2 and (vat[0], vat[1:]) or (False, False)
|
||||
|
||||
if vat_type and vat_type.upper() == 'D':
|
||||
# DNI
|
||||
return True
|
||||
elif vat_type and vat_type.upper() == 'R':
|
||||
# verify RUC
|
||||
factor = '5432765432'
|
||||
sum = 0
|
||||
dig_check = False
|
||||
if len(vat) != 11:
|
||||
return False
|
||||
try:
|
||||
int(vat)
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
for f in range(0, 10):
|
||||
sum += int(factor[f]) * int(vat[f])
|
||||
|
||||
subtraction = 11 - (sum % 11)
|
||||
if subtraction == 10:
|
||||
dig_check = 0
|
||||
elif subtraction == 11:
|
||||
dig_check = 1
|
||||
else:
|
||||
dig_check = subtraction
|
||||
|
||||
return int(vat[10]) == dig_check
|
||||
else:
|
||||
if len(vat) != 11 or not vat.isdigit():
|
||||
return False
|
||||
dig_check = 11 - (sum([int('5432765432'[f]) * int(vat[f]) for f in range(0, 10)]) % 11)
|
||||
if dig_check == 10:
|
||||
dig_check = 0
|
||||
elif dig_check == 11:
|
||||
dig_check = 1
|
||||
return int(vat[10]) == dig_check
|
||||
|
||||
# VAT validation in Turkey, contributed by # Levent Karakas @ Eska Yazilim A.S.
|
||||
def check_vat_tr(self, vat):
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from . import test_validate_ruc
|
||||
@@ -0,0 +1,16 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from odoo.tests import common
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class TestRUCStructure(common.TransactionCase):
|
||||
|
||||
def test_peru_ruc_format(self):
|
||||
"""Only values that has the length of 11 will be checked as RUC, that's what we are proving. The second part
|
||||
will check for a valid ruc and there will be no problem at all.
|
||||
"""
|
||||
partner = self.env['res.partner'].create({'name': "Dummy partner", 'country_id': self.env.ref('base.pe').id})
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
partner.vat = '11111111111'
|
||||
partner.vat = '20507822470'
|
||||
@@ -6,7 +6,7 @@
|
||||
<field name="property_account_payable_id" ref="chart4212"/>
|
||||
<field name="property_account_expense_categ_id" ref="chart6329"/>
|
||||
<field name="property_account_expense_id" ref="chart6011"/>
|
||||
<field name="property_account_income_categ_id" ref="chart70111"/>
|
||||
<field name="property_account_income_categ_id" ref="chart70121"/>
|
||||
<field name="property_stock_account_input_categ_id" ref="chart6111"/>
|
||||
<field name="property_stock_account_output_categ_id" ref="chart69111"/>
|
||||
<field name="property_stock_valuation_account_id" ref="chart20111"/>
|
||||
|
||||
@@ -9,22 +9,22 @@
|
||||
<div class="o_address_format">
|
||||
<field name="parent_id" invisible="1"/>
|
||||
<field name="type" invisible="1"/>
|
||||
<field name="street" invisible="1"/>
|
||||
<field name="street_name" placeholder="Street Name..." attrs="{'readonly': [('type', '=', 'contact'),('parent_id', '!=', False)]}"/>
|
||||
<field name="street2" placeholder="Street2"/>
|
||||
<field name="street_name" placeholder="Street Name..." attrs="{'readonly': [('type', '=', 'contact'),('parent_id', '!=', False)]}" class="oe_read_only"/>
|
||||
<field name="street" placeholder="Street" class="oe_edit_only"/>
|
||||
<field name="street2" placeholder="Street2" invisible="1"/>
|
||||
<div class="o_row">
|
||||
<label for="street_number" class="oe_edit_only"/>
|
||||
<span> </span>
|
||||
<field name="street_number" attrs="{'readonly': [('type', '=', 'contact'),('parent_id', '!=', False)]}"/>
|
||||
<span> </span>
|
||||
<label for="street_number2" class="oe_edit_only"/>
|
||||
<field name="street_number2" attrs="{'readonly': [('type', '=', 'contact'),('parent_id', '!=', False)]}"/>
|
||||
</div>
|
||||
<field name="l10n_pe_district" placeholder="District..."/>
|
||||
<field name="city" placeholder="Province..." invisible="1"/>
|
||||
<field name="city_id" placeholder="Province..." />
|
||||
<field name="city_id" placeholder="Province..."/>
|
||||
<field name="state_id" class="o_address_state" placeholder="State..." options='{"no_open": True}'/>
|
||||
<field name="zip" placeholder="ZIP" class="o_address_zip"/>
|
||||
<field name="country_id" placeholder="Country" class="o_address_country" options='{"no_open": True, "no_create": True}'/>
|
||||
<field name="zip" placeholder="ZIP" class="o_address_zip"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
@@ -32,5 +32,7 @@
|
||||
<record id="base.pe" model="res.country">
|
||||
<field name="enforce_cities" eval="1" />
|
||||
<field name="address_view_id" ref="pe_partner_address_form" />
|
||||
<field name="address_format" eval="'%(street)s\n%(city)s\n%(state_name)s\n%(country_name)s'"/>
|
||||
<field name="street_format" eval="'%(street_name)s %(street_number)s, %(street_number2)s'"/>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from . import account_tax
|
||||
from . import account_move
|
||||
from . import account_journal
|
||||
from . import account_chart_template
|
||||
from . import l10n_latam_identification_type
|
||||
from . import res_partner
|
||||
from . import res_city_district
|
||||
from . import res_city
|
||||
from . import res_company
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
from odoo import models
|
||||
|
||||
|
||||
class AccountChartTemplate(models.Model):
|
||||
|
||||
_inherit = 'account.chart.template'
|
||||
|
||||
def _load(self, sale_tax_rate, purchase_tax_rate, company):
|
||||
"""Load the rounding method properly to the company once the CoA is installed.
|
||||
"""
|
||||
company.filtered(lambda c: c.country_id.id == self.env.ref('base.pe').id).write({
|
||||
'tax_calculation_rounding_method': 'round_globally',
|
||||
})
|
||||
return super()._load(sale_tax_rate, purchase_tax_rate, company)
|
||||
@@ -0,0 +1,31 @@
|
||||
from odoo import models, api
|
||||
|
||||
|
||||
class AccountJournal(models.Model):
|
||||
_inherit = "account.journal"
|
||||
|
||||
@api.model
|
||||
def _get_sequence_prefix(self, code, refund=False):
|
||||
"""For peruvian companies we can not use sequences with **/** due to the edi generation which need in the
|
||||
sequence a plain text ended by a *-* and the length of this prefix"""
|
||||
if self.env.company.country_id != self.env.ref('base.pe'):
|
||||
return super()._get_sequence_prefix(code, refund=refund)
|
||||
prefix = code.upper()
|
||||
if len(prefix) > 3:
|
||||
prefix = prefix[:3]
|
||||
prefix = prefix.ljust(3, 'X')
|
||||
if refund:
|
||||
prefix = 'R' + prefix[:-1]
|
||||
return prefix + '-'
|
||||
|
||||
@api.model
|
||||
def _create_sequence(self, vals, refund=False):
|
||||
"""For Peruvian companies, a number reset by date do not make sense due to the fact that we can not use a free
|
||||
prefix the format does not have enough space to put a year on it or any other char, then with this approach we
|
||||
are avoiding the default behavior there."""
|
||||
res = super()._create_sequence(vals, refund=refund)
|
||||
# NOTE: the self element is coming filled just when write and not on create (which is Ok)
|
||||
journal_type = self.type if not vals.get('type') else vals.get('type')
|
||||
if self.env.company.country_id == self.env.ref('base.pe') or journal_type in ['sale', 'purchase']:
|
||||
res.write({'use_date_range': False})
|
||||
return res
|
||||
@@ -57,4 +57,4 @@ class AccountTaxTemplate(models.Model):
|
||||
'l10n_pe_edi_tax_code': self.l10n_pe_edi_tax_code,
|
||||
'l10n_pe_edi_unece_category': self.l10n_pe_edi_unece_category,
|
||||
})
|
||||
return val
|
||||
return val
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from odoo import models, api
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
|
||||
_inherit = "res.company"
|
||||
|
||||
@api.onchange('country_id')
|
||||
def onchange_country(self):
|
||||
"""In Peru, the rounding method it's calculated as global"""
|
||||
for rec in self.filtered(lambda x: x.country_id == self.env.ref('base.pe')):
|
||||
rec.tax_calculation_rounding_method = 'round_globally'
|
||||
Reference in New Issue
Block a user