Odoo18-Base/addons/l10n_es_edi_sii/tests/test_edi_xml.py
2025-01-06 10:57:38 +07:00

1232 lines
58 KiB
Python

# coding: utf-8
from .common import TestEsEdiCommon
import json
from freezegun import freeze_time
from unittest.mock import patch
from odoo.tests import tagged
def mocked_l10n_es_edi_call_web_service_sign(edi_format, invoices, info_list):
return {inv: {'success': True} for inv in invoices}
@tagged('post_install_l10n', 'post_install', '-at_install')
class TestEdiXmls(TestEsEdiCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.other_currency = cls.setup_other_currency('USD')
cls.certificate.write({
'date_start': '2019-01-01 01:00:00',
'date_end': '2021-01-01 01:00:00',
})
def test_010_out_invoice_s_iva10b_s_iva21s(self):
""" Invoice with goods and services as they need to be reported in different sections for customer invoices. """
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
partner_id=self.partner_a.id,
invoice_line_ids=[
{'price_unit': 100.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva10b').ids)]},
{'price_unit': 200.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva21s').ids)]},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'IDEmisorFactura': {'NIF': '59962470K'},
'NumSerieFacturaEmisor': 'INV/2019/00001',
'FechaExpedicionFacturaEmisor': '01-01-2019',
},
'PeriodoLiquidacion': {'Ejercicio': '2019', 'Periodo': '01'},
'FacturaExpedida': {
'TipoFactura': 'F1',
'ClaveRegimenEspecialOTrascendencia': '01',
'DescripcionOperacion': 'manual',
'TipoDesglose': {
'DesgloseTipoOperacion': {
'PrestacionServicios': {
'Sujeta': {
'NoExenta': {
'TipoNoExenta': 'S1',
'DesgloseIVA': {
'DetalleIVA': [
{
'TipoImpositivo': 21.0,
'BaseImponible': 200.0,
'CuotaRepercutida': 42.0,
},
],
},
},
},
},
'Entrega': {
'Sujeta': {
'NoExenta': {
'TipoNoExenta': 'S1',
'DesgloseIVA': {
'DetalleIVA': [
{
'TipoImpositivo': 10.0,
'BaseImponible': 100.0,
'CuotaRepercutida': 10.0,
},
],
},
},
},
},
},
},
'ImporteTotal': 352.0,
'Contraparte': {
'IDOtro': {'ID': 'BE0477472701', 'IDType': '02'},
'NombreRazon': 'partner_a',
},
},
})
def test_020_out_invoice_s_iva10b_s_iva0_ns(self):
""" The ns tax is a special case with l10n_es_type ignore and should not appear in what we send"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
partner_id=self.partner_b.id,
invoice_line_ids=[
{'price_unit': 100.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva10b').ids)]},
{'price_unit': 200.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva0_ns').ids)]},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'IDEmisorFactura': {'NIF': '59962470K'},
'NumSerieFacturaEmisor': 'INV/2019/00001',
'FechaExpedicionFacturaEmisor': '01-01-2019',
},
'PeriodoLiquidacion': {'Ejercicio': '2019', 'Periodo': '01'},
'FacturaExpedida': {
'TipoFactura': 'F1',
'ClaveRegimenEspecialOTrascendencia': '01',
'DescripcionOperacion': 'manual',
'TipoDesglose': {
'DesgloseFactura': {
'Sujeta': {
'NoExenta': {
'TipoNoExenta': 'S1',
'DesgloseIVA': {
'DetalleIVA': [
{
'TipoImpositivo': 10.0,
'BaseImponible': 100.0,
'CuotaRepercutida': 10.0
},
],
},
},
},
},
},
'ImporteTotal': 110.0,
'Contraparte': {'NombreRazon': 'partner_b', 'NIF': 'F35999705'},
},
})
def test_030_out_invoice_s_iva10b_s_req014_s_iva21s_s_req52(self):
"""Recargo de Equivalencia with 2 different taxes and 2 different IVAs as it is reported in the same tag as the IVA"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
partner_id=self.partner_a.id,
invoice_line_ids=[
{
'price_unit': 100.0,
'tax_ids': [(6, 0, (self._get_tax_by_xml_id('s_iva10b') + self._get_tax_by_xml_id('s_req014')).ids)],
},
{
'price_unit': 200.0,
'tax_ids': [(6, 0, (self._get_tax_by_xml_id('s_iva21s') + self._get_tax_by_xml_id('s_req52')).ids)],
},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'IDEmisorFactura': {'NIF': '59962470K'},
'NumSerieFacturaEmisor': 'INV/2019/00001',
'FechaExpedicionFacturaEmisor': '01-01-2019',
},
'PeriodoLiquidacion': {'Ejercicio': '2019', 'Periodo': '01'},
'FacturaExpedida': {
'TipoFactura': 'F1',
'ClaveRegimenEspecialOTrascendencia': '01',
'DescripcionOperacion': 'manual',
'TipoDesglose': {
'DesgloseTipoOperacion': {
'PrestacionServicios': {
'Sujeta': {
'NoExenta': {
'TipoNoExenta': 'S1',
'DesgloseIVA': {
'DetalleIVA': [
{
'TipoImpositivo': 21.0,
'BaseImponible': 200.0,
'CuotaRepercutida': 42.0,
'CuotaRecargoEquivalencia': 10.4,
'TipoRecargoEquivalencia': 5.2
}
]
}
}
}
},
'Entrega': {
'Sujeta': {
'NoExenta': {
'TipoNoExenta': 'S1',
'DesgloseIVA': {
'DetalleIVA': [
{
'TipoImpositivo': 10.0,
'BaseImponible': 100.0,
'CuotaRepercutida': 10.0,
'CuotaRecargoEquivalencia': 1.4,
'TipoRecargoEquivalencia': 1.4
}
]
}
}
}
}
}
},
'ImporteTotal': 363.8,
'Contraparte': {
'IDOtro': {'ID': 'BE0477472701', 'IDType': '02'},
'NombreRazon': 'partner_a',
},
},
})
def test_040_out_refund_s_iva10b_s_iva10b_s_iva21s(self):
"""For a customer refund, the amounts need to be reported as negative and also have goods and services separate"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='out_refund',
partner_id=self.partner_a.id,
invoice_line_ids=[
{'price_unit': 100.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva10b').ids)]},
{'price_unit': 100.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva10b').ids)]},
{'price_unit': 200.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva21s').ids)]},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'IDEmisorFactura': {'NIF': '59962470K'},
'NumSerieFacturaEmisor': 'RINV/2019/00001',
'FechaExpedicionFacturaEmisor': '01-01-2019',
},
'PeriodoLiquidacion': {'Ejercicio': '2019', 'Periodo': '01'},
'FacturaExpedida': {
'TipoFactura': 'R1',
'TipoRectificativa': 'I',
'ClaveRegimenEspecialOTrascendencia': '01',
'DescripcionOperacion': 'manual',
'TipoDesglose': {
'DesgloseTipoOperacion': {
'PrestacionServicios': {
'Sujeta': {
'NoExenta': {
'TipoNoExenta': 'S1',
'DesgloseIVA': {
'DetalleIVA': [
{
'TipoImpositivo': 21.0,
'BaseImponible': -200.0,
'CuotaRepercutida': -42.0
}
]
}
}
}
},
'Entrega': {
'Sujeta': {
'NoExenta': {
'TipoNoExenta': 'S1',
'DesgloseIVA': {
'DetalleIVA': [
{
'TipoImpositivo': 10.0,
'BaseImponible': -200.0,
'CuotaRepercutida': -20.0
}
]
}
}
}
}
}
},
'ImporteTotal': -462.0,
'Contraparte': {
'IDOtro': {'ID': 'BE0477472701', 'IDType': '02'},
'NombreRazon': 'partner_a',
},
},
})
def test_050_out_invoice_s_iva0_sp_i_s_iva0_ic(self):
"""An intra-community sale needs to be reported as exempt and intra-community services as no sujeto por reglas de localizacion (no_sujeto_loc)"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
partner_id=self.partner_a.id,
invoice_line_ids=[
{'price_unit': 100.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva0_sp_i').ids)]},
{'price_unit': 200.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva0_ic').ids)]},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'IDEmisorFactura': {'NIF': '59962470K'},
'NumSerieFacturaEmisor': 'INV/2019/00001',
'FechaExpedicionFacturaEmisor': '01-01-2019',
},
'PeriodoLiquidacion': {'Ejercicio': '2019', 'Periodo': '01'},
'FacturaExpedida': {
'TipoFactura': 'F1',
'ClaveRegimenEspecialOTrascendencia': '01',
'DescripcionOperacion': 'manual',
'TipoDesglose': {
'DesgloseTipoOperacion': {
'PrestacionServicios': {
'NoSujeta': {
'ImporteTAIReglasLocalizacion': 100.0
},
},
'Entrega': {
'Sujeta': {
'Exenta': {
'DetalleExenta': [
{
'BaseImponible': 200.0,
'CausaExencion': 'E5',
},
],
},
},
},
},
},
'ImporteTotal': 300.0,
'Contraparte': {
'IDOtro': {'ID': 'BE0477472701', 'IDType': '02'},
'NombreRazon': 'partner_a',
},
},
})
def test_060_out_refund_s_iva0_sp_i_s_iva0_ic(self):
""" Intra-community refund of service and good"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='out_refund',
partner_id=self.partner_a.id,
invoice_line_ids=[
{'price_unit': 100.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva0_sp_i').ids)]},
{'price_unit': 200.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva0_ic').ids)]},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'IDEmisorFactura': {'NIF': '59962470K'},
'NumSerieFacturaEmisor': 'RINV/2019/00001',
'FechaExpedicionFacturaEmisor': '01-01-2019',
},
'PeriodoLiquidacion': {'Ejercicio': '2019', 'Periodo': '01'},
'FacturaExpedida': {
'TipoFactura': 'R1',
'TipoRectificativa': 'I',
'ClaveRegimenEspecialOTrascendencia': '01',
'DescripcionOperacion': 'manual',
'TipoDesglose': {
'DesgloseTipoOperacion': {
'PrestacionServicios': {
'NoSujeta': {
'ImporteTAIReglasLocalizacion': -100.0
},
},
'Entrega': {
'Sujeta': {
'Exenta': {
'DetalleExenta': [
{
'BaseImponible': -200.0,
'CausaExencion': 'E5',
},
],
},
},
},
},
},
'ImporteTotal': -300.0,
'Contraparte': {
'IDOtro': {'ID': 'BE0477472701', 'IDType': '02'},
'NombreRazon': 'partner_a',
},
},
})
def test_070_out_invoice_s_iva_e_s_iva0_e(self):
""" Export of service (no sujeto por reglas de localization) and export of goods (exempt)"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
partner_id=self.partner_a.id,
invoice_line_ids=[
{'price_unit': 100.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva_e').ids)]},
{'price_unit': 200.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva0_e').ids)]},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'IDEmisorFactura': {'NIF': '59962470K'},
'NumSerieFacturaEmisor': 'INV/2019/00001',
'FechaExpedicionFacturaEmisor': '01-01-2019',
},
'PeriodoLiquidacion': {'Ejercicio': '2019', 'Periodo': '01'},
'FacturaExpedida': {
'TipoFactura': 'F1',
'ClaveRegimenEspecialOTrascendencia': '02',
'DescripcionOperacion': 'manual',
'TipoDesglose': {
'DesgloseTipoOperacion': {
'PrestacionServicios': {
'NoSujeta': {
'ImporteTAIReglasLocalizacion': 100.0,
},
},
'Entrega': {
'Sujeta': {
'Exenta': {
'DetalleExenta': [
{
'BaseImponible': 200.0,
'CausaExencion': 'E2',
},
],
},
},
},
},
},
'ImporteTotal': 300.0,
'Contraparte': {
'IDOtro': {'ID': 'BE0477472701', 'IDType': '02'},
'NombreRazon': 'partner_a',
},
},
})
def test_080_out_refund_s_iva0_sp_i_s_iva0_ic(self):
"""Customer refund of an intracom good and service"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='out_refund',
partner_id=self.partner_a.id,
invoice_line_ids=[
{'price_unit': 100.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva0_sp_i').ids)]},
{'price_unit': 200.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva0_ic').ids)]},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'IDEmisorFactura': {'NIF': '59962470K'},
'NumSerieFacturaEmisor': 'RINV/2019/00001',
'FechaExpedicionFacturaEmisor': '01-01-2019',
},
'PeriodoLiquidacion': {'Ejercicio': '2019', 'Periodo': '01'},
'FacturaExpedida': {
'TipoFactura': 'R1',
'TipoRectificativa': 'I',
'ClaveRegimenEspecialOTrascendencia': '01',
'DescripcionOperacion': 'manual',
'TipoDesglose': {
'DesgloseTipoOperacion': {
'PrestacionServicios': {
'NoSujeta': {
'ImporteTAIReglasLocalizacion': -100.0,
},
},
'Entrega': {
'Sujeta': {
'Exenta': {
'DetalleExenta': [
{
'BaseImponible': -200.0,
'CausaExencion': 'E5',
},
],
},
},
},
},
},
'ImporteTotal': -300.0,
'Contraparte': {
'IDOtro': {'ID': 'BE0477472701', 'IDType': '02'},
'NombreRazon': 'partner_a',
},
},
})
def test_085_out_refund_s_iva0_sp_i_s_iva0_ic_multi_currency(self):
""" Same as test_080 but in multi-currency"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='out_refund',
partner_id=self.partner_a.id,
currency_id=self.other_currency.id,
invoice_line_ids=[
{'price_unit': 200.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva0_sp_i').ids)]},
{'price_unit': 400.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('s_iva0_ic').ids)]},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'IDEmisorFactura': {'NIF': '59962470K'},
'NumSerieFacturaEmisor': 'RINV/2019/00001',
'FechaExpedicionFacturaEmisor': '01-01-2019',
},
'PeriodoLiquidacion': {'Ejercicio': '2019', 'Periodo': '01'},
'FacturaExpedida': {
'TipoFactura': 'R1',
'TipoRectificativa': 'I',
'ClaveRegimenEspecialOTrascendencia': '01',
'DescripcionOperacion': 'manual',
'TipoDesglose': {
'DesgloseTipoOperacion': {
'PrestacionServicios': {
'NoSujeta': {
'ImporteTAIReglasLocalizacion': -100.0,
},
},
'Entrega': {
'Sujeta': {
'Exenta': {
'DetalleExenta': [
{
'BaseImponible': -200.0,
'CausaExencion': 'E5',
},
],
},
},
},
},
},
'ImporteTotal': -300.0,
'Contraparte': {
'IDOtro': {'ID': 'BE0477472701', 'IDType': '02'},
'NombreRazon': 'partner_a',
},
},
})
def test_090_in_invoice_p_iva10_bc_p_irpf19_p_iva21_sc_p_irpf19(self):
""" Vendor bill 10% IVA 19% retention, 21% IVA 19% retention
The retention just needs to be ignored basically, but in the ImporteTotal,
we need the amount before retention (withholding). """
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='in_invoice',
ref='sup0001',
partner_id=self.partner_b.id,
l10n_es_registration_date='2019-01-02',
invoice_line_ids=[
{
'price_unit': 100.0,
'tax_ids': [(6, 0, (self._get_tax_by_xml_id('p_iva10_bc') + self._get_tax_by_xml_id('p_irpf19')).ids)],
},
{
'price_unit': 200.0,
'tax_ids': [(6, 0, (self._get_tax_by_xml_id('p_iva21_sc') + self._get_tax_by_xml_id('p_irpf19')).ids)],
},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'FechaExpedicionFacturaEmisor': '01-01-2019',
'NumSerieFacturaEmisor': 'sup0001',
'IDEmisorFactura': {'NIF': 'F35999705'}
},
'FacturaRecibida': {
'TipoFactura': 'F1',
'Contraparte': {'NombreRazon': 'partner_b', 'NIF': 'F35999705'},
'DescripcionOperacion': 'manual',
'ClaveRegimenEspecialOTrascendencia': '01',
'ImporteTotal': 352.0,
'FechaRegContable': '02-01-2019',
'DesgloseFactura': {
'DesgloseIVA': {
'DetalleIVA': [
{'BaseImponible': 100.0, 'CuotaSoportada': 10.0, 'TipoImpositivo': 10.0},
{'BaseImponible': 200.0, 'CuotaSoportada': 42.0, 'TipoImpositivo': 21.0}
]
}
},
'CuotaDeducible': 52.0
},
'PeriodoLiquidacion': {'Periodo': '01', 'Ejercicio': '2019'}
})
def test_100_in_refund_p_iva10_bc(self):
"""Vendor bill refund of VAT 10% goods"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='in_refund',
ref='sup0001',
partner_id=self.partner_b.id,
l10n_es_registration_date='2019-01-02',
invoice_line_ids=[{'price_unit': 100.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('p_iva10_bc').ids)]}],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'FechaExpedicionFacturaEmisor': '01-01-2019',
'NumSerieFacturaEmisor': 'sup0001',
'IDEmisorFactura': {'NIF': 'F35999705'},
},
'FacturaRecibida': {
'TipoFactura': 'R4',
'TipoRectificativa': 'I',
'Contraparte': {'NombreRazon': 'partner_b', 'NIF': 'F35999705'},
'DescripcionOperacion': 'manual',
'ClaveRegimenEspecialOTrascendencia': '01',
'ImporteTotal': -110.0,
'FechaRegContable': '02-01-2019',
'DesgloseFactura': {
'DesgloseIVA': {
'DetalleIVA': [
{'BaseImponible': -100.0, 'CuotaSoportada': -10.0, 'TipoImpositivo': 10.0},
],
},
},
'CuotaDeducible': -10.0,
},
'PeriodoLiquidacion': {'Periodo': '01', 'Ejercicio': '2019'},
})
def test_110_in_invoice_p_iva10_bc_p_req014_p_iva21_sc_p_req52(self):
"""Vendor bill with recargo de equivalencia that needs to be reported within the VAT tax"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='in_invoice',
ref='sup0001',
partner_id=self.partner_b.id,
l10n_es_registration_date='2019-01-02',
invoice_line_ids=[
{
'price_unit': 100.0,
'tax_ids': [(6, 0, (self._get_tax_by_xml_id('p_iva10_bc') + self._get_tax_by_xml_id('p_req014')).ids)],
},
{
'price_unit': 200.0,
'tax_ids': [(6, 0, (self._get_tax_by_xml_id('p_iva21_sc') + self._get_tax_by_xml_id('p_req52')).ids)],
},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'FechaExpedicionFacturaEmisor': '01-01-2019',
'NumSerieFacturaEmisor': 'sup0001',
'IDEmisorFactura': {'NIF': 'F35999705'},
},
'FacturaRecibida': {
'TipoFactura': 'F1',
'Contraparte': {'NombreRazon': 'partner_b', 'NIF': 'F35999705'},
'DescripcionOperacion': 'manual',
'ClaveRegimenEspecialOTrascendencia': '01',
'ImporteTotal': 363.8,
'FechaRegContable': '02-01-2019',
'DesgloseFactura': {
'DesgloseIVA': {
'DetalleIVA': [
{
'BaseImponible': 100.0,
'CuotaSoportada': 10.0,
'TipoImpositivo': 10.0,
'CuotaRecargoEquivalencia': 1.4,
'TipoRecargoEquivalencia': 1.4,
},
{
'BaseImponible': 200.0,
'CuotaSoportada': 42.0,
'TipoImpositivo': 21.0,
'CuotaRecargoEquivalencia': 10.4,
'TipoRecargoEquivalencia': 5.2,
},
],
},
},
'CuotaDeducible': 52.0,
},
'PeriodoLiquidacion': {'Periodo': '01', 'Ejercicio': '2019'},
})
def test_120_in_invoice_p_iva21_sp_ex(self):
""" Extra-community vendor bill with reverse charge (-100 line which changes importetotal)"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='in_invoice',
ref='sup0001',
partner_id=self.partner_b.id,
l10n_es_registration_date='2019-01-02',
invoice_line_ids=[{'price_unit': 100.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('p_iva21_sp_ex').ids)]}],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'FechaExpedicionFacturaEmisor': '01-01-2019',
'NumSerieFacturaEmisor': 'sup0001',
'IDEmisorFactura': {'NIF': 'F35999705'},
},
'FacturaRecibida': {
'TipoFactura': 'F1',
'Contraparte': {'NombreRazon': 'partner_b', 'NIF': 'F35999705'},
'DescripcionOperacion': 'manual',
'ClaveRegimenEspecialOTrascendencia': '01',
'ImporteTotal': 100.0,
'FechaRegContable': '02-01-2019',
'DesgloseFactura': {
'InversionSujetoPasivo': {
'DetalleIVA': [{
'BaseImponible': 100.0,
'CuotaSoportada': 21.0,
'TipoImpositivo': 21.0,
}],
},
},
'CuotaDeducible': 21.0,
},
'PeriodoLiquidacion': {'Periodo': '01', 'Ejercicio': '2019'},
})
def test_130_in_invoice_p_iva0_ns_p_iva10_bc(self):
"""Vendor bill with a line of no sujeto services and a line of 10% goods. Here, there is no separation between goods and services"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='in_invoice',
ref='sup0001',
partner_id=self.partner_b.id,
l10n_es_registration_date='2019-01-02',
invoice_line_ids=[
{'price_unit': 100.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('p_iva0_ns').ids)]},
{'price_unit': 200.0, 'tax_ids': [(6, 0, self._get_tax_by_xml_id('p_iva10_bc').ids)]},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'FechaExpedicionFacturaEmisor': '01-01-2019',
'NumSerieFacturaEmisor': 'sup0001',
'IDEmisorFactura': {'NIF': 'F35999705'},
},
'FacturaRecibida': {
'TipoFactura': 'F1',
'Contraparte': {'NombreRazon': 'partner_b', 'NIF': 'F35999705'},
'DescripcionOperacion': 'manual',
'ClaveRegimenEspecialOTrascendencia': '01',
'ImporteTotal': 320.0,
'FechaRegContable': '02-01-2019',
'DesgloseFactura': {
'DesgloseIVA': {
'DetalleIVA': [
{'BaseImponible': 100.0},
{'BaseImponible': 200.0, 'TipoImpositivo': 10.0, 'CuotaSoportada': 20.0},
],
},
},
'CuotaDeducible': 20.0,
},
'PeriodoLiquidacion': {'Periodo': '01', 'Ejercicio': '2019'},
})
def test_140_out_invoice_s_iva10b_s_irpf1(self):
"""Customer invoice with a 10% VAT and a retention. The retention should not be deducted from the importetotal."""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
partner_id=self.partner_b.id,
invoice_line_ids=[
{
'price_unit': 100.0,
'tax_ids': [(6, 0, (self._get_tax_by_xml_id('s_iva10b') + self._get_tax_by_xml_id('s_irpf1')).ids)],
},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'IDEmisorFactura': {'NIF': '59962470K'},
'NumSerieFacturaEmisor': 'INV/2019/00001',
'FechaExpedicionFacturaEmisor': '01-01-2019',
},
'PeriodoLiquidacion': {'Ejercicio': '2019', 'Periodo': '01'},
'FacturaExpedida': {
'TipoFactura': 'F1',
'ClaveRegimenEspecialOTrascendencia': '01',
'DescripcionOperacion': 'manual',
'TipoDesglose': {
'DesgloseFactura': {
'Sujeta': {
'NoExenta': {
'TipoNoExenta': 'S1',
'DesgloseIVA': {
'DetalleIVA': [
{
'TipoImpositivo': 10.0,
'BaseImponible': 100.0,
'CuotaRepercutida': 10.0,
},
],
},
},
},
},
},
'ImporteTotal': 110.0,
'Contraparte': {'NombreRazon': 'partner_b', 'NIF': 'F35999705'},
},
})
def test_150_in_invoice_p_iva10_bc_p_irpf1(self):
"""Same as test_140 but for vendor bills"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='in_invoice',
ref='sup0001',
partner_id=self.partner_b.id,
l10n_es_registration_date='2019-01-02',
invoice_line_ids=[
{
'price_unit': 100.0,
'tax_ids': [(6, 0, (self._get_tax_by_xml_id('p_iva10_bc') + self._get_tax_by_xml_id('p_irpf1')).ids)],
},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'FechaExpedicionFacturaEmisor': '01-01-2019',
'NumSerieFacturaEmisor': 'sup0001',
'IDEmisorFactura': {'NIF': 'F35999705'},
},
'FacturaRecibida': {
'TipoFactura': 'F1',
'Contraparte': {'NombreRazon': 'partner_b', 'NIF': 'F35999705'},
'DescripcionOperacion': 'manual',
'ClaveRegimenEspecialOTrascendencia': '01',
'ImporteTotal': 110.0,
'FechaRegContable': '02-01-2019',
'DesgloseFactura': {
'DesgloseIVA': {
'DetalleIVA': [
{
'BaseImponible': 100.0,
'CuotaSoportada': 10.0,
'TipoImpositivo': 10.0,
},
],
},
},
'CuotaDeducible': 10.0,
},
'PeriodoLiquidacion': {'Periodo': '01', 'Ejercicio': '2019'},
})
def test_160_in_refund_p_iva10_bc_p_irpf1(self):
"""Same as 150 but for supplier refunds. The amounts need to be negative. """
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='in_refund',
ref='sup0001',
partner_id=self.partner_b.id,
l10n_es_registration_date='2019-01-02',
invoice_line_ids=[
{
'price_unit': 100.0,
'tax_ids': [(6, 0, (self._get_tax_by_xml_id('p_iva10_bc') + self._get_tax_by_xml_id('p_irpf1')).ids)],
},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'FechaExpedicionFacturaEmisor': '01-01-2019',
'NumSerieFacturaEmisor': 'sup0001',
'IDEmisorFactura': {'NIF': 'F35999705'},
},
'FacturaRecibida': {
'TipoFactura': 'R4',
'TipoRectificativa': 'I',
'Contraparte': {'NombreRazon': 'partner_b', 'NIF': 'F35999705'},
'DescripcionOperacion': 'manual',
'ClaveRegimenEspecialOTrascendencia': '01',
'ImporteTotal': -110.0,
'FechaRegContable': '02-01-2019',
'DesgloseFactura': {
'DesgloseIVA': {
'DetalleIVA': [
{
'BaseImponible': -100.0,
'CuotaSoportada': -10.0,
'TipoImpositivo': 10.0,
},
],
},
},
'CuotaDeducible': -10.0,
},
'PeriodoLiquidacion': {'Periodo': '01', 'Ejercicio': '2019'},
})
def test_165_in_refund_p_iva10_bc_p_irpf1_multi_currency(self):
"""Same as test_160, but with another currency. With double the amounts, the result is the same. """
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='in_refund',
ref='sup0001',
partner_id=self.partner_b.id,
currency_id=self.other_currency.id,
l10n_es_registration_date='2019-01-02',
invoice_line_ids=[
{
'price_unit': 200.0,
'tax_ids': [(6, 0, (self._get_tax_by_xml_id('p_iva10_bc') + self._get_tax_by_xml_id('p_irpf1')).ids)],
},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'FechaExpedicionFacturaEmisor': '01-01-2019',
'NumSerieFacturaEmisor': 'sup0001',
'IDEmisorFactura': {'NIF': 'F35999705'},
},
'FacturaRecibida': {
'TipoFactura': 'R4',
'TipoRectificativa': 'I',
'Contraparte': {'NombreRazon': 'partner_b', 'NIF': 'F35999705'},
'DescripcionOperacion': 'manual',
'ClaveRegimenEspecialOTrascendencia': '01',
'ImporteTotal': -110.0,
'FechaRegContable': '02-01-2019',
'DesgloseFactura': {
'DesgloseIVA': {
'DetalleIVA': [
{
'BaseImponible': -100.0,
'CuotaSoportada': -10.0,
'TipoImpositivo': 10.0,
},
],
},
},
'CuotaDeducible': -10.0,
},
'PeriodoLiquidacion': {'Periodo': '01', 'Ejercicio': '2019'},
})
def test_170_in_invoice_dua(self):
"""DUA invoice. The TipoFactura needs to change as well as the importetotal needs to include the base. """
with freeze_time(self.frozen_today), patch(
'odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign
):
invoice = self.create_invoice(
move_type='in_invoice',
ref='fakedua',
partner_id=self.partner_b.id,
currency_id=self.other_currency.id,
l10n_es_registration_date='2019-01-02',
invoice_line_ids=[
{
'tax_ids': [(6, 0, (self._get_tax_by_xml_id('p_iva21_ibc_group').ids))],
},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'PeriodoLiquidacion': {'Ejercicio': '2019', 'Periodo': '01'},
'IDFactura': {
'FechaExpedicionFacturaEmisor': '01-01-2019',
'IDEmisorFactura': {'NIF': '59962470K'},
'NumSerieFacturaEmisor': 'fakedua'
},
'FacturaRecibida': {
'DescripcionOperacion': 'manual',
'Contraparte': {'NIF': '59962470K', 'NombreRazon': 'partner_b'},
'FechaRegContable': '02-01-2019',
'ClaveRegimenEspecialOTrascendencia': '01',
'TipoFactura': 'F5',
'DesgloseFactura': {
'DesgloseIVA': {
'DetalleIVA': [{'BaseImponible': 500.0, 'TipoImpositivo': 21.0, 'CuotaSoportada': 105.0}]
}
},
'ImporteTotal': 605.0,
'CuotaDeducible': 105.0
}})
def test_180_in_invoice_iva21_sp_in_iva21_ic_bc(self):
""" For intra-community purchase of services and goods, the -100 needs to be taken into account in the importe total.
The clave should also change to 09. """
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='in_invoice',
ref='sup0001',
partner_id=self.partner_a.id,
l10n_es_registration_date='2019-01-02',
invoice_line_ids=[
{
'price_unit': 100.0,
'tax_ids': [(6, 0, self._get_tax_by_xml_id('p_iva21_sp_in').ids)],
},
{
'price_unit': 200.0,
'tax_ids': [(6, 0, self._get_tax_by_xml_id('p_iva21_ic_bc').ids)],
},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'FechaExpedicionFacturaEmisor': '01-01-2019',
'NumSerieFacturaEmisor': 'sup0001',
'IDEmisorFactura': {'IDOtro': {'IDType': '02', 'ID': 'BE0477472701'}}
},
'FacturaRecibida': {
'TipoFactura': 'F1',
'Contraparte': {'IDOtro': {'IDType': '02', 'ID': 'BE0477472701'}, 'NombreRazon': 'partner_a'},
'DescripcionOperacion': 'manual',
'ClaveRegimenEspecialOTrascendencia': '09',
'ImporteTotal': 300.0,
'FechaRegContable': '02-01-2019',
'DesgloseFactura': {
'DesgloseIVA': {
'DetalleIVA': [
{'BaseImponible': 300.0, 'CuotaSoportada': 63.0, 'TipoImpositivo': 21.0},
]
}
},
'CuotaDeducible': 63.0
},
'PeriodoLiquidacion': {'Periodo': '01', 'Ejercicio': '2019'}
})
def test_190_in_refund_iva21_sp_in_iva21_ic_bc(self):
""" For intra-community purchase return services and goods, the -100 needs to be taken into account in the importe total.
For a refund, the type should change to R4"""
with freeze_time(self.frozen_today), \
patch('odoo.addons.l10n_es_edi_sii.models.account_edi_format.AccountEdiFormat._l10n_es_edi_call_web_service_sign',
new=mocked_l10n_es_edi_call_web_service_sign):
invoice = self.create_invoice(
move_type='in_refund',
ref='sup0001',
partner_id=self.partner_a.id,
l10n_es_registration_date='2019-01-02',
invoice_line_ids=[
{
'price_unit': 100.0,
'tax_ids': [(6, 0, self._get_tax_by_xml_id('p_iva21_sp_in').ids)],
},
{
'price_unit': 200.0,
'tax_ids': [(6, 0, self._get_tax_by_xml_id('p_iva21_ic_bc').ids)],
},
],
)
invoice.action_post()
generated_files = self._process_documents_web_services(invoice, {'es_sii'})
self.assertTrue(generated_files)
json_file = json.loads(generated_files[0].decode())[0]
self.assertEqual(json_file, {
'IDFactura': {
'FechaExpedicionFacturaEmisor': '01-01-2019',
'NumSerieFacturaEmisor': 'sup0001',
'IDEmisorFactura': {'IDOtro': {'IDType': '02', 'ID': 'BE0477472701'}}
},
'FacturaRecibida': {
'TipoFactura': 'R4',
'TipoRectificativa': 'I',
'Contraparte': {'IDOtro': {'IDType': '02', 'ID': 'BE0477472701'}, 'NombreRazon': 'partner_a'},
'DescripcionOperacion': 'manual',
'ClaveRegimenEspecialOTrascendencia': '09',
'ImporteTotal': -300.0,
'FechaRegContable': '02-01-2019',
'DesgloseFactura': {
'DesgloseIVA': {
'DetalleIVA': [
{'BaseImponible': -300.0, 'CuotaSoportada': -63.0, 'TipoImpositivo': 21.0},
]
}
},
'CuotaDeducible': -63.0
},
'PeriodoLiquidacion': {'Periodo': '01', 'Ejercicio': '2019'}
})