se adiciona comando validate-nominaindividual para validacion usando XSD de caja de herramientas
FossilOrigin-Name: e2f075b294e19cd447ad6e1e83ef7f00c8b863718abf35fcfccbb182097e300d
This commit is contained in:
parent
0c28eea6e2
commit
6d02ad0bf5
14
facho/cli.py
14
facho/cli.py
@ -200,6 +200,18 @@ def validate_invoice(invoice_path):
|
|||||||
XSD.validate(content, XSD.UBLInvoice)
|
XSD.validate(content, XSD.UBLInvoice)
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.argument('nomina_path')
|
||||||
|
def validate_nominaindividual(nomina_path):
|
||||||
|
from facho.fe.data.dian import XSD
|
||||||
|
content = open(nomina_path, 'r').read()
|
||||||
|
content = content.replace(
|
||||||
|
'xmlns="http://www.dian.gov.co/contratos/facturaelectronica/v1"',
|
||||||
|
'xmlns="dian:gov:co:facturaelectronica:NominaIndividual"',
|
||||||
|
)
|
||||||
|
XSD.validate(content, XSD.NominaIndividual)
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.option('--private-key', type=click.Path(exists=True))
|
@click.option('--private-key', type=click.Path(exists=True))
|
||||||
@click.option('--passphrase')
|
@click.option('--passphrase')
|
||||||
@ -327,7 +339,6 @@ def soap_send_nomina_sync(private_key, public_key, habilitacion, password, filen
|
|||||||
if habilitacion:
|
if habilitacion:
|
||||||
req = dian.Habilitacion.SendNominaSync
|
req = dian.Habilitacion.SendNominaSync
|
||||||
resp = client.request(req(
|
resp = client.request(req(
|
||||||
filename,
|
|
||||||
open(zipfile, 'rb').read()
|
open(zipfile, 'rb').read()
|
||||||
))
|
))
|
||||||
print(resp)
|
print(resp)
|
||||||
@ -372,3 +383,4 @@ main.add_command(sign_xml)
|
|||||||
main.add_command(sign_verify_xml)
|
main.add_command(sign_verify_xml)
|
||||||
main.add_command(generate_nomina)
|
main.add_command(generate_nomina)
|
||||||
main.add_command(soap_send_nomina_sync)
|
main.add_command(soap_send_nomina_sync)
|
||||||
|
main.add_command(validate_nominaindividual)
|
||||||
|
@ -177,7 +177,6 @@ class GetStatusZip(SOAPService):
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class SendNominaSync(SOAPService):
|
class SendNominaSync(SOAPService):
|
||||||
fileName: str
|
|
||||||
contentFile: bytes
|
contentFile: bytes
|
||||||
|
|
||||||
def get_wsdl(self):
|
def get_wsdl(self):
|
||||||
|
@ -9,5 +9,8 @@ def path_for_xsd(dirname, xsdname):
|
|||||||
|
|
||||||
UBLInvoice= xmlschema.XMLSchema(path_for_xsd('maindoc', 'UBL-Invoice-2.1.xsd'))
|
UBLInvoice= xmlschema.XMLSchema(path_for_xsd('maindoc', 'UBL-Invoice-2.1.xsd'))
|
||||||
|
|
||||||
|
NominaIndividual = xmlschema.XMLSchema(path_for_xsd('nomina', 'NominaIndividualElectronicaXSDV1.0.6.xsd'))
|
||||||
|
NominaIndividualDeAjuste = xmlschema.XMLSchema(path_for_xsd('nomina', 'NominaIndividualDeAjusteElectronicaXSDV1.0.6.xsd'))
|
||||||
|
|
||||||
def validate(xml, schema):
|
def validate(xml, schema):
|
||||||
schema.validate(xml)
|
schema.validate(xml)
|
||||||
|
@ -34,6 +34,30 @@ class NumeroSecuencia:
|
|||||||
# NIE012
|
# NIE012
|
||||||
Numero = self.numero)
|
Numero = self.numero)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Periodo:
|
||||||
|
fecha_ingreso: str
|
||||||
|
fecha_liquidacion_inicio: str
|
||||||
|
fecha_liquidacion_fin: str
|
||||||
|
fecha_generacion: str
|
||||||
|
|
||||||
|
tiempo_laborado: int = 1
|
||||||
|
fecha_retiro: str = None
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
fragment.set_attributes('./Periodo',
|
||||||
|
#NIE002
|
||||||
|
FechaIngreso=self.fecha_ingreso,
|
||||||
|
#NIE003
|
||||||
|
FechaRetiro=self.fecha_retiro,
|
||||||
|
#NIE004
|
||||||
|
FechaLiquidacionInicio=self.fecha_liquidacion_inicio,
|
||||||
|
#NIE005
|
||||||
|
FechaLiquidacionFin=self.fecha_liquidacion_fin,
|
||||||
|
#NIE006
|
||||||
|
TiempoLaborado=self.tiempo_laborado,
|
||||||
|
#NIE008
|
||||||
|
FechaGen=self.fecha_generacion)
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Proveedor:
|
class Proveedor:
|
||||||
@ -60,8 +84,7 @@ class Proveedor:
|
|||||||
# TODO(bit4bit) https://catalogo‐vpfe‐hab.dian.gov.co/document/searchqr?documentkey=CUNE para habilitacion
|
# TODO(bit4bit) https://catalogo‐vpfe‐hab.dian.gov.co/document/searchqr?documentkey=CUNE para habilitacion
|
||||||
# https://catalogo‐vpfe.dian.gov.co/document/searchqr?documentkey=CUNE
|
# https://catalogo‐vpfe.dian.gov.co/document/searchqr?documentkey=CUNE
|
||||||
codigo_qr = f"https://catalogo‐vpfe.dian.gov.co/document/searchqr?documentkey={cune}"
|
codigo_qr = f"https://catalogo‐vpfe.dian.gov.co/document/searchqr?documentkey={cune}"
|
||||||
fragment.set_attributes('./ProveedorXML',
|
fexml.set_element('./CodigoQR', codigo_qr)
|
||||||
CodigoQR=codigo_qr)
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Metadata:
|
class Metadata:
|
||||||
@ -184,10 +207,13 @@ class DianXMLExtensionSigner(fe.DianXMLExtensionSigner):
|
|||||||
|
|
||||||
|
|
||||||
class DIANNominaXML:
|
class DIANNominaXML:
|
||||||
def __init__(self, tag_document, xpath_ajuste=None):
|
def __init__(self, tag_document, xpath_ajuste=None,schemaLocation=None):
|
||||||
self.tag_document = tag_document
|
self.tag_document = tag_document
|
||||||
self.fexml = fe.FeXML(tag_document, 'http://www.dian.gov.co/contratos/facturaelectronica/v1')
|
self.fexml = fe.FeXML(tag_document, 'http://www.dian.gov.co/contratos/facturaelectronica/v1')
|
||||||
|
|
||||||
|
if schemaLocation is not None:
|
||||||
|
self.fexml.root.set("SchemaLocation", schemaLocation)
|
||||||
|
|
||||||
# layout, la dian requiere que los elementos
|
# layout, la dian requiere que los elementos
|
||||||
# esten ordenados segun el anexo tecnico
|
# esten ordenados segun el anexo tecnico
|
||||||
self.fexml.placeholder_for('./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent')
|
self.fexml.placeholder_for('./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent')
|
||||||
@ -203,15 +229,19 @@ class DIANNominaXML:
|
|||||||
self.root_fragment.placeholder_for('./NumeroSecuenciaXML')
|
self.root_fragment.placeholder_for('./NumeroSecuenciaXML')
|
||||||
self.root_fragment.placeholder_for('./LugarGeneracionXML')
|
self.root_fragment.placeholder_for('./LugarGeneracionXML')
|
||||||
self.root_fragment.placeholder_for('./ProveedorXML')
|
self.root_fragment.placeholder_for('./ProveedorXML')
|
||||||
|
self.root_fragment.placeholder_for('./CodigoQR')
|
||||||
self.root_fragment.placeholder_for('./InformacionGeneral')
|
self.root_fragment.placeholder_for('./InformacionGeneral')
|
||||||
self.root_fragment.placeholder_for('./Empleador')
|
self.root_fragment.placeholder_for('./Empleador')
|
||||||
self.root_fragment.placeholder_for('./Trabajador')
|
self.root_fragment.placeholder_for('./Trabajador')
|
||||||
self.root_fragment.placeholder_for('./Pago')
|
self.root_fragment.placeholder_for('./Pago')
|
||||||
|
self.root_fragment.placeholder_for('./FechasPagos')
|
||||||
self.root_fragment.placeholder_for('./Devengados/Basico')
|
self.root_fragment.placeholder_for('./Devengados/Basico')
|
||||||
self.root_fragment.placeholder_for('./Devengados/Transporte', optional=True)
|
self.root_fragment.placeholder_for('./Devengados/Transporte', optional=True)
|
||||||
|
|
||||||
|
|
||||||
self.informacion_general_xml = self.root_fragment.fragment('./InformacionGeneral')
|
self.informacion_general_xml = self.root_fragment.fragment('./InformacionGeneral')
|
||||||
|
self.periodo_xml = self.root_fragment.fragment('./Periodo')
|
||||||
|
|
||||||
self.numero_secuencia_xml = self.root_fragment.fragment('./NumeroSecuenciaXML')
|
self.numero_secuencia_xml = self.root_fragment.fragment('./NumeroSecuenciaXML')
|
||||||
self.lugar_generacion_xml = self.root_fragment.fragment('./LugarGeneracionXML')
|
self.lugar_generacion_xml = self.root_fragment.fragment('./LugarGeneracionXML')
|
||||||
self.proveedor_xml = self.root_fragment.fragment('./ProveedorXML')
|
self.proveedor_xml = self.root_fragment.fragment('./ProveedorXML')
|
||||||
@ -236,11 +266,20 @@ class DIANNominaXML:
|
|||||||
self.informacion_general = general
|
self.informacion_general = general
|
||||||
self.informacion_general.apply(self.informacion_general_xml)
|
self.informacion_general.apply(self.informacion_general_xml)
|
||||||
|
|
||||||
|
def asignar_periodo(self, periodo):
|
||||||
|
if not isinstance(periodo, Periodo):
|
||||||
|
raise ValueError('se espera tipo Periodo')
|
||||||
|
|
||||||
|
periodo.apply(self.periodo_xml)
|
||||||
|
|
||||||
def asignar_pago(self, pago):
|
def asignar_pago(self, pago):
|
||||||
if not isinstance(pago, Pago):
|
if not isinstance(pago, Pago):
|
||||||
raise ValueError('se espera tipo Pago')
|
raise ValueError('se espera tipo Pago')
|
||||||
pago.apply(self.pago_xml)
|
pago.apply(self.pago_xml)
|
||||||
|
|
||||||
|
def asignar_fecha_pago(self, fecha):
|
||||||
|
self.fexml.set_element('./FechasPagos/FechaPago', fecha)
|
||||||
|
|
||||||
def asignar_empleador(self, empleador):
|
def asignar_empleador(self, empleador):
|
||||||
if not isinstance(empleador, Empleador):
|
if not isinstance(empleador, Empleador):
|
||||||
raise ValueError('se espera tipo Empleador')
|
raise ValueError('se espera tipo Empleador')
|
||||||
@ -381,8 +420,9 @@ class DIANNominaXML:
|
|||||||
class DIANNominaIndividual(DIANNominaXML):
|
class DIANNominaIndividual(DIANNominaXML):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__('NominaIndividual')
|
schema = "dian:gov:co:facturaelectronica:NominaIndividual NominaIndividualElectronicaXSD.xsd"
|
||||||
|
|
||||||
|
super().__init__('NominaIndividual', schemaLocation=schema)
|
||||||
|
|
||||||
# TODO(bit4bit) confirmar que no tienen en comun con NominaIndividual
|
# TODO(bit4bit) confirmar que no tienen en comun con NominaIndividual
|
||||||
class DIANNominaIndividualDeAjuste(DIANNominaXML):
|
class DIANNominaIndividualDeAjuste(DIANNominaXML):
|
||||||
|
@ -21,4 +21,5 @@ class Lugar:
|
|||||||
fragment.set_attributes(root,
|
fragment.set_attributes(root,
|
||||||
Pais=self.pais.code,
|
Pais=self.pais.code,
|
||||||
DepartamentoEstado=self.departamento.code,
|
DepartamentoEstado=self.departamento.code,
|
||||||
MunicipioCiudad=self.municipio.code)
|
MunicipioCiudad=self.municipio.code,
|
||||||
|
Idioma=self.idioma)
|
||||||
|
@ -55,7 +55,7 @@ class Trabajador:
|
|||||||
LugarTrabajoPais = self.lugar_trabajo.pais.code,
|
LugarTrabajoPais = self.lugar_trabajo.pais.code,
|
||||||
|
|
||||||
# NIE051
|
# NIE051
|
||||||
LugarTrabajoDepartamentoEstadoEstado = self.lugar_trabajo.departamento.code,
|
LugarTrabajoDepartamentoEstado = self.lugar_trabajo.departamento.code,
|
||||||
|
|
||||||
# NIE052
|
# NIE052
|
||||||
LugarTrabajoMunicipioCiudad = self.lugar_trabajo.municipio.code,
|
LugarTrabajoMunicipioCiudad = self.lugar_trabajo.municipio.code,
|
||||||
|
Loading…
Reference in New Issue
Block a user