# -*- coding: utf-8 -*
from odoo import Command
from odoo.tests import tagged
from .common import TestPeEdiCommon, mocked_l10n_pe_edi_post_invoice_web_service
from unittest.mock import patch
from freezegun import freeze_time
@tagged('post_install_l10n', 'post_install', '-at_install')
class TestEdiXmls(TestPeEdiCommon):
def test_price_amount_rounding(self):
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_pe_edi.models.account_edi_format.AccountEdiFormat._l10n_pe_edi_post_invoice_web_service',
new=mocked_l10n_pe_edi_post_invoice_web_service):
move = self._create_invoice(invoice_line_ids=[(0, 0, {
'product_id': self.product.id,
'product_uom_id': self.env.ref('uom.product_uom_kgm').id,
'price_unit': 83.6, # We will compute 250.8 / 3, which results in 83.60000000000001. It must be rounded.
'quantity': 3,
'tax_ids': [(6, 0, self.tax_18.ids)],
})])
move.action_post()
generated_files = self._process_documents_web_services(move, {'pe_ubl_2_1'})
self.assertTrue(generated_files)
zip_edi_str = generated_files[0]
edi_xml = self.edi_format._l10n_pe_edi_unzip_edi_document(zip_edi_str)
etree = self.get_xml_tree_from_string(edi_xml)
price_amount = etree.find('.//{*}InvoiceLine/{*}Price/{*}PriceAmount')
self.assertEqual(price_amount.text, '83.6')
def test_invoice_simple_case(self):
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_pe_edi.models.account_edi_format.AccountEdiFormat._l10n_pe_edi_post_invoice_web_service',
new=mocked_l10n_pe_edi_post_invoice_web_service):
move = self._create_invoice()
move.action_post()
generated_files = self._process_documents_web_services(move, {'pe_ubl_2_1'})
self.assertTrue(generated_files)
zip_edi_str = generated_files[0]
edi_xml = self.edi_format._l10n_pe_edi_unzip_edi_document(zip_edi_str)
current_etree = self.get_xml_tree_from_string(edi_xml)
expected_etree = self.get_xml_tree_from_string(self.expected_invoice_xml_values)
self.assertXmlTreeEqual(current_etree, expected_etree)
def test_refund_simple_case(self):
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_pe_edi.models.account_edi_format.AccountEdiFormat._l10n_pe_edi_post_invoice_web_service',
new=mocked_l10n_pe_edi_post_invoice_web_service):
move = self._create_refund()
(move.reversed_entry_id + move).action_post()
generated_files = self._process_documents_web_services(move, {'pe_ubl_2_1'})
self.assertTrue(generated_files)
zip_edi_str = generated_files[0]
edi_xml = self.edi_format._l10n_pe_edi_unzip_edi_document(zip_edi_str)
current_etree = self.get_xml_tree_from_string(edi_xml)
expected_etree = self.get_xml_tree_from_string(self.expected_refund_xml_values)
self.assertXmlTreeEqual(current_etree, expected_etree)
def test_debit_note_simple_case(self):
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_pe_edi.models.account_edi_format.AccountEdiFormat._l10n_pe_edi_post_invoice_web_service',
new=mocked_l10n_pe_edi_post_invoice_web_service):
move = self._create_debit_note()
(move.debit_origin_id + move).action_post()
generated_files = self._process_documents_web_services(move, {'pe_ubl_2_1'})
self.assertTrue(generated_files)
zip_edi_str = generated_files[0]
edi_xml = self.edi_format._l10n_pe_edi_unzip_edi_document(zip_edi_str)
current_etree = self.get_xml_tree_from_string(edi_xml)
expected_etree = self.get_xml_tree_from_string(self.expected_debit_note_xml_values)
self.assertXmlTreeEqual(current_etree, expected_etree)
def test_invoice_payment_term_detraction_case(self):
""" Invoice in USD with detractions and multiple payment term lines"""
self.product.l10n_pe_withhold_percentage = 10
self.product.l10n_pe_withhold_code = '001'
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_pe_edi.models.account_edi_format.AccountEdiFormat._l10n_pe_edi_post_invoice_web_service',
new=mocked_l10n_pe_edi_post_invoice_web_service):
update_vals_dict = {"l10n_pe_edi_operation_type": "1001",
"invoice_payment_term_id": self.env.ref("account.account_payment_term_advance_60days").id}
invoice = self._create_invoice(**update_vals_dict).with_context(edi_test_mode=True)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'pe_ubl_2_1'})
self.assertTrue(generated_files)
zip_edi_str = generated_files[0]
edi_xml = self.edi_format._l10n_pe_edi_unzip_edi_document(zip_edi_str)
current_etree = self.get_xml_tree_from_string(edi_xml)
expected_etree = self.get_xml_tree_from_string(self.expected_invoice_xml_values)
expected_etree = self.with_applied_xpath(
expected_etree,
'''
1001
Leyenda: Operacion sujeta a detraccion
2017-03-02
Detraccion
999
CUENTAPRUEBA
Detraccion
001
10.0
472.00
FormaPago
Credito
8496.00
FormaPago
Cuota001
1888.00
2017-01-01
FormaPago
Cuota002
6608.00
2017-03-02
''')
self.assertXmlTreeEqual(current_etree, expected_etree)
def test_invoice_detraction_with_decimal(self):
""" Invoice in PEN with detraction containing decimal digits"""
self.product.l10n_pe_withhold_percentage = 10
self.product.l10n_pe_withhold_code = '019'
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_pe_edi.models.account_edi_format.AccountEdiFormat._l10n_pe_edi_post_invoice_web_service',
new=mocked_l10n_pe_edi_post_invoice_web_service):
vals = {
'name': 'F FFI-%s1' % self.time_name,
'move_type': 'out_invoice',
'partner_id': self.partner_a.id,
'invoice_date': '2017-01-01',
'date': '2017-01-01',
'invoice_payment_term_id': self.env.ref("account.account_payment_term_end_following_month").id,
'l10n_latam_document_type_id': self.env.ref('l10n_pe.document_type01').id,
'l10n_pe_edi_operation_type': '1001',
'invoice_line_ids': [Command.create({
'product_id': self.product.id,
'price_unit': 990.0,
'quantity': 1,
'tax_ids': [Command.set(self.tax_18.ids)],
})],
}
invoice = self.env['account.move'].create(vals).with_context(edi_test_mode=True)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'pe_ubl_2_1'})
self.assertTrue(generated_files)
zip_edi_str = generated_files[0]
edi_xml = self.edi_format._l10n_pe_edi_unzip_edi_document(zip_edi_str)
current_etree = self.get_xml_tree_from_string(edi_xml)
expected_invoice_xml_values = '''
2.1
2.0
___ignore___
2017-01-01
2017-02-28
01
MIL CIENTO SESENTA Y OCHO Y 20/100 SOLES
Leyenda: Operacion sujeta a detraccion
PEN
___ignore___
IDSignKG
20557912879
COMPANY_1_DATA
#SignVX
20557912879
20557912879
company_1_data
PE
Peru
company_1_data
20557912879
PE
Peru
VAT
company_1_data
20557912879
0000
PE
Peru
___ignore___
company_1_data
6
20462509236
partner_a
PE
Peru
partner_a
20462509236
PE
Peru
VAT
partner_a
20462509236
PE
Peru
___ignore___
partner_a
PE
Peru
Detraccion
999
CUENTAPRUEBA
Detraccion
019
10.0
117.00
FormaPago
Credito
1051.20
FormaPago
Cuota001
1051.20
2017-02-28
178.20
990.00
178.20
1000
IGV
VAT
990.00
990.00
1168.20
0.00
1168.20
1
1.0
990.00
1168.20
01
178.20
990.00
178.20
18.0
10
1000
IGV
VAT
-
product_pe
product_pe
01010101
990.0
'''
expected_etree = self.get_xml_tree_from_string(expected_invoice_xml_values)
self.assertXmlTreeEqual(current_etree, expected_etree)
def test_invoice_detraction_with_decimal_foreign_currency(self):
""" Invoice in USD with detraction containing decimal digits"""
self.product.l10n_pe_withhold_percentage = 10
self.product.l10n_pe_withhold_code = '019'
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_pe_edi.models.account_edi_format.AccountEdiFormat._l10n_pe_edi_post_invoice_web_service',
new=mocked_l10n_pe_edi_post_invoice_web_service):
vals = {
'name': 'F FFI-%s1' % self.time_name,
'move_type': 'out_invoice',
'partner_id': self.partner_a.id,
'invoice_date': '2017-01-01',
'date': '2017-01-01',
'currency_id': self.currency_data['currency'].id,
'invoice_payment_term_id': self.env.ref("account.account_payment_term_end_following_month").id,
'l10n_latam_document_type_id': self.env.ref('l10n_pe.document_type01').id,
'l10n_pe_edi_operation_type': '1001',
'invoice_line_ids': [Command.create({
'product_id': self.product.id,
'price_unit': 990.0,
'quantity': 1,
'tax_ids': [Command.set(self.tax_18.ids)],
})],
}
invoice = self.env['account.move'].create(vals).with_context(edi_test_mode=True)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'pe_ubl_2_1'})
self.assertTrue(generated_files)
zip_edi_str = generated_files[0]
edi_xml = self.edi_format._l10n_pe_edi_unzip_edi_document(zip_edi_str)
current_etree = self.get_xml_tree_from_string(edi_xml)
expected_invoice_xml_values = '''
2.1
2.0
___ignore___
2017-01-01
2017-02-28
01
MIL CIENTO SESENTA Y OCHO Y 20/100 GOLD
Leyenda: Operacion sujeta a detraccion
USD
___ignore___
IDSignKG
20557912879
COMPANY_1_DATA
#SignVX
20557912879
20557912879
company_1_data
PE
Peru
company_1_data
20557912879
PE
Peru
VAT
company_1_data
20557912879
0000
PE
Peru
___ignore___
company_1_data
6
20462509236
partner_a
PE
Peru
partner_a
20462509236
PE
Peru
VAT
partner_a
20462509236
PE
Peru
___ignore___
partner_a
PE
Peru
Detraccion
999
CUENTAPRUEBA
Detraccion
019
10.0
58.00
FormaPago
Credito
1051.38
FormaPago
Cuota001
1051.38
2017-02-28
178.20
990.00
178.20
1000
IGV
VAT
990.00
990.00
1168.20
0.00
1168.20
1
1.0
990.00
1168.20
01
178.20
990.00
178.20
18.0
10
1000
IGV
VAT
-
product_pe
product_pe
01010101
990.0
'''
expected_etree = self.get_xml_tree_from_string(expected_invoice_xml_values)
self.assertXmlTreeEqual(current_etree, expected_etree)