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)
|
||||
|
||||
|
||||
@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.option('--private-key', type=click.Path(exists=True))
|
||||
@click.option('--passphrase')
|
||||
@ -327,7 +339,6 @@ def soap_send_nomina_sync(private_key, public_key, habilitacion, password, filen
|
||||
if habilitacion:
|
||||
req = dian.Habilitacion.SendNominaSync
|
||||
resp = client.request(req(
|
||||
filename,
|
||||
open(zipfile, 'rb').read()
|
||||
))
|
||||
print(resp)
|
||||
@ -372,3 +383,4 @@ main.add_command(sign_xml)
|
||||
main.add_command(sign_verify_xml)
|
||||
main.add_command(generate_nomina)
|
||||
main.add_command(soap_send_nomina_sync)
|
||||
main.add_command(validate_nominaindividual)
|
||||
|
@ -177,7 +177,6 @@ class GetStatusZip(SOAPService):
|
||||
|
||||
@dataclass
|
||||
class SendNominaSync(SOAPService):
|
||||
fileName: str
|
||||
contentFile: bytes
|
||||
|
||||
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'))
|
||||
|
||||
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):
|
||||
schema.validate(xml)
|
||||
|
@ -34,7 +34,31 @@ class NumeroSecuencia:
|
||||
# NIE012
|
||||
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
|
||||
class Proveedor:
|
||||
nit: str
|
||||
@ -60,8 +84,7 @@ class Proveedor:
|
||||
# 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
|
||||
codigo_qr = f"https://catalogo‐vpfe.dian.gov.co/document/searchqr?documentkey={cune}"
|
||||
fragment.set_attributes('./ProveedorXML',
|
||||
CodigoQR=codigo_qr)
|
||||
fexml.set_element('./CodigoQR', codigo_qr)
|
||||
|
||||
@dataclass
|
||||
class Metadata:
|
||||
@ -184,10 +207,13 @@ class DianXMLExtensionSigner(fe.DianXMLExtensionSigner):
|
||||
|
||||
|
||||
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.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
|
||||
# esten ordenados segun el anexo tecnico
|
||||
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('./LugarGeneracionXML')
|
||||
self.root_fragment.placeholder_for('./ProveedorXML')
|
||||
self.root_fragment.placeholder_for('./CodigoQR')
|
||||
self.root_fragment.placeholder_for('./InformacionGeneral')
|
||||
self.root_fragment.placeholder_for('./Empleador')
|
||||
self.root_fragment.placeholder_for('./Trabajador')
|
||||
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/Transporte', optional=True)
|
||||
|
||||
|
||||
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.lugar_generacion_xml = self.root_fragment.fragment('./LugarGeneracionXML')
|
||||
self.proveedor_xml = self.root_fragment.fragment('./ProveedorXML')
|
||||
@ -236,11 +266,20 @@ class DIANNominaXML:
|
||||
self.informacion_general = general
|
||||
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):
|
||||
if not isinstance(pago, Pago):
|
||||
raise ValueError('se espera tipo Pago')
|
||||
pago.apply(self.pago_xml)
|
||||
|
||||
def asignar_fecha_pago(self, fecha):
|
||||
self.fexml.set_element('./FechasPagos/FechaPago', fecha)
|
||||
|
||||
def asignar_empleador(self, empleador):
|
||||
if not isinstance(empleador, Empleador):
|
||||
raise ValueError('se espera tipo Empleador')
|
||||
@ -381,8 +420,9 @@ class DIANNominaXML:
|
||||
class DIANNominaIndividual(DIANNominaXML):
|
||||
|
||||
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
|
||||
class DIANNominaIndividualDeAjuste(DIANNominaXML):
|
||||
|
@ -21,4 +21,5 @@ class Lugar:
|
||||
fragment.set_attributes(root,
|
||||
Pais=self.pais.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,
|
||||
|
||||
# NIE051
|
||||
LugarTrabajoDepartamentoEstadoEstado = self.lugar_trabajo.departamento.code,
|
||||
LugarTrabajoDepartamentoEstado = self.lugar_trabajo.departamento.code,
|
||||
|
||||
# NIE052
|
||||
LugarTrabajoMunicipioCiudad = self.lugar_trabajo.municipio.code,
|
||||
|
Loading…
Reference in New Issue
Block a user