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

Refactor service for invoice consult #37

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
226 changes: 117 additions & 109 deletions sii/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from zeep.transports import Transport
from zeep.helpers import serialize_object

from sii import __SII_VERSION__

MAX_ID_CHECKS = 9999


Expand All @@ -21,7 +23,21 @@ def __init__(self, certificate, key, url=None):
self.certificate = certificate
self.key = key
self.url = url
self.result = []

def create_service(self, config):
session = Session()
session.cert = (self.certificate, self.key)
session.verify = False
transport = Transport(session=session)

client = Client(wsdl=config['wsdl'], port_name=config['port_name'],
transport=transport, service_name=config['service_name']
)
if not self.url:
return client.service
address = '{0}{1}'.format(self.url, config['type_address'])
service = client.create_service(config['binding_name'], address)
return service


class IDService(Service):
Expand All @@ -30,25 +46,16 @@ def __init__(self, certificate, key, url=None):
self.validator_service = None

def ids_validate(self, partners, max_id_checks=MAX_ID_CHECKS):
self.validator_service = self.create_validation_service(partners)
self.validator_service = self.create_validation_service()

res = []
try:
if isinstance(partners, list):
partner_chunks = chunks(partners, max_id_checks)
for chunk in partner_chunks:
res.extend(self.send_validate_chunk(chunk=chunk))
else:
partners['Nif'] = partners.pop('vat')
partners['Nombre'] = partners.pop('name')
res = self.validator_service.VNifV1(
partners['Nif'], partners['Nombre']
)
partner_chunks = chunks(partners, max_id_checks)
for chunk in partner_chunks:
res.extend(self.send_validate_chunk(chunk=chunk))
return serialize_object(res)
except Fault as fault:
self.result = fault
if self.result.message != 'Codigo[-1].No identificado':
raise fault
raise fault

def send_validate_chunk(self, chunk):
for partner in chunk:
Expand All @@ -59,42 +66,23 @@ def send_validate_chunk(self, chunk):
def invalid_ids(self, partners, max_id_checks=MAX_ID_CHECKS):
res = self.ids_validate(partners, max_id_checks)
invalid_ids = []
if isinstance(partners, list):
for partner in res:
if partner['Resultado'] == 'NO IDENTIFICADO':
invalid_ids.append(partner)
else:
if isinstance(res, Exception) and res.message == 'Codigo[-1].No identificado':
return partners
for partner in res:
if partner['Resultado'] == 'NO IDENTIFICADO':
invalid_ids.append(partner)
return serialize_object(invalid_ids)

def create_validation_service(self, partners):
port_name = 'VNifPort1'
type_address = '/wlpl/BURT-JDIT/ws/VNifV1SOAP'
binding_name = '{http://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/burt/jdit/ws/VNifV1.wsdl}VNifV1SoapBinding'
service_name = 'VNifV1Service'
wsdl = self.wsdl_files['ids_validator_v1']
if isinstance(partners, list):
type_address = '/wlpl/BURT-JDIT/ws/VNifV2SOAP'
binding_name = '{http://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/burt/jdit/ws/VNifV2.wsdl}VNifV2SoapBinding'
service_name = 'VNifV2Service'
wsdl = self.wsdl_files['ids_validator_v2']
session = Session()
session.cert = (self.certificate, self.key)
session.verify = False
transport = Transport(session=session)

client = Client(wsdl=wsdl, port_name=port_name, transport=transport,
service_name=service_name)
if not self.url:
return client.service
address = '{0}{1}'.format(self.url, type_address)
service = client.create_service(binding_name, address)
return service

wsdl_files = {
'ids_validator_v1': 'https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/burt/jdit/ws/VNifV1.wsdl',
'ids_validator_v2': 'https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/burt/jdit/ws/VNifV2.wsdl'
def create_validation_service(self):
config = self.configs['ids_validator_v2'].copy()
return super(IDService, self).create_service(config)

configs = {
'ids_validator_v2': {
'wsdl': 'https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/burt/jdit/ws/VNifV2.wsdl',
'port_name': 'VNifPort1',
'binding_name': '{http://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/burt/jdit/ws/VNifV2.wsdl}VNifV2SoapBinding',
'type_address': '/wlpl/BURT-JDIT/ws/VNifV2SOAP',
'service_name': 'VNifV2Service'
}
}


Expand All @@ -106,67 +94,86 @@ def __init__(self, certificate, key, url=None, test_mode=False):
self.received_service = None
self.url = url
self.invoice = None
self.query = None
self.type = None

def send(self, invoice):
def send_invoice(self, invoice):
self.type = 'invoice'
self.invoice = invoice
if self.invoice.type.startswith('out_'):
if self.emitted_service is None:
self.emitted_service = self.create_service()
config = self.configs['out_inv_config'].copy()
self.emitted_service = self.create_service(config)
else:
if self.received_service is None:
self.received_service = self.create_service()
return self.send_invoice()

def create_service(self):
session = Session()
session.cert = (self.certificate, self.key)
session.verify = False
transport = Transport(session=session)
if self.invoice.type.startswith('out_'):
config = self.out_inv_config.copy()
config = self.configs['in_inv_config'].copy()
self.received_service = self.create_service(config)
return self.send()

def query_invoice(self, inv_type, nif_titular, name_titular, ejercicio,
periodo, nif_contraparte=None, name_contraparte=None,
num_invoice=None, date_invoice=None):
self.type = 'query'
self.query = {
'type': inv_type,
'query': {
'ConsultaLRFacturasEmitidas': {
'Cabecera': {
'IDVersionSii': __SII_VERSION__,
'Titular': {
'NombreRazon': name_titular,
'NIF': nif_titular
},
},
'FiltroConsulta': {
'PeriodoImpositivo': {
'Ejercicio': ejercicio,
'Periodo': periodo
}
}
}
}
}
if self.query['type'].startswith('out_'):
if self.emitted_service is None:
config = self.configs['out_inv_config'].copy()
self.emitted_service = self.create_service(config)
else:
config = self.in_inv_config.copy()
port_name = config['port_name']
if self.test_mode:
port_name += 'Pruebas'
if self.received_service is None:
config = self.configs['in_inv_config'].copy()
self.received_service = self.create_service(config)
return self.send()

client = Client(wsdl=config['wsdl'], port_name=port_name,
transport=transport, service_name=config['service_name']
)
if not self.url:
return client.service
address = '{0}{1}'.format(self.url, config['type_address'])
service = client.create_service(config['binding_name'], address)
return service
def create_service(self, config):
if self.test_mode:
config['port_name'] += 'Pruebas'
return super(SiiService, self).create_service(config)

def send_invoice(self):
def send(self):
msg_header, msg_invoice = self.get_msg()
# TODO: Adapt to new data model supporting invoice queries
try:
if self.invoice.type.startswith('out_'):
res = self.emitted_service.SuministroLRFacturasEmitidas(
msg_header, msg_invoice)
elif self.invoice.type.startswith('in_'):
res = self.received_service.SuministroLRFacturasRecibidas(
msg_header, msg_invoice)
self.result = res
return serialize_object(self.result)
if self.type == 'query':
if self.query['type'].startswith('out_'):
res = self.emitted_service.ConsultaLRFacturasEmitidas(
msg_header, msg_invoice)
elif self.query['type'].startswith('in_'):
res = self.received_service.ConsultaLRFacturasRecibidas(
msg_header, msg_invoice)
else:
if self.invoice.type.startswith('out_'):
res = self.emitted_service.SuministroLRFacturasEmitidas(
msg_header, msg_invoice)
elif self.invoice.type.startswith('in_'):
res = self.received_service.SuministroLRFacturasRecibidas(
msg_header, msg_invoice)

return serialize_object(res)
except Exception as fault:
self.result = fault
raise fault

# def list_invoice(self, invoice):
# msg_header, msg_invoice = self.get_msg(invoice)
# try:
# if invoice.type == 'in_invoice':
# res = self.received_service.ConsultaLRFacturasRecibidas(
# msg_header, msg_invoice)
# if res['EstadoEnvio'] == 'Correcto':
# self.result['sii_sent'] = True
# self.result['sii_return'] = res
# except Exception as fault:
# self.result['sii_return'] = fault

def get_msg(self):
# TODO: Adapt to new data model supporting invoice queries
dict_from_marsh = SII(self.invoice).generate_object()
res_header = res_invoices = None
if self.invoice.type.startswith('out_'):
Expand All @@ -182,18 +189,19 @@ def get_msg(self):

return res_header, res_invoices

out_inv_config = {
'wsdl': 'http://www.agenciatributaria.es/static_files/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/Suministro_inmediato_informacion/FicherosSuministros/V_07/SuministroFactEmitidas.wsdl',
'port_name': 'SuministroFactEmitidas',
'binding_name': '{https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/ssii/fact/ws/SuministroFactEmitidas.wsdl}siiBinding',
'type_address': '/wlpl/SSII-FACT/ws/fe/SiiFactFEV1SOAP',
'service_name': 'siiService'
}

in_inv_config = {
'wsdl': 'http://www.agenciatributaria.es/static_files/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/Suministro_inmediato_informacion/FicherosSuministros/V_07/SuministroFactRecibidas.wsdl',
'port_name': 'SuministroFactRecibidas',
'binding_name': '{https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/ssii/fact/ws/SuministroFactRecibidas.wsdl}siiBinding',
'type_address': '/wlpl/SSII-FACT/ws/fr/SiiFactFRV1SOAP',
'service_name': 'siiService'
configs = {
'out_inv_config': {
'wsdl': 'http://www.agenciatributaria.es/static_files/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/Suministro_inmediato_informacion/FicherosSuministros/V_07/SuministroFactEmitidas.wsdl',
'port_name': 'SuministroFactEmitidas',
'binding_name': '{https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/ssii/fact/ws/SuministroFactEmitidas.wsdl}siiBinding',
'type_address': '/wlpl/SSII-FACT/ws/fe/SiiFactFEV1SOAP',
'service_name': 'siiService'
},
'in_inv_config': {
'wsdl': 'http://www.agenciatributaria.es/static_files/AEAT/Contenidos_Comunes/La_Agencia_Tributaria/Modelos_y_formularios/Suministro_inmediato_informacion/FicherosSuministros/V_07/SuministroFactRecibidas.wsdl',
'port_name': 'SuministroFactRecibidas',
'binding_name': '{https://www2.agenciatributaria.gob.es/static_files/common/internet/dep/aplicaciones/es/aeat/ssii/fact/ws/SuministroFactRecibidas.wsdl}siiBinding',
'type_address': '/wlpl/SSII-FACT/ws/fr/SiiFactFRV1SOAP',
'service_name': 'siiService'
}
}