Skip to content

Commit

Permalink
Merge branch 'master' into 64739_intracomunitaries
Browse files Browse the repository at this point in the history
  • Loading branch information
nvillarroya authored Jan 14, 2025
2 parents baa3054 + 6109f0b commit 9a08188
Show file tree
Hide file tree
Showing 6 changed files with 412 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[bumpversion]
current_version = 3.3.6
current_version = 3.4.0
2 changes: 1 addition & 1 deletion sii/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-

__LIBRARY_VERSION__ = '3.3.6'
__LIBRARY_VERSION__ = '3.4.0'
__SII_VERSION__ = '1.1'
18 changes: 17 additions & 1 deletion sii/models/basic_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ def __init__(self,
origin_date_invoice=None,
origin=None,
fiscal_name=None,
fiscal_vat=None):
fiscal_vat=None,
sii_non_current_tax_rate='R4'):
self.journal_id = journal_id
self.number = number
self.type = invoice_type
Expand All @@ -136,3 +137,18 @@ def __init__(self,
self.sii_out_clave_regimen_especial = sii_out_clave_regimen_especial
self.rectificative_type = rectificative_type
self.rectifying_id = rectifying_id
self.sii_non_current_tax_rate = sii_non_current_tax_rate

def get_values_taxes_non_current_tax_rate(self):
if self.sii_non_current_tax_rate == 'R4':
return {
'TipoRectificativa': 'S',
'TipoFactura': 'R4',
'ImporteRectificacion': {
'BaseRectificada': 0,
'CuotaRectificada': 0
}
}
else:
return {}

25 changes: 23 additions & 2 deletions sii/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def get_iva_values(invoice, in_invoice, is_export=False, is_import=False):
'detalle_iva_exento': {'BaseImponible': 0},
'importe_no_sujeto': 0,
'inversion_sujeto_pasivo': [],
'factura_retencion': False,
'intracomunitarias': []
}

Expand Down Expand Up @@ -88,6 +89,10 @@ def get_iva_values(invoice, in_invoice, is_export=False, is_import=False):
vals['intracomunitarias'].append(new_value)
invoice_total -= base_imponible
continue
if ' IRPF ' in inv_tax.name.upper():
invoice_total -= (inv_tax.tax_amount)
vals['factura_retencion'] = True
continue
if 'iva' in inv_tax.name.lower():
base_iva = inv_tax.base
base_imponible = sign * base_iva
Expand Down Expand Up @@ -171,6 +176,15 @@ def get_iva_values(invoice, in_invoice, is_export=False, is_import=False):

return vals

def get_total_factura_retencion(invoice):
total_retencion = Decimal('0.0')
sign = get_invoice_sign(invoice)
for inv_tax in invoice.tax_line:
if 'iva' in inv_tax.name.lower():
total_retencion += inv_tax.base
total_retencion += sign * inv_tax.tax_amount
return total_retencion


def get_partner_info(fiscal_partner, in_invoice, nombre_razon=False):
vat_type = fiscal_partner.sii_get_vat_type()
Expand Down Expand Up @@ -466,10 +480,15 @@ def get_factura_emitida(invoice, rect_sust_opc1=False, rect_sust_opc2=False):

if invoice.rectificative_type in ('A', 'B'):
if tipo_impositivo_no_vigente:
if invoice.date_invoice > tipo_impositivo_no_vigente:
if invoice.date_invoice > tipo_impositivo_no_vigente:
factura_expedida.update(
{'FechaOperacion': get_fecha_operacion_rec(invoice)}
{
'FechaOperacion': get_fecha_operacion_rec(invoice)
}
)
extra_info = invoice.get_values_taxes_non_current_tax_rate()
if extra_info:
factura_expedida.update(extra_info)
if rectificativa:
opcion = 0
if rect_sust_opc1:
Expand Down Expand Up @@ -585,6 +604,8 @@ def get_factura_recibida(invoice, rect_sust_opc1=False, rect_sust_opc2=False):
# Fecha registro contable: Fecha del envío.
fecha_reg_contable = date.today().strftime('%Y-%m-%d')
cuota_deducible = 0 # Cuota deducible: Etiqueta con 0
if iva_values.get('factura_retencion'):
importe_total = get_total_factura_retencion(invoice)

rectificativa = rect_sust_opc1 or rect_sust_opc2
fiscal_partner = FiscalPartner(invoice)
Expand Down
242 changes: 240 additions & 2 deletions spec/serialization_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,65 @@ def group_by_tax_rate(iva_values, in_invoice):

expect(detalle_inmueble['SituacionInmueble']).to(equal('4'))

with context('en los detalles del IVA con IRPF'):
with before.all:
self.out_invoice_irpf = self.data_gen.get_out_invoice_with_irfp()

self.out_invoice_obj = SII(self.out_invoice_irpf).generate_object()
self.factura_emitida = (
self.out_invoice_obj['SuministroLRFacturasEmitidas']['RegistroLRFacturasEmitidas']
)
self.detalle_iva_irpf_list = get_iva_values(self.out_invoice_irpf, in_invoice=False)
self.detalle_iva_desglose_irpf = (
self.factura_emitida['FacturaExpedida']['TipoDesglose']
['DesgloseFactura']['Sujeta']['NoExenta']['DesgloseIVA']
['DetalleIVA'][0]
)

with context('debe contener'):
with it('solo la parte del IVA'):
tax_line_iva = None
for x in self.out_invoice_irpf.tax_line:
if 'IVA' in x.name.upper():
tax_line_iva = x
expect(
self.detalle_iva_desglose_irpf['BaseImponible']
).to(equal(
tax_line_iva.base
))
expect(
Decimal('2400')
).to(
equal(
self.detalle_iva_desglose_irpf['BaseImponible']
)
)
expect(
Decimal('504')
).to(
equal(
self.detalle_iva_desglose_irpf['CuotaRepercutida']

)
)
expect(
self.detalle_iva_desglose_irpf['CuotaRepercutida']
).to(equal(
tax_line_iva.tax_amount
))
expect(
Decimal('21.0')
).to(
equal(
self.detalle_iva_desglose_irpf['TipoImpositivo']
)
)
expect(
self.detalle_iva_desglose_irpf['TipoImpositivo']
).to(equal(
tax_line_iva.tax_id.amount * 100
))

with description('en los datos de una factura recibida'):
with before.all:
self.in_invoice = self.data_gen.get_in_invoice()
Expand Down Expand Up @@ -668,6 +727,65 @@ def group_by_tax_rate(iva_values, in_invoice):
)
)

with context('en los detalles del IVA con IRPF'):
with before.all:
self.in_invoice_irpf = self.data_gen.get_in_invoice_with_irfp()

self.in_invoice_obj = SII(self.in_invoice_irpf).generate_object()
self.factura_recibida = (
self.in_invoice_obj['SuministroLRFacturasRecibidas']
['RegistroLRFacturasRecibidas']
)
self.detalle_iva_irpf_list = get_iva_values(self.in_invoice_irpf, in_invoice=True)
self.detalle_iva_desglose_irpf = (
self.factura_recibida['FacturaRecibida']['DesgloseFactura']
['DesgloseIVA']['DetalleIVA'][0]
)

with context('debe contener'):
with it('solo la parte del IVA'):
tax_line_iva = None
for x in self.in_invoice_irpf.tax_line:
if 'IVA' in x.name.upper():
tax_line_iva = x
expect(
self.detalle_iva_desglose_irpf['BaseImponible']
).to(equal(
tax_line_iva.base
))
expect(
Decimal('2400')
).to(
equal(
self.detalle_iva_desglose_irpf['BaseImponible']
)
)
expect(
Decimal('504')
).to(
equal(
self.detalle_iva_desglose_irpf['CuotaSoportada']

)
)
expect(
self.detalle_iva_desglose_irpf['CuotaSoportada']
).to(equal(
tax_line_iva.tax_amount
))
expect(
Decimal('21.0')
).to(
equal(
self.detalle_iva_desglose_irpf['TipoImpositivo']
)
)
expect(
self.detalle_iva_desglose_irpf['TipoImpositivo']
).to(equal(
tax_line_iva.tax_id.amount * 100
))

with context('si es una importación'):
with before.all:
# Clave Régimen Especial importación: '13'
Expand Down Expand Up @@ -990,9 +1108,9 @@ def group_by_tax_rate(iva_values, in_invoice):
self.out_refund.tax_line[0].tax_id.amount * 100
))

with description('en los datos de una factura rectificativa emitida con IVA 5% fecha postrior vigencia'):
with description('en los datos de una factura rectificativa emitida con IVA 5% fecha postrior vigencia como tipo R4'):
with before.all:
self.out_refund, self.out_b_inovice = self.data_gen.get_out_refund_invoice_iva5()
self.out_refund, self.out_b_inovice = self.data_gen.get_out_refund_invoice_iva5(sii_non_current_tax_rate='R4')
self.out_refund_obj = SII(self.out_refund).generate_object()
self.out_b_inovice_obj = SII(self.out_b_inovice).generate_object()
self.fact_rect_emit = (
Expand All @@ -1008,6 +1126,100 @@ def group_by_tax_rate(iva_values, in_invoice):
expect(
self.fact_refund_emit['FacturaExpedida']['FechaOperacion']
).to(equal('01-01-2023'))
with it('la TipoRectificativa debe ser S'):
expect(
self.fact_refund_emit['FacturaExpedida']['TipoRectificativa']
).to(equal('S'))
with it('la TipoFactura tiene que ser R4'):
expect(
self.fact_refund_emit['FacturaExpedida'][
'TipoFactura']
).to(equal('R4'))
with context('en los datos de rectificación'):
with it('el TipoRectificativa debe ser por sustitución (S)'):
expect(
self.fact_rect_emit['FacturaExpedida']['TipoRectificativa']
).to(equal('S'))

with it('la FechaOperacion debe ser por factura original'):
expect(
self.fact_rect_emit['FacturaExpedida']['FechaOperacion']
).to(equal('01-01-2023'))

with before.all:
self.importe_rectificacion = (
self.fact_rect_emit['FacturaExpedida']
['ImporteRectificacion']
)

with it('la BaseRectificada debe ser 0'):
expect(
self.importe_rectificacion['BaseRectificada']
).to(equal(0))

with it('la CuotaRectificada debe ser 0'):
expect(
self.importe_rectificacion['CuotaRectificada']
).to(equal(0))

with context('en los detalles del IVA'):
with before.all:
detalle_iva = (
self.fact_rect_emit['FacturaExpedida']['TipoDesglose']
['DesgloseFactura']['Sujeta']['NoExenta']['DesgloseIVA']
['DetalleIVA']
)
self.grouped_detalle_iva = group_by_tax_rate(
detalle_iva, in_invoice=False
)

with it('la BaseImponible debe ser la original'):
expect(
self.grouped_detalle_iva[5.0]['BaseImponible']
).to(equal(
self.out_refund.tax_line[0].base
))
with it('la CuotaRepercutida debe ser la original'):
expect(
self.grouped_detalle_iva[5.0]['CuotaRepercutida']
).to(equal(
-1 * abs(self.out_refund.tax_line[0].tax_amount)
))
with it('el TipoImpositivo debe ser la original'):
expect(
self.grouped_detalle_iva[5.0]['TipoImpositivo']
).to(equal(
self.out_refund.tax_line[0].tax_id.amount * 100
))

with description('en los datos de una factura rectificativa emitida con IVA 5% fecha postrior vigencia como tipo F1'):
with before.all:
self.out_refund, self.out_b_inovice = self.data_gen.get_out_refund_invoice_iva5(sii_non_current_tax_rate='F1')
self.out_refund_obj = SII(self.out_refund).generate_object()
self.out_b_inovice_obj = SII(self.out_b_inovice).generate_object()
self.fact_rect_emit = (
self.out_refund_obj['SuministroLRFacturasEmitidas']
['RegistroLRFacturasEmitidas']
)
self.fact_refund_emit = (
self.out_b_inovice_obj['SuministroLRFacturasEmitidas']
['RegistroLRFacturasEmitidas']
)
with context('en los datos de abonadora'):
with it('la FechaOperacion debe ser por factura original'):
expect(
self.fact_refund_emit['FacturaExpedida']['FechaOperacion']
).to(equal('01-01-2023'))
with it('la TipoRectificativa NO debe existir'):
expect(
self.fact_refund_emit['FacturaExpedida'].get(
'TipoRectificativa', False)
).to(equal(False))
with it('la TipoFactura tiene que ser F1'):
expect(
self.fact_refund_emit['FacturaExpedida'][
'TipoFactura']
).to(equal('F1'))
with context('en los datos de rectificación'):
with it('el TipoRectificativa debe ser por sustitución (S)'):
expect(
Expand Down Expand Up @@ -1084,6 +1296,14 @@ def group_by_tax_rate(iva_values, in_invoice):
self.fact_refund_emit['FacturaExpedida'].get(
'FechaOperacion', False)
).to(equal(False))
with it('la TipoRectificativa NO debe ser informado'):
expect(
self.fact_refund_emit['FacturaExpedida'].get('TipoRectificativa',False)
).to(equal(False))
with it('la TipoFactura tiene que ser F1'):
expect(
self.fact_refund_emit['FacturaExpedida'].get('TipoFactura', False)
).to(equal('F1'))
with context('en los datos de rectificación'):
with it('el TipoRectificativa debe ser por sustitución (S)'):
expect(
Expand All @@ -1094,6 +1314,15 @@ def group_by_tax_rate(iva_values, in_invoice):
expect(
self.fact_rect_emit['FacturaExpedida'].get('FechaOperacion', False)
).to(equal(False))
with it('la TipoRectificativa debe ser S'):
expect(
self.fact_rect_emit['FacturaExpedida'].get('TipoRectificativa',False)
).to(equal('S'))
with it('la TipoFactura tiene que ser R4'):
expect(
self.fact_rect_emit['FacturaExpedida'][
'TipoFactura']
).to(equal('R4'))

with before.all:
self.importe_rectificacion = (
Expand Down Expand Up @@ -1159,6 +1388,15 @@ def group_by_tax_rate(iva_values, in_invoice):
expect(
self.fact_refund_emit['FacturaExpedida']['FechaOperacion']
).to(equal('01-01-2023'))
with it('la TipoRectificativa debe ser S'):
expect(
self.fact_refund_emit['FacturaExpedida']['TipoRectificativa']
).to(equal('S'))
with it('la TipoFactura tiene que ser R4'):
expect(
self.fact_refund_emit['FacturaExpedida'][
'TipoFactura']
).to(equal('R4'))
with context('en los datos de rectificación'):
with it('la FechaOperacion debe ser por factura original'):
expect(
Expand Down
Loading

0 comments on commit 9a08188

Please sign in to comment.