Skip to content

Commit

Permalink
Merge pull request #169 from gisce/imp_retenciones_irpf
Browse files Browse the repository at this point in the history
Añadir envió de facturas con Retenciones de IRPF
  • Loading branch information
guilleJB authored Dec 20, 2024
2 parents 0dfc420 + 0f70f5e commit 1f49dcd
Show file tree
Hide file tree
Showing 3 changed files with 261 additions and 1 deletion.
18 changes: 17 additions & 1 deletion sii/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ def get_iva_values(invoice, in_invoice, is_export=False, is_import=False):
'iva_no_exento': False,
'detalle_iva_exento': {'BaseImponible': 0},
'importe_no_sujeto': 0,
'inversion_sujeto_pasivo': []
'inversion_sujeto_pasivo': [],
'factura_retencion': False
}

# iva_values es un diccionario que agrupa los valores del IVA por el tipo
Expand All @@ -67,6 +68,10 @@ def get_iva_values(invoice, in_invoice, is_export=False, is_import=False):
invoice_total = sign * invoice.amount_total

for inv_tax in invoice.tax_line:
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 @@ -150,6 +155,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 @@ -564,6 +578,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
118 changes: 118 additions & 0 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
126 changes: 126 additions & 0 deletions spec/testing_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -1028,3 +1028,129 @@ def get_out_invoice_rescision(self):
sii_out_clave_regimen_especial=self.sii_out_clave_regimen_especial,
)
return invoice

def get_out_invoice_with_irfp(self):
journal = Journal(
name=u'Factura de Energía Recibida'
)

tax_iva_irpf_19 = Tax(
name='Retenciones IRPF 19%',
amount=-0.19, type='percent'
)
tax_iva_soportado_21 = Tax(
name='21% IVA repercutido',
amount=0.21, type='percent'
)
invoice_line = [
InvoiceLine(
price_subtotal=2400.0,
invoice_line_tax_id=[tax_iva_irpf_19, tax_iva_soportado_21])
]
base_iva_irfp = sum(
[line.price_subtotal
for line in invoice_line]
)
invoice_tax_iva_isp_soportado_21 = InvoiceTax(
name=tax_iva_soportado_21.name, base=base_iva_irfp,
tax_amount=504.0,
tax_id=tax_iva_soportado_21
)
tax_iva_irpf_19 = InvoiceTax(
name=tax_iva_irpf_19.name, base=base_iva_irfp,
tax_amount=-456.0,
tax_id=tax_iva_irpf_19
)
tax_line_inversion_sujeto_pasivo = [
tax_iva_irpf_19, invoice_tax_iva_isp_soportado_21
]
tax_lines = tax_line_inversion_sujeto_pasivo
invoice_lines = invoice_line

invoice = Invoice(
invoice_type='out_invoice',
journal_id=journal,
rectificative_type='N',
rectifying_id=False,
number='FEmit{}'.format(self.invoice_number),
partner_id=self.partner_invoice,
fiscal_name=self.fiscal_name,
fiscal_vat=self.fiscal_vat,
address_contact_id=self.address_contact_id,
company_id=self.company,
amount_total=self.amount_total,
amount_untaxed=self.amount_untaxed,
amount_tax=self.amount_tax,
period_id=self.period,
date_invoice=self.date_invoice,
tax_line=tax_lines,
invoice_line=invoice_lines,
sii_registered=self.sii_registered,
fiscal_position=self.fiscal_position,
sii_description=self.sii_description,
sii_out_clave_regimen_especial=self.sii_out_clave_regimen_especial,
)
return invoice

def get_in_invoice_with_irfp(self):
journal = Journal(
name=u'Factura de Energía Emitida'
)

tax_iva_irpf_19 = Tax(
name='Retenciones IRPF 19%',
amount=-0.19, type='percent'
)
tax_iva_soportado_21 = Tax(
name='21% IVA Soportado (operaciones corrientes)',
amount=0.21, type='percent'
)
invoice_line = [
InvoiceLine(
price_subtotal=2400.0,
invoice_line_tax_id=[tax_iva_irpf_19, tax_iva_soportado_21])
]
base_iva_irfp = sum(
[line.price_subtotal
for line in invoice_line]
)
invoice_tax_iva_isp_soportado_21 = InvoiceTax(
name=tax_iva_soportado_21.name, base=base_iva_irfp,
tax_amount=504.0,
tax_id=tax_iva_soportado_21
)
tax_iva_irpf_19 = InvoiceTax(
name=tax_iva_irpf_19.name, base=base_iva_irfp,
tax_amount=-456.0,
tax_id=tax_iva_irpf_19
)
tax_line_inversion_sujeto_pasivo = [
tax_iva_irpf_19, invoice_tax_iva_isp_soportado_21
]
tax_lines = tax_line_inversion_sujeto_pasivo
invoice_lines = invoice_line

invoice = Invoice(
invoice_type='in_invoice',
journal_id=journal,
rectificative_type='N',
rectifying_id=False,
number='FRecib{}'.format(self.invoice_number),
origin='FRecibOrigen{}'.format(self.invoice_number),
partner_id=self.partner_invoice,
address_contact_id=self.address_contact_id,
company_id=self.company,
amount_total=self.amount_total,
amount_untaxed=self.amount_untaxed,
amount_tax=self.amount_tax,
period_id=self.period,
origin_date_invoice=self.origin_date_invoice,
date_invoice=self.date_invoice,
tax_line=tax_lines,
invoice_line=invoice_lines,
sii_registered=self.sii_registered,
fiscal_position=self.fiscal_position,
sii_description=self.sii_description,
sii_in_clave_regimen_especial=self.sii_in_clave_regimen_especial,
)
return invoice

0 comments on commit 1f49dcd

Please sign in to comment.