Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Añadir modelos para dar de baja las facturas #112

Merged
merged 11 commits into from
Oct 9, 2017
97 changes: 97 additions & 0 deletions sii/models/invoices_deregister.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# coding=utf-8
from __future__ import absolute_import

from marshmallow import fields, ValidationError
from sii import __SII_VERSION__
from .invoices_record import (
MySchema, DateString, CustomStringField, Titular, NIF, PERIODO_VALUES
)


class Cabecera(MySchema):
IDVersionSii = CustomStringField(required=True, default=__SII_VERSION__)
Titular = fields.Nested(Titular, required=True)

@staticmethod
def validate_id_version_sii(value):
if value != __SII_VERSION__:
raise ValidationError(
'La version del SII es incorrecta. '
'Se esperaba "{}"'.format(__SII_VERSION__)
)


class RegistroFacturas(MySchema):
Cabecera = fields.Nested(Cabecera, required=True)


class IdentificacionFactura(MySchema):
NumSerieFacturaEmisor = CustomStringField(required=True)
FechaExpedicionFacturaEmisor = DateString(required=True)

def validate_num_serie_factura_emisor(self, value):
self.validate_field_max_length(
value=value, field_name='Numero de Factura del Emisor',
max_chars=60
)

def validate_fecha_expedicion_factura_emisor(self, value):
self.validate_field_max_length(
value=value, field_name='Fecha de Expedicion de la Factura',
max_chars=10
)


class IdentificacionFacturaEmitida(IdentificacionFactura):
IDEmisorFactura = fields.Nested(NIF, required=True)


class IdentificacionFacturaRecibida(IdentificacionFactura):
IDEmisorFactura = fields.Nested(Titular, required=True)


class PeriodoImpositivo(MySchema):
Ejercicio = CustomStringField(required=True)
Periodo = CustomStringField(required=True)

def validate_ejercicio(self, value):
self.validate_field_is_one_of(
value=value, field_name='Ejercicio',
choices=[str(x) for x in range(0, 10000)]
)

def validate_periodo(self, value):
self.validate_field_is_one_of(
value=value, field_name='Periodo',
choices=PERIODO_VALUES
)


class Factura(MySchema):
PeriodoImpositivo = fields.Nested(PeriodoImpositivo, required=True)


class FacturaEmitida(Factura):
IDFactura = fields.Nested(IdentificacionFacturaEmitida, required=True)


class FacturaRecibida(Factura):
IDFactura = fields.Nested(IdentificacionFacturaRecibida, required=True)


class RegistroBajaExpedidas(RegistroFacturas):
RegistroLRBajaExpedidas = fields.Nested(FacturaEmitida, required=True)


class BajaFacturasEmitidas(MySchema):
BajaLRFacturasEmitidas = fields.Nested(RegistroBajaExpedidas, required=True)


class RegistroBajaRecibidas(RegistroFacturas):
RegistroLRBajaRecibidas = fields.Nested(FacturaRecibida, required=True)


class BajaFacturasRecibidas(MySchema):
BajaLRFacturasRecibidas = fields.Nested(
RegistroBajaRecibidas, required=True
)
119 changes: 118 additions & 1 deletion sii/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from decimal import Decimal, localcontext

from sii import __SII_VERSION__
from sii.models import invoices_record
from sii.models import invoices_record, invoices_deregister
from sii.utils import COUNTRY_CODES

SIGN = {'N': 1, 'R': 1, 'A': -1, 'B': -1, 'RA': 1, 'C': 1, 'G': 1} # 'BRA': -1
Expand Down Expand Up @@ -598,3 +598,120 @@ def generate_object(self):
)

return res.data


def get_baja_factura_recibida_dict(invoice):

cabecera = get_header(invoice)
cabecera.pop('TipoComunicacion')

obj = {
'BajaLRFacturasRecibidas': {
'Cabecera': cabecera,
'RegistroLRBajaRecibidas': {
'PeriodoImpositivo': {
'Ejercicio': invoice.period_id.name[3:7],
'Periodo': invoice.period_id.name[0:2]
},
'IDFactura': {
'IDEmisorFactura': {
'NombreRazon': invoice.partner_id.name,
'NIF': invoice.partner_id.vat
},
'NumSerieFacturaEmisor': invoice.origin,
'FechaExpedicionFacturaEmisor': invoice.origin_date_invoice
}
}
}
}

return obj


def get_baja_factura_emitida_dict(invoice):

cabecera = get_header(invoice)
cabecera.pop('TipoComunicacion')

obj = {
'BajaLRFacturasEmitidas': {
'Cabecera': cabecera,
'RegistroLRBajaExpedidas': {
'PeriodoImpositivo': {
'Ejercicio': invoice.period_id.name[3:7],
'Periodo': invoice.period_id.name[0:2]
},
'IDFactura': {
'IDEmisorFactura': {
'NIF': invoice.company_id.partner_id.vat
},
'NumSerieFacturaEmisor': invoice.number,
'FechaExpedicionFacturaEmisor': invoice.date_invoice
}
}
}
}

return obj


class SIIDeregister(SII):

def __init__(self, invoice):
super(SIIDeregister, self).__init__(invoice)
if invoice.type.startswith('in'):
self.invoice_deregister_model = (
invoices_deregister.BajaFacturasRecibidas()
)
self.invoice_deregister_dict = get_baja_factura_recibida_dict(
self.invoice
)
elif invoice.type.startswith('out'):
self.invoice_deregister_model = (
invoices_deregister.BajaFacturasEmitidas()
)
self.invoice_deregister_dict = get_baja_factura_emitida_dict(
self.invoice
)
else:
raise AttributeError(
'Valor desconocido en el tipo de factura: {}'.format(
invoice.type
)
)

def validate_deregister_invoice(self):

res = {}

errors = self.invoice_deregister_model.validate(
self.invoice_deregister_dict
)

res['successful'] = False if errors else True
res['object_validated'] = self.invoice_deregister_dict
if errors:
errors_list = self.get_validation_errors_list(errors)
res['errors'] = errors_list

return res

def generate_deregister_object(self):

validation_values = self.validate_deregister_invoice()
if not validation_values['successful']:
raise Exception(
'Errors were found while trying to validate the data:',
validation_values['errors']
)

res = self.invoice_deregister_model.dump(
self.invoice_deregister_dict
)
if res.errors:
raise Exception(
'Errors were found while trying to generate the dump:',
res.errors
)

return res.data
54 changes: 53 additions & 1 deletion sii/server.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: UTF-8 -*-

from sii.resource import SII
from sii.resource import SII, SIIDeregister
from zeep import Client
from requests import Session
from zeep.exceptions import Fault
Expand Down Expand Up @@ -197,3 +197,55 @@ def get_msg(self):
'type_address': '/wlpl/SSII-FACT/ws/fr/SiiFactFRV1SOAP',
'service_name': 'siiService'
}


class SiiDeregisterService(SiiService):

def get_deregister_msg(self):
dict_from_marsh = (
SIIDeregister(self.invoice).generate_deregister_object()
)
res_header = res_invoice = None
if self.invoice.type.startswith('out_'):
res_header = (
dict_from_marsh['BajaLRFacturasEmitidas']['Cabecera']
)
res_invoice = (
dict_from_marsh['BajaLRFacturasEmitidas']
['RegistroLRBajaExpedidas']
)
elif self.invoice.type.startswith('in_'):
res_header = (
dict_from_marsh['BajaLRFacturasRecibidas']['Cabecera']
)
res_invoice = (
dict_from_marsh['BajaLRFacturasRecibidas']
['RegistroLRBajaRecibidas']
)

return res_header, res_invoice

def deregister_invoice(self):
msg_header, msg_invoice = self.get_deregister_msg()
try:
if self.invoice.type.startswith('out_'):
res = self.emitted_service.BajaLRFacturasEmitidas(
msg_header, msg_invoice)
elif self.invoice.type.startswith('in_'):
res = self.received_service.BajaLRFacturasRecibidas(
msg_header, msg_invoice)
self.result = res
return serialize_object(self.result)
except Exception as fault:
self.result = fault
raise fault

def deregister(self, invoice):
self.invoice = invoice
if self.invoice.type.startswith('out_'):
if self.emitted_service is None:
self.emitted_service = self.create_service()
else:
if self.received_service is None:
self.received_service = self.create_service()
return self.deregister_invoice()
Loading