Compare commits
131 Commits
model
...
MigrationP
| Author | SHA1 | Date | |
|---|---|---|---|
| f98ab98c9c | |||
| d04596ed3a | |||
| 9297be22e0 | |||
|
|
30773e042b | ||
| fb44498e53 | |||
| 9f7349ccee | |||
| 9cc41e1c5d | |||
| fc75126ca0 | |||
| d061077b30 | |||
| a3d2176068 | |||
| 98677bc162 | |||
| 398d27d049 | |||
| 8765a3d2c8 | |||
| 1935ed3048 | |||
| 097cf97fc3 | |||
| de99633211 | |||
|
|
028cf8b687 | ||
| e7a3976b14 | |||
| f08954ee43 | |||
| a0321020c7 | |||
| dde24b9739 | |||
| 6e5d358c73 | |||
| c12d985f76 | |||
| 9c126d961b | |||
| 95f16b2842 | |||
| 8f327f7abc | |||
|
|
b7c9f2b201 | ||
| 7f974b7077 | |||
| 78477de2c2 | |||
|
|
75b41379c4 | ||
|
|
d26cc2bef7 | ||
|
|
1abf34d4f0 | ||
|
|
3862b3e934 | ||
|
|
5cf929cca9 | ||
|
|
7e51726a0d | ||
|
|
f05eb61d6e | ||
|
|
5a045ccdef | ||
|
|
bd0fe70f33 | ||
|
|
7c4c9648fe | ||
|
|
5eecae0740 | ||
|
|
a59df60fc2 | ||
|
|
19c5a5bca6 | ||
|
|
c50f1df1e7 | ||
|
|
2a1f3b6b43 | ||
|
|
a208d924dd | ||
|
|
c3b0f7cfe8 | ||
|
|
005f90166e | ||
|
|
73bb90b74b | ||
|
|
6bed600dd4 | ||
|
|
aa3c83933d | ||
|
|
ac1678b1cc | ||
|
|
29db6b0342 | ||
|
|
417de535f3 | ||
|
|
a9564f9a70 | ||
|
|
48c56631ec | ||
|
|
d5f484ac30 | ||
|
|
fc904f8f92 | ||
|
|
6e2f450ee9 | ||
|
|
099b23df74 | ||
|
|
82e043e01d | ||
|
|
7054e2da22 | ||
|
|
dc9e0d9ad7 | ||
|
|
c08629337c | ||
|
|
95bc4e73f5 | ||
|
|
a411562af1 | ||
|
|
27ebbecc01 | ||
|
|
7181c004cb | ||
|
|
012615f984 | ||
|
|
a320b5a7b0 | ||
|
|
ebc67d1327 | ||
|
|
9c2c3d9ce3 | ||
|
|
d36259d121 | ||
|
|
23d6f668bf | ||
|
|
dd445b59f0 | ||
|
|
1a302f605f | ||
|
|
cbe0c512eb | ||
|
|
1e03d4f289 | ||
|
|
ec391f93f6 | ||
|
|
27208c46ec | ||
|
|
c861cf5a79 | ||
|
|
e88c2dd83b | ||
|
|
67f29fcca6 | ||
|
|
ee3910136d | ||
|
|
ab1646f156 | ||
|
|
e13896db28 | ||
|
|
44f551ff77 | ||
|
|
c1cdd4815c | ||
|
|
b52a90dd76 | ||
|
|
a4d0d214dc | ||
|
|
248ec4304d | ||
|
|
4ceec2ca53 | ||
|
|
49a6cb75ff | ||
|
|
6d02ad0bf5 | ||
|
|
0c28eea6e2 | ||
|
|
56c7e2c453 | ||
|
|
cd1b14ff1d | ||
|
|
903b1bad64 | ||
|
|
aa3e14de95 | ||
|
|
fb88d56652 | ||
|
|
a34963ca49 | ||
|
|
8deebbdfa4 | ||
|
|
b23be4b42f | ||
|
|
f7a29b6daa | ||
|
|
080014cbb6 | ||
|
|
d152da31ed | ||
|
|
311bfef3e3 | ||
|
|
bb16b5e968 | ||
|
|
b60fe675c1 | ||
|
|
0e5235b095 | ||
|
|
d5fd7db23c | ||
|
|
3ec31c36b4 | ||
|
|
8d17c282e3 | ||
|
|
35e1c5b609 | ||
|
|
3b2e3ff8a0 | ||
|
|
4b11f6b06d | ||
|
|
791d534653 | ||
|
|
74d98e249d | ||
|
|
3ef002e137 | ||
|
|
c758912cf2 | ||
|
|
18342b7e23 | ||
|
|
1602dd35e3 | ||
|
|
7f72bab06a | ||
|
|
adbd6d0d0e | ||
|
|
2b76cf6a10 | ||
|
|
f975e666ee | ||
|
|
fcd5060485 | ||
|
|
f627e3e22a | ||
|
|
58307bf9cf | ||
|
|
9199af9b68 | ||
|
|
4c871afb73 | ||
|
|
50b1a13c0a |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -215,3 +215,4 @@ tags
|
|||||||
pyvenv.cfg
|
pyvenv.cfg
|
||||||
.venv
|
.venv
|
||||||
pip-selfcheck.json
|
pip-selfcheck.json
|
||||||
|
invoice.xml
|
||||||
@@ -94,6 +94,14 @@ Ready to contribute? Here's how to set up `facho` for local development.
|
|||||||
|
|
||||||
7. Submit a pull request through the GitHub website.
|
7. Submit a pull request through the GitHub website.
|
||||||
|
|
||||||
|
Using docker
|
||||||
|
------------
|
||||||
|
|
||||||
|
1. make -f Makefile.dev build
|
||||||
|
2. make -f Makefile.dev dev-shell
|
||||||
|
3. make -f Makefile.dev python3.8 setup.py develop
|
||||||
|
4. make -f Makefile.dev python3.8 setup.py test
|
||||||
|
|
||||||
Pull Request Guidelines
|
Pull Request Guidelines
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
|||||||
40
Dockerfile
Normal file
40
Dockerfile
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# DERIVADO DE https://alextereshenkov.github.io/run-python-tests-with-tox-in-docker.html
|
||||||
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
|
RUN apt-get -qq update
|
||||||
|
|
||||||
|
RUN apt install software-properties-common -y \
|
||||||
|
&& add-apt-repository ppa:deadsnakes/ppa
|
||||||
|
|
||||||
|
RUN apt-get install -y --no-install-recommends \
|
||||||
|
python3.9 python3.9-distutils python3.9-dev \
|
||||||
|
python3.10 python3.10-distutils python3.10-dev \
|
||||||
|
python3.11 python3.11-distutils python3.11-dev \
|
||||||
|
python3.12 python3-setuptools python3.12-dev \
|
||||||
|
wget \
|
||||||
|
ca-certificates
|
||||||
|
|
||||||
|
RUN wget https://bootstrap.pypa.io/get-pip.py \
|
||||||
|
&& python3.9 get-pip.py pip==23.2.1 --break-system-packages \
|
||||||
|
&& python3.10 get-pip.py pip==23.2.1 --break-system-packages \
|
||||||
|
&& python3.11 get-pip.py pip==23.2.1 --break-system-packages \
|
||||||
|
&& python3.12 get-pip.py pip==23.2.1 --break-system-packages \
|
||||||
|
&& rm get-pip.py
|
||||||
|
|
||||||
|
RUN apt-get install -y --no-install-recommends \
|
||||||
|
libxml2-dev \
|
||||||
|
libxmlsec1-dev \
|
||||||
|
build-essential \
|
||||||
|
zip
|
||||||
|
|
||||||
|
RUN python3.9 --version
|
||||||
|
RUN python3.10 --version
|
||||||
|
RUN python3.11 --version
|
||||||
|
RUN python3.12 --version
|
||||||
|
|
||||||
|
RUN pip3.9 install setuptools setuptools-rust
|
||||||
|
RUN pip3.10 install setuptools setuptools-rust
|
||||||
|
RUN pip3.11 install setuptools setuptools-rust --break-system-packages
|
||||||
|
RUN pip3.12 install setuptools setuptools-rust --break-system-packages
|
||||||
|
|
||||||
|
RUN pip3 install tox pytest --break-system-packages
|
||||||
21
Makefile.dev
Normal file
21
Makefile.dev
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Entorno de desarrollo
|
||||||
|
#
|
||||||
|
# solo es necesario una vez:
|
||||||
|
# * make -f Makefile.dev dev-setup
|
||||||
|
#
|
||||||
|
# luego se pueden ejecutar las pruebas:
|
||||||
|
# * make -f Makefile.dev test
|
||||||
|
|
||||||
|
.PHONY: dev-setup dev-shell py-develop test tox
|
||||||
|
|
||||||
|
dev-setup:
|
||||||
|
docker build -t facho .
|
||||||
|
|
||||||
|
dev-shell:
|
||||||
|
docker run --rm -ti -v "$(PWD):/app" -w /app --name facho-cli facho bash
|
||||||
|
|
||||||
|
test:
|
||||||
|
docker run -t -v $(PWD):/app -w /app facho sh -c 'cd /app; python3.12 setup.py test'
|
||||||
|
|
||||||
|
tox:
|
||||||
|
docker run -it -v $(PWD)/:/app -w /app facho tox
|
||||||
Binary file not shown.
14706
docs/DIAN/nomina/Anexo Tecnico 11-02-2021.pdf
Normal file
14706
docs/DIAN/nomina/Anexo Tecnico 11-02-2021.pdf
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
13
docs/DIAN/nomina/README.md
Normal file
13
docs/DIAN/nomina/README.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# notas
|
||||||
|
|
||||||
|
* se extrae documento tecnico de resolucion usando **pdfarranger**
|
||||||
|
|
||||||
|
## CUNE
|
||||||
|
|
||||||
|
ver 8.1.1.1 del archivo **Resolucion 000013 de 11-02-2021.pdf**
|
||||||
|
|
||||||
|
# enlaces
|
||||||
|
|
||||||
|
* https://www.dian.gov.co/impuestos/Paginas/Sistema-de-Factura-Electronica/documento-soporte-de-pago-de-nomina-electronica.aspx
|
||||||
|
* https://bitbucket.org/presik/electronic_payroll.git
|
||||||
|
* https://bitbucket.org/presik/trytonpsk-staff_payroll_co.git
|
||||||
BIN
docs/DIAN/nomina/Resolución 000013 de 11-02-2021.pdf
Normal file
BIN
docs/DIAN/nomina/Resolución 000013 de 11-02-2021.pdf
Normal file
Binary file not shown.
@@ -14,7 +14,7 @@ from facho.fe import fe
|
|||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
|
|
||||||
# Datos del fomulario del SET de pruebas
|
# Datos del fomulario del SET de pruebas
|
||||||
INVOICE_AUTHORIZATION = '181360000001' #Número suministrado por la Dian en el momento de la creación del SET de Pruebas
|
INVOICE_AUTHORIZATION = '181360000001' # Número suministrado por la Dian en el momento de la creación del SET de Pruebas
|
||||||
ID_SOFTWARE = '57bcb6d1-c591-5a90-b80a-cb030ec91440' #Id suministrado por la Dian en el momento de la creación del SET de Pruebas
|
ID_SOFTWARE = '57bcb6d1-c591-5a90-b80a-cb030ec91440' #Id suministrado por la Dian en el momento de la creación del SET de Pruebas
|
||||||
PIN = '19642' #Número creado por la empresa para poder crear el SET de pruebas
|
PIN = '19642' #Número creado por la empresa para poder crear el SET de pruebas
|
||||||
CLAVE_TECNICA = 'fc9eac422eba16e21ffd8c5f94b3f30a6e38162d' ##Id suministrado por la Dian en el momento de la creación del SET de Pruebas
|
CLAVE_TECNICA = 'fc9eac422eba16e21ffd8c5f94b3f30a6e38162d' ##Id suministrado por la Dian en el momento de la creación del SET de Pruebas
|
||||||
@@ -36,6 +36,7 @@ def extensions(inv):
|
|||||||
'SETP', 990000000, 995000000)#del SET de pruebas
|
'SETP', 990000000, 995000000)#del SET de pruebas
|
||||||
return [security_code, authorization_provider, cufe, software_provider, inv_authorization]
|
return [security_code, authorization_provider, cufe, software_provider, inv_authorization]
|
||||||
|
|
||||||
|
|
||||||
def invoice():
|
def invoice():
|
||||||
# factura de venta nacional
|
# factura de venta nacional
|
||||||
inv = form.Invoice('01')
|
inv = form.Invoice('01')
|
||||||
@@ -49,16 +50,17 @@ def invoice():
|
|||||||
inv.set_operation_type('10')
|
inv.set_operation_type('10')
|
||||||
inv.set_supplier(form.Party(
|
inv.set_supplier(form.Party(
|
||||||
legal_name = 'Nombre registrado de la empresa',
|
legal_name = 'Nombre registrado de la empresa',
|
||||||
name = 'Nombre comercial o él mismo nombre registrado',
|
name='Nombre comercial o él mismo nombre registrado',
|
||||||
ident = form.PartyIdentification('nit_empresa', 'digito_verificación', '31'),
|
ident=form.PartyIdentification(
|
||||||
|
'nit_empresa', 'digito_verificación', '31'),
|
||||||
# obligaciones del contribuyente ver DIAN:FAK26
|
# obligaciones del contribuyente ver DIAN:FAK26
|
||||||
responsability_code = form.Responsability(['O-07', 'O-14', 'O-48']),
|
responsability_code=form.Responsability(['ZZ', 'O-14', 'O-48']),
|
||||||
# ver DIAN:FAJ28
|
# ver DIAN:FAJ28
|
||||||
responsability_regime_code = '48',
|
responsability_regime_code='48',
|
||||||
# tipo de organizacion juridica ver DIAN:6.2.3
|
# tipo de organizacion juridica ver DIAN:6.2.3
|
||||||
organization_code = '1',
|
organization_code='1',
|
||||||
email = "correoempresa@correoempresa.correo",
|
email="correoempresa@correoempresa.correo",
|
||||||
address = form.Address(
|
address=form.Address(
|
||||||
'', '', form.City('05001', 'Medellín'),
|
'', '', form.City('05001', 'Medellín'),
|
||||||
form.Country('CO', 'Colombia'),
|
form.Country('CO', 'Colombia'),
|
||||||
form.CountrySubentity('05', 'Antioquia')),
|
form.CountrySubentity('05', 'Antioquia')),
|
||||||
@@ -76,42 +78,43 @@ def invoice():
|
|||||||
'', '', form.City('05001', 'Medellín'),
|
'', '', form.City('05001', 'Medellín'),
|
||||||
form.Country('CO', 'Colombia'),
|
form.Country('CO', 'Colombia'),
|
||||||
form.CountrySubentity('05', 'Antioquia')),
|
form.CountrySubentity('05', 'Antioquia')),
|
||||||
#tax_scheme = form.TaxScheme('01', 'IVA')
|
# tax_scheme = form.TaxScheme('01', 'IVA')
|
||||||
))
|
))
|
||||||
# asignar metodo de pago
|
# asignar metodo de pago
|
||||||
inv.set_payment_mean(form.PaymentMean(
|
inv.set_payment_mean(form.PaymentMean(
|
||||||
# metodo de pago ver DIAN:3.4.1
|
# metodo de pago ver DIAN:3.4.1
|
||||||
id = '1',
|
id='1',
|
||||||
# codigo correspondiente al medio de pago ver DIAN:3.4.2
|
# codigocorrespondientealmediodepagoverDIAN:3.4.2
|
||||||
code = '20',
|
code='20',
|
||||||
# fecha de vencimiento de la factura
|
# fechadevencimientodelafactura
|
||||||
due_at = datetime.now(),
|
due_at=datetime.now(),
|
||||||
# identificador numerico
|
# identificadornumerico
|
||||||
payment_id = '2'
|
payment_id='2'
|
||||||
))
|
))
|
||||||
# adicionar una linea al documento
|
# adicionar una linea al documento
|
||||||
inv.add_invoice_line(form.InvoiceLine(
|
inv.add_invoice_line(
|
||||||
quantity = form.Quantity(int(20.5), '94'),
|
form.InvoiceLine(
|
||||||
# item general de codigo 999
|
quantity=form.Quantity(int(20.5), '94'),
|
||||||
description = 'productO3',
|
# item general de codigo 999
|
||||||
item = form.StandardItem('test', 9999),
|
description='productO3',
|
||||||
price = form.Price(
|
sitem=form.StandardItem('test', 9999),
|
||||||
# precio base del item (sin iva)
|
price=form.Price(
|
||||||
amount = form.Amount(200.00),
|
# precio base del item (sin iva)
|
||||||
# ver DIAN:6.3.5.1
|
amount=form.Amount(200.00),
|
||||||
type_code = '01',
|
# ver DIAN:6.3.5.1
|
||||||
type = 'x'
|
type_code='01',
|
||||||
),
|
type='x'
|
||||||
tax = form.TaxTotal(
|
),
|
||||||
subtotals = [
|
tax=form.TaxTotal(
|
||||||
form.TaxSubTotal(
|
subtotals=[
|
||||||
percent = 19.00,
|
form.TaxSubTotal(
|
||||||
scheme=form.TaxScheme('01')
|
percent=19.00,
|
||||||
)
|
scheme=form.TaxScheme('01')
|
||||||
]
|
)]
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
return inv
|
return inv
|
||||||
|
|
||||||
|
|
||||||
def document_xml():
|
def document_xml():
|
||||||
return form_xml.DIANInvoiceXML
|
return form_xml.DIANInvoiceXML
|
||||||
|
|||||||
93
examples/generate-nomina-from-cli.py
Normal file
93
examples/generate-nomina-from-cli.py
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
|
||||||
|
from facho import fe
|
||||||
|
|
||||||
|
def extensions(nomina):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def nomina():
|
||||||
|
nomina = fe.nomina.DIANNominaIndividual()
|
||||||
|
|
||||||
|
nomina.asignar_metadata(fe.nomina.Metadata(
|
||||||
|
secuencia=fe.nomina.NumeroSecuencia(
|
||||||
|
numero = 'N00001',
|
||||||
|
consecutivo=232
|
||||||
|
),
|
||||||
|
lugar_generacion=fe.nomina.Lugar(
|
||||||
|
pais = fe.nomina.Pais(
|
||||||
|
code = 'CO'
|
||||||
|
),
|
||||||
|
departamento = fe.nomina.Departamento(
|
||||||
|
code = '05'
|
||||||
|
),
|
||||||
|
municipio = fe.nomina.Municipio(
|
||||||
|
code = '05001'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
proveedor=fe.nomina.Proveedor(
|
||||||
|
nit='999999',
|
||||||
|
dv=2,
|
||||||
|
software_id='xx',
|
||||||
|
software_sc='yy'
|
||||||
|
)
|
||||||
|
))
|
||||||
|
|
||||||
|
nomina.asignar_informacion_general(fe.nomina.InformacionGeneral(
|
||||||
|
fecha_generacion = '2020-01-16',
|
||||||
|
hora_generacion = '1053:10-05:00',
|
||||||
|
tipo_ambiente = fe.nomina.InformacionGeneral.AMBIENTE_PRODUCCION,
|
||||||
|
software_pin = '693',
|
||||||
|
periodo_nomina = fe.nomina.PeriodoNomina(code='1'),
|
||||||
|
tipo_moneda = fe.nomina.TipoMoneda(code='COP')
|
||||||
|
))
|
||||||
|
|
||||||
|
nomina.asignar_empleador(fe.nomina.Empleador(
|
||||||
|
nit = '700085371',
|
||||||
|
dv = '1',
|
||||||
|
pais = fe.nomina.Pais(
|
||||||
|
code = 'CO'
|
||||||
|
),
|
||||||
|
departamento = fe.nomina.Departamento(
|
||||||
|
code = '05'
|
||||||
|
),
|
||||||
|
municipio = fe.nomina.Municipio(
|
||||||
|
code = '05001'
|
||||||
|
),
|
||||||
|
direccion = 'calle etrivial'
|
||||||
|
))
|
||||||
|
|
||||||
|
nomina.asignar_trabajador(fe.nomina.Trabajador(
|
||||||
|
tipo_contrato = fe.nomina.TipoContrato(
|
||||||
|
code = '1'
|
||||||
|
),
|
||||||
|
alto_riesgo = False,
|
||||||
|
tipo_documento = fe.nomina.TipoDocumento(
|
||||||
|
code = '11'
|
||||||
|
),
|
||||||
|
primer_apellido = 'gnu',
|
||||||
|
segundo_apellido = 'emacs',
|
||||||
|
primer_nombre = 'facho',
|
||||||
|
lugar_trabajo = fe.nomina.LugarTrabajo(
|
||||||
|
pais = fe.nomina.Pais(code='CO'),
|
||||||
|
departamento = fe.nomina.Departamento(code='05'),
|
||||||
|
municipio = fe.nomina.Municipio(code='05001'),
|
||||||
|
direccion = 'calle facho'
|
||||||
|
),
|
||||||
|
numero_documento = '800199436',
|
||||||
|
tipo = fe.nomina.TipoTrabajador(
|
||||||
|
code = '01'
|
||||||
|
),
|
||||||
|
salario_integral = True,
|
||||||
|
sueldo = fe.nomina.Amount(1_500_000)
|
||||||
|
))
|
||||||
|
|
||||||
|
nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
|
||||||
|
dias_trabajados = 60,
|
||||||
|
sueldo_trabajado = fe.nomina.Amount(3_500_000)
|
||||||
|
))
|
||||||
|
|
||||||
|
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||||
|
porcentaje = fe.nomina.Amount(19),
|
||||||
|
deduccion = fe.nomina.Amount(1_000_000)
|
||||||
|
))
|
||||||
|
|
||||||
|
return nomina
|
||||||
@@ -1,109 +1,127 @@
|
|||||||
# importar libreria de modelos
|
# importar libreria de modelos
|
||||||
|
from facho import fe, form_xml
|
||||||
import facho.fe.form as form
|
import facho.fe.form as form
|
||||||
import facho.fe.form_xml
|
import datetime
|
||||||
|
|
||||||
|
PRIVATE_KEY_PATH = 'ruta a mi llave privada'
|
||||||
|
PRIVATE_PASSPHRASE = 'clave de la llave privada'
|
||||||
|
|
||||||
PRIVATE_KEY_PATH='ruta a mi llave privada'
|
|
||||||
PRIVATE_PASSPHRASE='clave de la llave privada'
|
|
||||||
|
|
||||||
# consultar las extensiones necesarias
|
# consultar las extensiones necesarias
|
||||||
def extensions(inv):
|
def extensions(inv):
|
||||||
security_code = fe.DianXMLExtensionSoftwareSecurityCode('id software', 'pin', inv.invoice_ident)
|
security_code = fe.DianXMLExtensionSoftwareSecurityCode(
|
||||||
|
'id software', 'pin', inv.invoice_ident)
|
||||||
authorization_provider = fe.DianXMLExtensionAuthorizationProvider()
|
authorization_provider = fe.DianXMLExtensionAuthorizationProvider()
|
||||||
cufe = fe.DianXMLExtensionCUFE(inv, fe.DianXMLExtensionCUFE.AMBIENTE_PRUEBAS,
|
cufe = fe.DianXMLExtensionCUFE(
|
||||||
'clave tecnica')
|
inv, fe.DianXMLExtensionCUFE.AMBIENTE_PRUEBAS,
|
||||||
|
'clave tecnica')
|
||||||
nit = form.PartyIdentification('nit', '5', '31')
|
nit = form.PartyIdentification('nit', '5', '31')
|
||||||
software_provider = fe.DianXMLExtensionSoftwareProvider(nit, nit.dv, 'id software')
|
software_provider = fe.DianXMLExtensionSoftwareProvider(
|
||||||
inv_authorization = fe.DianXMLExtensionInvoiceAuthorization('invoice autorization',
|
nit, nit.dv, 'id software')
|
||||||
datetime(2019, 1, 19),
|
inv_authorization = fe.DianXMLExtensionInvoiceAuthorization(
|
||||||
datetime(2030, 1, 19),
|
'invoice autorization',
|
||||||
'SETP', 990000001, 995000000)
|
datetime(2019, 1, 19),
|
||||||
return [security_code, authorization_provider, cufe, software_provider, inv_authorization]
|
datetime(2030, 1, 19),
|
||||||
|
'SETP', 990000001, 995000000)
|
||||||
|
return [
|
||||||
|
security_code,
|
||||||
|
authorization_provider,
|
||||||
|
cufe, software_provider,
|
||||||
|
inv_authorization
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# generar documento desde modelo a ruta indicada
|
# generar documento desde modelo a ruta indicada
|
||||||
def generate_document(invoice, filepath):
|
def generate_document(invoice, filepath):
|
||||||
xml = form_xml.DIANInvoiceXML(invoice)
|
xml = form_xml.DIANInvoiceXML(invoice)
|
||||||
for extension in extensions(invoice):
|
for extension in extensions(invoice):
|
||||||
xml.add_extension(extension)
|
xml.add_extension(extension)
|
||||||
form_xml.utils.DIANWriteSigned(xml, filepath, PRIVATE_KEY_PATH, PRIVATE_PASSPHRASE, True)
|
form_xml.utils.DIANWriteSigned(
|
||||||
|
xml, filepath, PRIVATE_KEY_PATH, PRIVATE_PASSPHRASE, True)
|
||||||
|
|
||||||
|
|
||||||
# Modelars las facturas
|
# Modelars las facturas
|
||||||
# ...
|
# ...
|
||||||
|
|
||||||
# factura de venta nacional
|
# factura de venta nacional
|
||||||
inv = form.NationalSalesInvoice()
|
inv = form.NationalSalesInvoice()
|
||||||
|
|
||||||
# asignar periodo de facturacion
|
# asignar periodo de facturacion
|
||||||
inv.set_period(datetime.now(), datetime.now())
|
inv.set_period(datetime.now(), datetime.now())
|
||||||
|
|
||||||
# asignar fecha de emision de la factura
|
# asignar fecha de emision de la factura
|
||||||
|
|
||||||
inv.set_issue(datetime.now())
|
inv.set_issue(datetime.now())
|
||||||
# asignar prefijo y numero del documento
|
# asignar prefijo y numero del documento
|
||||||
|
|
||||||
inv.set_ident('SETP990003033')
|
inv.set_ident('SETP990003033')
|
||||||
# asignar tipo de operacion ver DIAN:6.1.5
|
# asignar tipo de operacion ver DIAN:6.1.5
|
||||||
inv.set_operation_type('10')
|
inv.set_operation_type('10')
|
||||||
|
|
||||||
# asignar proveedor
|
# asignar proveedor
|
||||||
inv.set_supplier(form.Party(
|
inv.set_supplier(form.Party(
|
||||||
legal_name = 'FACHO SOS',
|
legal_name='FACHOSOS',
|
||||||
name = 'FACHO SOS',
|
name='FACHOSOS',
|
||||||
ident = form.PartyIdentification('900579212', '5', '31'),
|
ident=form.PartyIdentification('900579212', '5', '31'),
|
||||||
# obligaciones del contribuyente ver DIAN:FAK26
|
# obligaciones del contribuyente ver DIAN:FAK26
|
||||||
responsability_code = form.Responsability(['O-07', 'O-09', 'O-14', 'O-48']),
|
responsability_code=form.Responsability(['ZZ', 'O-09', 'O-14', 'O-48']),
|
||||||
# ver DIAN:FAJ28
|
# ver DIAN:FAJ28
|
||||||
responsability_regime_code = '48',
|
responsability_regime_code='48',
|
||||||
# tipo de organizacion juridica ver DIAN:6.2.3
|
# tipo de organizacion juridica ver DIAN:6.2.3
|
||||||
organization_code = '1',
|
organization_code='1',
|
||||||
email = "sdds@sd.com",
|
email="sdds@sd.com",
|
||||||
address = form.Address(
|
address=form.Address(
|
||||||
name = '',
|
name='',
|
||||||
street = '',
|
street='',
|
||||||
city = form.City('05001', 'Medellín'),
|
city=form.City('05001', 'Medellín'),
|
||||||
country = form.Country('CO', 'Colombia'),
|
country=form.Country('CO', 'Colombia'),
|
||||||
countrysubentity = form.CountrySubentity('05', 'Antioquia'))
|
countrysubentity=form.CountrySubentity('05', 'Antioquia'))
|
||||||
))
|
))
|
||||||
|
|
||||||
inv.set_customer(form.Party(
|
inv.set_customer(form.Party(
|
||||||
legal_name = 'facho-customer',
|
legal_name='facho-customer',
|
||||||
name = 'facho-customer',
|
name='facho-customer',
|
||||||
ident = form.PartyIdentification('999999999', '', '13'),
|
ident=form.PartyIdentification('999999999', '', '13'),
|
||||||
responsability_code = form.Responsability(['R-99-PN']),
|
responsability_code=form.Responsability(['R-99-PN']),
|
||||||
responsability_regime_code = '49',
|
responsability_regime_code='49',
|
||||||
organization_code = '2',
|
organization_code='2',
|
||||||
email = "sdds@sd.com",
|
email="sdds@sd.com",
|
||||||
address = form.Address(
|
address=form.Address(
|
||||||
name = '',
|
name='',
|
||||||
street = '',
|
street='',
|
||||||
city = form.City('05001', 'Medellín'),
|
city=form.City('05001', 'Medellín'),
|
||||||
country = form.Country('CO', 'Colombia'),
|
country=form.Country('CO', 'Colombia'),
|
||||||
countrysubentity = form.CountrySubentity('05', 'Antioquia'))
|
countrysubentity=form.CountrySubentity('05', 'Antioquia'))
|
||||||
))
|
))
|
||||||
# asignar metodo de pago
|
# asignar metodo de pago
|
||||||
inv.set_payment_mean(form.PaymentMean(
|
inv.set_payment_mean(form.PaymentMean(
|
||||||
# metodo de pago ver DIAN:3.4.1
|
# metodo de pago ver DIAN:3.4.1
|
||||||
id = '1',
|
id='1',
|
||||||
# codigo correspondiente al medio de pago ver DIAN:3.4.2
|
# codigo correspondiente al medio de pago ver DIAN:3.4.2
|
||||||
code = '10',
|
code='10',
|
||||||
# fecha de vencimiento de la factura
|
# fecha de vencimiento de la factura
|
||||||
due_at = datetime.now(),
|
due_at=datetime.now(),
|
||||||
|
|
||||||
# identificador numerico
|
# identificador numerico
|
||||||
payment_id = '1'
|
payment_id='1'
|
||||||
))
|
))
|
||||||
# adicionar una linea al documento
|
# adicionar una linea al documento
|
||||||
inv.add_invoice_line(form.InvoiceLine(
|
inv.add_invoice_line(form.InvoiceLine(
|
||||||
quantity = form.Quantity(1, '94'),
|
quantity=form.Quantity(1, '94'),
|
||||||
description = 'producto facho',
|
description='producto facho',
|
||||||
# item general de codigo 999
|
# item general de codigo 999
|
||||||
item = form.StandardItem('test', 9999),
|
item=form.StandardItem('test', 9999),
|
||||||
price = form.Price(
|
price=form.Price(
|
||||||
# precio base del tiem
|
# precio base del tiem
|
||||||
amount = form.Amount(100.00),
|
amount=form.Amount(100.00),
|
||||||
# ver DIAN:6.3.5.1
|
# ver DIAN:6.3.5.1
|
||||||
type_code = '01',
|
type_code='01',
|
||||||
type = 'x'
|
type='x'
|
||||||
),
|
),
|
||||||
tax = form.TaxTotal(
|
tax=form.TaxTotal(
|
||||||
subtotals = [
|
subtotals=[
|
||||||
form.TaxSubTotal(
|
form.TaxSubTotal(
|
||||||
percent = 19.00,
|
percent=19.00,
|
||||||
)
|
)]
|
||||||
]
|
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|||||||
0
experimental/facho-signer/AUTHORS
Normal file
0
experimental/facho-signer/AUTHORS
Normal file
674
experimental/facho-signer/COPYING
Normal file
674
experimental/facho-signer/COPYING
Normal file
@@ -0,0 +1,674 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
facho-signer Copyright (C) 2021 Jovany Leandro G.C <bit4bit@riseup.net>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||||
0
experimental/facho-signer/ChangeLog
Normal file
0
experimental/facho-signer/ChangeLog
Normal file
1
experimental/facho-signer/Makefile.am
Normal file
1
experimental/facho-signer/Makefile.am
Normal file
@@ -0,0 +1 @@
|
|||||||
|
SUBDIRS = src
|
||||||
0
experimental/facho-signer/NEWS
Normal file
0
experimental/facho-signer/NEWS
Normal file
0
experimental/facho-signer/README
Normal file
0
experimental/facho-signer/README
Normal file
3
experimental/facho-signer/boostrap.sh
Normal file
3
experimental/facho-signer/boostrap.sh
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
libtoolize -c --force
|
||||||
|
autoreconf --install --force
|
||||||
56
experimental/facho-signer/configure.ac
Normal file
56
experimental/facho-signer/configure.ac
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# -*- Autoconf -*-
|
||||||
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
|
AC_PREREQ([2.71])
|
||||||
|
AC_INIT([facho-signer], [0.0.1], [bit4bit@riseup.net])
|
||||||
|
AM_INIT_AUTOMAKE
|
||||||
|
AC_CONFIG_SRCDIR([src/facho_signer.c])
|
||||||
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
AC_CONFIG_MACRO_DIRS([m4])
|
||||||
|
|
||||||
|
# Checks for programs.
|
||||||
|
AC_PROG_CC
|
||||||
|
|
||||||
|
# Checks for libraries.
|
||||||
|
PKG_CHECK_MODULES([OPENSSL], [openssl])
|
||||||
|
PKG_CHECK_MODULES([XMLSEC1], [xmlsec1-openssl], [
|
||||||
|
AC_DEFINE([XMLSEC_CRYPTO_OPENSSL], [1], [enable crypto openssl])
|
||||||
|
])
|
||||||
|
PKG_CHECK_MODULES([LZMA], [liblzma])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([xmlsec-crypto-dynamic-loading],
|
||||||
|
AS_HELP_STRING([--enable-xmlsec-crypto-dynamic-loading],
|
||||||
|
[enable crypto xmlsec dynamic loading])
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "x$enable_xmlsec_crypto_dynamic_loading" == xyes; then
|
||||||
|
AC_DEFINE([XMLSEC_CRYPTO_DYNAMIC_LOADING], [1], [enable xmlsec crypto dynamic loading])
|
||||||
|
AC_CHECK_HEADER([ltdl.h], [
|
||||||
|
AC_CHECK_LIB(
|
||||||
|
[ltdl],
|
||||||
|
[lt_dlopenext],
|
||||||
|
[LIBLTDL=-lltdl],
|
||||||
|
[LIBLTDL=]
|
||||||
|
)
|
||||||
|
], [ LIBLTDL= ])
|
||||||
|
|
||||||
|
else
|
||||||
|
AC_DEFINE([XMLSEC_NO_CRYPTO_DYNAMIC_LOADING], [1], [disable xmlsec crypto dynamic loading])
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Checks for header files.
|
||||||
|
AC_CHECK_HEADERS([sys/time.h unistd.h])
|
||||||
|
|
||||||
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
|
||||||
|
# Checks for library functions.
|
||||||
|
AC_FUNC_MALLOC
|
||||||
|
AC_CHECK_FUNCS([clock_gettime gethrtime gettimeofday memset strdup])
|
||||||
|
|
||||||
|
# libtool
|
||||||
|
|
||||||
|
LT_INIT
|
||||||
|
|
||||||
|
AC_CONFIG_FILES([Makefile src/Makefile])
|
||||||
|
AC_OUTPUT
|
||||||
12
experimental/facho-signer/src/Makefile.am
Normal file
12
experimental/facho-signer/src/Makefile.am
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
SOURCES = xades/xmlsec1/xmltree.c xades/xmlsec1/errors.c xades/templates.c xades/xades.c facho_signer.c
|
||||||
|
|
||||||
|
lib_LTLIBRARIES = libfachosigner.la
|
||||||
|
libfachosigner_la_SOURCES = $(LTDL_SOURCE_FILES) $(SOURCES)
|
||||||
|
libfachosigner_la_CFLAGS = $(OPENSSL_CFLAGS) $(XMLSEC1_CFLAGS) -DXMLSEC_NOT_CRYPTO_DYNAMIC_LOADING
|
||||||
|
libfachosigner_la_LDFLAGS = $(OPENSSL_LIBS) $(LIBLTDL) $(XMLSEC1_LIBS)
|
||||||
|
|
||||||
|
bin_PROGRAMS = facho_signer
|
||||||
|
facho_signer_SOURCES = main.c
|
||||||
|
facho_signer_CFLAGS = $(OPENSSL_CFLAGS) $(XMLSEC1_CFLAGS) -DXMLSEC_NOT_CRYPTO_DYNAMIC_LOADING
|
||||||
|
facho_signer_LDADD = libfachosigner.la
|
||||||
|
|
||||||
11
experimental/facho-signer/src/README.md
Normal file
11
experimental/facho-signer/src/README.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# facho-signer
|
||||||
|
|
||||||
|
|
||||||
|
## guia
|
||||||
|
|
||||||
|
- http://xmlsoft.org/html/libxml-tree.html
|
||||||
|
- http://xmlsoft.org/html/libxml-xpath.html
|
||||||
|
- http://xmlsoft.org/examples/xpath1.c
|
||||||
|
- http://xmlsoft.org/tutorial/ar01s05.html
|
||||||
|
- https://www.aleksey.com/xmlsec/api/xmlsec-reference.html
|
||||||
|
- https://zakird.com/2013/10/13/certificate-parsing-with-openssl
|
||||||
371
experimental/facho-signer/src/facho_signer.c
Normal file
371
experimental/facho-signer/src/facho_signer.c
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of facho. The COPYRIGHT file at the top level of
|
||||||
|
* this repository contains the full copyright notices and license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "xades/xades.h"
|
||||||
|
|
||||||
|
#include <xmlsec/xmlsec.h>
|
||||||
|
#include <xmlsec/xmltree.h>
|
||||||
|
#include <xmlsec/xmldsig.h>
|
||||||
|
#include <xmlsec/templates.h>
|
||||||
|
#include <xmlsec/crypto.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define xmlFachoPrintError(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
|
||||||
|
#define xmlFachoPrintInfo(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
static const xmlChar ublExtensionDSigNs[] = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2";
|
||||||
|
static const xmlChar policyIdDescription[] = "Política de firma para facturas electrónicas de la República de Colombia.";
|
||||||
|
static const xmlChar policyIdIdentifier[] = "https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf";
|
||||||
|
|
||||||
|
// crea elemento /Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent
|
||||||
|
static xmlNodePtr
|
||||||
|
xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc);
|
||||||
|
|
||||||
|
// FeC requiere que el digest value del policy identifier sea
|
||||||
|
// apartir del contenido de la url.
|
||||||
|
static int
|
||||||
|
xmlFachoPolicyIdentifierCtxFromFilename(const xmlChar *, xmlSecBufferPtr);
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
xmlFachoTmplXadesCreate(xmlDocPtr doc, xmlNodePtr signNode) {
|
||||||
|
xmlNodePtr qualifyingPropertiesNode = NULL;
|
||||||
|
xmlNodePtr signedPropertiesNode = NULL;
|
||||||
|
xmlNodePtr signedSignaturePropertiesNode = NULL;
|
||||||
|
xmlNodePtr signingCertificateNode = NULL;
|
||||||
|
xmlNodePtr signaturePolicyIdentifierNode = NULL;
|
||||||
|
xmlNodePtr signaturePolicyIdNode = NULL;
|
||||||
|
xmlNodePtr sigPolicyIdNode = NULL;
|
||||||
|
xmlNodePtr sigPolicyHashNode = NULL;
|
||||||
|
xmlNodePtr signerRoleNode = NULL;
|
||||||
|
xmlNodePtr refNode = NULL;
|
||||||
|
const xmlChar signedPropertiesId[] = "xmldsig-facho-signed-props";
|
||||||
|
const xmlChar signedPropertiesRef[] = "#xmldsig-facho-signed-props";
|
||||||
|
|
||||||
|
qualifyingPropertiesNode = xmlXadesTmplQualifyingPropertiesCreate(doc, signNode, BAD_CAST "xades-ref1");
|
||||||
|
if ( qualifyingPropertiesNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add QualifyingProperties node.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
signedPropertiesNode = xmlXadesTmplAddSignedProperties(qualifyingPropertiesNode, signedPropertiesId);
|
||||||
|
if ( signedPropertiesNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: xades failed to add signed properties node.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
refNode = xmlSecTmplSignatureAddReference(signNode,
|
||||||
|
xmlSecTransformSha256Id,
|
||||||
|
BAD_CAST "xmldsig-facho-ref1",
|
||||||
|
signedPropertiesRef,
|
||||||
|
BAD_CAST "http://uri.etsi.org/01903#SignedProperties");
|
||||||
|
if ( refNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add reference to signature template xades.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if ( xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformInclC14NId) == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add enveloped transform to reference for xades\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
const time_t now = time(NULL);
|
||||||
|
signedSignaturePropertiesNode = xmlXadesTmplAddSignedSignatureProperties(signedPropertiesNode, localtime(&now));
|
||||||
|
if ( signedSignaturePropertiesNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: xades failed to add signed signature properties node.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
signingCertificateNode = xmlXadesTmplAddSigningCertificate(signedSignaturePropertiesNode, xmlSecTransformSha256Id);
|
||||||
|
if ( signingCertificateNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add SigningCertificate node \n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
signaturePolicyIdentifierNode = xmlXadesTmplAddSignaturePolicyIdentifier(signedSignaturePropertiesNode);
|
||||||
|
if ( signaturePolicyIdentifierNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add PolicyIdentifier node\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
signaturePolicyIdNode = xmlXadesTmplAddSignaturePolicyId(signaturePolicyIdentifierNode);
|
||||||
|
if ( signaturePolicyIdNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add SignaturePolicyId node.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigPolicyIdNode = xmlXadesTmplAddSigPolicyId(signaturePolicyIdNode, policyIdIdentifier, policyIdDescription);
|
||||||
|
if ( sigPolicyIdNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add SigPolicyId node.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigPolicyHashNode = xmlXadesTmplAddSigPolicyHash(signaturePolicyIdNode, xmlSecTransformSha256Id);
|
||||||
|
if ( sigPolicyHashNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add SigPolicyHash node.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
signerRoleNode = xmlXadesTmplAddSignerRole(signedSignaturePropertiesNode, BAD_CAST "supplier");
|
||||||
|
if ( signerRoleNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add SignerRole node.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
fail:
|
||||||
|
xmlUnlinkNode(qualifyingPropertiesNode);
|
||||||
|
xmlFreeNode(qualifyingPropertiesNode);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xmlFachoInit() {
|
||||||
|
xmlInitParser();
|
||||||
|
LIBXML_TEST_VERSION;
|
||||||
|
|
||||||
|
if ( xmlSecInit() < 0 ) {
|
||||||
|
xmlFachoPrintError("xmlsec initialization failed.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlSecCheckVersion() != 1 ) {
|
||||||
|
xmlFachoPrintError("loaded xmlsec library version is not compatible.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
|
||||||
|
if(xmlSecCryptoDLLoadLibrary( NULL ) < 0) {
|
||||||
|
fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
|
||||||
|
"that you have it installed and check shared libraries path\n"
|
||||||
|
"(LD_LIBRARY_PATH and/or LTDL_LIBRARY_PATH) environment variables.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
|
||||||
|
|
||||||
|
if ( xmlSecCryptoAppInit(NULL) < 0 ) {
|
||||||
|
xmlFachoPrintError("crypto initialization failed.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlSecCryptoInit() < 0 ) {
|
||||||
|
xmlFachoPrintError("xmlsec-crypto initialization failed.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xmlFachoShutdown() {
|
||||||
|
|
||||||
|
if ( xmlSecCryptoShutdown() < 0 ) {
|
||||||
|
xmlFachoPrintError("xmlSecCryptoShutdown failed.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlSecCryptoAppShutdown() < 0 ) {
|
||||||
|
xmlFachoPrintError("xmlSecCryptoAppShutdown failed.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlSecShutdown() < 0 ) {
|
||||||
|
xmlFachoPrintError("xmlsec shutdown failed.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlCleanupParser();
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xmlFachoSignFile(FILE *out, const char *filename, const char *pkcs12name, const char *password) {
|
||||||
|
xmlDocPtr doc = NULL;
|
||||||
|
xmlNodePtr signNode = NULL;
|
||||||
|
xmlNodePtr refNode = NULL;
|
||||||
|
xmlNodePtr keyInfoNode = NULL;
|
||||||
|
xmlNodePtr x509DataNode = NULL;
|
||||||
|
xmlNodePtr node = NULL;
|
||||||
|
xmlSecDSigCtxPtr dsigCtx = NULL;
|
||||||
|
xmlXadesDSigCtxPtr xadesDsigCtx = NULL;
|
||||||
|
|
||||||
|
int res = -1;
|
||||||
|
|
||||||
|
if (filename == NULL) {
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
doc = xmlParseFile(filename);
|
||||||
|
if ( (doc == NULL) || (xmlDocGetRootElement(doc) == NULL) ) {
|
||||||
|
xmlFachoPrintError("error: unable to parse file %s\n", filename);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
signNode = xmlSecTmplSignatureCreate(doc, xmlSecTransformInclC14NId,
|
||||||
|
xmlSecTransformRsaSha256Id, NULL);
|
||||||
|
if ( signNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to create signature template.\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlAddChild(xmlDocGetRootElement(doc), signNode);
|
||||||
|
|
||||||
|
refNode = xmlSecTmplSignatureAddReference(signNode,
|
||||||
|
xmlSecTransformSha256Id,
|
||||||
|
BAD_CAST "xmldsig-facho-ref0", // id
|
||||||
|
BAD_CAST "", //uri
|
||||||
|
NULL); //type
|
||||||
|
if ( refNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add reference to signature template.\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ( xmlSecTmplReferenceAddTransform(refNode, xmlSecTransformEnvelopedId) == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add enveloped transform to reference\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
refNode = xmlSecTmplSignatureAddReference(signNode,
|
||||||
|
xmlSecTransformSha256Id,
|
||||||
|
BAD_CAST "xmldsig-facho-ref2",
|
||||||
|
BAD_CAST "#xmldsig-facho-KeyInfo",
|
||||||
|
NULL);
|
||||||
|
if ( refNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add reference to signature template key-info.\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(signNode, BAD_CAST "xmldsig-facho-KeyInfo");
|
||||||
|
if ( keyInfoNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add key info.\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
x509DataNode = xmlSecTmplKeyInfoAddX509Data(keyInfoNode);
|
||||||
|
if ( x509DataNode == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failde to add x509 DATA \n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlSecTmplX509DataAddCertificate(x509DataNode) == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failde to add x509Certificate node\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( xmlFachoTmplXadesCreate(doc, signNode) < 0 ){
|
||||||
|
xmlFachoPrintError("error: xmlFachoTmplXadesCreate failed.\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
dsigCtx = xmlSecDSigCtxCreate(NULL);
|
||||||
|
if ( dsigCtx == NULL ) {
|
||||||
|
xmlFachoPrintError("error: dsig context creating failed\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cargamos el archivo pkcs12 con llave privado y certificados x509
|
||||||
|
dsigCtx->signKey = xmlSecCryptoAppKeyLoad(pkcs12name,
|
||||||
|
xmlSecKeyDataFormatPkcs12,
|
||||||
|
password,
|
||||||
|
NULL, NULL);
|
||||||
|
if ( dsigCtx->signKey == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to load pkcs12\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlXadesPolicyIdentifierCtx policyIdCtx;
|
||||||
|
|
||||||
|
// por ahora el hash del identificador lo tomamos del pdf de la dian
|
||||||
|
policyIdCtx.contentCallback = &xmlFachoPolicyIdentifierCtxFromFilename;
|
||||||
|
|
||||||
|
xadesDsigCtx = xmlXadesDSigCtxCreate(dsigCtx, XADES_DIGEST_SHA256, &policyIdCtx);
|
||||||
|
if ( xadesDsigCtx == NULL ) {
|
||||||
|
xmlFachoPrintError("error: xades context creating failed.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// debe existir el elemento antes del firmado
|
||||||
|
node = xmlFachoTmplUBLExtensionAddExtensionContent(doc);
|
||||||
|
if ( node == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add UBLExtensions/UBLExtension/ExtensionContent\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// realizar firma de documento
|
||||||
|
if ( xmlXadesDSigCtxSign(xadesDsigCtx, signNode) < 0 ) {
|
||||||
|
xmlFachoPrintError("error: signature failed\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmlUnlinkNode(signNode);
|
||||||
|
xmlSecAddChildNode(node, signNode);
|
||||||
|
|
||||||
|
xmlDocDump(out, doc);
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
|
||||||
|
done:
|
||||||
|
if ( xadesDsigCtx != NULL ) {
|
||||||
|
xmlXadesDSigCtxDestroy(xadesDsigCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( dsigCtx != NULL ) {
|
||||||
|
xmlSecDSigCtxDestroy(dsigCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( doc != NULL ) {
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
}
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static xmlNodePtr
|
||||||
|
xmlFachoTmplUBLExtensionAddExtensionContent(xmlDocPtr doc) {
|
||||||
|
xmlNodePtr node = NULL;
|
||||||
|
xmlNodePtr parent = NULL;
|
||||||
|
const xmlChar ublExtensionsName[] = "UBLExtensions";
|
||||||
|
const xmlChar ublExtensionName[] = "UBLExtension";
|
||||||
|
const xmlChar extensionContentName[] = "ExtensionContent";
|
||||||
|
|
||||||
|
parent = xmlSecFindNode(xmlDocGetRootElement(doc), ublExtensionsName, ublExtensionDSigNs);
|
||||||
|
if ( parent == NULL ) {
|
||||||
|
parent = xmlSecAddChild(xmlDocGetRootElement(doc), ublExtensionsName, ublExtensionDSigNs);
|
||||||
|
if ( parent == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to cleate UBLExtensions.\n");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// adicionamos nuevo elemento UBLExtension
|
||||||
|
node = xmlSecAddChild(parent, ublExtensionName, ublExtensionDSigNs);
|
||||||
|
if ( node == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add UBLExtension\n");
|
||||||
|
xmlFreeNode(parent);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// adicionamos nuevo elemento ExtensionContent
|
||||||
|
node = xmlSecAddChild(node, extensionContentName, ublExtensionDSigNs);
|
||||||
|
if ( node == NULL ) {
|
||||||
|
xmlFachoPrintError("error: failed to add ExtensionContent");
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
xmlFachoPolicyIdentifierCtxFromFilename(const xmlChar *policyId, xmlSecBufferPtr buffer) {
|
||||||
|
static unsigned char politicafirmav2[] = {
|
||||||
|
/**
|
||||||
|
* generado con https://github.com/Jamesits/bin2array
|
||||||
|
*/
|
||||||
|
#include "politicafirmav2.c"
|
||||||
|
};
|
||||||
|
|
||||||
|
return xmlSecBufferAppend(buffer, politicafirmav2, sizeof(politicafirmav2));
|
||||||
|
}
|
||||||
20
experimental/facho-signer/src/facho_signer.h
Normal file
20
experimental/facho-signer/src/facho_signer.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of facho. The COPYRIGHT file at the top level of
|
||||||
|
* this repository contains the full copyright notices and license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FACHO_SIGNER_H
|
||||||
|
#define FACHO_SIGNER_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
xmlFachoInit();
|
||||||
|
|
||||||
|
int
|
||||||
|
xmlFachoShutdown();
|
||||||
|
|
||||||
|
int
|
||||||
|
xmlFachoSignFile(FILE *out, const char *filename, const char *pkcs12name, const char *password);
|
||||||
|
|
||||||
|
#endif /* FACHO_SIGNER_H */
|
||||||
47
experimental/facho-signer/src/main.c
Normal file
47
experimental/facho-signer/src/main.c
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of facho. The COPYRIGHT file at the top level of
|
||||||
|
* this repository contains the full copyright notices and license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xades/xades.h"
|
||||||
|
#include "facho_signer.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
|
static char *basename = NULL;
|
||||||
|
|
||||||
|
void usage(FILE *out);
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
int exitStatus = EXIT_SUCCESS;
|
||||||
|
basename = argv[0];
|
||||||
|
|
||||||
|
if (argc != 4) {
|
||||||
|
usage(stderr);
|
||||||
|
return(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlFachoInit() < 0 ) {
|
||||||
|
fprintf(stderr, "initialization failed.\n");
|
||||||
|
return(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlFachoSignFile( stdout, argv[1], argv[2], argv[3] ) != 0 ) {
|
||||||
|
fprintf(stderr, "fail to sign file\n");
|
||||||
|
exitStatus = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlFachoShutdown();
|
||||||
|
return(exitStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(FILE *out) {
|
||||||
|
fprintf(out, "%s: <factura.xml> <pc12> <password>\n", basename);
|
||||||
|
fprintf(out, "%s", "Firmado electronico para facturacion en Colombia.\n"
|
||||||
|
"Segun el documento (Anexo Técnico de Factura Electrónica de Venta – Versión 1.7.-2020).\n"
|
||||||
|
"A considerar:\n" \
|
||||||
|
" * adiciona un nuevo elemento //ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent\n");
|
||||||
|
}
|
||||||
1
experimental/facho-signer/src/politicafirmav2.c
Normal file
1
experimental/facho-signer/src/politicafirmav2.c
Normal file
File diff suppressed because one or more lines are too long
391
experimental/facho-signer/src/xades/minunit.h
Normal file
391
experimental/facho-signer/src/xades/minunit.h
Normal file
@@ -0,0 +1,391 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 David Siñuela Pastor, siu.4coders@gmail.com
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef MINUNIT_MINUNIT_H
|
||||||
|
#define MINUNIT_MINUNIT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <Windows.h>
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#define __func__ __FUNCTION__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
|
||||||
|
|
||||||
|
/* Change POSIX C SOURCE version for pure c99 compilers */
|
||||||
|
#if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE < 200112L
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 200112L
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <unistd.h> /* POSIX flags */
|
||||||
|
#include <time.h> /* clock_gettime(), time() */
|
||||||
|
#include <sys/time.h> /* gethrtime(), gettimeofday() */
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <sys/times.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
|
#include <mach/mach.h>
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __GNUC__ >= 5 && !defined(__STDC_VERSION__)
|
||||||
|
#define __func__ __extension__ __FUNCTION__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Unable to define timers for an unknown OS."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* Maximum length of last message */
|
||||||
|
#define MINUNIT_MESSAGE_LEN 1024
|
||||||
|
/* Accuracy with which floats are compared */
|
||||||
|
#define MINUNIT_EPSILON 1E-12
|
||||||
|
|
||||||
|
/* Misc. counters */
|
||||||
|
static int minunit_run = 0;
|
||||||
|
static int minunit_assert = 0;
|
||||||
|
static int minunit_fail = 0;
|
||||||
|
static int minunit_status = 0;
|
||||||
|
|
||||||
|
/* Timers */
|
||||||
|
static double minunit_real_timer = 0;
|
||||||
|
static double minunit_proc_timer = 0;
|
||||||
|
|
||||||
|
/* Last message */
|
||||||
|
static char minunit_last_message[MINUNIT_MESSAGE_LEN];
|
||||||
|
|
||||||
|
/* Test setup and teardown function pointers */
|
||||||
|
static void (*minunit_setup)(void) = NULL;
|
||||||
|
static void (*minunit_teardown)(void) = NULL;
|
||||||
|
|
||||||
|
/* Definitions */
|
||||||
|
#define MU_TEST(method_name) static void method_name(void)
|
||||||
|
#define MU_TEST_SUITE(suite_name) static void suite_name(void)
|
||||||
|
|
||||||
|
#define MU__SAFE_BLOCK(block) do {\
|
||||||
|
block\
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/* Run test suite and unset setup and teardown functions */
|
||||||
|
#define MU_RUN_SUITE(suite_name) MU__SAFE_BLOCK(\
|
||||||
|
suite_name();\
|
||||||
|
minunit_setup = NULL;\
|
||||||
|
minunit_teardown = NULL;\
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Configure setup and teardown functions */
|
||||||
|
#define MU_SUITE_CONFIGURE(setup_fun, teardown_fun) MU__SAFE_BLOCK(\
|
||||||
|
minunit_setup = setup_fun;\
|
||||||
|
minunit_teardown = teardown_fun;\
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Test runner */
|
||||||
|
#define MU_RUN_TEST(test) MU__SAFE_BLOCK(\
|
||||||
|
if (minunit_real_timer==0 && minunit_proc_timer==0) {\
|
||||||
|
minunit_real_timer = mu_timer_real();\
|
||||||
|
minunit_proc_timer = mu_timer_cpu();\
|
||||||
|
}\
|
||||||
|
if (minunit_setup) (*minunit_setup)();\
|
||||||
|
minunit_status = 0;\
|
||||||
|
test();\
|
||||||
|
minunit_run++;\
|
||||||
|
if (minunit_status) {\
|
||||||
|
minunit_fail++;\
|
||||||
|
printf("F");\
|
||||||
|
printf("\n%s\n", minunit_last_message);\
|
||||||
|
}\
|
||||||
|
fflush(stdout);\
|
||||||
|
if (minunit_teardown) (*minunit_teardown)();\
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Report */
|
||||||
|
#define MU_REPORT() MU__SAFE_BLOCK(\
|
||||||
|
double minunit_end_real_timer;\
|
||||||
|
double minunit_end_proc_timer;\
|
||||||
|
printf("\n\n%d tests, %d assertions, %d failures\n", minunit_run, minunit_assert, minunit_fail);\
|
||||||
|
minunit_end_real_timer = mu_timer_real();\
|
||||||
|
minunit_end_proc_timer = mu_timer_cpu();\
|
||||||
|
printf("\nFinished in %.8f seconds (real) %.8f seconds (proc)\n\n",\
|
||||||
|
minunit_end_real_timer - minunit_real_timer,\
|
||||||
|
minunit_end_proc_timer - minunit_proc_timer);\
|
||||||
|
)
|
||||||
|
#define MU_EXIT_CODE minunit_fail
|
||||||
|
|
||||||
|
/* Assertions */
|
||||||
|
#define mu_check(test) MU__SAFE_BLOCK(\
|
||||||
|
minunit_assert++;\
|
||||||
|
if (!(test)) {\
|
||||||
|
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, #test);\
|
||||||
|
minunit_status = 1;\
|
||||||
|
return;\
|
||||||
|
} else {\
|
||||||
|
printf(".");\
|
||||||
|
}\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define mu_fail(message) MU__SAFE_BLOCK(\
|
||||||
|
minunit_assert++;\
|
||||||
|
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, message);\
|
||||||
|
minunit_status = 1;\
|
||||||
|
return;\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define mu_assert(test, message) MU__SAFE_BLOCK(\
|
||||||
|
minunit_assert++;\
|
||||||
|
if (!(test)) {\
|
||||||
|
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %s", __func__, __FILE__, __LINE__, message);\
|
||||||
|
minunit_status = 1;\
|
||||||
|
return;\
|
||||||
|
} else {\
|
||||||
|
printf(".");\
|
||||||
|
}\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define mu_assert_int_eq(expected, result) MU__SAFE_BLOCK(\
|
||||||
|
int minunit_tmp_e;\
|
||||||
|
int minunit_tmp_r;\
|
||||||
|
minunit_assert++;\
|
||||||
|
minunit_tmp_e = (expected);\
|
||||||
|
minunit_tmp_r = (result);\
|
||||||
|
if (minunit_tmp_e != minunit_tmp_r) {\
|
||||||
|
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %d expected but was %d", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r);\
|
||||||
|
minunit_status = 1;\
|
||||||
|
return;\
|
||||||
|
} else {\
|
||||||
|
printf(".");\
|
||||||
|
}\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define mu_assert_double_eq(expected, result) MU__SAFE_BLOCK(\
|
||||||
|
double minunit_tmp_e;\
|
||||||
|
double minunit_tmp_r;\
|
||||||
|
minunit_assert++;\
|
||||||
|
minunit_tmp_e = (expected);\
|
||||||
|
minunit_tmp_r = (result);\
|
||||||
|
if (fabs(minunit_tmp_e-minunit_tmp_r) > MINUNIT_EPSILON) {\
|
||||||
|
int minunit_significant_figures = 1 - log10(MINUNIT_EPSILON);\
|
||||||
|
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: %.*g expected but was %.*g", __func__, __FILE__, __LINE__, minunit_significant_figures, minunit_tmp_e, minunit_significant_figures, minunit_tmp_r);\
|
||||||
|
minunit_status = 1;\
|
||||||
|
return;\
|
||||||
|
} else {\
|
||||||
|
printf(".");\
|
||||||
|
}\
|
||||||
|
)
|
||||||
|
|
||||||
|
#define mu_assert_string_eq(expected, result) MU__SAFE_BLOCK(\
|
||||||
|
const char* minunit_tmp_e = expected;\
|
||||||
|
const char* minunit_tmp_r = result;\
|
||||||
|
minunit_assert++;\
|
||||||
|
if (!minunit_tmp_e) {\
|
||||||
|
minunit_tmp_e = "<null pointer>";\
|
||||||
|
}\
|
||||||
|
if (!minunit_tmp_r) {\
|
||||||
|
minunit_tmp_r = "<null pointer>";\
|
||||||
|
}\
|
||||||
|
if(strcmp(minunit_tmp_e, minunit_tmp_r)) {\
|
||||||
|
snprintf(minunit_last_message, MINUNIT_MESSAGE_LEN, "%s failed:\n\t%s:%d: '%s' expected but was '%s'", __func__, __FILE__, __LINE__, minunit_tmp_e, minunit_tmp_r);\
|
||||||
|
minunit_status = 1;\
|
||||||
|
return;\
|
||||||
|
} else {\
|
||||||
|
printf(".");\
|
||||||
|
}\
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following two functions were written by David Robert Nadeau
|
||||||
|
* from http://NadeauSoftware.com/ and distributed under the
|
||||||
|
* Creative Commons Attribution 3.0 Unported License
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the real time, in seconds, or -1.0 if an error occurred.
|
||||||
|
*
|
||||||
|
* Time is measured since an arbitrary and OS-dependent start time.
|
||||||
|
* The returned real time is only useful for computing an elapsed time
|
||||||
|
* between two calls to this function.
|
||||||
|
*/
|
||||||
|
static double mu_timer_real(void)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
/* Windows 2000 and later. ---------------------------------- */
|
||||||
|
LARGE_INTEGER Time;
|
||||||
|
LARGE_INTEGER Frequency;
|
||||||
|
|
||||||
|
QueryPerformanceFrequency(&Frequency);
|
||||||
|
QueryPerformanceCounter(&Time);
|
||||||
|
|
||||||
|
Time.QuadPart *= 1000000;
|
||||||
|
Time.QuadPart /= Frequency.QuadPart;
|
||||||
|
|
||||||
|
return (double)Time.QuadPart / 1000000.0;
|
||||||
|
|
||||||
|
#elif (defined(__hpux) || defined(hpux)) || ((defined(__sun__) || defined(__sun) || defined(sun)) && (defined(__SVR4) || defined(__svr4__)))
|
||||||
|
/* HP-UX, Solaris. ------------------------------------------ */
|
||||||
|
return (double)gethrtime( ) / 1000000000.0;
|
||||||
|
|
||||||
|
#elif defined(__MACH__) && defined(__APPLE__)
|
||||||
|
/* OSX. ----------------------------------------------------- */
|
||||||
|
static double timeConvert = 0.0;
|
||||||
|
if ( timeConvert == 0.0 )
|
||||||
|
{
|
||||||
|
mach_timebase_info_data_t timeBase;
|
||||||
|
(void)mach_timebase_info( &timeBase );
|
||||||
|
timeConvert = (double)timeBase.numer /
|
||||||
|
(double)timeBase.denom /
|
||||||
|
1000000000.0;
|
||||||
|
}
|
||||||
|
return (double)mach_absolute_time( ) * timeConvert;
|
||||||
|
|
||||||
|
#elif defined(_POSIX_VERSION)
|
||||||
|
/* POSIX. --------------------------------------------------- */
|
||||||
|
struct timeval tm;
|
||||||
|
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
#if defined(CLOCK_MONOTONIC_PRECISE)
|
||||||
|
/* BSD. --------------------------------------------- */
|
||||||
|
const clockid_t id = CLOCK_MONOTONIC_PRECISE;
|
||||||
|
#elif defined(CLOCK_MONOTONIC_RAW)
|
||||||
|
/* Linux. ------------------------------------------- */
|
||||||
|
const clockid_t id = CLOCK_MONOTONIC_RAW;
|
||||||
|
#elif defined(CLOCK_HIGHRES)
|
||||||
|
/* Solaris. ----------------------------------------- */
|
||||||
|
const clockid_t id = CLOCK_HIGHRES;
|
||||||
|
#elif defined(CLOCK_MONOTONIC)
|
||||||
|
/* AIX, BSD, Linux, POSIX, Solaris. ----------------- */
|
||||||
|
const clockid_t id = CLOCK_MONOTONIC;
|
||||||
|
#elif defined(CLOCK_REALTIME)
|
||||||
|
/* AIX, BSD, HP-UX, Linux, POSIX. ------------------- */
|
||||||
|
const clockid_t id = CLOCK_REALTIME;
|
||||||
|
#else
|
||||||
|
const clockid_t id = (clockid_t)-1; /* Unknown. */
|
||||||
|
#endif /* CLOCK_* */
|
||||||
|
if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 )
|
||||||
|
return (double)ts.tv_sec +
|
||||||
|
(double)ts.tv_nsec / 1000000000.0;
|
||||||
|
/* Fall thru. */
|
||||||
|
}
|
||||||
|
#endif /* _POSIX_TIMERS */
|
||||||
|
|
||||||
|
/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, POSIX, Solaris. ----- */
|
||||||
|
gettimeofday( &tm, NULL );
|
||||||
|
return (double)tm.tv_sec + (double)tm.tv_usec / 1000000.0;
|
||||||
|
#else
|
||||||
|
return -1.0; /* Failed. */
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount of CPU time used by the current process,
|
||||||
|
* in seconds, or -1.0 if an error occurred.
|
||||||
|
*/
|
||||||
|
static double mu_timer_cpu(void)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32)
|
||||||
|
/* Windows -------------------------------------------------- */
|
||||||
|
FILETIME createTime;
|
||||||
|
FILETIME exitTime;
|
||||||
|
FILETIME kernelTime;
|
||||||
|
FILETIME userTime;
|
||||||
|
|
||||||
|
/* This approach has a resolution of 1/64 second. Unfortunately, Windows' API does not offer better */
|
||||||
|
if ( GetProcessTimes( GetCurrentProcess( ),
|
||||||
|
&createTime, &exitTime, &kernelTime, &userTime ) != 0 )
|
||||||
|
{
|
||||||
|
ULARGE_INTEGER userSystemTime;
|
||||||
|
memcpy(&userSystemTime, &userTime, sizeof(ULARGE_INTEGER));
|
||||||
|
return (double)userSystemTime.QuadPart / 10000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__unix__) || defined(__unix) || defined(unix) || (defined(__APPLE__) && defined(__MACH__))
|
||||||
|
/* AIX, BSD, Cygwin, HP-UX, Linux, OSX, and Solaris --------- */
|
||||||
|
|
||||||
|
#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
|
||||||
|
/* Prefer high-res POSIX timers, when available. */
|
||||||
|
{
|
||||||
|
clockid_t id;
|
||||||
|
struct timespec ts;
|
||||||
|
#if _POSIX_CPUTIME > 0
|
||||||
|
/* Clock ids vary by OS. Query the id, if possible. */
|
||||||
|
if ( clock_getcpuclockid( 0, &id ) == -1 )
|
||||||
|
#endif
|
||||||
|
#if defined(CLOCK_PROCESS_CPUTIME_ID)
|
||||||
|
/* Use known clock id for AIX, Linux, or Solaris. */
|
||||||
|
id = CLOCK_PROCESS_CPUTIME_ID;
|
||||||
|
#elif defined(CLOCK_VIRTUAL)
|
||||||
|
/* Use known clock id for BSD or HP-UX. */
|
||||||
|
id = CLOCK_VIRTUAL;
|
||||||
|
#else
|
||||||
|
id = (clockid_t)-1;
|
||||||
|
#endif
|
||||||
|
if ( id != (clockid_t)-1 && clock_gettime( id, &ts ) != -1 )
|
||||||
|
return (double)ts.tv_sec +
|
||||||
|
(double)ts.tv_nsec / 1000000000.0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(RUSAGE_SELF)
|
||||||
|
{
|
||||||
|
struct rusage rusage;
|
||||||
|
if ( getrusage( RUSAGE_SELF, &rusage ) != -1 )
|
||||||
|
return (double)rusage.ru_utime.tv_sec +
|
||||||
|
(double)rusage.ru_utime.tv_usec / 1000000.0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_SC_CLK_TCK)
|
||||||
|
{
|
||||||
|
const double ticks = (double)sysconf( _SC_CLK_TCK );
|
||||||
|
struct tms tms;
|
||||||
|
if ( times( &tms ) != (clock_t)-1 )
|
||||||
|
return (double)tms.tms_utime / ticks;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CLOCKS_PER_SEC)
|
||||||
|
{
|
||||||
|
clock_t cl = clock( );
|
||||||
|
if ( cl != (clock_t)-1 )
|
||||||
|
return (double)cl / (double)CLOCKS_PER_SEC;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -1; /* Failed. */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* MINUNIT_MINUNIT_H */
|
||||||
13
experimental/facho-signer/src/xades/minunit_ext.h
Normal file
13
experimental/facho-signer/src/xades/minunit_ext.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef MINUNIT_EXT_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "minunit.h"
|
||||||
|
|
||||||
|
// cuando escribe esto el compilar me arrojo que si no era
|
||||||
|
// mejor usar mu_assert_string_eq increble a
|
||||||
|
//int mu_assert_string_equals(const char *a, const char *b) {
|
||||||
|
// return mu_assert(strcmp(a, b) == 0, "string not equals");
|
||||||
|
//}
|
||||||
|
|
||||||
|
#endif //MINUNIT_EXT_H
|
||||||
456
experimental/facho-signer/src/xades/templates.c
Normal file
456
experimental/facho-signer/src/xades/templates.c
Normal file
@@ -0,0 +1,456 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of facho. The COPYRIGHT file at the top level of
|
||||||
|
* this repository contains the full copyright notices and license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xades.h"
|
||||||
|
|
||||||
|
#include <xmlsec/templates.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const xmlChar xmlXadesNodeQualifyingProperties[] = "QualifyingProperties";
|
||||||
|
static const xmlChar xmlXadesNodeSignedProperties[] = "SignedProperties";
|
||||||
|
|
||||||
|
static const xmlChar xmlXadesNodeSignedSignatureProperties[] = "SignedSignatureProperties";
|
||||||
|
static const xmlChar xmlXadesNodeSigningTime[] = "SigningTime";
|
||||||
|
static const xmlChar xmlXadesNodeSigningCertificate[] = "SigningCertificate";
|
||||||
|
static const xmlChar xmlXadesNodeCert[] = "Cert";
|
||||||
|
static const xmlChar xmlXadesNodeCertDigest[] = "CertDigest";
|
||||||
|
static const xmlChar xmlXadesNodeSignaturePolicyIdentifier[] = "SignaturePolicyIdentifier";
|
||||||
|
static const xmlChar xmlXadesNodeSignaturePolicyId[] = "SignaturePolicyId";
|
||||||
|
static const xmlChar xmlXadesNodeSigPolicyId[] = "SigPolicyId";
|
||||||
|
static const xmlChar xmlXadesNodeIdentifier[] = "Identifier";
|
||||||
|
static const xmlChar xmlXadesNodeDescription[] = "Description";
|
||||||
|
static const xmlChar xmlXadesNodeSigPolicyHash[] = "SigPolicyHash";
|
||||||
|
|
||||||
|
static const xmlChar xmlXadesNodeSignerRole[] = "SignerRole";
|
||||||
|
static const xmlChar xmlXadesNodeClaimedRoles[] = "ClaimedRoles";
|
||||||
|
static const xmlChar xmlXadesNodeClaimedRole[] = "ClaimedRole";
|
||||||
|
static const xmlChar xmlXadesNodeIssuerSerial[] = "IssuerSerial";
|
||||||
|
static const xmlChar xmlXadesNodeX509IssuerName[] = "X509IssuerName";
|
||||||
|
static const xmlChar xmlXadesNodeX509IssuerNumber[] = "X509IssuerNumber";
|
||||||
|
|
||||||
|
static const xmlChar xmlXadesDSigNs[] = "http://uri.etsi.org/01903/v1.3.2#";
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesAddChildRecursiveNs(xmlNodePtr startNode, const xmlChar* path, const xmlChar* nsPrefix) {
|
||||||
|
char *curToken;
|
||||||
|
char* cpath = strdup((char *)path);
|
||||||
|
char* savePtr;
|
||||||
|
xmlNodePtr curNode = NULL;
|
||||||
|
xmlNodePtr parentNode = startNode;
|
||||||
|
|
||||||
|
|
||||||
|
curToken = strtok_r(cpath, "/", &savePtr);
|
||||||
|
while(curToken != NULL) {
|
||||||
|
curNode = xmlSecFindChild(parentNode, BAD_CAST curToken, nsPrefix);
|
||||||
|
if (curNode == NULL) {
|
||||||
|
curNode = xmlSecAddChild(parentNode, BAD_CAST curToken, nsPrefix);
|
||||||
|
if (curNode == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(%s)", curToken);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parentNode = curNode;
|
||||||
|
|
||||||
|
curToken = strtok_r(NULL, "/", &savePtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(cpath);
|
||||||
|
return(curNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplQualifyingPropertiesCreate(xmlDocPtr doc, xmlNodePtr signatureNode, const xmlChar *id) {
|
||||||
|
xmlNodePtr objectNode;
|
||||||
|
xmlNodePtr qualifyingPropertiesNode;
|
||||||
|
|
||||||
|
xmlNewGlobalNs(doc, xmlXadesDSigNs, BAD_CAST "xades");
|
||||||
|
|
||||||
|
objectNode = xmlSecTmplSignatureAddObject(signatureNode, NULL, NULL, NULL);
|
||||||
|
if (objectNode == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecTmplSignatureAddObject(signatureNode)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
qualifyingPropertiesNode = xmlSecAddChild(objectNode, xmlXadesNodeQualifyingProperties, xmlXadesDSigNs);
|
||||||
|
if (qualifyingPropertiesNode == NULL) {
|
||||||
|
xmlXadesXmlError2("xmlNewDocNode", NULL, "node=%s", xmlXadesErrorsSafeString(xmlXadesNodeQualifyingProperties));
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id != NULL) {
|
||||||
|
xmlSetProp(qualifyingPropertiesNode, BAD_CAST "Id", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(qualifyingPropertiesNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplQualifyingPropertiesCreateNsPref(xmlDocPtr doc, const xmlChar* id, const xmlChar* nsPrefix) {
|
||||||
|
xmlNodePtr qualifyingPropertiesNode;
|
||||||
|
xmlNsPtr ns;
|
||||||
|
|
||||||
|
// crear nodo
|
||||||
|
qualifyingPropertiesNode = xmlNewDocNode(doc, NULL, xmlXadesNodeQualifyingProperties, NULL);
|
||||||
|
if (qualifyingPropertiesNode == NULL) {
|
||||||
|
xmlXadesXmlError2("xmlNewDocNode", NULL, "node=%s", xmlXadesErrorsSafeString(xmlXadesNodeQualifyingProperties));
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// crear namespace y asignar
|
||||||
|
ns = xmlNewNs(qualifyingPropertiesNode, xmlXadesDSigNs, nsPrefix);
|
||||||
|
if (ns == NULL) {
|
||||||
|
xmlXadesXmlError2("xmlNewNs", NULL,
|
||||||
|
"ns=%s", xmlXadesErrorsSafeString(xmlXadesDSigNs));
|
||||||
|
xmlFreeNode(qualifyingPropertiesNode);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
xmlSetNs(qualifyingPropertiesNode, ns);
|
||||||
|
|
||||||
|
if (id != NULL) {
|
||||||
|
xmlSetProp(qualifyingPropertiesNode, BAD_CAST "Id", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (qualifyingPropertiesNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSignedProperties(xmlNodePtr qualifyingPropertiesNode, const xmlChar* id) {
|
||||||
|
xmlNodePtr cur;
|
||||||
|
|
||||||
|
xmlXadesAssert2(qualifyingPropertiesNode != NULL, NULL);
|
||||||
|
|
||||||
|
cur = xmlSecAddChild(qualifyingPropertiesNode, xmlXadesNodeSignedProperties, xmlXadesDSigNs);
|
||||||
|
if (cur == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSignedProperties)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id != NULL) {
|
||||||
|
xmlSetProp(cur, BAD_CAST "Id", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSignedSignatureProperties(xmlNodePtr signedPropertiesNode, struct tm* signingTime) {
|
||||||
|
xmlNodePtr cur;
|
||||||
|
xmlNodePtr node;
|
||||||
|
|
||||||
|
xmlXadesAssert2(signedPropertiesNode != NULL, NULL);
|
||||||
|
|
||||||
|
// add SignedSignatureProperties
|
||||||
|
node = xmlSecAddChild(signedPropertiesNode, xmlXadesNodeSignedSignatureProperties, xmlXadesDSigNs);
|
||||||
|
if (node == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSignedSignatureProperties)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add SignigTime
|
||||||
|
cur = xmlSecAddChild(node, xmlXadesNodeSigningTime, xmlXadesDSigNs);
|
||||||
|
if (cur == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSigningTime)", NULL);
|
||||||
|
xmlFreeNode(node);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char strtime[200];
|
||||||
|
|
||||||
|
if (strftime(strtime, sizeof(strtime), "%Y-%m-%dT%T", signingTime) == 0) {
|
||||||
|
xmlXadesInternalError("strftime", NULL);
|
||||||
|
xmlFreeNode(cur);
|
||||||
|
xmlFreeNode(node);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = xmlSecNodeEncodeAndSetContent(cur, BAD_CAST strtime);
|
||||||
|
if (ret < 0) {
|
||||||
|
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||||
|
xmlFreeNode(cur);
|
||||||
|
xmlFreeNode(node);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSigningCertificate(xmlNodePtr signedSignaturePropertiesNode, xmlSecTransformId digestMethodId) {
|
||||||
|
xmlNodePtr node;
|
||||||
|
|
||||||
|
xmlXadesAssert2(signedSignaturePropertiesNode != NULL, NULL);
|
||||||
|
if (xmlSecFindChild(signedSignaturePropertiesNode, xmlXadesNodeSigningCertificate, xmlXadesDSigNs) != NULL) {
|
||||||
|
xmlXadesNodeAlreadyPresentError(signedSignaturePropertiesNode, xmlXadesNodeSigningCertificate, NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
node = xmlSecAddChild(signedSignaturePropertiesNode, xmlXadesNodeSigningCertificate, xmlXadesDSigNs);
|
||||||
|
if (node == NULL) {
|
||||||
|
xmlXadesInternalError("xmlsecAddChild(xmlXadesNodeSigningCertificate)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddCert(xmlNodePtr signingCertificateNode) {
|
||||||
|
xmlNodePtr certNode;
|
||||||
|
|
||||||
|
xmlXadesAssert2(signingCertificateNode != NULL, NULL);
|
||||||
|
|
||||||
|
certNode = xmlSecAddChild(signingCertificateNode, xmlXadesNodeCert, xmlXadesDSigNs);
|
||||||
|
if (certNode == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeCert)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(certNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddCertDigest(xmlNodePtr certNode, const xmlChar *digestMethod, const xmlChar *digestValue) {
|
||||||
|
xmlNodePtr node;
|
||||||
|
|
||||||
|
xmlXadesAssert2(certNode != NULL, NULL);
|
||||||
|
|
||||||
|
node = xmlSecAddChild(certNode, xmlXadesNodeCertDigest, xmlXadesDSigNs);
|
||||||
|
if ( node == NULL ) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeCertDigest)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlXadesTmplAddDigest(node, digestMethod, digestValue) == NULL) {
|
||||||
|
xmlXadesInternalError("xmlXadesTmplAddDigest(node, digestMethodId)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(certNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSignaturePolicyIdentifier(xmlNodePtr signedSignaturePropertiesNode) {
|
||||||
|
xmlNodePtr cur;
|
||||||
|
|
||||||
|
xmlXadesAssert2(signedSignaturePropertiesNode != NULL, NULL);
|
||||||
|
|
||||||
|
cur = xmlSecAddChild(signedSignaturePropertiesNode, xmlXadesNodeSignaturePolicyIdentifier, xmlXadesDSigNs);
|
||||||
|
if (cur == NULL) {
|
||||||
|
xmlXadesInternalError("xmlsecAddChild(xmlXadesNodeSignaturePolicyIdentifier)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSignaturePolicyId(xmlNodePtr signaturePolicyIdentifierNode) {
|
||||||
|
xmlNodePtr cur;
|
||||||
|
|
||||||
|
xmlXadesAssert2(signaturePolicyIdentifierNode != NULL, NULL);
|
||||||
|
|
||||||
|
cur = xmlSecAddChild(signaturePolicyIdentifierNode, xmlXadesNodeSignaturePolicyId, xmlXadesDSigNs);
|
||||||
|
if (cur == NULL) {
|
||||||
|
xmlXadesInternalError("xmlsecAddChild(cur)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifier, const xmlChar *description) {
|
||||||
|
xmlNodePtr sigPolicyIdNode;
|
||||||
|
xmlNodePtr node;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
sigPolicyIdNode = xmlSecAddChild(signaturePolicyId, xmlXadesNodeSigPolicyId, xmlXadesDSigNs);
|
||||||
|
if (sigPolicyIdNode == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSigPolicyId)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
node = xmlSecAddChild(sigPolicyIdNode, xmlXadesNodeIdentifier, xmlXadesDSigNs);
|
||||||
|
if (node == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeIdentifier)", NULL);
|
||||||
|
xmlFreeNode(sigPolicyIdNode);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = xmlSecNodeEncodeAndSetContent(node, identifier);
|
||||||
|
if (ret < 0) {
|
||||||
|
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||||
|
xmlFreeNode(sigPolicyIdNode);
|
||||||
|
xmlFreeNode(node);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
node = xmlSecAddChild(sigPolicyIdNode, xmlXadesNodeDescription, xmlXadesDSigNs);
|
||||||
|
if (node == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeDescription)", NULL);
|
||||||
|
xmlFreeNode(sigPolicyIdNode);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = xmlSecNodeEncodeAndSetContent(node, description);
|
||||||
|
if (ret < 0) {
|
||||||
|
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||||
|
xmlFreeNode(sigPolicyIdNode);
|
||||||
|
xmlFreeNode(node);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(sigPolicyIdNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode, xmlSecTransformId digestMethodId) {
|
||||||
|
xmlNodePtr node;
|
||||||
|
xmlXadesAssert2(parentNode != NULL, NULL);
|
||||||
|
|
||||||
|
//add policyHash
|
||||||
|
node = xmlSecAddChild(parentNode, xmlXadesNodeSigPolicyHash, xmlXadesDSigNs);
|
||||||
|
if (node == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSigPolicyHash)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlXadesTmplAddDigest(node, digestMethodId->href, NULL) == NULL) {
|
||||||
|
xmlXadesInternalError("xmlXadesTmplAddDigest(node, digestMethodId)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MACHETE(bit4bit) como usar SecTransform para almacenar el digest
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddDigest(xmlNodePtr parentNode, const xmlChar *digestMethod, const xmlChar *digestValue) {
|
||||||
|
xmlNodePtr node;
|
||||||
|
|
||||||
|
xmlXadesAssert2(parentNode != NULL, NULL);
|
||||||
|
|
||||||
|
if ( digestMethod != NULL ) {
|
||||||
|
node = xmlSecAddChild(parentNode, xmlSecNodeDigestMethod, xmlSecDSigNs);
|
||||||
|
if (node == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlSecNodeDigestMethod)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
if (xmlSetProp(node, xmlSecAttrAlgorithm, digestMethod) == NULL) {
|
||||||
|
xmlXadesXmlError2("xmlSetProp", NULL,
|
||||||
|
"name=%s", xmlXadesErrorsSafeString(xmlSecAttrAlgorithm));
|
||||||
|
xmlUnlinkNode(node);
|
||||||
|
xmlFreeNode(node);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( digestValue != NULL ) {
|
||||||
|
node = xmlSecAddChild(parentNode, xmlSecNodeDigestValue, xmlSecDSigNs);
|
||||||
|
if (node == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlSecNodeDigestValue)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xmlSecNodeEncodeAndSetContent(node, digestValue) < 0) {
|
||||||
|
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parentNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSignerRole(xmlNodePtr signedSignaturePropertiesNode, const xmlChar* role) {
|
||||||
|
xmlNodePtr signerRoleNode;
|
||||||
|
xmlNodePtr claimedRolesNode;
|
||||||
|
xmlNodePtr claimedRoleNode;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
signerRoleNode = xmlSecAddChild(signedSignaturePropertiesNode, xmlXadesNodeSignerRole, xmlXadesDSigNs);
|
||||||
|
if (signerRoleNode == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeSignerRole)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
claimedRolesNode = xmlSecAddChild(signerRoleNode, xmlXadesNodeClaimedRoles, xmlXadesDSigNs);
|
||||||
|
if (claimedRolesNode == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeClaimedRoles)", NULL);
|
||||||
|
xmlUnlinkNode(signerRoleNode);
|
||||||
|
xmlFreeNode(signerRoleNode);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
claimedRoleNode = xmlSecAddChild(claimedRolesNode, xmlXadesNodeClaimedRole, xmlXadesDSigNs);
|
||||||
|
if (claimedRoleNode == NULL) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeClaimedRole)", NULL);
|
||||||
|
xmlUnlinkNode(signerRoleNode);
|
||||||
|
xmlFreeNode(signerRoleNode);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = xmlSecNodeEncodeAndSetContent(claimedRoleNode, role);
|
||||||
|
if (ret < 0) {
|
||||||
|
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||||
|
xmlUnlinkNode(signerRoleNode);
|
||||||
|
xmlFreeNode(signerRoleNode);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(signerRoleNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddIssuerSerial(xmlNodePtr certNode, const xmlChar *issuerName, const xmlChar *issuerNumber) {
|
||||||
|
xmlNodePtr issuerSerialNode;
|
||||||
|
xmlNodePtr node;
|
||||||
|
|
||||||
|
xmlXadesAssert2(certNode != NULL, NULL);
|
||||||
|
|
||||||
|
issuerSerialNode = xmlSecAddChild(certNode, xmlXadesNodeIssuerSerial, xmlXadesDSigNs);
|
||||||
|
if ( issuerSerialNode == NULL ) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(certNode, xmlXadesIssuerSerial)", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
node = xmlSecAddChild(issuerSerialNode, xmlXadesNodeX509IssuerName, xmlSecDSigNs);
|
||||||
|
if ( node == NULL ) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeX509IssuerName)", NULL);
|
||||||
|
xmlFreeNode(issuerSerialNode);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xmlSecNodeEncodeAndSetContent(node, issuerName) < 0) {
|
||||||
|
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||||
|
xmlUnlinkNode(issuerSerialNode);
|
||||||
|
xmlFreeNode(issuerSerialNode);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
node = xmlSecAddChild(issuerSerialNode, xmlXadesNodeX509IssuerNumber, xmlSecDSigNs);
|
||||||
|
if ( node == NULL ) {
|
||||||
|
xmlXadesInternalError("xmlSecAddChild(xmlXadesNodeX509IssuerNumber)", NULL);
|
||||||
|
xmlFreeNode(issuerSerialNode);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xmlSecNodeEncodeAndSetContent(node, issuerNumber) < 0) {
|
||||||
|
xmlXadesInternalError("xmlSecNodeEncodeAndSetContent", NULL);
|
||||||
|
xmlUnlinkNode(issuerSerialNode);
|
||||||
|
xmlFreeNode(issuerSerialNode);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(issuerSerialNode);
|
||||||
|
}
|
||||||
301
experimental/facho-signer/src/xades/xades.c
Normal file
301
experimental/facho-signer/src/xades/xades.c
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of facho. The COPYRIGHT file at the top level of
|
||||||
|
* this repository contains the full copyright notices and license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "xades.h"
|
||||||
|
|
||||||
|
#include <libxml/xpath.h>
|
||||||
|
#include <libxml/xpathInternals.h>
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
#include <openssl/bio.h>
|
||||||
|
#include <openssl/asn1.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
|
||||||
|
#include <xmlsec/buffer.h>
|
||||||
|
#include <xmlsec/app.h>
|
||||||
|
#include <xmlsec/transforms.h>
|
||||||
|
#include <xmlsec/keysdata.h>
|
||||||
|
|
||||||
|
#ifdef XMLSEC_NO_CRYPTO_DYNAMIC_LOADING
|
||||||
|
#include <xmlsec/openssl/x509.h>
|
||||||
|
#include <xmlsec/openssl/crypto.h>
|
||||||
|
#include <xmlsec/openssl/symbols.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
|
||||||
|
static xmlChar *
|
||||||
|
xmlXadesSha256DigestValueInBase64(const unsigned char *message, size_t message_len);
|
||||||
|
|
||||||
|
static xmlNodePtr
|
||||||
|
xmlXadesXPathFirstElement(xmlDocPtr doc, const xmlChar *xpath);
|
||||||
|
|
||||||
|
xmlXadesDSigCtxPtr
|
||||||
|
xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx, XADES_DIGEST_METHOD digestMethod, xmlXadesPolicyIdentifierCtxPtr policyCtx) {
|
||||||
|
xmlXadesDSigCtxPtr ctx = NULL;
|
||||||
|
|
||||||
|
ctx = malloc(sizeof(xmlXadesDSigCtx));
|
||||||
|
if ( ctx == NULL ) {
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->dsigCtx = dsigCtx;
|
||||||
|
ctx->digestMethod = digestMethod;
|
||||||
|
ctx->policyCtx = policyCtx;
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
xmlXadesDSigCtxSign(xmlXadesDSigCtxPtr ctx, xmlNodePtr signNode) {
|
||||||
|
xmlNodePtr signingCertificateNode = NULL;
|
||||||
|
xmlSecKeyDataPtr keyDataX509;
|
||||||
|
xmlSecSize certsSize;
|
||||||
|
|
||||||
|
signingCertificateNode = xmlXadesXPathFirstElement(signNode->doc, BAD_CAST "//ds:Object/xades:QualifyingProperties//xades:SigningCertificate[1]");
|
||||||
|
if ( signingCertificateNode == NULL ) {
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
keyDataX509 = xmlSecKeyEnsureData(ctx->dsigCtx->signKey, xmlSecKeyDataX509Id);
|
||||||
|
if ( keyDataX509 == NULL ) {
|
||||||
|
xmlXadesInternalError("failed to get X509.\n", NULL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
certsSize = xmlSecOpenSSLKeyDataX509GetCertsSize(keyDataX509);
|
||||||
|
for (xmlSecSize i = 0; i < certsSize; i++) {
|
||||||
|
// calculamos el digest del certificado
|
||||||
|
unsigned char md[EVP_MAX_MD_SIZE];
|
||||||
|
unsigned int md_n;
|
||||||
|
// TODO(bit4bit) podemos obtener el digest de openssl por medio de la transformacion? o se puede usar la transformacion para generar el digest?
|
||||||
|
xmlChar *digestMethod = NULL;
|
||||||
|
EVP_MD *digest = NULL;
|
||||||
|
|
||||||
|
switch(ctx->digestMethod) {
|
||||||
|
case XADES_DIGEST_SHA256:
|
||||||
|
digestMethod = (xmlChar *)xmlSecTransformSha256Id->href;
|
||||||
|
digest = (EVP_MD *) EVP_sha256();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
xmlXadesInternalError("xmlXadesDSigCtxSign not known how to handle digest method.\n", NULL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
X509 *cert = xmlSecOpenSSLKeyDataX509GetCert(keyDataX509, i);
|
||||||
|
if ( cert == NULL ) {
|
||||||
|
xmlXadesInternalError("openssl: failed to get X509 cert.\n", NULL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
X509_digest(cert, digest, md, &md_n);
|
||||||
|
xmlChar *digestValue = xmlSecBase64Encode(md, md_n, 0);
|
||||||
|
|
||||||
|
xmlNodePtr certNode = xmlXadesTmplAddCert(signingCertificateNode);
|
||||||
|
if ( certNode == NULL ) {
|
||||||
|
xmlXadesInternalError("xmlXadesTmplAddCert(signingCertificateNode)\n", NULL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// adicionamos digest
|
||||||
|
xmlXadesTmplAddCertDigest(certNode,
|
||||||
|
digestMethod,
|
||||||
|
digestValue);
|
||||||
|
|
||||||
|
char *issuerName = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0);
|
||||||
|
|
||||||
|
/* TODO(bit4bit) formatear?
|
||||||
|
char *issuerNamePtr = issuerName;
|
||||||
|
|
||||||
|
for(issuerNamePtr = strchr(issuerNamePtr, '/'); issuerNamePtr != NULL; issuerNamePtr = strchr(issuerNamePtr, '/')) {
|
||||||
|
if (issuerNamePtr == issuerName) {
|
||||||
|
issuerName += 1;
|
||||||
|
} else {
|
||||||
|
*issuerNamePtr = ',';
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
ASN1_INTEGER *serial = X509_get_serialNumber(cert);
|
||||||
|
BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL);
|
||||||
|
if ( bn == NULL ) {
|
||||||
|
xmlXadesInternalError("unable to convert ASN1_INTEGER_to_BN to BN\n", NULL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
char *issuerNumber = BN_bn2dec(bn);
|
||||||
|
if ( issuerNumber == NULL ) {
|
||||||
|
xmlXadesInternalError("unable to convert BN to decimal string\n", NULL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xmlXadesTmplAddIssuerSerial(certNode, BAD_CAST issuerName, BAD_CAST issuerNumber) == NULL) {
|
||||||
|
xmlXadesInternalError("xmlXadesTmplAddIssuerSerial", NULL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
BN_free(bn);
|
||||||
|
OPENSSL_free(issuerNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
// digest de policy identifier
|
||||||
|
xmlNodePtr sigPolicyId = xmlXadesXPathFirstElement(signNode->doc, BAD_CAST "//xades:SigPolicyId/xades:Identifier[1]");
|
||||||
|
if ( sigPolicyId == NULL ) {
|
||||||
|
xmlXadesInternalError("xmlXadesXPathFirstElement(xades:SigPolicyId/xades:Identifier\n", NULL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ctx->policyCtx == NULL ) {
|
||||||
|
xmlXadesInternalError("not found policy context.\n", NULL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ctx->policyCtx != NULL ) {
|
||||||
|
|
||||||
|
|
||||||
|
if ( ctx->policyCtx->contentCallback == NULL ) {
|
||||||
|
xmlXadesInternalError("not found policy content callback.\n", NULL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xmlSecTransformCtxPtr transformCtx = xmlSecTransformCtxCreate();
|
||||||
|
if (transformCtx == NULL ) {
|
||||||
|
xmlXadesInternalError("xmlSecTransformCtxCreate().\n", NULL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// elemento del digest
|
||||||
|
xmlNodePtr sigPolicyHashDigestMethod = xmlXadesXPathFirstElement(signNode->doc, BAD_CAST "//xades:SigPolicyHash/ds:DigestMethod[1]");
|
||||||
|
if ( sigPolicyHashDigestMethod == NULL ) {
|
||||||
|
xmlXadesInternalError("xmlXadesXPathFirstElement(xades:SigPolicyHash/xades:DigestMethod\n", NULL);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
xmlSecTransformPtr transformPolicyDigestMethod = xmlSecTransformNodeRead(sigPolicyHashDigestMethod,
|
||||||
|
xmlSecTransformUsageDigestMethod,
|
||||||
|
transformCtx);
|
||||||
|
if ( transformPolicyDigestMethod == NULL ) {
|
||||||
|
xmlXadesInternalError("xmlSecTransformNodeRead\n", NULL);
|
||||||
|
xmlFreeNode(sigPolicyHashDigestMethod);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( xmlSecTransformCheckId(transformPolicyDigestMethod, xmlSecTransformSha256Id) == 0 ) {
|
||||||
|
xmlXadesInternalError("sigPolicyHash only support sha256 digest method .\n", NULL);
|
||||||
|
xmlFreeNode(sigPolicyHashDigestMethod);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(bit4bit) podemos usar xmlSecTransform para calcular el digest?
|
||||||
|
xmlNodePtr sigPolicyHashNode = xmlXadesXPathFirstElement(signNode->doc, BAD_CAST "//xades:SigPolicyHash[1]");
|
||||||
|
if ( sigPolicyHashNode == NULL ) {
|
||||||
|
xmlXadesInternalError("failed to find sigPolicyHash node.\n", NULL);
|
||||||
|
xmlFreeNode(sigPolicyHashDigestMethod);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// obtenemos contenido de la policy
|
||||||
|
xmlChar *identifier = xmlNodeListGetString(signNode->doc, sigPolicyId->xmlChildrenNode, 1);
|
||||||
|
xmlSecBufferPtr policyContent = xmlSecBufferCreate(1024);
|
||||||
|
;
|
||||||
|
if ( (ctx->policyCtx->contentCallback)(identifier, policyContent) < 0 ) {
|
||||||
|
xmlXadesInternalError("policyContext callback fails.\n", NULL);
|
||||||
|
xmlFree(identifier);
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
xmlFree(identifier);
|
||||||
|
|
||||||
|
xmlChar *policyHashValue = xmlXadesSha256DigestValueInBase64(xmlSecBufferGetData(policyContent),
|
||||||
|
xmlSecBufferGetSize(policyContent));
|
||||||
|
|
||||||
|
xmlSecBufferDestroy(policyContent);
|
||||||
|
xmlXadesTmplAddDigest(sigPolicyHashNode, NULL, policyHashValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return xmlSecDSigCtxSign(ctx->dsigCtx, signNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
xmlXadesDSigCtxDestroy(xmlXadesDSigCtxPtr ctx) {
|
||||||
|
if ( ctx == NULL ) {
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ctx);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesXPathFirstElement(xmlDocPtr doc, const xmlChar *xpath) {
|
||||||
|
xmlXPathContextPtr xpathCtx;
|
||||||
|
xmlXPathObjectPtr xpathResult;
|
||||||
|
xmlNodePtr node;
|
||||||
|
|
||||||
|
// obtener QualifyingProteries
|
||||||
|
|
||||||
|
xpathCtx = xmlXPathNewContext(doc);
|
||||||
|
/* register namespaces */
|
||||||
|
// TOMADO DE: xmlsec1/src/xpath.c
|
||||||
|
for(xmlNsPtr ns = xmlDocGetRootElement(doc)->nsDef; ns != NULL; ns = ns->next) {
|
||||||
|
/* check that we have no other namespace with same prefix already */
|
||||||
|
if((ns->prefix != NULL) && (xmlXPathNsLookup(xpathCtx, ns->prefix) == NULL)){
|
||||||
|
int ret = xmlXPathRegisterNs(xpathCtx, ns->prefix, ns->href);
|
||||||
|
if(ret != 0) {
|
||||||
|
xmlXadesXmlError2("xmlXPathRegisterNs", NULL,
|
||||||
|
"prefix=%s", xmlSecErrorsSafeString(ns->prefix));
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xpathResult = xmlXPathEvalExpression(xpath, xpathCtx);
|
||||||
|
if ( xmlXPathNodeSetIsEmpty( xpathResult->nodesetval ) ) {
|
||||||
|
xmlXadesInternalError("can't find %s \n", xpath);
|
||||||
|
xmlXPathFreeObject(xpathResult);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// obtener puntero a nodo
|
||||||
|
node = xpathResult->nodesetval->nodeTab[0];
|
||||||
|
if ( node->type != XML_ELEMENT_NODE ) {
|
||||||
|
xmlXadesInternalError("expected element\n", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static xmlChar *
|
||||||
|
xmlXadesSha256DigestValueInBase64(const unsigned char *message, size_t message_len)
|
||||||
|
{
|
||||||
|
unsigned char digest[2048];
|
||||||
|
unsigned int digest_len;
|
||||||
|
EVP_MD_CTX *mdctx;
|
||||||
|
|
||||||
|
if((mdctx = EVP_MD_CTX_new()) == NULL) {
|
||||||
|
xmlXadesInternalError("EVP_MD_CTX_new().\n", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(1 != EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL)) {
|
||||||
|
xmlXadesInternalError("EVP_DigestInit_ex().\n", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(1 != EVP_DigestUpdate(mdctx, message, message_len)) {
|
||||||
|
xmlXadesInternalError("EVP_DigestUpdate().\n", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(1 != EVP_DigestFinal_ex(mdctx, digest, &digest_len)) {
|
||||||
|
xmlXadesInternalError("EVP_DigestFinal_ex().\n", NULL);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_MD_CTX_free(mdctx);
|
||||||
|
return(xmlSecBase64Encode(digest, digest_len, 0));
|
||||||
|
}
|
||||||
108
experimental/facho-signer/src/xades/xades.h
Normal file
108
experimental/facho-signer/src/xades/xades.h
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of facho. The COPYRIGHT file at the top level of
|
||||||
|
* this repository contains the full copyright notices and license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XADES_H
|
||||||
|
#define XADES_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
|
||||||
|
#define XMLSEC_NO_XSLT 1
|
||||||
|
|
||||||
|
#include <xmlsec/xmltree.h>
|
||||||
|
#include <xmlsec/transforms.h>
|
||||||
|
#include <xmlsec/xmldsig.h>
|
||||||
|
#include <xmlsec/base64.h>
|
||||||
|
|
||||||
|
#include "xmlsec1/errors_helpers.h"
|
||||||
|
|
||||||
|
#define xmlXadesAssert2(p, ret) \
|
||||||
|
xmlSecAssert2(p, ret)
|
||||||
|
|
||||||
|
#define xmlXadesNodeNotFoundError(errorFunction, startNode, targetNodeName, errorObject) \
|
||||||
|
xmlSecNodeNotFoundError(errorFunction, startNode, targetNodeName, errorObject)
|
||||||
|
|
||||||
|
#define xmlXadesXmlError2(errorFunction, errorObject, msg, param) \
|
||||||
|
xmlSecXmlError2(errorFunction, errorObject, msg, param)
|
||||||
|
|
||||||
|
#define xmlXadesErrorsSafeString(msg) \
|
||||||
|
xmlSecErrorsSafeString(msg)
|
||||||
|
|
||||||
|
#define xmlXadesInternalError(errorFunction, errorObject) \
|
||||||
|
xmlSecInternalError(errorFunction, errorObject)
|
||||||
|
|
||||||
|
#define xmlXadesNodeAlreadyPresentError(parent, nodeName, errObject) \
|
||||||
|
xmlSecNodeAlreadyPresentError(parent, nodeName, errObject)
|
||||||
|
|
||||||
|
|
||||||
|
typedef int xmlXadesSize;
|
||||||
|
typedef enum _XADES_DIGEST_METHOD{
|
||||||
|
XADES_DIGEST_SHA256
|
||||||
|
} XADES_DIGEST_METHOD;
|
||||||
|
|
||||||
|
typedef int(*xmlXadesPolicyIdentifierContentCallback)(const xmlChar *policyId, xmlSecBuffer *);
|
||||||
|
|
||||||
|
typedef struct _xmlXadesPolicyIdentifierCtx xmlXadesPolicyIdentifierCtx, *xmlXadesPolicyIdentifierCtxPtr;
|
||||||
|
struct _xmlXadesPolicyIdentifierCtx {
|
||||||
|
xmlXadesPolicyIdentifierContentCallback contentCallback;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _xmlXadesDSigCtx xmlXadesDSigCtx, *xmlXadesDSigCtxPtr;
|
||||||
|
struct _xmlXadesDSigCtx {
|
||||||
|
xmlSecDSigCtxPtr dsigCtx;
|
||||||
|
XADES_DIGEST_METHOD digestMethod;
|
||||||
|
xmlXadesPolicyIdentifierCtxPtr policyCtx;
|
||||||
|
};
|
||||||
|
|
||||||
|
xmlXadesDSigCtxPtr
|
||||||
|
xmlXadesDSigCtxCreate(xmlSecDSigCtxPtr dsigCtx, XADES_DIGEST_METHOD digestMethod, xmlXadesPolicyIdentifierCtxPtr policyCtx);
|
||||||
|
|
||||||
|
int
|
||||||
|
xmlXadesDSigCtxSign(xmlXadesDSigCtxPtr ctx, xmlNodePtr signNode);
|
||||||
|
|
||||||
|
int
|
||||||
|
xmlXadesDSigCtxDestroy(xmlXadesDSigCtxPtr ctx);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplQualifyingPropertiesCreate(xmlDocPtr doc, xmlNodePtr signatureNode, const xmlChar *id);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSignedProperties(xmlNodePtr qualifyingPropertiesNode, const xmlChar* id);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSigningCertificate(xmlNodePtr parentNode, xmlSecTransformId digestMethodId);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddCert(xmlNodePtr signingCertificateNode);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddCertDigest(xmlNodePtr signingCertificateNode, const xmlChar *digestMethod, const xmlChar *digestValue);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSignedSignatureProperties(xmlNodePtr parentNode, struct tm* signingTime);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSignaturePolicyIdentifier(xmlNodePtr signedSignaturePropertiesNode);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSignaturePolicyId(xmlNodePtr signaturePolicyIdentifierNode);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSigPolicyId(xmlNodePtr signaturePolicyId, const xmlChar* identifier, const xmlChar *description);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSigPolicyHash(xmlNodePtr parentNode, xmlSecTransformId digestMethodId);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddSignerRole(xmlNodePtr signedSignaturePropertiesNode, const xmlChar* role);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddDigest(xmlNodePtr parentNode, const xmlChar *digestMethod, const xmlChar *digestValue);
|
||||||
|
|
||||||
|
xmlNodePtr
|
||||||
|
xmlXadesTmplAddIssuerSerial(xmlNodePtr certNode, const xmlChar *issuerName, const xmlChar *issuerNumber);
|
||||||
|
|
||||||
|
#endif //XADES_H
|
||||||
94
experimental/facho-signer/src/xades/xades_test.c
Normal file
94
experimental/facho-signer/src/xades/xades_test.c
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
/**
|
||||||
|
* This file is part of facho. The COPYRIGHT file at the top level of
|
||||||
|
* this repository contains the full copyright notices and license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include "minunit.h"
|
||||||
|
|
||||||
|
#include "xades.h"
|
||||||
|
|
||||||
|
|
||||||
|
MU_TEST(test_xml_add_node_recursive) {
|
||||||
|
xmlDocPtr doc;
|
||||||
|
xmlNodePtr root;
|
||||||
|
xmlNodePtr child;
|
||||||
|
xmlChar* xmlbuff;
|
||||||
|
int xmlbuffsize;
|
||||||
|
|
||||||
|
doc = xmlNewDoc(BAD_CAST "1.0");
|
||||||
|
root = xmlNewNode(NULL, BAD_CAST "root");
|
||||||
|
xmlDocSetRootElement(doc, root);
|
||||||
|
|
||||||
|
child = xmlXadesAddChildRecursiveNs(root, BAD_CAST "A/B/C", NULL);
|
||||||
|
mu_check(child != NULL);
|
||||||
|
|
||||||
|
xmlDocDumpMemory(doc, &xmlbuff, &xmlbuffsize);
|
||||||
|
mu_assert_string_eq("<?xml version=\"1.0\"?>\n"
|
||||||
|
"<root>\n"
|
||||||
|
"<A>\n"
|
||||||
|
"<B>\n"
|
||||||
|
"<C/>\n"
|
||||||
|
"</B>\n"
|
||||||
|
"</A>\n"
|
||||||
|
"</root>\n"
|
||||||
|
, (char *)xmlbuff);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_qualifying_properties_layout) {
|
||||||
|
xmlDocPtr doc;
|
||||||
|
xmlNodePtr root;
|
||||||
|
xmlNodePtr node;
|
||||||
|
xmlChar* xmlbuff;
|
||||||
|
int buffersize;
|
||||||
|
struct tm tm;
|
||||||
|
|
||||||
|
memset(&tm, 0, sizeof(tm));
|
||||||
|
tm.tm_year = 2021 - 1900;
|
||||||
|
tm.tm_mon = 11;
|
||||||
|
tm.tm_mday = 6;
|
||||||
|
tm.tm_hour = 12;
|
||||||
|
tm.tm_min = 0;
|
||||||
|
tm.tm_sec = 50;
|
||||||
|
|
||||||
|
|
||||||
|
doc = xmlNewDoc(BAD_CAST "1.0");
|
||||||
|
root = xmlNewNode(NULL, BAD_CAST "root");
|
||||||
|
xmlDocSetRootElement(doc, root);
|
||||||
|
|
||||||
|
node = xmlXadesTmplQualifyingPropertiesCreateNsPref(doc, BAD_CAST "123", NULL);
|
||||||
|
xmlXadesTmplAddSignedSignatureProperties(node, &tm);
|
||||||
|
mu_check(node != NULL);
|
||||||
|
|
||||||
|
xmlSecAddChildNode(root, node);
|
||||||
|
xmlDocDumpMemory(doc, &xmlbuff, &buffersize);
|
||||||
|
|
||||||
|
// bit4bit: no se como pasar el namespace al root
|
||||||
|
mu_assert_string_eq("<?xml version=\"1.0\"?>\n"
|
||||||
|
"<root>\n"
|
||||||
|
"<QualifyingProperties xmlns=\"http://uri.etsi.org/01903/v1.3.2#\" id=\"123\">\n"
|
||||||
|
"<SignedProperties>\n"
|
||||||
|
"<SignedSignatureProperties>\n"
|
||||||
|
"<SigningTime>2021-12-06T12:00:50</SigningTime>\n"
|
||||||
|
"</SignedSignatureProperties>\n"
|
||||||
|
"</SignedProperties>\n"
|
||||||
|
"</QualifyingProperties>\n"
|
||||||
|
"</root>\n"
|
||||||
|
, (char *)xmlbuff);
|
||||||
|
|
||||||
|
xmlFree(xmlbuff);
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(test_suite) {
|
||||||
|
MU_RUN_TEST(test_xml_add_node_recursive);
|
||||||
|
MU_RUN_TEST(test_qualifying_properties_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
MU_RUN_SUITE(test_suite);
|
||||||
|
MU_REPORT();
|
||||||
|
return MU_EXIT_CODE;
|
||||||
|
}
|
||||||
260
experimental/facho-signer/src/xades/xmlsec1/errors.c
Normal file
260
experimental/facho-signer/src/xades/xmlsec1/errors.c
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
/*
|
||||||
|
* XML Security Library (http://www.aleksey.com/xmlsec).
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This is free software; see Copyright file in the source
|
||||||
|
* distribution for preciese wording.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* SECTION:errors
|
||||||
|
* @Short_description: Error reporting and logging functions.
|
||||||
|
* @Stability: Stable
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define XMLSEC_PRIVATE 1
|
||||||
|
#define XMLSEC_NO_XSLT 1
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
|
||||||
|
#include <xmlsec/xmlsec.h>
|
||||||
|
#include <xmlsec/xmltree.h>
|
||||||
|
#include <xmlsec/private.h>
|
||||||
|
#include <xmlsec/errors.h>
|
||||||
|
|
||||||
|
/* Must be bigger than fatal_error */
|
||||||
|
#define XMLSEC_ERRORS_BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
/* Must fit into xmlChar[XMLSEC_ERRORS_BUFFER_SIZE] */
|
||||||
|
static const xmlChar fatal_error[] = "Can not format error message";
|
||||||
|
|
||||||
|
typedef struct _xmlSecErrorDescription xmlSecErrorDescription, *xmlSecErrorDescriptionPtr;
|
||||||
|
struct _xmlSecErrorDescription {
|
||||||
|
int errorCode;
|
||||||
|
const char* errorMsg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static xmlSecErrorDescription xmlSecErrorsTable[XMLSEC_ERRORS_MAX_NUMBER + 1] = {
|
||||||
|
{ XMLSEC_ERRORS_R_XMLSEC_FAILED, "xmlsec library function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_MALLOC_FAILED, "malloc function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_STRDUP_FAILED, "strdup function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_CRYPTO_FAILED, "crypto library function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_XML_FAILED, "libxml2 library function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_XSLT_FAILED, "libxslt library function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_IO_FAILED, "io function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_DISABLED, "feature is disabled" },
|
||||||
|
{ XMLSEC_ERRORS_R_NOT_IMPLEMENTED, "feature is not implemented" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_CONFIG, "invalid configuration" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_SIZE, "invalid size" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_DATA, "invalid data" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_RESULT, "invalid result" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_TYPE, "invalid type" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_OPERATION, "invalid operation" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_STATUS, "invalid status" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_FORMAT, "invalid format" },
|
||||||
|
{ XMLSEC_ERRORS_R_DATA_NOT_MATCH, "data do not match" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_VERSION, "invalid version" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_NODE, "invalid node" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, "invalid node content" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, "invalid node attribute" },
|
||||||
|
{ XMLSEC_ERRORS_R_MISSING_NODE_ATTRIBUTE, "missing node attribute" },
|
||||||
|
{ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT, "node already present" },
|
||||||
|
{ XMLSEC_ERRORS_R_UNEXPECTED_NODE, "unexpected node" },
|
||||||
|
{ XMLSEC_ERRORS_R_NODE_NOT_FOUND, "node node found" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_TRANSFORM, "invalid transform" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_TRANSFORM_KEY, "invalid transform key" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_URI_TYPE, "invalid URI type" },
|
||||||
|
{ XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED, "same document is required for transform" },
|
||||||
|
{ XMLSEC_ERRORS_R_TRANSFORM_DISABLED, "transform is disabled" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_KEY_DATA, "invalid key data" },
|
||||||
|
{ XMLSEC_ERRORS_R_KEY_DATA_NOT_FOUND, "key data is not found" },
|
||||||
|
{ XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST, "key data already exist" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, "invalid key data size" },
|
||||||
|
{ XMLSEC_ERRORS_R_KEY_NOT_FOUND, "key is not found" },
|
||||||
|
{ XMLSEC_ERRORS_R_KEYDATA_DISABLED, "key data is disabled" },
|
||||||
|
{ XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL, "maximum key retrieval level" },
|
||||||
|
{ XMLSEC_ERRORS_R_MAX_RETRIEVAL_TYPE_MISMATCH,"key retrieval type mismatch" },
|
||||||
|
{ XMLSEC_ERRORS_R_MAX_ENCKEY_LEVEL, "maximum encrypted key level" },
|
||||||
|
{ XMLSEC_ERRORS_R_CERT_VERIFY_FAILED, "certificate verification failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_CERT_NOT_FOUND, "certificate is not found" },
|
||||||
|
{ XMLSEC_ERRORS_R_CERT_REVOKED, "certificate is revoked" },
|
||||||
|
{ XMLSEC_ERRORS_R_CERT_ISSUER_FAILED, "certificate issuer check failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_CERT_NOT_YET_VALID, "certificate is not yet valid" },
|
||||||
|
{ XMLSEC_ERRORS_R_CERT_HAS_EXPIRED, "certificate has expired" },
|
||||||
|
{ XMLSEC_ERRORS_R_DSIG_NO_REFERENCES, "Reference nodes are not found" },
|
||||||
|
{ XMLSEC_ERRORS_R_DSIG_INVALID_REFERENCE, "Reference verification failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_ASSERTION, "assertion" },
|
||||||
|
{ 0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static xmlSecErrorsCallback xmlSecErrorsClbk = xmlSecErrorsDefaultCallback;
|
||||||
|
static int xmlSecPrintErrorMessages = 1; /* whether the error messages will be printed immediately */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsInit:
|
||||||
|
*
|
||||||
|
* Initializes the errors reporting. It is called from #xmlSecInit function.
|
||||||
|
* and applications must not call this function directly.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlSecErrorsInit(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsShutdown:
|
||||||
|
*
|
||||||
|
* Cleanups the errors reporting. It is called from #xmlSecShutdown function.
|
||||||
|
* and applications must not call this function directly.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlSecErrorsShutdown(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsSetCallback:
|
||||||
|
* @callback: the new errors callback function.
|
||||||
|
*
|
||||||
|
* Sets the errors callback function to @callback that will be called
|
||||||
|
* every time an error occurs.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlSecErrorsSetCallback(xmlSecErrorsCallback callback) {
|
||||||
|
xmlSecErrorsClbk = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsDefaultCallback:
|
||||||
|
* @file: the error location file name (__FILE__ macro).
|
||||||
|
* @line: the error location line number (__LINE__ macro).
|
||||||
|
* @func: the error location function name (__FUNCTION__ macro).
|
||||||
|
* @errorObject: the error specific error object
|
||||||
|
* @errorSubject: the error specific error subject.
|
||||||
|
* @reason: the error code.
|
||||||
|
* @msg: the additional error message.
|
||||||
|
*
|
||||||
|
* The default error reporting callback that utilizes LibXML
|
||||||
|
* error reporting #xmlGenericError function.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlSecErrorsDefaultCallback(const char* file, int line, const char* func,
|
||||||
|
const char* errorObject, const char* errorSubject,
|
||||||
|
int reason, const char* msg) {
|
||||||
|
if(xmlSecPrintErrorMessages) {
|
||||||
|
const char* error_msg = NULL;
|
||||||
|
xmlSecSize i;
|
||||||
|
|
||||||
|
for(i = 0; (i < XMLSEC_ERRORS_MAX_NUMBER) && (xmlSecErrorsGetMsg(i) != NULL); ++i) {
|
||||||
|
if(xmlSecErrorsGetCode(i) == reason) {
|
||||||
|
error_msg = xmlSecErrorsGetMsg(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"func=%s:file=%s:line=%d:obj=%s:subj=%s:error=%d:%s:%s\n",
|
||||||
|
(func != NULL) ? func : "unknown",
|
||||||
|
(file != NULL) ? file : "unknown",
|
||||||
|
line,
|
||||||
|
(errorObject != NULL) ? errorObject : "unknown",
|
||||||
|
(errorSubject != NULL) ? errorSubject : "unknown",
|
||||||
|
reason,
|
||||||
|
(error_msg != NULL) ? error_msg : "",
|
||||||
|
(msg != NULL) ? msg : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsDefaultCallbackEnableOutput:
|
||||||
|
* @enabled: the flag.
|
||||||
|
*
|
||||||
|
* Enables or disables calling LibXML2 callback from the default
|
||||||
|
* errors callback.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlSecErrorsDefaultCallbackEnableOutput(int enabled) {
|
||||||
|
xmlSecPrintErrorMessages = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsGetCode:
|
||||||
|
* @pos: the error position.
|
||||||
|
*
|
||||||
|
* Gets the known error code at position @pos.
|
||||||
|
*
|
||||||
|
* Returns: the known error code or 0 if @pos is greater than
|
||||||
|
* total number of known error codes.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlSecErrorsGetCode(xmlSecSize pos) {
|
||||||
|
/* could not use asserts here! */
|
||||||
|
if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) {
|
||||||
|
return(xmlSecErrorsTable[pos].errorCode);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsGetMsg:
|
||||||
|
* @pos: the error position.
|
||||||
|
*
|
||||||
|
* Gets the known error message at position @pos.
|
||||||
|
*
|
||||||
|
* Returns: the known error message or NULL if @pos is greater than
|
||||||
|
* total number of known error codes.
|
||||||
|
*/
|
||||||
|
const char*
|
||||||
|
xmlSecErrorsGetMsg(xmlSecSize pos) {
|
||||||
|
/* could not use asserts here! */
|
||||||
|
if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) {
|
||||||
|
return(xmlSecErrorsTable[pos].errorMsg);
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecError:
|
||||||
|
* @file: the error location filename (__FILE__).
|
||||||
|
* @line: the error location line number (__LINE__).
|
||||||
|
* @func: the error location function (__FUNCTION__).
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @errorSubject: the error specific error subject (e.g. failed function name).
|
||||||
|
* @reason: the error code.
|
||||||
|
* @msg: the error message in printf format.
|
||||||
|
* @...: the parameters for the @msg.
|
||||||
|
*
|
||||||
|
* Reports an error to the default (#xmlSecErrorsDefaultCallback) or
|
||||||
|
* application specific callback installed using #xmlSecErrorsSetCallback
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlSecError(const char* file, int line, const char* func,
|
||||||
|
const char* errorObject, const char* errorSubject,
|
||||||
|
int reason, const char* msg, ...) {
|
||||||
|
if(xmlSecErrorsClbk != NULL) {
|
||||||
|
xmlChar error_msg[XMLSEC_ERRORS_BUFFER_SIZE];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if(msg != NULL) {
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, msg);
|
||||||
|
ret = xmlStrVPrintf(error_msg, sizeof(error_msg), msg, va);
|
||||||
|
if(ret < 0) {
|
||||||
|
/* Can't really report an error from an error callback */
|
||||||
|
memcpy(error_msg, fatal_error, sizeof(fatal_error));
|
||||||
|
}
|
||||||
|
error_msg[sizeof(error_msg) - 1] = '\0'; /* just in case */
|
||||||
|
va_end(va);
|
||||||
|
} else {
|
||||||
|
error_msg[0] = '\0';
|
||||||
|
}
|
||||||
|
xmlSecErrorsClbk(file, line, func, errorObject, errorSubject, reason, (char*)error_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
869
experimental/facho-signer/src/xades/xmlsec1/errors_helpers.h
Normal file
869
experimental/facho-signer/src/xades/xmlsec1/errors_helpers.h
Normal file
@@ -0,0 +1,869 @@
|
|||||||
|
/*
|
||||||
|
* XML Security Library (http://www.aleksey.com/xmlsec).
|
||||||
|
*
|
||||||
|
* Internal header only used during the compilation,
|
||||||
|
*
|
||||||
|
* This is free software; see Copyright file in the source
|
||||||
|
* distribution for preciese wording.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XMLSEC_ERROR_HELPERS_H__
|
||||||
|
#define __XMLSEC_ERROR_HELPERS_H__
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <xmlsec/errors.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* Error handling macros.
|
||||||
|
*
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInternalError:
|
||||||
|
* @errorFunction: the failed function name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting internal XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInternalError(errorFunction, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XMLSEC_FAILED, \
|
||||||
|
XMLSEC_ERRORS_NO_MESSAGE \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInternalError2:
|
||||||
|
* @errorFunction: the failed function name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting internal XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInternalError2(errorFunction, errorObject, msg, param) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XMLSEC_FAILED, \
|
||||||
|
(msg), (param) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInternalError3:
|
||||||
|
* @errorFunction: the failed function name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param1: the extra message param1.
|
||||||
|
* @param2: the extra message param2.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting internal XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInternalError3(errorFunction, errorObject, msg, param1, param2) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XMLSEC_FAILED, \
|
||||||
|
(msg), (param1), (param2) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInternalError4:
|
||||||
|
* @errorFunction: the failed function name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param1: the extra message param1.
|
||||||
|
* @param2: the extra message param2.
|
||||||
|
* @param3: the extra message param3.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting internal XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInternalError4(errorFunction, errorObject, msg, param1, param2, param3) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XMLSEC_FAILED, \
|
||||||
|
(msg), (param1), (param2), (param3) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecMallocError:
|
||||||
|
* @allocSize: the failed allocation size.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting xmlMalloc() errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecMallocError(allocSize, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
"xmlMalloc", \
|
||||||
|
XMLSEC_ERRORS_R_MALLOC_FAILED, \
|
||||||
|
"size=%lu", (unsigned long)(allocSize) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecStrdupError:
|
||||||
|
* @str: the failed string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting xmlStrdup() errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecStrdupError(str, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
"xmlStrdup", \
|
||||||
|
XMLSEC_ERRORS_R_STRDUP_FAILED, \
|
||||||
|
"size=%lu", (unsigned long)xmlStrlen(str) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecXmlError:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting generic XML errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecXmlError(errorFunction, errorObject) \
|
||||||
|
{ \
|
||||||
|
xmlErrorPtr error = xmlGetLastError(); \
|
||||||
|
int code = (error != NULL) ? error->code : 0; \
|
||||||
|
const char* message = (error != NULL) ? error->message : NULL; \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XML_FAILED, \
|
||||||
|
"xml error: %lu: %s", \
|
||||||
|
(unsigned long)code, \
|
||||||
|
xmlSecErrorsSafeString(message) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecXmlError2:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting generic XML errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecXmlError2(errorFunction, errorObject, msg, param) \
|
||||||
|
{ \
|
||||||
|
xmlErrorPtr error = xmlGetLastError(); \
|
||||||
|
int code = (error != NULL) ? error->code : 0; \
|
||||||
|
const char* message = (error != NULL) ? error->message : NULL; \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XML_FAILED, \
|
||||||
|
msg "; xml error: %lu: %s", \
|
||||||
|
(param), \
|
||||||
|
(unsigned long)code, \
|
||||||
|
xmlSecErrorsSafeString(message) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecXmlParserError:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @ctxt: the parser context.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting XML parser errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecXmlParserError(errorFunction, ctxt, errorObject) \
|
||||||
|
{ \
|
||||||
|
xmlErrorPtr error = xmlCtxtGetLastError(ctxt);\
|
||||||
|
int code = (error != NULL) ? error->code : 0; \
|
||||||
|
const char* message = (error != NULL) ? error->message : NULL; \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XML_FAILED, \
|
||||||
|
"xml error: %lu: %s", \
|
||||||
|
(unsigned long)code, \
|
||||||
|
xmlSecErrorsSafeString(message) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecXmlParserError2:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @ctxt: the parser context.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting XML parser errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecXmlParserError2(errorFunction, ctxt, errorObject, msg, param) \
|
||||||
|
{ \
|
||||||
|
xmlErrorPtr error = xmlCtxtGetLastError(ctxt);\
|
||||||
|
int code = (error != NULL) ? error->code : 0; \
|
||||||
|
const char* message = (error != NULL) ? error->message : NULL; \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XML_FAILED, \
|
||||||
|
msg "; xml error: %lu: %s", \
|
||||||
|
(param), \
|
||||||
|
(unsigned long)code, \
|
||||||
|
xmlSecErrorsSafeString(message) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecXsltError:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @ctxt: the parser context.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting XSLT errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecXsltError(errorFunction, ctxt, errorObject) \
|
||||||
|
{ \
|
||||||
|
xmlErrorPtr error = xmlGetLastError(); \
|
||||||
|
int code = (error != NULL) ? error->code : 0; \
|
||||||
|
const char* message = (error != NULL) ? error->message : NULL; \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XSLT_FAILED, \
|
||||||
|
"xslt error: %lu: %s", \
|
||||||
|
(unsigned long)code, \
|
||||||
|
xmlSecErrorsSafeString(message) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecIOError:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @name: the filename, function name, uri, etc.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting IO errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecIOError(errorFunction, name, errorObject) \
|
||||||
|
{ \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_IO_FAILED, \
|
||||||
|
"name=\"%s\"; errno=%d", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
errno \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecNotImplementedError:
|
||||||
|
* @details: the additional details.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "not implemented" errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecNotImplementedError(details) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
NULL, \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_NOT_IMPLEMENTED, \
|
||||||
|
"details=%s", \
|
||||||
|
xmlSecErrorsSafeString(details) \
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidSizeError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value.
|
||||||
|
* @expected: the expected value.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid size" errors when
|
||||||
|
* we expect exact match.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidSizeError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_SIZE, \
|
||||||
|
"invalid size for '%s': actual=%lu is not equal to expected=%lu", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(unsigned long)(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidSizeLessThanError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value.
|
||||||
|
* @expected: the expected value.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid size" errors when
|
||||||
|
* we expect at least the expected size.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidSizeLessThanError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_SIZE, \
|
||||||
|
"invalid size for '%s': actual=%lu is less than expected=%lu", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(unsigned long)(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidSizeMoreThanError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value.
|
||||||
|
* @expected: the expected value.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid size" errors when
|
||||||
|
* we expect at most the expected size.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidSizeMoreThanError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_NOT_IMPLEMENTED, \
|
||||||
|
"invalid size for '%s': actual=%lu is more than expected=%lu", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(unsigned long)(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidSizeNotMultipleOfError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value.
|
||||||
|
* @divider: the expected divider.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid size" errors when
|
||||||
|
* we expect the size to be a multiple of the divider.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidSizeNotMultipleOfError(name, actual, divider, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_NOT_IMPLEMENTED, \
|
||||||
|
"invalid size for '%s': actual=%lu is not a multiple of %lu", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(unsigned long)(divider) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidSizeOtherError:
|
||||||
|
* @msg: the message about the error.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid size" errors when
|
||||||
|
* we expect exact match.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidSizeOtherError(msg, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_SIZE, \
|
||||||
|
"invalid size: %s", \
|
||||||
|
xmlSecErrorsSafeString(msg) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidDataError:
|
||||||
|
* @msg: the msg with explanation.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid data" errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidDataError(msg, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_DATA, \
|
||||||
|
"%s", \
|
||||||
|
xmlSecErrorsSafeString(msg) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidStringDataError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value as a string.
|
||||||
|
* @expected: the expected value(s) as a string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid data" errors for string.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidStringDataError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_DATA, \
|
||||||
|
"invalid data for '%s': actual='%s' and expected %s", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
xmlSecErrorsSafeString(actual), \
|
||||||
|
(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidIntegerDataError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value as an integer.
|
||||||
|
* @expected: the expected value(s) as a string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid data" errors for integers.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidIntegerDataError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_DATA, \
|
||||||
|
"invalid data for '%s': actual=%ld and expected %s", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidIntegerDataError2:
|
||||||
|
* @name1: the name of the first variable, parameter, etc.
|
||||||
|
* @actual1: the actual first value as an integer.
|
||||||
|
* @name2: the name of the second variable, parameter, etc.
|
||||||
|
* @actual2: the actual second value as an integer.
|
||||||
|
* @expected: the expected value(s) as a string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid data" errors for integers.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidIntegerDataError2(name1, actual1, name2, actual2, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_DATA, \
|
||||||
|
"invalid data: actual value '%s'=%ld, actual value '%s'=%ld and expected %s", \
|
||||||
|
xmlSecErrorsSafeString(name1), \
|
||||||
|
(unsigned long)(actual1), \
|
||||||
|
xmlSecErrorsSafeString(name2), \
|
||||||
|
(unsigned long)(actual2), \
|
||||||
|
(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidTypeError:
|
||||||
|
* @msg: the msg with explanation.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid type" errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidTypeError(msg, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_TYPE, \
|
||||||
|
"%s", \
|
||||||
|
xmlSecErrorsSafeString(msg) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidStringTypeError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value as a string.
|
||||||
|
* @expected: the expected value(s) as a string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid type" errors for string.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidStringTypeError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_TYPE, \
|
||||||
|
"invalid type for '%s': actual='%s' and expected %s", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
xmlSecErrorsSafeString(actual), \
|
||||||
|
(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidIntegerTypeError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value as an integer.
|
||||||
|
* @expected: the expected value(s) as a string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid type" errors for integers.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidIntegerTypeError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_TYPE, \
|
||||||
|
"invalid type for '%s': actual=%ld and expected %s", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidIntegerTypeError2:
|
||||||
|
* @name1: the name of the first variable, parameter, etc.
|
||||||
|
* @actual1: the actual first value as an integer.
|
||||||
|
* @name2: the name of the second variable, parameter, etc.
|
||||||
|
* @actual2: the actual second value as an integer.
|
||||||
|
* @expected: the expected value(s) as a string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid type" errors for integers.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidIntegerTypeError2(name1, actual1, name2, actual2, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_TYPE, \
|
||||||
|
"invalid type: actual value '%s'=%ld, actual value '%s'=%ld and expected %s", \
|
||||||
|
xmlSecErrorsSafeString(name1), \
|
||||||
|
(unsigned long)(actual1), \
|
||||||
|
xmlSecErrorsSafeString(name2), \
|
||||||
|
(unsigned long)(actual2), \
|
||||||
|
(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidNodeError:
|
||||||
|
* @actualNode: the actual node.
|
||||||
|
* @expectedNodeName: the expected node name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid node errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidNodeError(actualNode, expectedNodeName, errorObject) \
|
||||||
|
{ \
|
||||||
|
const char* actualNodeName = xmlSecNodeGetName(actualNode); \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_NODE, \
|
||||||
|
"actual=%s; expected=%s", \
|
||||||
|
xmlSecErrorsSafeString(actualNodeName), \
|
||||||
|
xmlSecErrorsSafeString(expectedNodeName) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidNodeContentError:
|
||||||
|
* @node: the node.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @reason: the reason why node content is invalid.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid node content errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidNodeContentError(node, errorObject, reason) \
|
||||||
|
{ \
|
||||||
|
const char* nName = xmlSecNodeGetName(node); \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, \
|
||||||
|
"node=%s; reason=%s", \
|
||||||
|
xmlSecErrorsSafeString(nName), \
|
||||||
|
xmlSecErrorsSafeString(reason) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidNodeAttributeError:
|
||||||
|
* @node: the node.
|
||||||
|
* @attrName: the attribute name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @reason: the reason why node content is invalid.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid node attribute errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidNodeAttributeError(node, attrName, errorObject, reason) \
|
||||||
|
{ \
|
||||||
|
const char* nName = xmlSecNodeGetName(node); \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, \
|
||||||
|
"node=%s; attribute=%s; reason=%s",\
|
||||||
|
xmlSecErrorsSafeString(nName), \
|
||||||
|
xmlSecErrorsSafeString(attrName), \
|
||||||
|
xmlSecErrorsSafeString(reason) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecNodeAlreadyPresentError:
|
||||||
|
* @parent: the parent node.
|
||||||
|
* @nodeName: the node name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting node already present errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecNodeAlreadyPresentError(parent, nodeName, errorObject) \
|
||||||
|
{ \
|
||||||
|
const char* pName = xmlSecNodeGetName(parent);\
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT, \
|
||||||
|
"parent=%s; node=%s", \
|
||||||
|
xmlSecErrorsSafeString(pName), \
|
||||||
|
xmlSecErrorsSafeString(nodeName) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecUnexpectedNodeError:
|
||||||
|
* @node: the node.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid node errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecUnexpectedNodeError(node, errorObject) \
|
||||||
|
{ \
|
||||||
|
const char* nName = xmlSecNodeGetName(node); \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_UNEXPECTED_NODE, \
|
||||||
|
"node=%s", \
|
||||||
|
xmlSecErrorsSafeString(nName) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecNodeNotFoundError:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @startNode: the search start node.
|
||||||
|
* @targetNodeName: the expected child node name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting node not found errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecNodeNotFoundError(errorFunction, startNode, targetNodeName, errorObject) \
|
||||||
|
{ \
|
||||||
|
const char* startNodeName = xmlSecNodeGetName(startNode); \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_NODE_NOT_FOUND, \
|
||||||
|
"startNode=%s; target=%s", \
|
||||||
|
xmlSecErrorsSafeString(startNodeName), \
|
||||||
|
xmlSecErrorsSafeString(targetNodeName) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidTransfromError:
|
||||||
|
* @transform: the transform.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid transform errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidTransfromError(transform) \
|
||||||
|
{ \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)xmlSecTransformGetName(transform), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_TRANSFORM, \
|
||||||
|
XMLSEC_ERRORS_NO_MESSAGE \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidTransfromError2:
|
||||||
|
* @transform: the transform.
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param: the extra message param.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid transform errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidTransfromError2(transform, msg, param) \
|
||||||
|
{ \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)xmlSecTransformGetName(transform), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_TRANSFORM, \
|
||||||
|
(msg), (param) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidTransfromStatusError:
|
||||||
|
* @transform: the transform.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid transform status errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidTransfromStatusError(transform) \
|
||||||
|
{ \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)xmlSecTransformGetName(transform), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_STATUS, \
|
||||||
|
"transformStatus=%d", \
|
||||||
|
(int)((transform)->status) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidTransfromStatusError2:
|
||||||
|
* @transform: the transform.
|
||||||
|
* @msg: the extra message.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid transform status errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidTransfromStatusError2(transform, msg) \
|
||||||
|
{ \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)xmlSecTransformGetName(transform), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_STATUS, \
|
||||||
|
"transformStatus=%ld, msg=%s", \
|
||||||
|
(long int)((transform)->status), \
|
||||||
|
msg \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidKeyDataSizeError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value.
|
||||||
|
* @expected: the expected value(s).
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid keydata size" errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidKeyDataSizeError(actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, \
|
||||||
|
"invalid key data size: actual=%ld and expected=%ld", \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(unsigned long)(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidZeroKeyDataSizeError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid keydata size" errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidZeroKeyDataSizeError(errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, \
|
||||||
|
"invalid zero key data size" \
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecOtherError:
|
||||||
|
* @code: the error code.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @details: the error message.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting other XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecOtherError(code, errorObject, details) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
(code), \
|
||||||
|
"details=%s", \
|
||||||
|
xmlSecErrorsSafeString(details) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecOtherError2:
|
||||||
|
* @code: the error code.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting other XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecOtherError2(code, errorObject, msg, param) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
(code), \
|
||||||
|
(msg), (param) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecOtherError3:
|
||||||
|
* @code: the error code.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param1: the extra message param.
|
||||||
|
* @param2: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting other XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecOtherError3(code, errorObject, msg, param1, param2) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
(code), \
|
||||||
|
(msg), (param1), (param2) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecOtherError4:
|
||||||
|
* @code: the error code.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param1: the extra message param.
|
||||||
|
* @param2: the extra message param.
|
||||||
|
* @param3: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting other XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecOtherError4(code, errorObject, msg, param1, param2, param3) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
(code), \
|
||||||
|
(msg), (param1), (param2), (param3) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecOtherError5:
|
||||||
|
* @code: the error code.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param1: the extra message param.
|
||||||
|
* @param2: the extra message param.
|
||||||
|
* @param3: the extra message param.
|
||||||
|
* @param4: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting other XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecOtherError5(code, errorObject, msg, param1, param2, param3, param4) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
(code), \
|
||||||
|
(msg), (param1), (param2), (param3), (param4) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* __XMLSEC_ERROR_HELPERS_H__ */
|
||||||
1952
experimental/facho-signer/src/xades/xmlsec1/xmltree.c
Normal file
1952
experimental/facho-signer/src/xades/xmlsec1/xmltree.c
Normal file
File diff suppressed because it is too large
Load Diff
259
experimental/facho-signer/src/xmlsec1/errors.c
Normal file
259
experimental/facho-signer/src/xmlsec1/errors.c
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
/*
|
||||||
|
* XML Security Library (http://www.aleksey.com/xmlsec).
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This is free software; see Copyright file in the source
|
||||||
|
* distribution for preciese wording.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* SECTION:errors
|
||||||
|
* @Short_description: Error reporting and logging functions.
|
||||||
|
* @Stability: Stable
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define XMLSEC_PRIVATE 1
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
|
||||||
|
#include <xmlsec/xmlsec.h>
|
||||||
|
#include <xmlsec/xmltree.h>
|
||||||
|
#include <xmlsec/private.h>
|
||||||
|
#include <xmlsec/errors.h>
|
||||||
|
|
||||||
|
/* Must be bigger than fatal_error */
|
||||||
|
#define XMLSEC_ERRORS_BUFFER_SIZE 1024
|
||||||
|
|
||||||
|
/* Must fit into xmlChar[XMLSEC_ERRORS_BUFFER_SIZE] */
|
||||||
|
static const xmlChar fatal_error[] = "Can not format error message";
|
||||||
|
|
||||||
|
typedef struct _xmlSecErrorDescription xmlSecErrorDescription, *xmlSecErrorDescriptionPtr;
|
||||||
|
struct _xmlSecErrorDescription {
|
||||||
|
int errorCode;
|
||||||
|
const char* errorMsg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static xmlSecErrorDescription xmlSecErrorsTable[XMLSEC_ERRORS_MAX_NUMBER + 1] = {
|
||||||
|
{ XMLSEC_ERRORS_R_XMLSEC_FAILED, "xmlsec library function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_MALLOC_FAILED, "malloc function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_STRDUP_FAILED, "strdup function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_CRYPTO_FAILED, "crypto library function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_XML_FAILED, "libxml2 library function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_XSLT_FAILED, "libxslt library function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_IO_FAILED, "io function failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_DISABLED, "feature is disabled" },
|
||||||
|
{ XMLSEC_ERRORS_R_NOT_IMPLEMENTED, "feature is not implemented" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_CONFIG, "invalid configuration" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_SIZE, "invalid size" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_DATA, "invalid data" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_RESULT, "invalid result" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_TYPE, "invalid type" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_OPERATION, "invalid operation" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_STATUS, "invalid status" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_FORMAT, "invalid format" },
|
||||||
|
{ XMLSEC_ERRORS_R_DATA_NOT_MATCH, "data do not match" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_VERSION, "invalid version" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_NODE, "invalid node" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, "invalid node content" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, "invalid node attribute" },
|
||||||
|
{ XMLSEC_ERRORS_R_MISSING_NODE_ATTRIBUTE, "missing node attribute" },
|
||||||
|
{ XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT, "node already present" },
|
||||||
|
{ XMLSEC_ERRORS_R_UNEXPECTED_NODE, "unexpected node" },
|
||||||
|
{ XMLSEC_ERRORS_R_NODE_NOT_FOUND, "node node found" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_TRANSFORM, "invalid transform" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_TRANSFORM_KEY, "invalid transform key" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_URI_TYPE, "invalid URI type" },
|
||||||
|
{ XMLSEC_ERRORS_R_TRANSFORM_SAME_DOCUMENT_REQUIRED, "same document is required for transform" },
|
||||||
|
{ XMLSEC_ERRORS_R_TRANSFORM_DISABLED, "transform is disabled" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_KEY_DATA, "invalid key data" },
|
||||||
|
{ XMLSEC_ERRORS_R_KEY_DATA_NOT_FOUND, "key data is not found" },
|
||||||
|
{ XMLSEC_ERRORS_R_KEY_DATA_ALREADY_EXIST, "key data already exist" },
|
||||||
|
{ XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, "invalid key data size" },
|
||||||
|
{ XMLSEC_ERRORS_R_KEY_NOT_FOUND, "key is not found" },
|
||||||
|
{ XMLSEC_ERRORS_R_KEYDATA_DISABLED, "key data is disabled" },
|
||||||
|
{ XMLSEC_ERRORS_R_MAX_RETRIEVALS_LEVEL, "maximum key retrieval level" },
|
||||||
|
{ XMLSEC_ERRORS_R_MAX_RETRIEVAL_TYPE_MISMATCH,"key retrieval type mismatch" },
|
||||||
|
{ XMLSEC_ERRORS_R_MAX_ENCKEY_LEVEL, "maximum encrypted key level" },
|
||||||
|
{ XMLSEC_ERRORS_R_CERT_VERIFY_FAILED, "certificate verification failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_CERT_NOT_FOUND, "certificate is not found" },
|
||||||
|
{ XMLSEC_ERRORS_R_CERT_REVOKED, "certificate is revoked" },
|
||||||
|
{ XMLSEC_ERRORS_R_CERT_ISSUER_FAILED, "certificate issuer check failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_CERT_NOT_YET_VALID, "certificate is not yet valid" },
|
||||||
|
{ XMLSEC_ERRORS_R_CERT_HAS_EXPIRED, "certificate has expired" },
|
||||||
|
{ XMLSEC_ERRORS_R_DSIG_NO_REFERENCES, "Reference nodes are not found" },
|
||||||
|
{ XMLSEC_ERRORS_R_DSIG_INVALID_REFERENCE, "Reference verification failed" },
|
||||||
|
{ XMLSEC_ERRORS_R_ASSERTION, "assertion" },
|
||||||
|
{ 0, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
|
static xmlSecErrorsCallback xmlSecErrorsClbk = xmlSecErrorsDefaultCallback;
|
||||||
|
static int xmlSecPrintErrorMessages = 1; /* whether the error messages will be printed immediately */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsInit:
|
||||||
|
*
|
||||||
|
* Initializes the errors reporting. It is called from #xmlSecInit function.
|
||||||
|
* and applications must not call this function directly.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlSecErrorsInit(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsShutdown:
|
||||||
|
*
|
||||||
|
* Cleanups the errors reporting. It is called from #xmlSecShutdown function.
|
||||||
|
* and applications must not call this function directly.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlSecErrorsShutdown(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsSetCallback:
|
||||||
|
* @callback: the new errors callback function.
|
||||||
|
*
|
||||||
|
* Sets the errors callback function to @callback that will be called
|
||||||
|
* every time an error occurs.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlSecErrorsSetCallback(xmlSecErrorsCallback callback) {
|
||||||
|
xmlSecErrorsClbk = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsDefaultCallback:
|
||||||
|
* @file: the error location file name (__FILE__ macro).
|
||||||
|
* @line: the error location line number (__LINE__ macro).
|
||||||
|
* @func: the error location function name (__FUNCTION__ macro).
|
||||||
|
* @errorObject: the error specific error object
|
||||||
|
* @errorSubject: the error specific error subject.
|
||||||
|
* @reason: the error code.
|
||||||
|
* @msg: the additional error message.
|
||||||
|
*
|
||||||
|
* The default error reporting callback that utilizes LibXML
|
||||||
|
* error reporting #xmlGenericError function.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlSecErrorsDefaultCallback(const char* file, int line, const char* func,
|
||||||
|
const char* errorObject, const char* errorSubject,
|
||||||
|
int reason, const char* msg) {
|
||||||
|
if(xmlSecPrintErrorMessages) {
|
||||||
|
const char* error_msg = NULL;
|
||||||
|
xmlSecSize i;
|
||||||
|
|
||||||
|
for(i = 0; (i < XMLSEC_ERRORS_MAX_NUMBER) && (xmlSecErrorsGetMsg(i) != NULL); ++i) {
|
||||||
|
if(xmlSecErrorsGetCode(i) == reason) {
|
||||||
|
error_msg = xmlSecErrorsGetMsg(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlGenericError(xmlGenericErrorContext,
|
||||||
|
"func=%s:file=%s:line=%d:obj=%s:subj=%s:error=%d:%s:%s\n",
|
||||||
|
(func != NULL) ? func : "unknown",
|
||||||
|
(file != NULL) ? file : "unknown",
|
||||||
|
line,
|
||||||
|
(errorObject != NULL) ? errorObject : "unknown",
|
||||||
|
(errorSubject != NULL) ? errorSubject : "unknown",
|
||||||
|
reason,
|
||||||
|
(error_msg != NULL) ? error_msg : "",
|
||||||
|
(msg != NULL) ? msg : "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsDefaultCallbackEnableOutput:
|
||||||
|
* @enabled: the flag.
|
||||||
|
*
|
||||||
|
* Enables or disables calling LibXML2 callback from the default
|
||||||
|
* errors callback.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlSecErrorsDefaultCallbackEnableOutput(int enabled) {
|
||||||
|
xmlSecPrintErrorMessages = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsGetCode:
|
||||||
|
* @pos: the error position.
|
||||||
|
*
|
||||||
|
* Gets the known error code at position @pos.
|
||||||
|
*
|
||||||
|
* Returns: the known error code or 0 if @pos is greater than
|
||||||
|
* total number of known error codes.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xmlSecErrorsGetCode(xmlSecSize pos) {
|
||||||
|
/* could not use asserts here! */
|
||||||
|
if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) {
|
||||||
|
return(xmlSecErrorsTable[pos].errorCode);
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecErrorsGetMsg:
|
||||||
|
* @pos: the error position.
|
||||||
|
*
|
||||||
|
* Gets the known error message at position @pos.
|
||||||
|
*
|
||||||
|
* Returns: the known error message or NULL if @pos is greater than
|
||||||
|
* total number of known error codes.
|
||||||
|
*/
|
||||||
|
const char*
|
||||||
|
xmlSecErrorsGetMsg(xmlSecSize pos) {
|
||||||
|
/* could not use asserts here! */
|
||||||
|
if(pos < sizeof(xmlSecErrorsTable) / sizeof(xmlSecErrorsTable[0])) {
|
||||||
|
return(xmlSecErrorsTable[pos].errorMsg);
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecError:
|
||||||
|
* @file: the error location filename (__FILE__).
|
||||||
|
* @line: the error location line number (__LINE__).
|
||||||
|
* @func: the error location function (__FUNCTION__).
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @errorSubject: the error specific error subject (e.g. failed function name).
|
||||||
|
* @reason: the error code.
|
||||||
|
* @msg: the error message in printf format.
|
||||||
|
* @...: the parameters for the @msg.
|
||||||
|
*
|
||||||
|
* Reports an error to the default (#xmlSecErrorsDefaultCallback) or
|
||||||
|
* application specific callback installed using #xmlSecErrorsSetCallback
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
xmlSecError(const char* file, int line, const char* func,
|
||||||
|
const char* errorObject, const char* errorSubject,
|
||||||
|
int reason, const char* msg, ...) {
|
||||||
|
if(xmlSecErrorsClbk != NULL) {
|
||||||
|
xmlChar error_msg[XMLSEC_ERRORS_BUFFER_SIZE];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if(msg != NULL) {
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, msg);
|
||||||
|
ret = xmlStrVPrintf(error_msg, sizeof(error_msg), msg, va);
|
||||||
|
if(ret < 0) {
|
||||||
|
/* Can't really report an error from an error callback */
|
||||||
|
memcpy(error_msg, fatal_error, sizeof(fatal_error));
|
||||||
|
}
|
||||||
|
error_msg[sizeof(error_msg) - 1] = '\0'; /* just in case */
|
||||||
|
va_end(va);
|
||||||
|
} else {
|
||||||
|
error_msg[0] = '\0';
|
||||||
|
}
|
||||||
|
xmlSecErrorsClbk(file, line, func, errorObject, errorSubject, reason, (char*)error_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
869
experimental/facho-signer/src/xmlsec1/errors_helpers.h
Normal file
869
experimental/facho-signer/src/xmlsec1/errors_helpers.h
Normal file
@@ -0,0 +1,869 @@
|
|||||||
|
/*
|
||||||
|
* XML Security Library (http://www.aleksey.com/xmlsec).
|
||||||
|
*
|
||||||
|
* Internal header only used during the compilation,
|
||||||
|
*
|
||||||
|
* This is free software; see Copyright file in the source
|
||||||
|
* distribution for preciese wording.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __XMLSEC_ERROR_HELPERS_H__
|
||||||
|
#define __XMLSEC_ERROR_HELPERS_H__
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <xmlsec/errors.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
*
|
||||||
|
* Error handling macros.
|
||||||
|
*
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInternalError:
|
||||||
|
* @errorFunction: the failed function name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting internal XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInternalError(errorFunction, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XMLSEC_FAILED, \
|
||||||
|
XMLSEC_ERRORS_NO_MESSAGE \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInternalError2:
|
||||||
|
* @errorFunction: the failed function name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting internal XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInternalError2(errorFunction, errorObject, msg, param) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XMLSEC_FAILED, \
|
||||||
|
(msg), (param) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInternalError3:
|
||||||
|
* @errorFunction: the failed function name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param1: the extra message param1.
|
||||||
|
* @param2: the extra message param2.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting internal XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInternalError3(errorFunction, errorObject, msg, param1, param2) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XMLSEC_FAILED, \
|
||||||
|
(msg), (param1), (param2) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInternalError4:
|
||||||
|
* @errorFunction: the failed function name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param1: the extra message param1.
|
||||||
|
* @param2: the extra message param2.
|
||||||
|
* @param3: the extra message param3.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting internal XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInternalError4(errorFunction, errorObject, msg, param1, param2, param3) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XMLSEC_FAILED, \
|
||||||
|
(msg), (param1), (param2), (param3) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecMallocError:
|
||||||
|
* @allocSize: the failed allocation size.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting xmlMalloc() errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecMallocError(allocSize, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
"xmlMalloc", \
|
||||||
|
XMLSEC_ERRORS_R_MALLOC_FAILED, \
|
||||||
|
"size=%lu", (unsigned long)(allocSize) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecStrdupError:
|
||||||
|
* @str: the failed string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting xmlStrdup() errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecStrdupError(str, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
"xmlStrdup", \
|
||||||
|
XMLSEC_ERRORS_R_STRDUP_FAILED, \
|
||||||
|
"size=%lu", (unsigned long)xmlStrlen(str) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecXmlError:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting generic XML errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecXmlError(errorFunction, errorObject) \
|
||||||
|
{ \
|
||||||
|
xmlErrorPtr error = xmlGetLastError(); \
|
||||||
|
int code = (error != NULL) ? error->code : 0; \
|
||||||
|
const char* message = (error != NULL) ? error->message : NULL; \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XML_FAILED, \
|
||||||
|
"xml error: %lu: %s", \
|
||||||
|
(unsigned long)code, \
|
||||||
|
xmlSecErrorsSafeString(message) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecXmlError2:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting generic XML errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecXmlError2(errorFunction, errorObject, msg, param) \
|
||||||
|
{ \
|
||||||
|
xmlErrorPtr error = xmlGetLastError(); \
|
||||||
|
int code = (error != NULL) ? error->code : 0; \
|
||||||
|
const char* message = (error != NULL) ? error->message : NULL; \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XML_FAILED, \
|
||||||
|
msg "; xml error: %lu: %s", \
|
||||||
|
(param), \
|
||||||
|
(unsigned long)code, \
|
||||||
|
xmlSecErrorsSafeString(message) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecXmlParserError:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @ctxt: the parser context.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting XML parser errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecXmlParserError(errorFunction, ctxt, errorObject) \
|
||||||
|
{ \
|
||||||
|
xmlErrorPtr error = xmlCtxtGetLastError(ctxt);\
|
||||||
|
int code = (error != NULL) ? error->code : 0; \
|
||||||
|
const char* message = (error != NULL) ? error->message : NULL; \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XML_FAILED, \
|
||||||
|
"xml error: %lu: %s", \
|
||||||
|
(unsigned long)code, \
|
||||||
|
xmlSecErrorsSafeString(message) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecXmlParserError2:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @ctxt: the parser context.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting XML parser errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecXmlParserError2(errorFunction, ctxt, errorObject, msg, param) \
|
||||||
|
{ \
|
||||||
|
xmlErrorPtr error = xmlCtxtGetLastError(ctxt);\
|
||||||
|
int code = (error != NULL) ? error->code : 0; \
|
||||||
|
const char* message = (error != NULL) ? error->message : NULL; \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XML_FAILED, \
|
||||||
|
msg "; xml error: %lu: %s", \
|
||||||
|
(param), \
|
||||||
|
(unsigned long)code, \
|
||||||
|
xmlSecErrorsSafeString(message) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecXsltError:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @ctxt: the parser context.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting XSLT errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecXsltError(errorFunction, ctxt, errorObject) \
|
||||||
|
{ \
|
||||||
|
xmlErrorPtr error = xmlGetLastError(); \
|
||||||
|
int code = (error != NULL) ? error->code : 0; \
|
||||||
|
const char* message = (error != NULL) ? error->message : NULL; \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_XSLT_FAILED, \
|
||||||
|
"xslt error: %lu: %s", \
|
||||||
|
(unsigned long)code, \
|
||||||
|
xmlSecErrorsSafeString(message) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecIOError:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @name: the filename, function name, uri, etc.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting IO errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecIOError(errorFunction, name, errorObject) \
|
||||||
|
{ \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_IO_FAILED, \
|
||||||
|
"name=\"%s\"; errno=%d", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
errno \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecNotImplementedError:
|
||||||
|
* @details: the additional details.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "not implemented" errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecNotImplementedError(details) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
NULL, \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_NOT_IMPLEMENTED, \
|
||||||
|
"details=%s", \
|
||||||
|
xmlSecErrorsSafeString(details) \
|
||||||
|
)
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidSizeError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value.
|
||||||
|
* @expected: the expected value.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid size" errors when
|
||||||
|
* we expect exact match.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidSizeError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_SIZE, \
|
||||||
|
"invalid size for '%s': actual=%lu is not equal to expected=%lu", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(unsigned long)(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidSizeLessThanError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value.
|
||||||
|
* @expected: the expected value.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid size" errors when
|
||||||
|
* we expect at least the expected size.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidSizeLessThanError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_SIZE, \
|
||||||
|
"invalid size for '%s': actual=%lu is less than expected=%lu", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(unsigned long)(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidSizeMoreThanError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value.
|
||||||
|
* @expected: the expected value.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid size" errors when
|
||||||
|
* we expect at most the expected size.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidSizeMoreThanError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_NOT_IMPLEMENTED, \
|
||||||
|
"invalid size for '%s': actual=%lu is more than expected=%lu", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(unsigned long)(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidSizeNotMultipleOfError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value.
|
||||||
|
* @divider: the expected divider.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid size" errors when
|
||||||
|
* we expect the size to be a multiple of the divider.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidSizeNotMultipleOfError(name, actual, divider, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_NOT_IMPLEMENTED, \
|
||||||
|
"invalid size for '%s': actual=%lu is not a multiple of %lu", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(unsigned long)(divider) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidSizeOtherError:
|
||||||
|
* @msg: the message about the error.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid size" errors when
|
||||||
|
* we expect exact match.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidSizeOtherError(msg, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_SIZE, \
|
||||||
|
"invalid size: %s", \
|
||||||
|
xmlSecErrorsSafeString(msg) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidDataError:
|
||||||
|
* @msg: the msg with explanation.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid data" errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidDataError(msg, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_DATA, \
|
||||||
|
"%s", \
|
||||||
|
xmlSecErrorsSafeString(msg) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidStringDataError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value as a string.
|
||||||
|
* @expected: the expected value(s) as a string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid data" errors for string.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidStringDataError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_DATA, \
|
||||||
|
"invalid data for '%s': actual='%s' and expected %s", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
xmlSecErrorsSafeString(actual), \
|
||||||
|
(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidIntegerDataError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value as an integer.
|
||||||
|
* @expected: the expected value(s) as a string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid data" errors for integers.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidIntegerDataError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_DATA, \
|
||||||
|
"invalid data for '%s': actual=%ld and expected %s", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidIntegerDataError2:
|
||||||
|
* @name1: the name of the first variable, parameter, etc.
|
||||||
|
* @actual1: the actual first value as an integer.
|
||||||
|
* @name2: the name of the second variable, parameter, etc.
|
||||||
|
* @actual2: the actual second value as an integer.
|
||||||
|
* @expected: the expected value(s) as a string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid data" errors for integers.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidIntegerDataError2(name1, actual1, name2, actual2, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_DATA, \
|
||||||
|
"invalid data: actual value '%s'=%ld, actual value '%s'=%ld and expected %s", \
|
||||||
|
xmlSecErrorsSafeString(name1), \
|
||||||
|
(unsigned long)(actual1), \
|
||||||
|
xmlSecErrorsSafeString(name2), \
|
||||||
|
(unsigned long)(actual2), \
|
||||||
|
(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidTypeError:
|
||||||
|
* @msg: the msg with explanation.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid type" errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidTypeError(msg, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_TYPE, \
|
||||||
|
"%s", \
|
||||||
|
xmlSecErrorsSafeString(msg) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidStringTypeError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value as a string.
|
||||||
|
* @expected: the expected value(s) as a string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid type" errors for string.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidStringTypeError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_TYPE, \
|
||||||
|
"invalid type for '%s': actual='%s' and expected %s", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
xmlSecErrorsSafeString(actual), \
|
||||||
|
(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidIntegerTypeError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value as an integer.
|
||||||
|
* @expected: the expected value(s) as a string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid type" errors for integers.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidIntegerTypeError(name, actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_TYPE, \
|
||||||
|
"invalid type for '%s': actual=%ld and expected %s", \
|
||||||
|
xmlSecErrorsSafeString(name), \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidIntegerTypeError2:
|
||||||
|
* @name1: the name of the first variable, parameter, etc.
|
||||||
|
* @actual1: the actual first value as an integer.
|
||||||
|
* @name2: the name of the second variable, parameter, etc.
|
||||||
|
* @actual2: the actual second value as an integer.
|
||||||
|
* @expected: the expected value(s) as a string.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid type" errors for integers.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidIntegerTypeError2(name1, actual1, name2, actual2, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_TYPE, \
|
||||||
|
"invalid type: actual value '%s'=%ld, actual value '%s'=%ld and expected %s", \
|
||||||
|
xmlSecErrorsSafeString(name1), \
|
||||||
|
(unsigned long)(actual1), \
|
||||||
|
xmlSecErrorsSafeString(name2), \
|
||||||
|
(unsigned long)(actual2), \
|
||||||
|
(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidNodeError:
|
||||||
|
* @actualNode: the actual node.
|
||||||
|
* @expectedNodeName: the expected node name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid node errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidNodeError(actualNode, expectedNodeName, errorObject) \
|
||||||
|
{ \
|
||||||
|
const char* actualNodeName = xmlSecNodeGetName(actualNode); \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_NODE, \
|
||||||
|
"actual=%s; expected=%s", \
|
||||||
|
xmlSecErrorsSafeString(actualNodeName), \
|
||||||
|
xmlSecErrorsSafeString(expectedNodeName) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidNodeContentError:
|
||||||
|
* @node: the node.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @reason: the reason why node content is invalid.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid node content errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidNodeContentError(node, errorObject, reason) \
|
||||||
|
{ \
|
||||||
|
const char* nName = xmlSecNodeGetName(node); \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_NODE_CONTENT, \
|
||||||
|
"node=%s; reason=%s", \
|
||||||
|
xmlSecErrorsSafeString(nName), \
|
||||||
|
xmlSecErrorsSafeString(reason) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidNodeAttributeError:
|
||||||
|
* @node: the node.
|
||||||
|
* @attrName: the attribute name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @reason: the reason why node content is invalid.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid node attribute errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidNodeAttributeError(node, attrName, errorObject, reason) \
|
||||||
|
{ \
|
||||||
|
const char* nName = xmlSecNodeGetName(node); \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_NODE_ATTRIBUTE, \
|
||||||
|
"node=%s; attribute=%s; reason=%s",\
|
||||||
|
xmlSecErrorsSafeString(nName), \
|
||||||
|
xmlSecErrorsSafeString(attrName), \
|
||||||
|
xmlSecErrorsSafeString(reason) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecNodeAlreadyPresentError:
|
||||||
|
* @parent: the parent node.
|
||||||
|
* @nodeName: the node name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting node already present errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecNodeAlreadyPresentError(parent, nodeName, errorObject) \
|
||||||
|
{ \
|
||||||
|
const char* pName = xmlSecNodeGetName(parent);\
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_NODE_ALREADY_PRESENT, \
|
||||||
|
"parent=%s; node=%s", \
|
||||||
|
xmlSecErrorsSafeString(pName), \
|
||||||
|
xmlSecErrorsSafeString(nodeName) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecUnexpectedNodeError:
|
||||||
|
* @node: the node.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid node errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecUnexpectedNodeError(node, errorObject) \
|
||||||
|
{ \
|
||||||
|
const char* nName = xmlSecNodeGetName(node); \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_UNEXPECTED_NODE, \
|
||||||
|
"node=%s", \
|
||||||
|
xmlSecErrorsSafeString(nName) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecNodeNotFoundError:
|
||||||
|
* @errorFunction: the failed function.
|
||||||
|
* @startNode: the search start node.
|
||||||
|
* @targetNodeName: the expected child node name.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting node not found errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecNodeNotFoundError(errorFunction, startNode, targetNodeName, errorObject) \
|
||||||
|
{ \
|
||||||
|
const char* startNodeName = xmlSecNodeGetName(startNode); \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
(errorFunction), \
|
||||||
|
XMLSEC_ERRORS_R_NODE_NOT_FOUND, \
|
||||||
|
"startNode=%s; target=%s", \
|
||||||
|
xmlSecErrorsSafeString(startNodeName), \
|
||||||
|
xmlSecErrorsSafeString(targetNodeName) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidTransfromError:
|
||||||
|
* @transform: the transform.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid transform errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidTransfromError(transform) \
|
||||||
|
{ \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)xmlSecTransformGetName(transform), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_TRANSFORM, \
|
||||||
|
XMLSEC_ERRORS_NO_MESSAGE \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidTransfromError2:
|
||||||
|
* @transform: the transform.
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param: the extra message param.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid transform errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidTransfromError2(transform, msg, param) \
|
||||||
|
{ \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)xmlSecTransformGetName(transform), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_TRANSFORM, \
|
||||||
|
(msg), (param) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidTransfromStatusError:
|
||||||
|
* @transform: the transform.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid transform status errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidTransfromStatusError(transform) \
|
||||||
|
{ \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)xmlSecTransformGetName(transform), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_STATUS, \
|
||||||
|
"transformStatus=%d", \
|
||||||
|
(int)((transform)->status) \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidTransfromStatusError2:
|
||||||
|
* @transform: the transform.
|
||||||
|
* @msg: the extra message.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting an invalid transform status errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidTransfromStatusError2(transform, msg) \
|
||||||
|
{ \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)xmlSecTransformGetName(transform), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_STATUS, \
|
||||||
|
"transformStatus=%ld, msg=%s", \
|
||||||
|
(long int)((transform)->status), \
|
||||||
|
msg \
|
||||||
|
); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidKeyDataSizeError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @actual: the actual value.
|
||||||
|
* @expected: the expected value(s).
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid keydata size" errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidKeyDataSizeError(actual, expected, errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, \
|
||||||
|
"invalid key data size: actual=%ld and expected=%ld", \
|
||||||
|
(unsigned long)(actual), \
|
||||||
|
(unsigned long)(expected) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecInvalidZeroKeyDataSizeError:
|
||||||
|
* @name: the name of the variable, parameter, etc.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting "invalid keydata size" errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecInvalidZeroKeyDataSizeError(errorObject) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
XMLSEC_ERRORS_R_INVALID_KEY_DATA_SIZE, \
|
||||||
|
"invalid zero key data size" \
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecOtherError:
|
||||||
|
* @code: the error code.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @details: the error message.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting other XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecOtherError(code, errorObject, details) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
(code), \
|
||||||
|
"details=%s", \
|
||||||
|
xmlSecErrorsSafeString(details) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecOtherError2:
|
||||||
|
* @code: the error code.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting other XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecOtherError2(code, errorObject, msg, param) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
(code), \
|
||||||
|
(msg), (param) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecOtherError3:
|
||||||
|
* @code: the error code.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param1: the extra message param.
|
||||||
|
* @param2: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting other XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecOtherError3(code, errorObject, msg, param1, param2) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
(code), \
|
||||||
|
(msg), (param1), (param2) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecOtherError4:
|
||||||
|
* @code: the error code.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param1: the extra message param.
|
||||||
|
* @param2: the extra message param.
|
||||||
|
* @param3: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting other XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecOtherError4(code, errorObject, msg, param1, param2, param3) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
(code), \
|
||||||
|
(msg), (param1), (param2), (param3) \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xmlSecOtherError5:
|
||||||
|
* @code: the error code.
|
||||||
|
* @errorObject: the error specific error object (e.g. transform, key data, etc).
|
||||||
|
* @msg: the extra message.
|
||||||
|
* @param1: the extra message param.
|
||||||
|
* @param2: the extra message param.
|
||||||
|
* @param3: the extra message param.
|
||||||
|
* @param4: the extra message param.
|
||||||
|
*
|
||||||
|
* Macro. The XMLSec library macro for reporting other XMLSec errors.
|
||||||
|
*/
|
||||||
|
#define xmlSecOtherError5(code, errorObject, msg, param1, param2, param3, param4) \
|
||||||
|
xmlSecError(XMLSEC_ERRORS_HERE, \
|
||||||
|
(const char*)(errorObject), \
|
||||||
|
NULL, \
|
||||||
|
(code), \
|
||||||
|
(msg), (param1), (param2), (param3), (param4) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif /* __XMLSEC_ERROR_HELPERS_H__ */
|
||||||
1950
experimental/facho-signer/src/xmlsec1/xmltree.c
Normal file
1950
experimental/facho-signer/src/xmlsec1/xmltree.c
Normal file
File diff suppressed because it is too large
Load Diff
200
experimental/facho-signer/src/xmlusigned.xml
Normal file
200
experimental/facho-signer/src/xmlusigned.xml
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Invoice xmlns="http://www.dian.gov.co/contratos/facturaelectronica/v1" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cdt="urn:DocumentInformation:names:specification:ubl:colombia:schema:xsd:DocumentInformationAggregateComponents-1" xmlns:clm54217="urn:un:unece:uncefact:codelist:specification:54217:2001" xmlns:clmIANAMIMEMediaType="urn:un:unece:uncefact:codelist:specification:IANAMIMEMediaType:2003" xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2" xmlns:sts="http://www.dian.gov.co/contratos/facturaelectronica/v1/Structures" xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:sig="http://www.w3.org/2000/09/xmldsig#">
|
||||||
|
<ext:UBLExtensions>
|
||||||
|
<ext:UBLExtension>
|
||||||
|
<ext:ExtensionContent>
|
||||||
|
<sts:DianExtensions>
|
||||||
|
<sts:SoftwareSecurityCode schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195">2bd9a18f23cf1188d36888d218e9b0c31df77aa00bc036eaeaa1619184054237eee56d2d8db4ecab0173f65f8dab7753</sts:SoftwareSecurityCode>
|
||||||
|
<sts:AuthorizationProvider>
|
||||||
|
<sts:AuthorizationProviderID schemeID="4" schemeName="31" schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195">800197268</sts:AuthorizationProviderID>
|
||||||
|
</sts:AuthorizationProvider>
|
||||||
|
<sts:SoftwareProvider>
|
||||||
|
<sts:ProviderID schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195" schemeID="5" schemaName="31">900579212</sts:ProviderID>
|
||||||
|
<sts:SoftwareID schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195">01ab9caa-6838-461e-82fb-da44da36a084</sts:SoftwareID>
|
||||||
|
</sts:SoftwareProvider>
|
||||||
|
<sts:InvoiceSource>
|
||||||
|
<cbc:IdentificationCode>CO</cbc:IdentificationCode>
|
||||||
|
</sts:InvoiceSource>
|
||||||
|
<sts:InvoiceControl>
|
||||||
|
<sts:InvoiceAuthorization>fc8eac422eba16e22ffd8c6f94b3f40a6e38162c</sts:InvoiceAuthorization>
|
||||||
|
<sts:AuthorizationPeriod>
|
||||||
|
<cbc:StartDate>2019-01-19</cbc:StartDate>
|
||||||
|
<cbc:EndDate>2030-01-19</cbc:EndDate>
|
||||||
|
</sts:AuthorizationPeriod>
|
||||||
|
<sts:AuthorizedInvoices>
|
||||||
|
<sts:Prefix>SETP</sts:Prefix>
|
||||||
|
<sts:From>990000000</sts:From>
|
||||||
|
<sts:To>995000000</sts:To>
|
||||||
|
</sts:AuthorizedInvoices>
|
||||||
|
</sts:InvoiceControl>
|
||||||
|
</sts:DianExtensions>
|
||||||
|
</ext:ExtensionContent>
|
||||||
|
</ext:UBLExtension>
|
||||||
|
</ext:UBLExtensions>
|
||||||
|
<cbc:UBLVersionID>UBL 2.1</cbc:UBLVersionID>
|
||||||
|
<cbc:CustomizationID>10</cbc:CustomizationID>
|
||||||
|
<cbc:ProfileID>DIAN 2.1</cbc:ProfileID>
|
||||||
|
<cbc:ProfileExecutionID>2</cbc:ProfileExecutionID>
|
||||||
|
<cbc:ID>SETP990000001</cbc:ID>
|
||||||
|
<cbc:UUID schemeID="2" schemeName="CUFE-SHA384">50578625ce1fb2f6bb2bc57b22180d2763c8a868c4e62da72e0e43001f9c7f3459c81e2bf9324830175b1225af37e435</cbc:UUID>
|
||||||
|
<cbc:DocumentCurrencyCode>COP</cbc:DocumentCurrencyCode>
|
||||||
|
<cbc:IssueDate>2020-09-05</cbc:IssueDate>
|
||||||
|
<cbc:IssueTime>22:38:53-05:00</cbc:IssueTime>
|
||||||
|
<cbc:InvoiceTypeCode listAgencyID="195" listAgencyName="No matching global declaration available for the validation root" listURI="http://www.dian.gov.co">01</cbc:InvoiceTypeCode>
|
||||||
|
<cbc:LineCountNumeric>1</cbc:LineCountNumeric>
|
||||||
|
<cac:InvoicePeriod>
|
||||||
|
<cbc:StartDate>2020-09-05</cbc:StartDate>
|
||||||
|
<cbc:EndDate>2020-09-05</cbc:EndDate>
|
||||||
|
</cac:InvoicePeriod>
|
||||||
|
<cac:AccountingSupplierParty>
|
||||||
|
<cbc:AdditionalAccountID>1</cbc:AdditionalAccountID>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>NEUROTEC TECNOLOGIA S.A.S</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PhysicalLocation>
|
||||||
|
<cac:Address>
|
||||||
|
<cac:AddressLine>
|
||||||
|
<cbc:Line/>
|
||||||
|
</cac:AddressLine>
|
||||||
|
</cac:Address>
|
||||||
|
</cac:PhysicalLocation>
|
||||||
|
<cac:PartyLegalEntity>
|
||||||
|
<cbc:CompanyID schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195" schemeID="5" schemeName="31">900579212</cbc:CompanyID>
|
||||||
|
<cbc:RegistrationName>NEUROTEC TECNOLOGIA S.A.S</cbc:RegistrationName>
|
||||||
|
<cac:RegistrationAddress>
|
||||||
|
<cbc:CityName/>
|
||||||
|
<cac:AddressLine>
|
||||||
|
<cbc:Line/>
|
||||||
|
</cac:AddressLine>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>CO</cbc:IdentificationCode>
|
||||||
|
<cbc:Name>COLOMBIA</cbc:Name>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:RegistrationAddress>
|
||||||
|
</cac:PartyLegalEntity>
|
||||||
|
<cac:PartyTaxScheme>
|
||||||
|
<cbc:RegistrationName>NEUROTEC TECNOLOGIA S.A.S</cbc:RegistrationName>
|
||||||
|
<cbc:CompanyID schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195" schemeID="5" schemeName="31">900579212</cbc:CompanyID>
|
||||||
|
<cbc:TaxLevelCode listName="48">ZZ;O-09;O-14;O-48</cbc:TaxLevelCode>
|
||||||
|
<cac:TaxScheme/>
|
||||||
|
</cac:PartyTaxScheme>
|
||||||
|
<cac:Contact>
|
||||||
|
<cbc:ElectronicMail>sdds@sd.com</cbc:ElectronicMail>
|
||||||
|
</cac:Contact>
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingSupplierParty>
|
||||||
|
<cac:AccountingCustomerParty>
|
||||||
|
<cbc:AdditionalAccountID>2</cbc:AdditionalAccountID>
|
||||||
|
<cac:Party>
|
||||||
|
<cac:PartyName>
|
||||||
|
<cbc:Name>facho-customer</cbc:Name>
|
||||||
|
</cac:PartyName>
|
||||||
|
<cac:PhysicalLocation>
|
||||||
|
<cac:Address>
|
||||||
|
<cac:AddressLine>
|
||||||
|
<cbc:Line/>
|
||||||
|
</cac:AddressLine>
|
||||||
|
</cac:Address>
|
||||||
|
</cac:PhysicalLocation>
|
||||||
|
<cac:PartyTaxScheme>
|
||||||
|
<cbc:CompanyID schemeAgencyName="CO, DIAN (Dirección de Impuestos y Aduanas Nacionales)" schemeAgencyID="195" schemeID="" schemeName="13">43851425</cbc:CompanyID>
|
||||||
|
<cbc:RegistrationName>facho-customer</cbc:RegistrationName>
|
||||||
|
<cbc:TaxLevelCode>ZZ</cbc:TaxLevelCode>
|
||||||
|
<cac:TaxScheme/>
|
||||||
|
</cac:PartyTaxScheme>
|
||||||
|
<cac:PartyLegalEntity>
|
||||||
|
<cbc:RegistrationName>facho-customer</cbc:RegistrationName>
|
||||||
|
<cac:RegistrationAddress>
|
||||||
|
<cbc:CityName/>
|
||||||
|
<cac:AddressLine>
|
||||||
|
<cbc:Line/>
|
||||||
|
</cac:AddressLine>
|
||||||
|
<cac:Country>
|
||||||
|
<cbc:IdentificationCode>CO</cbc:IdentificationCode>
|
||||||
|
<cbc:Name>COLOMBIA</cbc:Name>
|
||||||
|
</cac:Country>
|
||||||
|
</cac:RegistrationAddress>
|
||||||
|
</cac:PartyLegalEntity>
|
||||||
|
</cac:Party>
|
||||||
|
</cac:AccountingCustomerParty>
|
||||||
|
<cac:LegalMonetaryTotal>
|
||||||
|
<cbc:LineExtensionAmount currencyID="COP">100.00</cbc:LineExtensionAmount>
|
||||||
|
<cbc:TaxExclusiveAmount currencyID="COP">100.00</cbc:TaxExclusiveAmount>
|
||||||
|
<cbc:TaxInclusiveAmount currencyID="COP">119.00</cbc:TaxInclusiveAmount>
|
||||||
|
<cbc:ChargeTotalAmount currencyID="COP">19.00</cbc:ChargeTotalAmount>
|
||||||
|
<cbc:PayableAmount currencyID="COP">119.00</cbc:PayableAmount>
|
||||||
|
</cac:LegalMonetaryTotal>
|
||||||
|
<cac:TaxTotal/>
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cac:TaxSubtotal>
|
||||||
|
<cac:TaxCategory>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>01</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:TaxCategory>
|
||||||
|
</cac:TaxSubtotal>
|
||||||
|
<cbc:TaxAmount>19.00</cbc:TaxAmount>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cac:TaxSubtotal>
|
||||||
|
<cac:TaxCategory>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>04</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:TaxCategory>
|
||||||
|
</cac:TaxSubtotal>
|
||||||
|
<cbc:TaxAmount>0.00</cbc:TaxAmount>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cac:TaxSubtotal>
|
||||||
|
<cac:TaxCategory>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>03</cbc:ID>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:TaxCategory>
|
||||||
|
</cac:TaxSubtotal>
|
||||||
|
<cbc:TaxAmount>0.00</cbc:TaxAmount>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
<cac:InvoiceLine>
|
||||||
|
<cbc:ID>1</cbc:ID>
|
||||||
|
<cbc:InvoicedQuantity unitCode="NAR">1</cbc:InvoicedQuantity>
|
||||||
|
<cbc:LineExtensionAmount currencyID="COP">100.0</cbc:LineExtensionAmount>
|
||||||
|
<cac:TaxTotal>
|
||||||
|
<cbc:TaxAmount currencyID="COP">19.0</cbc:TaxAmount>
|
||||||
|
<cac:TaxSubtotal>
|
||||||
|
<cbc:TaxableAmount currencyID="COP">100.0</cbc:TaxableAmount>
|
||||||
|
<cbc:TaxAmount currencyID="COP">19.0</cbc:TaxAmount>
|
||||||
|
<cac:TaxCategory>
|
||||||
|
<cbc:Percent>19.0</cbc:Percent>
|
||||||
|
<cac:TaxScheme>
|
||||||
|
<cbc:ID>01</cbc:ID>
|
||||||
|
<cbc:Name>IVA</cbc:Name>
|
||||||
|
</cac:TaxScheme>
|
||||||
|
</cac:TaxCategory>
|
||||||
|
</cac:TaxSubtotal>
|
||||||
|
</cac:TaxTotal>
|
||||||
|
<cac:PricingReference>
|
||||||
|
<cac:AlternativeConditionPrice>
|
||||||
|
<cbc:PriceAmount currencyID="COP">100.0</cbc:PriceAmount>
|
||||||
|
<cbc:PriceTypeCode>01</cbc:PriceTypeCode>
|
||||||
|
<cbc:PriceType>x</cbc:PriceType>
|
||||||
|
</cac:AlternativeConditionPrice>
|
||||||
|
</cac:PricingReference>
|
||||||
|
<cac:Item>
|
||||||
|
<cbc:Description>test</cbc:Description>
|
||||||
|
<cac:StandardItemIdentification>
|
||||||
|
<cbc:ID>9999</cbc:ID>
|
||||||
|
</cac:StandardItemIdentification>
|
||||||
|
</cac:Item>
|
||||||
|
<cac:Price>
|
||||||
|
<cbc:PriceAmount currencyID="COP">100.0</cbc:PriceAmount>
|
||||||
|
</cac:Price>
|
||||||
|
</cac:InvoiceLine>
|
||||||
|
<cac:PaymentMeans>
|
||||||
|
<cbc:ID>1</cbc:ID>
|
||||||
|
<cbc:PaymentMeansCode>10</cbc:PaymentMeansCode>
|
||||||
|
<cbc:PaymentDueDate>2020-09-05</cbc:PaymentDueDate>
|
||||||
|
<cbc:PaymentID>1</cbc:PaymentID>
|
||||||
|
</cac:PaymentMeans>
|
||||||
|
</Invoice>
|
||||||
7
experimental/facho-wasm/xmlsec-wasm/build.sh
Normal file
7
experimental/facho-wasm/xmlsec-wasm/build.sh
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
sh build_openssl.sh
|
||||||
|
sh build_libxml2.sh
|
||||||
|
sh build_xmlsec.sh
|
||||||
21
experimental/facho-wasm/xmlsec-wasm/build_libxml2.sh
Normal file
21
experimental/facho-wasm/xmlsec-wasm/build_libxml2.sh
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
LIBXML2_VERSION=2.9.12
|
||||||
|
|
||||||
|
tar xf libxml2-${LIBXML2_VERSION}.tar.gz
|
||||||
|
|
||||||
|
mv libxml2-${LIBXML2_VERSION} libxml2
|
||||||
|
|
||||||
|
pushd libxml2
|
||||||
|
|
||||||
|
wasiconfigure ./configure --enable-static --without-http --without-ftp --without-modules --without-python --without-zlib --without-lzma --without-threads --host=x86_64
|
||||||
|
|
||||||
|
wasimake make clean
|
||||||
|
wasimake make -j4
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
mkdir -p vendor/libxml2/lib
|
||||||
|
mkdir -p vendor/libxml2/include
|
||||||
|
cp -r libxml2/include/libxml2 vendor/libxml2/include
|
||||||
|
cp -r libxml2/.libs/libxml2.a vendor/libxml2/lib
|
||||||
41
experimental/facho-wasm/xmlsec-wasm/build_openssl.sh
Normal file
41
experimental/facho-wasm/xmlsec-wasm/build_openssl.sh
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# TOMADO DE: https://github.com/voltbuilder/openssl-wasm
|
||||||
|
|
||||||
|
OPENSSL_VERSION=1.1.1l
|
||||||
|
|
||||||
|
# get the source
|
||||||
|
tar xf openssl-${OPENSSL_VERSION}.tar.gz
|
||||||
|
|
||||||
|
patch -p0 < openssl-${OPENSSL_VERSION}.patch
|
||||||
|
|
||||||
|
cd openssl-${OPENSSL_VERSION}
|
||||||
|
make clean
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# why ./Configure instead of ./config? We want to force using the generic gcc profile which is more conservative than linux-x32
|
||||||
|
# -no-sock - we don't have sockets in WASI
|
||||||
|
# new -no-ui-console - sdk 12 has no termios???
|
||||||
|
# check in 12 -DHAVE_FORK=0 - no fork() in WASI
|
||||||
|
# new -D_WASI_EMULATED_MMAN - works with the library below to enable WASI mman emulation
|
||||||
|
# new -D_WASI_EMULATED_SIGNAL - with sdk 12
|
||||||
|
# new -DOPENSSL_NO_SECURE_MEMORY - wasi doesn't have secure mem (madvise, mlock, etc...)
|
||||||
|
# new -DNO_SYSLOG - get rid of need for patch above
|
||||||
|
# --with-rand-seed=getrandom (needed to force using getentropy because WASI has no /dev/random or getrandom)
|
||||||
|
wasiconfigure ./Configure gcc -no-sock -no-ui-console -DHAVE_FORK=0 -D_WASI_EMULATED_MMAN -D_WASI_EMULATED_SIGNAL -DOPENSSL_NO_SECURE_MEMORY -DNO_SYSLOG --with-rand-seed=getrandom
|
||||||
|
|
||||||
|
# enables stuff from mman.h (see define above) also add -lwasi-emulated-signal
|
||||||
|
#sed -i -e "s/CNF_EX_LIBS=/CNF_EX_LIBS=-lwasi-emulated-mman -lwasi-emulated-signal /g" Makefile
|
||||||
|
|
||||||
|
# build!
|
||||||
|
wasimake make -j4 build_generated libssl.a libcrypto.a
|
||||||
|
|
||||||
|
rm -rf ../vendor/openssl/include
|
||||||
|
mkdir -p ../vendor/openssl/include
|
||||||
|
cp -R include/openssl ../vendor/openssl/include
|
||||||
|
|
||||||
|
mkdir -p ../vendor/openssl/lib/
|
||||||
|
cp libssl.a ../vendor/openssl/lib/
|
||||||
|
cp libcrypto.a ../vendor/openssl/lib/
|
||||||
|
|
||||||
|
exit 0
|
||||||
14
experimental/facho-wasm/xmlsec-wasm/build_xmlsec.sh
Normal file
14
experimental/facho-wasm/xmlsec-wasm/build_xmlsec.sh
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
XMLSEC1_VERSION=1.2.33
|
||||||
|
|
||||||
|
tar xf xmlsec1-${XMLSEC1_VERSION}.tar.gz
|
||||||
|
|
||||||
|
cd xmlsec1-${XMLSEC1_VERSION}
|
||||||
|
|
||||||
|
cp -r ../libxml2 .
|
||||||
|
cp -r ../vendor .
|
||||||
|
|
||||||
|
wasiconfigure ./configure --with-libxml-src=`pwd`/libxml2 --with-openssl=`pwd`/vendor/openssl --enable-static-linking --disable-folders-search --disable-apps --disable-apps-crypto-dl --disable-crypto-dl
|
||||||
|
|
||||||
|
wasimake make -j4
|
||||||
6
experimental/facho-wasm/xmlsec-wasm/examples/README.md
Normal file
6
experimental/facho-wasm/xmlsec-wasm/examples/README.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# ejemplo
|
||||||
|
|
||||||
|
~~~
|
||||||
|
$ bash build.sh
|
||||||
|
$ wasirun ./a.out sign1-tmpl.xml example.key
|
||||||
|
~~~
|
||||||
12
experimental/facho-wasm/xmlsec-wasm/examples/build.sh
Normal file
12
experimental/facho-wasm/xmlsec-wasm/examples/build.sh
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
cp ../vendor/openssl/lib/*.a .
|
||||||
|
cp ../xmlsec1-1.2.33/src/.libs/*.a .
|
||||||
|
cp ../xmlsec1-1.2.33/src/openssl/.libs/*.a .
|
||||||
|
cp ../libxml2/.libs/libxml2.a .
|
||||||
|
|
||||||
|
mkdir -p include
|
||||||
|
|
||||||
|
cp -r ../libxml2/include/libxml include/
|
||||||
|
cp -r ../xmlsec1-1.2.33/include/xmlsec include/
|
||||||
|
cp -r ../vendor/openssl/include/* include/
|
||||||
|
|
||||||
|
wasicc -Iinclude libxml2.a libcrypto.a libssl.a libxmlsec1.a libxmlsec1-openssl.a sign.c
|
||||||
216
experimental/facho-wasm/xmlsec-wasm/examples/sign.c
Normal file
216
experimental/facho-wasm/xmlsec-wasm/examples/sign.c
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
/**
|
||||||
|
* XML Security Library example: Signing a template file.
|
||||||
|
*
|
||||||
|
* Signs a template file using a key from PEM file
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* ./sign1 <xml-tmpl> <pem-key>
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ./sign1 sign1-tmpl.xml rsakey.pem > sign1-res.xml
|
||||||
|
*
|
||||||
|
* The result signature could be validated using verify1 example:
|
||||||
|
* ./verify1 sign1-res.xml rsapub.pem
|
||||||
|
*
|
||||||
|
* This is free software; see Copyright file in the source
|
||||||
|
* distribution for preciese wording.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-2016 Aleksey Sanin <aleksey@aleksey.com>. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#include <libxml/xmlmemory.h>
|
||||||
|
#include <libxml/parser.h>
|
||||||
|
|
||||||
|
#define XMLSEC_NO_XSLT
|
||||||
|
#define XMLSEC_CRYPTO_OPENSSL
|
||||||
|
|
||||||
|
#ifndef XMLSEC_NO_XSLT
|
||||||
|
#include <libxslt/xslt.h>
|
||||||
|
#include <libxslt/security.h>
|
||||||
|
#endif /* XMLSEC_NO_XSLT */
|
||||||
|
|
||||||
|
#include <xmlsec/xmlsec.h>
|
||||||
|
#include <xmlsec/xmltree.h>
|
||||||
|
#include <xmlsec/xmldsig.h>
|
||||||
|
#include <xmlsec/crypto.h>
|
||||||
|
|
||||||
|
int sign_file(const char* tmpl_file, const char* key_file);
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv) {
|
||||||
|
#ifndef XMLSEC_NO_XSLT
|
||||||
|
xsltSecurityPrefsPtr xsltSecPrefs = NULL;
|
||||||
|
#endif /* XMLSEC_NO_XSLT */
|
||||||
|
setenv("RANDFILE", "/dev/random", 1);
|
||||||
|
assert(argv);
|
||||||
|
|
||||||
|
if(argc != 3) {
|
||||||
|
fprintf(stderr, "Error: wrong number of arguments.\n");
|
||||||
|
fprintf(stderr, "Usage: %s <tmpl-file> <key-file>\n", argv[0]);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("template %s key %s\n", argv[1], argv[2]);
|
||||||
|
/* Init libxml and libxslt libraries */
|
||||||
|
xmlInitParser();
|
||||||
|
LIBXML_TEST_VERSION
|
||||||
|
xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
|
||||||
|
xmlSubstituteEntitiesDefault(1);
|
||||||
|
#ifndef XMLSEC_NO_XSLT
|
||||||
|
xmlIndentTreeOutput = 1;
|
||||||
|
#endif /* XMLSEC_NO_XSLT */
|
||||||
|
|
||||||
|
/* Init libxslt */
|
||||||
|
#ifndef XMLSEC_NO_XSLT
|
||||||
|
/* disable everything */
|
||||||
|
xsltSecPrefs = xsltNewSecurityPrefs();
|
||||||
|
xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid);
|
||||||
|
xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid);
|
||||||
|
xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid);
|
||||||
|
xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid);
|
||||||
|
xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid);
|
||||||
|
xsltSetDefaultSecurityPrefs(xsltSecPrefs);
|
||||||
|
#endif /* XMLSEC_NO_XSLT */
|
||||||
|
|
||||||
|
/* Init xmlsec library */
|
||||||
|
if(xmlSecInit() < 0) {
|
||||||
|
fprintf(stderr, "Error: xmlsec initialization failed.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
puts("done xmlSecInit");
|
||||||
|
|
||||||
|
/* Check loaded library version */
|
||||||
|
if(xmlSecCheckVersion() != 1) {
|
||||||
|
fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
puts("done xmlSecCheckVersion");
|
||||||
|
/* Load default crypto engine if we are supporting dynamic
|
||||||
|
* loading for xmlsec-crypto libraries. Use the crypto library
|
||||||
|
* name ("openssl", "nss", etc.) to load corresponding
|
||||||
|
* xmlsec-crypto library.
|
||||||
|
*/
|
||||||
|
#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
|
||||||
|
if(xmlSecCryptoDLLoadLibrary(NULL) < 0) {
|
||||||
|
fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n"
|
||||||
|
"that you have it installed and check shared libraries path\n"
|
||||||
|
"(LD_LIBRARY_PATH and/or LTDL_LIBRARY_PATH) environment variables.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */
|
||||||
|
|
||||||
|
/* Init crypto library */
|
||||||
|
if(xmlSecCryptoAppInit(NULL) < 0) {
|
||||||
|
fprintf(stderr, "Error: crypto initialization failed.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
puts("done xmlSecCryptoAppInit");
|
||||||
|
/* Init xmlsec-crypto library */
|
||||||
|
if(xmlSecCryptoInit() < 0) {
|
||||||
|
fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n");
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
puts("done xmlSecCryptoInit");
|
||||||
|
if(sign_file(argv[1], argv[2]) < 0) {
|
||||||
|
return(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Shutdown xmlsec-crypto library */
|
||||||
|
xmlSecCryptoShutdown();
|
||||||
|
|
||||||
|
/* Shutdown crypto library */
|
||||||
|
xmlSecCryptoAppShutdown();
|
||||||
|
|
||||||
|
/* Shutdown xmlsec library */
|
||||||
|
xmlSecShutdown();
|
||||||
|
|
||||||
|
/* Shutdown libxslt/libxml */
|
||||||
|
#ifndef XMLSEC_NO_XSLT
|
||||||
|
xsltFreeSecurityPrefs(xsltSecPrefs);
|
||||||
|
xsltCleanupGlobals();
|
||||||
|
#endif /* XMLSEC_NO_XSLT */
|
||||||
|
xmlCleanupParser();
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sign_file:
|
||||||
|
* @tmpl_file: the signature template file name.
|
||||||
|
* @key_file: the PEM private key file name.
|
||||||
|
*
|
||||||
|
* Signs the #tmpl_file using private key from #key_file.
|
||||||
|
*
|
||||||
|
* Returns 0 on success or a negative value if an error occurs.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
sign_file(const char* tmpl_file, const char* key_file) {
|
||||||
|
xmlDocPtr doc = NULL;
|
||||||
|
xmlNodePtr node = NULL;
|
||||||
|
xmlSecDSigCtxPtr dsigCtx = NULL;
|
||||||
|
int res = -1;
|
||||||
|
|
||||||
|
assert(tmpl_file);
|
||||||
|
assert(key_file);
|
||||||
|
|
||||||
|
/* load template */
|
||||||
|
doc = xmlParseFile(tmpl_file);
|
||||||
|
if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){
|
||||||
|
fprintf(stderr, "Error: unable to parse file \"%s\"\n", tmpl_file);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find start node */
|
||||||
|
node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs);
|
||||||
|
if(node == NULL) {
|
||||||
|
fprintf(stderr, "Error: start node not found in \"%s\"\n", tmpl_file);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create signature context, we don't need keys manager in this example */
|
||||||
|
dsigCtx = xmlSecDSigCtxCreate(NULL);
|
||||||
|
if(dsigCtx == NULL) {
|
||||||
|
fprintf(stderr,"Error: failed to create signature context\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load private key, assuming that there is not password */
|
||||||
|
dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL);
|
||||||
|
if(dsigCtx->signKey == NULL) {
|
||||||
|
fprintf(stderr,"Error: failed to load private pem key from \"%s\"\n", key_file);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set key name to the file name, this is just an example! */
|
||||||
|
if(xmlSecKeySetName(dsigCtx->signKey, key_file) < 0) {
|
||||||
|
fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sign the template */
|
||||||
|
if(xmlSecDSigCtxSign(dsigCtx, node) < 0) {
|
||||||
|
fprintf(stderr,"Error: signature failed\n");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* print signed document to stdout */
|
||||||
|
xmlDocDump(stdout, doc);
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
res = 0;
|
||||||
|
|
||||||
|
done:
|
||||||
|
/* cleanup */
|
||||||
|
if(dsigCtx != NULL) {
|
||||||
|
xmlSecDSigCtxDestroy(dsigCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(doc != NULL) {
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
}
|
||||||
|
return(res);
|
||||||
|
}
|
||||||
27
experimental/facho-wasm/xmlsec-wasm/examples/sign1-tmpl.xml
Normal file
27
experimental/facho-wasm/xmlsec-wasm/examples/sign1-tmpl.xml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
XML Security Library example: Simple signature template file for sign1 example.
|
||||||
|
-->
|
||||||
|
<Envelope xmlns="urn:envelope">
|
||||||
|
<Data>
|
||||||
|
Hello, World!
|
||||||
|
</Data>
|
||||||
|
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
|
||||||
|
<SignedInfo>
|
||||||
|
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
|
||||||
|
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
|
||||||
|
<Reference URI="">
|
||||||
|
<Transforms>
|
||||||
|
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
|
||||||
|
</Transforms>
|
||||||
|
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
|
||||||
|
<DigestValue></DigestValue>
|
||||||
|
</Reference>
|
||||||
|
</SignedInfo>
|
||||||
|
<SignatureValue/>
|
||||||
|
<KeyInfo>
|
||||||
|
<KeyName/>
|
||||||
|
</KeyInfo>
|
||||||
|
</Signature>
|
||||||
|
</Envelope>
|
||||||
|
|
||||||
199
experimental/facho-wasm/xmlsec-wasm/openssl-1.1.1l.patch
Normal file
199
experimental/facho-wasm/xmlsec-wasm/openssl-1.1.1l.patch
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
diff '--color=auto' -ruN openssl-1.1.1l/crypto/rand/rand_unix.c patch-1.1.1l/crypto/rand/rand_unix.c
|
||||||
|
--- openssl-1.1.1l/crypto/rand/rand_unix.c 2021-08-24 09:38:47.000000000 -0400
|
||||||
|
+++ patch-1.1.1l/crypto/rand/rand_unix.c 2021-09-12 02:26:35.765347423 -0400
|
||||||
|
@@ -372,36 +372,36 @@
|
||||||
|
* Note: Sometimes getentropy() can be provided but not implemented
|
||||||
|
* internally. So we need to check errno for ENOSYS
|
||||||
|
*/
|
||||||
|
-# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux)
|
||||||
|
- extern int getentropy(void *buffer, size_t length) __attribute__((weak));
|
||||||
|
+/* # if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux) */
|
||||||
|
+/* extern int getentropy(void *buffer, size_t length) __attribute__((weak)); */
|
||||||
|
|
||||||
|
- if (getentropy != NULL) {
|
||||||
|
+/* if (getentropy != NULL) { */
|
||||||
|
if (getentropy(buf, buflen) == 0)
|
||||||
|
return (ssize_t)buflen;
|
||||||
|
if (errno != ENOSYS)
|
||||||
|
return -1;
|
||||||
|
- }
|
||||||
|
-# elif defined(__APPLE__)
|
||||||
|
- if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess)
|
||||||
|
- return (ssize_t)buflen;
|
||||||
|
-
|
||||||
|
- return -1;
|
||||||
|
-# else
|
||||||
|
- union {
|
||||||
|
- void *p;
|
||||||
|
- int (*f)(void *buffer, size_t length);
|
||||||
|
- } p_getentropy;
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * We could cache the result of the lookup, but we normally don't
|
||||||
|
- * call this function often.
|
||||||
|
- */
|
||||||
|
- ERR_set_mark();
|
||||||
|
- p_getentropy.p = DSO_global_lookup("getentropy");
|
||||||
|
- ERR_pop_to_mark();
|
||||||
|
- if (p_getentropy.p != NULL)
|
||||||
|
- return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1;
|
||||||
|
-# endif
|
||||||
|
+/* } */
|
||||||
|
+/* # elif defined(__APPLE__) */
|
||||||
|
+/* if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess) */
|
||||||
|
+/* return (ssize_t)buflen; */
|
||||||
|
+
|
||||||
|
+/* return -1; */
|
||||||
|
+/* # else */
|
||||||
|
+/* union { */
|
||||||
|
+/* void *p; */
|
||||||
|
+/* int (*f)(void *buffer, size_t length); */
|
||||||
|
+/* } p_getentropy; */
|
||||||
|
+
|
||||||
|
+/* /\* */
|
||||||
|
+/* * We could cache the result of the lookup, but we normally don't */
|
||||||
|
+/* * call this function often. */
|
||||||
|
+/* *\/ */
|
||||||
|
+/* ERR_set_mark(); */
|
||||||
|
+/* p_getentropy.p = DSO_global_lookup("getentropy"); */
|
||||||
|
+/* ERR_pop_to_mark(); */
|
||||||
|
+/* if (p_getentropy.p != NULL) */
|
||||||
|
+/* return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1; */
|
||||||
|
+/* # endif */
|
||||||
|
|
||||||
|
/* Linux supports this since version 3.17 */
|
||||||
|
# if defined(__linux) && defined(__NR_getrandom)
|
||||||
|
@@ -635,12 +635,12 @@
|
||||||
|
*/
|
||||||
|
size_t rand_pool_acquire_entropy(RAND_POOL *pool)
|
||||||
|
{
|
||||||
|
-# if defined(OPENSSL_RAND_SEED_NONE)
|
||||||
|
- return rand_pool_entropy_available(pool);
|
||||||
|
-# else
|
||||||
|
+/* # if defined(OPENSSL_RAND_SEED_NONE) */
|
||||||
|
+/* return rand_pool_entropy_available(pool); */
|
||||||
|
+/* # else */
|
||||||
|
size_t entropy_available;
|
||||||
|
|
||||||
|
-# if defined(OPENSSL_RAND_SEED_GETRANDOM)
|
||||||
|
+/* # if defined(OPENSSL_RAND_SEED_GETRANDOM) */
|
||||||
|
{
|
||||||
|
size_t bytes_needed;
|
||||||
|
unsigned char *buffer;
|
||||||
|
@@ -664,7 +664,7 @@
|
||||||
|
entropy_available = rand_pool_entropy_available(pool);
|
||||||
|
if (entropy_available > 0)
|
||||||
|
return entropy_available;
|
||||||
|
-# endif
|
||||||
|
+/* # endif */
|
||||||
|
|
||||||
|
# if defined(OPENSSL_RAND_SEED_LIBRANDOM)
|
||||||
|
{
|
||||||
|
@@ -752,7 +752,7 @@
|
||||||
|
# endif
|
||||||
|
|
||||||
|
return rand_pool_entropy_available(pool);
|
||||||
|
-# endif
|
||||||
|
+/* # endif */
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
diff '--color=auto' -ruN openssl-1.1.1l/test/drbgtest.c patch-1.1.1l/test/drbgtest.c
|
||||||
|
--- openssl-1.1.1l/test/drbgtest.c 2021-08-24 09:38:47.000000000 -0400
|
||||||
|
+++ patch-1.1.1l/test/drbgtest.c 2021-09-12 02:07:38.062332301 -0400
|
||||||
|
@@ -22,8 +22,21 @@
|
||||||
|
# include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#ifndef HAVE_FORK
|
||||||
|
+# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_VXWORKS)
|
||||||
|
+# define HAVE_FORK 0
|
||||||
|
+# else
|
||||||
|
+# define HAVE_FORK 1
|
||||||
|
+# endif
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+#if HAVE_FORK
|
||||||
|
+# undef NO_FORK
|
||||||
|
+#else
|
||||||
|
+# define NO_FORK
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
-#if defined(OPENSSL_SYS_UNIX)
|
||||||
|
+#if defined(OPENSSL_SYS_UNIX) && !defined(NO_FORK)
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/wait.h>
|
||||||
|
# include <unistd.h>
|
||||||
|
@@ -676,7 +689,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-#if defined(OPENSSL_SYS_UNIX)
|
||||||
|
+#if defined(OPENSSL_SYS_UNIX) && !defined(NO_FORK)
|
||||||
|
/*
|
||||||
|
* Test whether master, public and private DRBG are reseeded after
|
||||||
|
* forking the process.
|
||||||
|
@@ -795,7 +808,7 @@
|
||||||
|
goto error;
|
||||||
|
reset_drbg_hook_ctx();
|
||||||
|
|
||||||
|
-#if defined(OPENSSL_SYS_UNIX)
|
||||||
|
+#if defined(OPENSSL_SYS_UNIX) && !defined(NO_FORK)
|
||||||
|
if (!TEST_true(test_drbg_reseed_after_fork(master, public, private)))
|
||||||
|
goto error;
|
||||||
|
#endif
|
||||||
|
diff '--color=auto' -ruN openssl-1.1.1l/test/run_tests.pl patch-1.1.1l/test/run_tests.pl
|
||||||
|
--- openssl-1.1.1l/test/run_tests.pl 2021-08-24 09:38:47.000000000 -0400
|
||||||
|
+++ patch-1.1.1l/test/run_tests.pl 2021-09-12 02:03:57.603451471 -0400
|
||||||
|
@@ -28,7 +28,7 @@
|
||||||
|
my $recipesdir = catdir($srctop, "test", "recipes");
|
||||||
|
my $libdir = rel2abs(catdir($srctop, "util", "perl"));
|
||||||
|
|
||||||
|
-$ENV{OPENSSL_CONF} = catdir($srctop, "apps", "openssl.cnf");
|
||||||
|
+$ENV{OPENSSL_CONF} = rel2abs(catdir($srctop, "apps", "openssl.cnf"));
|
||||||
|
|
||||||
|
my %tapargs =
|
||||||
|
( verbosity => $ENV{VERBOSE} || $ENV{V} || $ENV{HARNESS_VERBOSE} ? 1 : 0,
|
||||||
|
diff '--color=auto' -ruN openssl-1.1.1l/util/perl/OpenSSL/Test.pm patch-1.1.1l/util/perl/OpenSSL/Test.pm
|
||||||
|
--- openssl-1.1.1l/util/perl/OpenSSL/Test.pm 2021-08-24 09:38:47.000000000 -0400
|
||||||
|
+++ patch-1.1.1l/util/perl/OpenSSL/Test.pm 2021-09-12 02:01:14.155136681 -0400
|
||||||
|
@@ -65,7 +65,7 @@
|
||||||
|
rel2abs/;
|
||||||
|
use File::Path 2.00 qw/rmtree mkpath/;
|
||||||
|
use File::Basename;
|
||||||
|
-use Cwd qw/getcwd abs_path/;
|
||||||
|
+use Cwd qw/abs_path/;
|
||||||
|
|
||||||
|
my $level = 0;
|
||||||
|
|
||||||
|
@@ -904,26 +904,26 @@
|
||||||
|
BAIL_OUT("Must run setup() first") if (! $test_name);
|
||||||
|
|
||||||
|
my $f = pop;
|
||||||
|
- return abs2rel(catfile($directories{SRCTOP},@_,$f),getcwd);
|
||||||
|
+ return catfile($directories{SRCTOP},@_,$f);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub __srctop_dir {
|
||||||
|
BAIL_OUT("Must run setup() first") if (! $test_name);
|
||||||
|
|
||||||
|
- return abs2rel(catdir($directories{SRCTOP},@_), getcwd);
|
||||||
|
+ return catdir($directories{SRCTOP},@_);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub __bldtop_file {
|
||||||
|
BAIL_OUT("Must run setup() first") if (! $test_name);
|
||||||
|
|
||||||
|
my $f = pop;
|
||||||
|
- return abs2rel(catfile($directories{BLDTOP},@_,$f), getcwd);
|
||||||
|
+ return catfile($directories{BLDTOP},@_,$f);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub __bldtop_dir {
|
||||||
|
BAIL_OUT("Must run setup() first") if (! $test_name);
|
||||||
|
|
||||||
|
- return abs2rel(catdir($directories{BLDTOP},@_), getcwd);
|
||||||
|
+ return catdir($directories{BLDTOP},@_);
|
||||||
|
}
|
||||||
|
|
||||||
|
# __exeext is a function that returns the platform dependent file extension
|
||||||
104
facho/cli.py
104
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')
|
||||||
@@ -215,7 +227,7 @@ def sign_xml(private_key, passphrase, xmlfile, ssl=True, use_cache_policy=False,
|
|||||||
if use_cache_policy:
|
if use_cache_policy:
|
||||||
warnings.warn("xades using cache policy")
|
warnings.warn("xades using cache policy")
|
||||||
|
|
||||||
signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase, mockpolicy=use_cache_policy)
|
signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase, localpolicy=use_cache_policy)
|
||||||
document = open(xmlfile, 'r').read().encode('utf-8')
|
document = open(xmlfile, 'r').read().encode('utf-8')
|
||||||
with open(output, 'w') as f:
|
with open(output, 'w') as f:
|
||||||
f.write(signer.sign_xml_string(document))
|
f.write(signer.sign_xml_string(document))
|
||||||
@@ -247,14 +259,14 @@ def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=Tr
|
|||||||
spec.loader.exec_module(module)
|
spec.loader.exec_module(module)
|
||||||
|
|
||||||
import facho.fe.form as form
|
import facho.fe.form as form
|
||||||
from facho.fe.form_xml import DIANInvoiceXML, DIANWriteSigned,DIANWrite
|
from facho.fe.form_xml import DIANInvoiceXML, DIANWriteSigned, DIANWrite, DIANSupportDocumentXML
|
||||||
from facho import fe
|
from facho import fe
|
||||||
|
|
||||||
try:
|
try:
|
||||||
invoice_xml = module.document_xml()
|
invoice_xml = module.document_xml()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
invoice_xml = DIANInvoiceXML
|
#invoice_xml = DIANInvoiceXML
|
||||||
|
invoice_xml = DIANSupportDocumentXML
|
||||||
print("Using document xml:", invoice_xml)
|
print("Using document xml:", invoice_xml)
|
||||||
invoice = module.invoice()
|
invoice = module.invoice()
|
||||||
invoice.calculate()
|
invoice.calculate()
|
||||||
@@ -271,6 +283,65 @@ def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=Tr
|
|||||||
else:
|
else:
|
||||||
DIANWrite(xml, output)
|
DIANWrite(xml, output)
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.option('--private-key', type=click.Path(exists=True))
|
||||||
|
@click.option('--passphrase')
|
||||||
|
@click.option('--ssl/--no-ssl', default=False)
|
||||||
|
@click.option('--sign/--no-sign', default=False)
|
||||||
|
@click.option('--use-cache-policy/--no-use-cache-policy', default=False)
|
||||||
|
@click.argument('scriptname', type=click.Path(exists=True), required=True)
|
||||||
|
@click.argument('output', required=True)
|
||||||
|
def generate_nomina(private_key, passphrase, scriptname, ssl=True, sign=False, use_cache_policy=False, output=None):
|
||||||
|
"""
|
||||||
|
imprime xml en pantalla.
|
||||||
|
SCRIPTNAME espera
|
||||||
|
def nomina() -> fe.nomina.NominaIndividual
|
||||||
|
def extensions(fe.nomina.NominaIndividual): -> List[facho.FachoXMLExtension]
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not ssl:
|
||||||
|
disable_ssl()
|
||||||
|
|
||||||
|
import importlib.util
|
||||||
|
|
||||||
|
spec = importlib.util.spec_from_file_location('nomina', scriptname)
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
|
||||||
|
from facho.fe.form_xml import DIANWriteSigned, DIANWrite
|
||||||
|
import facho.fe
|
||||||
|
|
||||||
|
nomina = module.nomina()
|
||||||
|
|
||||||
|
xml = nomina.toFachoXML()
|
||||||
|
|
||||||
|
extensions = module.extensions(nomina)
|
||||||
|
for extension in extensions:
|
||||||
|
xml.add_extension(extension)
|
||||||
|
|
||||||
|
if sign:
|
||||||
|
DIANWriteSigned(xml, output, private_key, passphrase, use_cache_policy, dian_signer=facho.fe.nomina.DianXMLExtensionSigner)
|
||||||
|
else:
|
||||||
|
DIANWrite(xml, output)
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.option('--private-key', required=True)
|
||||||
|
@click.option('--public-key', required=True)
|
||||||
|
@click.option('--habilitacion/--produccion', default=False)
|
||||||
|
@click.option('--password')
|
||||||
|
@click.argument('filename', required=True)
|
||||||
|
@click.argument('zipfile', type=click.Path(exists=True))
|
||||||
|
def soap_send_nomina_sync(private_key, public_key, habilitacion, password, filename, zipfile):
|
||||||
|
from facho.fe.client import dian
|
||||||
|
|
||||||
|
client = dian.DianSignatureClient(private_key, public_key, password=password)
|
||||||
|
req = dian.SendNominaSync
|
||||||
|
if habilitacion:
|
||||||
|
req = dian.Habilitacion.SendNominaSync
|
||||||
|
resp = client.request(req(
|
||||||
|
open(zipfile, 'rb').read()
|
||||||
|
))
|
||||||
|
print(resp)
|
||||||
|
|
||||||
@click.command()
|
@click.command()
|
||||||
@click.option('--private-key', type=click.Path(exists=True))
|
@click.option('--private-key', type=click.Path(exists=True))
|
||||||
@@ -287,7 +358,7 @@ def sign_verify_xml(private_key, passphrase, xmlfile, ssl=True, use_cache_policy
|
|||||||
warnings.warn("xades using cache policy")
|
warnings.warn("xades using cache policy")
|
||||||
|
|
||||||
print("THIS ONLY WORKS FOR DOCUMENTS GENERATE WITH FACHO")
|
print("THIS ONLY WORKS FOR DOCUMENTS GENERATE WITH FACHO")
|
||||||
signer = fe.DianXMLExtensionSignerVerifier(private_key, passphrase=passphrase, mockpolicy=use_cache_policy)
|
signer = fe.DianXMLExtensionSignerVerifier(private_key, passphrase=passphrase, localpolicy=use_cache_policy)
|
||||||
document = open(xmlfile, 'r').read().encode('utf-8')
|
document = open(xmlfile, 'r').read().encode('utf-8')
|
||||||
|
|
||||||
if signer.verify_string(document):
|
if signer.verify_string(document):
|
||||||
@@ -295,6 +366,25 @@ def sign_verify_xml(private_key, passphrase, xmlfile, ssl=True, use_cache_policy
|
|||||||
else:
|
else:
|
||||||
print("-INVALID")
|
print("-INVALID")
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.option('--software-id')
|
||||||
|
@click.option('--software-pin')
|
||||||
|
@click.option('--nit')
|
||||||
|
@click.option('--dv')
|
||||||
|
@click.option('--output-zippath')
|
||||||
|
def generate_nomina_habilitacion(software_id, software_pin, nit, dv, output_zippath):
|
||||||
|
from facho import fe
|
||||||
|
|
||||||
|
generador = fe.nomina.habilitacion.Habilitacion(
|
||||||
|
fe.nomina.habilitacion.Habilitacion.Metadata(
|
||||||
|
software_id=software_id,
|
||||||
|
software_pin=software_pin,
|
||||||
|
nit=nit,
|
||||||
|
dv=dv
|
||||||
|
)
|
||||||
|
)
|
||||||
|
generador.generar(output_zippath)
|
||||||
|
|
||||||
@click.group()
|
@click.group()
|
||||||
def main():
|
def main():
|
||||||
pass
|
pass
|
||||||
@@ -310,3 +400,7 @@ main.add_command(generate_invoice)
|
|||||||
main.add_command(validate_invoice)
|
main.add_command(validate_invoice)
|
||||||
main.add_command(sign_xml)
|
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(soap_send_nomina_sync)
|
||||||
|
main.add_command(validate_nominaindividual)
|
||||||
|
main.add_command(generate_nomina_habilitacion)
|
||||||
|
|||||||
302
facho/facho.py
302
facho/facho.py
@@ -1,9 +1,15 @@
|
|||||||
# This file is part of facho. The COPYRIGHT file at the top level of
|
# This file is part of facho. The COPYRIGHT file at the top level of
|
||||||
# this repository contains the full copyright notices and license terms.
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from lxml.etree import Element, SubElement, tostring
|
from lxml.etree import Element, tostring
|
||||||
import re
|
import re
|
||||||
|
from collections import defaultdict
|
||||||
|
from copy import deepcopy
|
||||||
|
|
||||||
|
|
||||||
|
class FachoValueInvalid(Exception):
|
||||||
|
def __init__(self, xpath):
|
||||||
|
super().__init__('FachoValueInvalid invalid xpath %s' % (xpath))
|
||||||
|
|
||||||
|
|
||||||
class FachoXMLExtension:
|
class FachoXMLExtension:
|
||||||
@@ -25,7 +31,10 @@ class LXMLBuilder:
|
|||||||
|
|
||||||
def __init__(self, nsmap):
|
def __init__(self, nsmap):
|
||||||
self.nsmap = nsmap
|
self.nsmap = nsmap
|
||||||
self._re_node_expr = re.compile(r'^(?P<path>((?P<ns>\w+):)?(?P<tag>[a-zA-Z0-9_-]+))(?P<attrs>\[.+\])?')
|
self._re_node_expr = \
|
||||||
|
re.compile(
|
||||||
|
r'^(?P<path>((?P<ns>\w+):)?(?P<tag>[a-zA-Z0-9_-]+))'
|
||||||
|
r'(?P<attrs>\[.+\])?')
|
||||||
self._re_attrs = re.compile(r'(\w+)\s*=\s*\"?(\w+)\"?')
|
self._re_attrs = re.compile(r'(\w+)\s*=\s*\"?(\w+)\"?')
|
||||||
|
|
||||||
def match_expression(self, node_expr):
|
def match_expression(self, node_expr):
|
||||||
@@ -82,29 +91,64 @@ class LXMLBuilder:
|
|||||||
def append(self, elem, child):
|
def append(self, elem, child):
|
||||||
elem.append(child)
|
elem.append(child)
|
||||||
|
|
||||||
|
def append_next(self, elem, slibing):
|
||||||
|
elem.addnext(slibing)
|
||||||
|
|
||||||
def remove(self, elem):
|
def remove(self, elem):
|
||||||
elem.getparent().remove(elem)
|
elem.getparent().remove(elem)
|
||||||
|
|
||||||
def set_text(self, elem, text):
|
def set_text(self, elem, text):
|
||||||
elem.text = text
|
elem.text = text
|
||||||
|
|
||||||
def xpath(self, elem, xpath):
|
def xpath(self, elem, xpath, multiple=False):
|
||||||
elems = elem.xpath(xpath, namespaces=self.nsmap)
|
elems = elem.xpath(xpath, namespaces=self.nsmap)
|
||||||
if elems:
|
if elems:
|
||||||
return elems[0]
|
if multiple:
|
||||||
|
return elems
|
||||||
|
else:
|
||||||
|
return elems[0]
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_text(self, elem):
|
def get_text(self, elem):
|
||||||
return elem.text
|
return elem.text
|
||||||
|
|
||||||
|
def get_attribute(self, elem, key):
|
||||||
|
return elem.attrib[key]
|
||||||
|
|
||||||
|
def is_attribute(self, elem, key, value):
|
||||||
|
return elem.get(key, False) == value
|
||||||
|
|
||||||
def set_attribute(self, elem, key, value):
|
def set_attribute(self, elem, key, value):
|
||||||
elem.attrib[key] = value
|
elem.attrib[key] = value
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def tostring(self, elem, **attrs):
|
def remove_attributes(cls, elem, keys, exclude=[]):
|
||||||
|
for key in keys:
|
||||||
|
if key in exclude:
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
del elem.attrib[key]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tostring(self, oelem, **attrs):
|
||||||
|
elem = deepcopy(oelem)
|
||||||
|
|
||||||
attrs['pretty_print'] = attrs.pop('pretty_print', False)
|
attrs['pretty_print'] = attrs.pop('pretty_print', False)
|
||||||
attrs['encoding'] = attrs.pop('encoding', 'UTF-8')
|
attrs['encoding'] = attrs.pop('encoding', 'UTF-8')
|
||||||
|
|
||||||
|
for el in elem.getiterator():
|
||||||
|
keys = filter(lambda key: key.startswith('facho_'), el.keys())
|
||||||
|
self.remove_attributes(el, keys, exclude=['facho_optional'])
|
||||||
|
|
||||||
|
is_optional = el.get('facho_optional', 'False') == 'True'
|
||||||
|
if is_optional and el.getchildren() == [] and el.keys() == [
|
||||||
|
'facho_optional']:
|
||||||
|
el.getparent().remove(el)
|
||||||
|
|
||||||
return tostring(elem, **attrs).decode('utf-8')
|
return tostring(elem, **attrs).decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
@@ -112,7 +156,8 @@ class FachoXML:
|
|||||||
"""
|
"""
|
||||||
Decora XML con funciones de consulta XPATH de un solo elemento
|
Decora XML con funciones de consulta XPATH de un solo elemento
|
||||||
"""
|
"""
|
||||||
def __init__(self, root, builder=None, nsmap=None, fragment_prefix=''):
|
def __init__(self, root, builder=None, nsmap=None, fragment_prefix='',
|
||||||
|
fragment_root_element=None):
|
||||||
if builder is None:
|
if builder is None:
|
||||||
self.builder = LXMLBuilder(nsmap)
|
self.builder = LXMLBuilder(nsmap)
|
||||||
else:
|
else:
|
||||||
@@ -125,25 +170,33 @@ class FachoXML:
|
|||||||
else:
|
else:
|
||||||
self.root = root
|
self.root = root
|
||||||
|
|
||||||
|
self.fragment_root_element = fragment_root_element
|
||||||
self.fragment_prefix = fragment_prefix
|
self.fragment_prefix = fragment_prefix
|
||||||
self.xpath_for = {}
|
self.xpath_for = {}
|
||||||
self.extensions = []
|
self.extensions = []
|
||||||
|
self._validators = defaultdict(lambda: lambda v, attrs: True)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_string(cls, document: str, namespaces: dict() = []) -> 'FachoXML':
|
def from_string(cls, document: str, namespaces: dict() = []) -> 'FachoXML':
|
||||||
xml = LXMLBuilder.from_string(document)
|
xml = LXMLBuilder.from_string(document)
|
||||||
return FachoXML(xml, nsmap=namespaces)
|
return FachoXML(xml, nsmap=namespaces)
|
||||||
|
|
||||||
|
def root_namespace(self):
|
||||||
|
return etree.QName(self.root).namespace
|
||||||
|
|
||||||
|
def root_localname(self):
|
||||||
|
return etree.QName(self.root).localname
|
||||||
|
|
||||||
def append_element(self, elem, new_elem):
|
def append_element(self, elem, new_elem):
|
||||||
#elem = self.find_or_create_element(xpath, append=append)
|
# elem = self.find_or_create_element(xpath, append=append)
|
||||||
#self.builder.append(elem, new_elem)
|
# self.builder.append(elem, new_elem)
|
||||||
self.builder.append(elem, new_elem)
|
self.builder.append(elem, new_elem)
|
||||||
|
|
||||||
def add_extension(self, extension):
|
def add_extension(self, extension):
|
||||||
extension.build(self)
|
extension.build(self)
|
||||||
|
|
||||||
|
def fragment(
|
||||||
def fragment(self, xpath, append=False, append_not_exists=False):
|
self, xpath, append=False, append_not_exists=False):
|
||||||
nodes = xpath.split('/')
|
nodes = xpath.split('/')
|
||||||
nodes.pop()
|
nodes.pop()
|
||||||
root_prefix = '/'.join(nodes)
|
root_prefix = '/'.join(nodes)
|
||||||
@@ -153,7 +206,9 @@ class FachoXML:
|
|||||||
|
|
||||||
if parent is None:
|
if parent is None:
|
||||||
parent = self.find_or_create_element(xpath, append=append)
|
parent = self.find_or_create_element(xpath, append=append)
|
||||||
return FachoXML(parent, nsmap=self.nsmap, fragment_prefix=root_prefix)
|
return FachoXML(
|
||||||
|
parent, nsmap=self.nsmap, fragment_prefix=root_prefix,
|
||||||
|
fragment_root_element=self.root)
|
||||||
|
|
||||||
def register_alias_xpath(self, alias, xpath):
|
def register_alias_xpath(self, alias, xpath):
|
||||||
self.xpath_for[alias] = xpath
|
self.xpath_for[alias] = xpath
|
||||||
@@ -169,8 +224,12 @@ class FachoXML:
|
|||||||
def _path_xpath_for(self, xpath):
|
def _path_xpath_for(self, xpath):
|
||||||
return self._normalize_xpath(self._translate_xpath_for(xpath))
|
return self._normalize_xpath(self._translate_xpath_for(xpath))
|
||||||
|
|
||||||
def placeholder_for(self, xpath, append=False):
|
def placeholder_for(self, xpath, append=False, optional=False):
|
||||||
return self.find_or_create_element(xpath, append)
|
elem = self.find_or_create_element(xpath, append)
|
||||||
|
if optional:
|
||||||
|
elem.set('facho_optional', 'True')
|
||||||
|
elem.set('facho_placeholder', 'True')
|
||||||
|
return elem
|
||||||
|
|
||||||
def replacement_for(self, xpath, new_xpath, content, **attrs):
|
def replacement_for(self, xpath, new_xpath, content, **attrs):
|
||||||
elem = self.get_element(xpath)
|
elem = self.get_element(xpath)
|
||||||
@@ -185,7 +244,8 @@ class FachoXML:
|
|||||||
"""
|
"""
|
||||||
xpath = self._path_xpath_for(xpath)
|
xpath = self._path_xpath_for(xpath)
|
||||||
node_paths = xpath.split('/')
|
node_paths = xpath.split('/')
|
||||||
node_paths.pop(0) #remove empty /
|
# remove empty /
|
||||||
|
node_paths.pop(0)
|
||||||
root_tag = node_paths.pop(0)
|
root_tag = node_paths.pop(0)
|
||||||
|
|
||||||
root_node = self.builder.build_from_expression(root_tag)
|
root_node = self.builder.build_from_expression(root_tag)
|
||||||
@@ -193,18 +253,21 @@ class FachoXML:
|
|||||||
# restaurar ya que no es la raiz y asignar actual como raiz
|
# restaurar ya que no es la raiz y asignar actual como raiz
|
||||||
node_paths.insert(0, root_tag)
|
node_paths.insert(0, root_tag)
|
||||||
root_node = self.root
|
root_node = self.root
|
||||||
|
|
||||||
if not self.builder.same_tag(root_node.tag, self.root.tag):
|
if not self.builder.same_tag(root_node.tag, self.root.tag):
|
||||||
|
raise ValueError('xpath %s must be absolute to /%s' % (
|
||||||
raise ValueError('xpath %s must be absolute to /%s' % (xpath, self.root.tag))
|
xpath, self.root.tag))
|
||||||
|
|
||||||
# crea jerarquia segun xpath indicado
|
# crea jerarquia segun xpath indicado
|
||||||
parent = None
|
parent = None
|
||||||
current_elem = self.root
|
current_elem = self.root
|
||||||
|
node_tag = node_paths.pop(-1)
|
||||||
|
|
||||||
for node_path in node_paths:
|
for node_path in node_paths:
|
||||||
node_expr = self.builder.match_expression(node_path)
|
node_expr = self.builder.match_expression(node_path)
|
||||||
node = self.builder.build_from_expression(node_path)
|
node = self.builder.build_from_expression(node_path)
|
||||||
child = self.builder.find_relative(current_elem, node_expr['path'], self.nsmap)
|
child = self.builder.find_relative(
|
||||||
|
current_elem, node_expr['path'], self.nsmap)
|
||||||
|
|
||||||
parent = current_elem
|
parent = current_elem
|
||||||
if child is not None:
|
if child is not None:
|
||||||
@@ -213,15 +276,61 @@ class FachoXML:
|
|||||||
self.builder.append(current_elem, node)
|
self.builder.append(current_elem, node)
|
||||||
current_elem = node
|
current_elem = node
|
||||||
|
|
||||||
# se fuerza la adicion como un nuevo elemento
|
node_expr = self.builder.match_expression(node_tag)
|
||||||
if append:
|
node = self.builder.build_from_expression(node_tag)
|
||||||
node = self.builder.build_from_expression(node_paths[-1])
|
child = self.builder.find_relative(
|
||||||
|
current_elem, node_expr['path'], self.nsmap)
|
||||||
|
parent = current_elem
|
||||||
|
if child is not None:
|
||||||
|
current_elem = child
|
||||||
|
|
||||||
|
if parent == current_elem:
|
||||||
self.builder.append(parent, node)
|
self.builder.append(parent, node)
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
# se fuerza la adicion como un nuevo elemento
|
||||||
|
if append:
|
||||||
|
last_slibing = None
|
||||||
|
for child in parent.getchildren():
|
||||||
|
if child.tag == node_tag:
|
||||||
|
last_slibing = child
|
||||||
|
|
||||||
|
# si no ahi primos se adiciona como hijo
|
||||||
|
if last_slibing is None:
|
||||||
|
self.builder.append(parent, node)
|
||||||
|
return node
|
||||||
|
|
||||||
|
if self.builder.is_attribute(
|
||||||
|
last_slibing, 'facho_placeholder', 'True'):
|
||||||
|
self._remove_facho_attributes(last_slibing)
|
||||||
|
return last_slibing
|
||||||
|
self.builder.append_next(last_slibing, node)
|
||||||
|
return node
|
||||||
|
|
||||||
|
if child is None:
|
||||||
|
self.builder.append(current_elem, node)
|
||||||
|
return node
|
||||||
|
|
||||||
|
self._remove_facho_attributes(current_elem)
|
||||||
return current_elem
|
return current_elem
|
||||||
|
|
||||||
def set_element(self, xpath, content, **attrs):
|
def set_element_validator(
|
||||||
|
self, xpath, validator=False):
|
||||||
|
"""
|
||||||
|
validador al asignar contenido a xpath indicado
|
||||||
|
|
||||||
|
@param xpath ruta tipo XPath
|
||||||
|
@param validator callback(content, attributes)
|
||||||
|
"""
|
||||||
|
|
||||||
|
key = self._path_xpath_for(xpath)
|
||||||
|
if not validator:
|
||||||
|
self._validators[key] = lambda v, attrs: True
|
||||||
|
else:
|
||||||
|
self._validators[key] = validator
|
||||||
|
|
||||||
|
def set_element(
|
||||||
|
self, xpath, content, **attrs):
|
||||||
"""
|
"""
|
||||||
asigna contenido ubicado por ruta tipo XPATH.
|
asigna contenido ubicado por ruta tipo XPATH.
|
||||||
@param xpath ruta tipo XPATH
|
@param xpath ruta tipo XPATH
|
||||||
@@ -232,10 +341,18 @@ class FachoXML:
|
|||||||
format_ = attrs.pop('format_', '%s')
|
format_ = attrs.pop('format_', '%s')
|
||||||
append_ = attrs.pop('append_', False)
|
append_ = attrs.pop('append_', False)
|
||||||
elem = self.find_or_create_element(xpath, append=append_)
|
elem = self.find_or_create_element(xpath, append=append_)
|
||||||
|
|
||||||
|
validator = self._validators[xpath]
|
||||||
|
|
||||||
|
if not validator(content, attrs):
|
||||||
|
raise FachoValueInvalid(xpath)
|
||||||
|
|
||||||
if content:
|
if content:
|
||||||
self.builder.set_text(elem, format_ % content)
|
self.builder.set_text(elem, format_ % content)
|
||||||
for k, v in attrs.items():
|
for k, v in attrs.items():
|
||||||
self.builder.set_attribute(elem, k, v)
|
if v is not None or str(v) != 'None':
|
||||||
|
self.builder.set_attribute(elem, k, str(v))
|
||||||
|
|
||||||
return elem
|
return elem
|
||||||
|
|
||||||
def set_attributes(self, xpath, **attrs):
|
def set_attributes(self, xpath, **attrs):
|
||||||
@@ -246,22 +363,143 @@ class FachoXML:
|
|||||||
"""
|
"""
|
||||||
xpath = self._path_xpath_for(xpath)
|
xpath = self._path_xpath_for(xpath)
|
||||||
elem = self.get_element(xpath)
|
elem = self.get_element(xpath)
|
||||||
|
|
||||||
|
if elem is None:
|
||||||
|
raise ValueError("xpath %s not found" % (xpath))
|
||||||
|
|
||||||
for k, v in attrs.items():
|
for k, v in attrs.items():
|
||||||
self.builder.set_attribute(elem, k, v)
|
if v is not None or str(v) != 'None':
|
||||||
|
self.builder.set_attribute(elem, k, str(v))
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def get_element(self, xpath):
|
def get_element_attribute(
|
||||||
xpath = self.fragment_prefix + self._path_xpath_for(xpath)
|
self, xpath, attribute, multiple=False):
|
||||||
return self.builder.xpath(self.root, xpath)
|
elem = self.get_element(xpath, multiple=multiple)
|
||||||
|
|
||||||
def get_element_text(self, xpath, format_=str):
|
if elem is None:
|
||||||
|
raise ValueError("xpath %s not found" % (xpath))
|
||||||
|
|
||||||
|
if multiple:
|
||||||
|
vals = []
|
||||||
|
for e in elem:
|
||||||
|
vals.append(self.builder.get_attribute(e, attribute))
|
||||||
|
return vals
|
||||||
|
else:
|
||||||
|
return self.builder.get_attribute(elem, attribute)
|
||||||
|
|
||||||
|
def get_element(self, xpath, multiple=False):
|
||||||
xpath = self.fragment_prefix + self._path_xpath_for(xpath)
|
xpath = self.fragment_prefix + self._path_xpath_for(xpath)
|
||||||
elem = self.builder.xpath(self.root, xpath)
|
return self.builder.xpath(self.root, xpath, multiple=multiple)
|
||||||
text = self.builder.get_text(elem)
|
|
||||||
return format_(text)
|
def get_element_text(self, xpath, format_=str, multiple=False):
|
||||||
|
xpath = self.fragment_prefix + self._path_xpath_for(xpath)
|
||||||
|
# MACHETE(bit4bit) al usar ./ queda ../
|
||||||
|
xpath = re.sub(r'^\.\.+', '.', xpath)
|
||||||
|
|
||||||
|
elem = self.builder.xpath(self.root, xpath, multiple=multiple)
|
||||||
|
if multiple:
|
||||||
|
vals = []
|
||||||
|
for e in elem:
|
||||||
|
text = self.builder.get_text(e)
|
||||||
|
if text is not None:
|
||||||
|
vals.append(format_(text))
|
||||||
|
return vals
|
||||||
|
else:
|
||||||
|
text = self.builder.get_text(elem)
|
||||||
|
if text is None:
|
||||||
|
return None
|
||||||
|
return format_(text)
|
||||||
|
|
||||||
|
def get_element_text_or_attribute(
|
||||||
|
self, xpath, default=None, multiple=False, raise_on_fail=False):
|
||||||
|
parts = xpath.split('/')
|
||||||
|
is_attribute = parts[-1].startswith('@')
|
||||||
|
if is_attribute:
|
||||||
|
attribute_name = parts.pop(-1).lstrip('@')
|
||||||
|
element_path = "/".join(parts)
|
||||||
|
try:
|
||||||
|
val = self.get_element_attribute(
|
||||||
|
element_path, attribute_name, multiple=multiple)
|
||||||
|
if val is None:
|
||||||
|
return default
|
||||||
|
return val
|
||||||
|
except KeyError as e:
|
||||||
|
if raise_on_fail:
|
||||||
|
raise e
|
||||||
|
return default
|
||||||
|
except ValueError as e:
|
||||||
|
if raise_on_fail:
|
||||||
|
raise e
|
||||||
|
return default
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
val = self.get_element_text(xpath, multiple=multiple)
|
||||||
|
if val is None:
|
||||||
|
return default
|
||||||
|
return val
|
||||||
|
except ValueError as e:
|
||||||
|
if raise_on_fail:
|
||||||
|
raise e
|
||||||
|
return default
|
||||||
|
|
||||||
|
def get_elements_text_or_attributes(self, xpaths, raise_on_fail=True):
|
||||||
|
"""
|
||||||
|
returna el contenido o attributos de un conjunto de XPATHS
|
||||||
|
si algun XPATH es una tupla se retorna el primer elemento del mismo.
|
||||||
|
"""
|
||||||
|
vals = []
|
||||||
|
for xpath in xpaths:
|
||||||
|
if isinstance(xpath, tuple):
|
||||||
|
val = xpath[0]
|
||||||
|
else:
|
||||||
|
val = self.get_element_text_or_attribute(
|
||||||
|
xpath, raise_on_fail=raise_on_fail)
|
||||||
|
vals.append(val)
|
||||||
|
return vals
|
||||||
|
|
||||||
|
def exist_element(self, xpath):
|
||||||
|
elem = self.get_element(xpath)
|
||||||
|
|
||||||
|
# no se encontro elemento
|
||||||
|
if elem is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# el placeholder no ha sido populado
|
||||||
|
if elem.get('facho_placeholder') == 'True':
|
||||||
|
return False
|
||||||
|
|
||||||
|
# el valor opcional no ha sido populado
|
||||||
|
if elem.get('facho_optional') == 'True':
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _remove_facho_attributes(self, elem):
|
||||||
|
self.builder.remove_attributes(
|
||||||
|
elem, ['facho_optional', 'facho_placeholder'])
|
||||||
|
|
||||||
def tostring(self, **kw):
|
def tostring(self, **kw):
|
||||||
return self.builder.tostring(self.root, **kw)
|
return self.builder.tostring(self.root, **kw)
|
||||||
|
|
||||||
|
def xpath_from_root(self, xpath):
|
||||||
|
nsmap = {}
|
||||||
|
ns = ''
|
||||||
|
|
||||||
|
root = self.root
|
||||||
|
if self.fragment_root_element is not None:
|
||||||
|
root = self.fragment_root_element
|
||||||
|
|
||||||
|
if isinstance(self.nsmap, dict):
|
||||||
|
nsmap = dict(map(reversed, self.nsmap.items()))
|
||||||
|
ns = nsmap[etree.QName(root).namespace] + ':'
|
||||||
|
|
||||||
|
if self.fragment_root_element is not None:
|
||||||
|
new_xpath = '/' + ns + etree.QName(root).localname + '/' + \
|
||||||
|
etree.QName(self.root).localname + '/' + xpath.lstrip('/')
|
||||||
|
else:
|
||||||
|
new_xpath = '/' + ns + etree.QName(root).localname + '/' + \
|
||||||
|
xpath.lstrip('/')
|
||||||
|
return new_xpath
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.tostring()
|
return self.tostring()
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from .fe import DianXMLExtensionSigner
|
|||||||
from .fe import DianXMLExtensionSoftwareSecurityCode
|
from .fe import DianXMLExtensionSoftwareSecurityCode
|
||||||
from .fe import DianXMLExtensionCUFE
|
from .fe import DianXMLExtensionCUFE
|
||||||
from .fe import DianXMLExtensionCUDE
|
from .fe import DianXMLExtensionCUDE
|
||||||
|
from .fe import DianXMLExtensionCUDS
|
||||||
from .fe import DianXMLExtensionInvoiceAuthorization
|
from .fe import DianXMLExtensionInvoiceAuthorization
|
||||||
from .fe import DianXMLExtensionSoftwareProvider
|
from .fe import DianXMLExtensionSoftwareProvider
|
||||||
from .fe import DianXMLExtensionAuthorizationProvider
|
from .fe import DianXMLExtensionAuthorizationProvider
|
||||||
@@ -12,3 +13,4 @@ from .fe import DianZIP
|
|||||||
from .fe import AMBIENTE_PRUEBAS
|
from .fe import AMBIENTE_PRUEBAS
|
||||||
from .fe import AMBIENTE_PRODUCCION
|
from .fe import AMBIENTE_PRODUCCION
|
||||||
from . import form_xml
|
from . import form_xml
|
||||||
|
from . import nomina
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class SOAPService:
|
|||||||
def get_service(self):
|
def get_service(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def builder_response(self, as_dict):
|
def build_response(self, as_dict):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def todict(self):
|
def todict(self):
|
||||||
@@ -175,7 +175,20 @@ class GetStatusZip(SOAPService):
|
|||||||
def build_response(self, as_dict):
|
def build_response(self, as_dict):
|
||||||
return GetStatusResponse.fromdict(as_dict[0])
|
return GetStatusResponse.fromdict(as_dict[0])
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class SendNominaSync(SOAPService):
|
||||||
|
contentFile: bytes
|
||||||
|
|
||||||
|
def get_wsdl(self):
|
||||||
|
return 'https://vpfe.dian.gov.co/WcfDianCustomerServices.svc?wsdl'
|
||||||
|
|
||||||
|
def get_service(self):
|
||||||
|
return 'SendNominaSync'
|
||||||
|
|
||||||
|
def build_response(self, as_dict):
|
||||||
|
return as_dict
|
||||||
|
|
||||||
|
|
||||||
class Habilitacion:
|
class Habilitacion:
|
||||||
WSDL = 'https://vpfe-hab.dian.gov.co/WcfDianCustomerServices.svc?wsdl'
|
WSDL = 'https://vpfe-hab.dian.gov.co/WcfDianCustomerServices.svc?wsdl'
|
||||||
|
|
||||||
@@ -203,6 +216,9 @@ class Habilitacion:
|
|||||||
def get_wsdl(self):
|
def get_wsdl(self):
|
||||||
return Habilitacion.WSDL
|
return Habilitacion.WSDL
|
||||||
|
|
||||||
|
class SendNominaSync(SendNominaSync):
|
||||||
|
def get_wsdl(self):
|
||||||
|
return Habilitacion.WSDL
|
||||||
|
|
||||||
class DianGateway:
|
class DianGateway:
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
36
facho/fe/data/dian/codelist/Idioma-2.1.gc
Normal file
36
facho/fe/data/dian/codelist/Idioma-2.1.gc
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
creado por facho, la dian tiene oficial?
|
||||||
|
poblar usando anexo tecnico 5.3.1
|
||||||
|
-->
|
||||||
|
<gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/">
|
||||||
|
<Identification>
|
||||||
|
<ShortName>Idioma</ShortName>
|
||||||
|
<LongName xml:lang="es">Idioma</LongName>
|
||||||
|
<Version>1</Version>
|
||||||
|
</Identification>
|
||||||
|
<ColumnSet>
|
||||||
|
<Column Id="iso-639-1" Use="required">
|
||||||
|
<ShortName>ISO 639 1</ShortName>
|
||||||
|
<Data Type="normalizedString"/>
|
||||||
|
</Column>
|
||||||
|
<Column Id="name" Use="required">
|
||||||
|
<ShortName>Nombre</ShortName>
|
||||||
|
<Data Type="normalizedString"/>
|
||||||
|
</Column>
|
||||||
|
<Key Id="codeKey">
|
||||||
|
<ShortName>CodeKey</ShortName>
|
||||||
|
<ColumnRef Ref="code"/>
|
||||||
|
</Key>
|
||||||
|
</ColumnSet>
|
||||||
|
<SimpleCodeList>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="iso-639-1">
|
||||||
|
<SimpleValue>es</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Español, castellano</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
</SimpleCodeList>
|
||||||
|
</gc:CodeList>
|
||||||
76
facho/fe/data/dian/codelist/PeriodoNomina-2.1.gc
Normal file
76
facho/fe/data/dian/codelist/PeriodoNomina-2.1.gc
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
creado por facho, la dian tiene oficial?
|
||||||
|
poblar usando anexo tecnico 5.5.1
|
||||||
|
-->
|
||||||
|
<gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/">
|
||||||
|
<Identification>
|
||||||
|
<ShortName>PeriodoNomina</ShortName>
|
||||||
|
<LongName xml:lang="es">Periodos Nomina</LongName>
|
||||||
|
<Version>1</Version>
|
||||||
|
</Identification>
|
||||||
|
<ColumnSet>
|
||||||
|
<Column Id="code" Use="required">
|
||||||
|
<ShortName>Code</ShortName>
|
||||||
|
<Data Type="normalizedString"/>
|
||||||
|
</Column>
|
||||||
|
<Column Id="name" Use="required">
|
||||||
|
<ShortName>Nombre</ShortName>
|
||||||
|
<Data Type="normalizedString"/>
|
||||||
|
</Column>
|
||||||
|
<Key Id="codeKey">
|
||||||
|
<ShortName>CodeKey</ShortName>
|
||||||
|
<ColumnRef Ref="code"/>
|
||||||
|
</Key>
|
||||||
|
</ColumnSet>
|
||||||
|
<SimpleCodeList>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>1</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Semanal</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>2</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Decenal</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>3</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Catorcenal</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>4</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Quincenal</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>5</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Mensual</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>6</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Otro</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
</SimpleCodeList>
|
||||||
|
</gc:CodeList>
|
||||||
44
facho/fe/data/dian/codelist/SubTipoTrabajador-2.1.gc
Normal file
44
facho/fe/data/dian/codelist/SubTipoTrabajador-2.1.gc
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
creado por facho, la dian tiene oficial?
|
||||||
|
poblar usando anexo tecnico 5.5.4
|
||||||
|
-->
|
||||||
|
<gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/">
|
||||||
|
<Identification>
|
||||||
|
<ShortName>SubTipoTrabajador</ShortName>
|
||||||
|
<LongName xml:lang="es">Sub tipos de trabajador</LongName>
|
||||||
|
<Version>1</Version>
|
||||||
|
</Identification>
|
||||||
|
<ColumnSet>
|
||||||
|
<Column Id="code" Use="required">
|
||||||
|
<ShortName>Code</ShortName>
|
||||||
|
<Data Type="normalizedString"/>
|
||||||
|
</Column>
|
||||||
|
<Column Id="name" Use="required">
|
||||||
|
<ShortName>Nombre</ShortName>
|
||||||
|
<Data Type="normalizedString"/>
|
||||||
|
</Column>
|
||||||
|
<Key Id="codeKey">
|
||||||
|
<ShortName>CodeKey</ShortName>
|
||||||
|
<ColumnRef Ref="code"/>
|
||||||
|
</Key>
|
||||||
|
</ColumnSet>
|
||||||
|
<SimpleCodeList>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>00</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>No Aplica</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>01</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Dependiente pensionado por vejez activo</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
</SimpleCodeList>
|
||||||
|
</gc:CodeList>
|
||||||
@@ -1,50 +1,61 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- DIAN Genericode listas de validacion :: Ultima modificación 18-02-2019 - evb-->
|
<!-- DIAN Genericode listas de validacion :: Ultima modificación 18-02-2019 - evb-->
|
||||||
<gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/">
|
<gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/">
|
||||||
<Identification>
|
<Identification>
|
||||||
<ShortName>TarifaImpuestos</ShortName>
|
<ShortName>TarifaImpuestos</ShortName>
|
||||||
<LongName xml:lang="es">Tarifas por Impuesto</LongName>
|
<LongName xml:lang="es">Tarifas por Impuesto</LongName>
|
||||||
<Version>1</Version>
|
<Version>1</Version>
|
||||||
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TarifaImpuestos</CanonicalUri>
|
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TarifaImpuestos</CanonicalUri>
|
||||||
<CanonicalVersionUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TarifaImpuestos-2.1</CanonicalVersionUri>
|
<CanonicalVersionUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TarifaImpuestos-2.1</CanonicalVersionUri>
|
||||||
<LocationUri>http://dian.gov.co/ubl/os-ubl-2.0/cl/gc/default/TarifaImpuestos-2.1.gc</LocationUri>
|
<LocationUri>http://dian.gov.co/ubl/os-ubl-2.0/cl/gc/default/TarifaImpuestos-2.1.gc</LocationUri>
|
||||||
<Agency>
|
<Agency>
|
||||||
<LongName xml:lang="es">DIAN (Dirección de Impuestos y Aduanas Nacionales)</LongName>
|
<LongName xml:lang="es">DIAN (Dirección de Impuestos y Aduanas Nacionales)</LongName>
|
||||||
<Identifier>195</Identifier>
|
<Identifier>195</Identifier>
|
||||||
</Agency>
|
</Agency>
|
||||||
</Identification>
|
</Identification>
|
||||||
<ColumnSet>
|
<ColumnSet>
|
||||||
<Column Id="code" Use="required">
|
<Column Id="code" Use="required">
|
||||||
<ShortName>Code</ShortName>
|
<ShortName>Code</ShortName>
|
||||||
<LongName xml:lang="es">Codigo Comun</LongName>
|
<LongName xml:lang="es">Codigo Comun</LongName>
|
||||||
<Data Type="normalizedString"/>
|
<Data Type="normalizedString"/>
|
||||||
</Column>
|
</Column>
|
||||||
<Column Id="name" Use="required">
|
<Column Id="name" Use="required">
|
||||||
<ShortName>Name</ShortName>
|
<ShortName>Name</ShortName>
|
||||||
<LongName xml:lang="es">Nombre</LongName>
|
<LongName xml:lang="es">Nombre</LongName>
|
||||||
<Data Type="string"/>
|
<Data Type="string"/>
|
||||||
</Column>
|
</Column>
|
||||||
<Column Id="description" Use="required">
|
<Column Id="description" Use="required">
|
||||||
<ShortName>Description</ShortName>
|
<ShortName>Description</ShortName>
|
||||||
<LongName xml:lang="es">Descripcion</LongName>
|
<LongName xml:lang="es">Descripcion</LongName>
|
||||||
<Data Type="string"/>
|
<Data Type="string"/>
|
||||||
</Column>
|
</Column>
|
||||||
<Key Id="codeKey">
|
<Key Id="codeKey">
|
||||||
<ShortName>CodeKey</ShortName>
|
<ShortName>CodeKey</ShortName>
|
||||||
<ColumnRef Ref="code"/>
|
<ColumnRef Ref="code"/>
|
||||||
</Key>
|
</Key>
|
||||||
</ColumnSet>
|
</ColumnSet>
|
||||||
<SimpleCodeList>
|
<SimpleCodeList>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>15.00</SimpleValue>
|
<SimpleValue>15.00</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>ReteIVA</SimpleValue>
|
<SimpleValue>ReteIVA</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="description">
|
<Value ColumnRef="description">
|
||||||
<SimpleValue>ReteIVA</SimpleValue>
|
<SimpleValue>ReteIVA</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
</SimpleCodeList>
|
<Row>
|
||||||
</gc:CodeList>
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>100.00</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>ReteIVA</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="description">
|
||||||
|
<SimpleValue>ReteIVA</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
</SimpleCodeList>
|
||||||
|
</gc:CodeList>
|
||||||
|
|||||||
68
facho/fe/data/dian/codelist/TipoContrato-2.1.gc
Normal file
68
facho/fe/data/dian/codelist/TipoContrato-2.1.gc
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
creado por facho, la dian tiene oficial?
|
||||||
|
poblar usando anexo tecnico 5.5.2
|
||||||
|
-->
|
||||||
|
<gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/">
|
||||||
|
<Identification>
|
||||||
|
<ShortName>TipoContrato</ShortName>
|
||||||
|
<LongName xml:lang="es">Tipos de contratos</LongName>
|
||||||
|
<Version>1</Version>
|
||||||
|
</Identification>
|
||||||
|
<ColumnSet>
|
||||||
|
<Column Id="code" Use="required">
|
||||||
|
<ShortName>Code</ShortName>
|
||||||
|
<Data Type="normalizedString"/>
|
||||||
|
</Column>
|
||||||
|
<Column Id="name" Use="required">
|
||||||
|
<ShortName>Nombre</ShortName>
|
||||||
|
<Data Type="normalizedString"/>
|
||||||
|
</Column>
|
||||||
|
<Key Id="codeKey">
|
||||||
|
<ShortName>CodeKey</ShortName>
|
||||||
|
<ColumnRef Ref="code"/>
|
||||||
|
</Key>
|
||||||
|
</ColumnSet>
|
||||||
|
<SimpleCodeList>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>1</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Termino Fijo</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>2</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Término Indefinido</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>3</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Obra o Labor</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>4</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Aprendizaje</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>5</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Pŕacticas o Pasantías</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
</SimpleCodeList>
|
||||||
|
</gc:CodeList>
|
||||||
@@ -1,74 +1,100 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- DIAN Genericode listas de valores:: Ultima modificación 18-02-2019 - evb-->
|
<!-- DIAN Genericode listas de valores: Ultima modificación 03-04-2022 - wcbr-->
|
||||||
<gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/">
|
<gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/">
|
||||||
<Identification>
|
<Identification>
|
||||||
<ShortName>TipoDocumento</ShortName>
|
<ShortName>TipoDocumento</ShortName>
|
||||||
<LongName xml:lang="es">Tipo de Documento</LongName>
|
<LongName xml:lang="es">Tipo de Documento</LongName>
|
||||||
<Version>1</Version>
|
<Version>1</Version>
|
||||||
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoDocumento</CanonicalUri>
|
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoDocumento</CanonicalUri>
|
||||||
<CanonicalVersionUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoDocumento-2.1</CanonicalVersionUri>
|
<CanonicalVersionUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoDocumento-2.1</CanonicalVersionUri>
|
||||||
<LocationUri>http://dian.gov.co/ubl/os-ubl-2.0/cl/gc/default/TipoDocumento-2.1.gc</LocationUri>
|
<LocationUri>http://dian.gov.co/ubl/os-ubl-2.0/cl/gc/default/TipoDocumento-2.1.gc</LocationUri>
|
||||||
<Agency>
|
<Agency>
|
||||||
<LongName xml:lang="es">DIAN (Dirección de Impuestos y Aduanas Nacionales)</LongName>
|
<LongName xml:lang="es">DIAN (Dirección de Impuestos y Aduanas Nacionales)</LongName>
|
||||||
<Identifier>195</Identifier>
|
<Identifier>195</Identifier>
|
||||||
</Agency>
|
</Agency>
|
||||||
</Identification>
|
</Identification>
|
||||||
<ColumnSet>
|
<ColumnSet>
|
||||||
<Column Id="code" Use="required">
|
<Column Id="code" Use="required">
|
||||||
<ShortName>Code</ShortName>
|
<ShortName>Code</ShortName>
|
||||||
<LongName xml:lang="es">Codigo Comun</LongName>
|
<LongName xml:lang="es">Codigo Comun</LongName>
|
||||||
<Data Type="normalizedString"/>
|
<Data Type="normalizedString"/>
|
||||||
</Column>
|
</Column>
|
||||||
<Column Id="name" Use="required">
|
<Column Id="name" Use="required">
|
||||||
<ShortName>Name</ShortName>
|
<ShortName>Name</ShortName>
|
||||||
<LongName xml:lang="es">Nombre</LongName>
|
<LongName xml:lang="es">Nombre</LongName>
|
||||||
<Data Type="string"/>
|
<Data Type="string"/>
|
||||||
</Column>
|
</Column>
|
||||||
<Key Id="codeKey">
|
<Key Id="codeKey">
|
||||||
<ShortName>CodeKey</ShortName>
|
<ShortName>CodeKey</ShortName>
|
||||||
<ColumnRef Ref="code"/>
|
<ColumnRef Ref="code"/>
|
||||||
</Key>
|
</Key>
|
||||||
</ColumnSet>
|
</ColumnSet>
|
||||||
<SimpleCodeList>
|
<SimpleCodeList>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>01</SimpleValue>
|
<SimpleValue>01</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>Factura de Venta Nacional</SimpleValue>
|
<SimpleValue>Factura electrónica de Venta</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
<Value ColumnRef="description">
|
||||||
<Row>
|
<SimpleValue>Tipos de factura</SimpleValue>
|
||||||
<Value ColumnRef="code">
|
</Value>
|
||||||
<SimpleValue>02</SimpleValue>
|
</Row>
|
||||||
</Value>
|
<Row>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>Factura de Exportación </SimpleValue>
|
<SimpleValue>02</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
<Value ColumnRef="name">
|
||||||
<Row>
|
<SimpleValue>Factura electrónica de venta con propósito de exportación</SimpleValue>
|
||||||
<Value ColumnRef="code">
|
</Value>
|
||||||
<SimpleValue>03</SimpleValue>
|
<Value ColumnRef="description">
|
||||||
</Value>
|
<SimpleValue>Tipos de factura</SimpleValue>
|
||||||
<Value ColumnRef="name">
|
</Value>
|
||||||
<SimpleValue>Factura de Contingencia</SimpleValue>
|
</Row>
|
||||||
</Value>
|
<Row>
|
||||||
</Row>
|
<Value ColumnRef="code">
|
||||||
<Row>
|
<SimpleValue>03</SimpleValue>
|
||||||
<Value ColumnRef="code">
|
</Value>
|
||||||
<SimpleValue>91</SimpleValue>
|
<Value ColumnRef="name">
|
||||||
</Value>
|
<SimpleValue>Factura de talonario o papel con numeración de contingencia.</SimpleValue>
|
||||||
<Value ColumnRef="name">
|
</Value>
|
||||||
<SimpleValue>Nota Crédito</SimpleValue>
|
<Value ColumnRef="description">
|
||||||
</Value>
|
<SimpleValue>Tipos de factura</SimpleValue>
|
||||||
</Row>
|
</Value>
|
||||||
<Row>
|
</Row>
|
||||||
<Value ColumnRef="code">
|
<Row>
|
||||||
<SimpleValue>92</SimpleValue>
|
<Value ColumnRef="code">
|
||||||
</Value>
|
<SimpleValue>04</SimpleValue>
|
||||||
<Value ColumnRef="name">
|
</Value>
|
||||||
<SimpleValue>Nota Débito</SimpleValue>
|
<Value ColumnRef="name">
|
||||||
</Value>
|
<SimpleValue>Factura electrónica de Venta por Contingencia DIAN</SimpleValue>
|
||||||
</Row>
|
</Value>
|
||||||
</SimpleCodeList>
|
<Value ColumnRef="description">
|
||||||
|
<SimpleValue>Tipos de factura</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>91</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Nota Crédito</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="description">
|
||||||
|
<SimpleValue>Exclusivo en referencias a documentos (elementos DocumentReference)</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>92</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Nota Débito</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="description">
|
||||||
|
<SimpleValue>Exclusivo en referencias a documentos (elementos DocumentReference)</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
</SimpleCodeList>
|
||||||
</gc:CodeList>
|
</gc:CodeList>
|
||||||
|
|||||||
@@ -1,162 +1,171 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- DIAN Genericode listas de valores:: Ultima modificación 18-02-2019 - evb-->
|
<!-- DIAN Genericode listas de valores:: Ultima modificación 18-02-2019 - evb-->
|
||||||
<gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/">
|
<gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/">
|
||||||
<Identification>
|
<Identification>
|
||||||
<ShortName>TipoImpuesto</ShortName>
|
<ShortName>TipoImpuesto</ShortName>
|
||||||
<LongName xml:lang="es">Tipo de Tributos</LongName>
|
<LongName xml:lang="es">Tipo de Tributos</LongName>
|
||||||
<Version>1</Version>
|
<Version>1</Version>
|
||||||
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoImpuesto</CanonicalUri>
|
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoImpuesto</CanonicalUri>
|
||||||
<CanonicalVersionUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoImpuesto-2.1</CanonicalVersionUri>
|
<CanonicalVersionUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoImpuesto-2.1</CanonicalVersionUri>
|
||||||
<LocationUri>http://dian.gov.co/ubl/os-ubl-2.0/cl/gc/default/TipoImpuesto-2.1.gc</LocationUri>
|
<LocationUri>http://dian.gov.co/ubl/os-ubl-2.0/cl/gc/default/TipoImpuesto-2.1.gc</LocationUri>
|
||||||
<Agency>
|
<Agency>
|
||||||
<LongName xml:lang="es">DIAN (Dirección de Impuestos y Aduanas Nacionales)</LongName>
|
<LongName xml:lang="es">DIAN (Dirección de Impuestos y Aduanas Nacionales)</LongName>
|
||||||
<Identifier>195</Identifier>
|
<Identifier>195</Identifier>
|
||||||
</Agency>
|
</Agency>
|
||||||
</Identification>
|
</Identification>
|
||||||
<ColumnSet>
|
<ColumnSet>
|
||||||
<Column Id="code" Use="required">
|
<Column Id="code" Use="required">
|
||||||
<ShortName>Code</ShortName>
|
<ShortName>Code</ShortName>
|
||||||
<LongName xml:lang="es">Codigo Comun</LongName>
|
<LongName xml:lang="es">Codigo Comun</LongName>
|
||||||
<Data Type="normalizedString"/>
|
<Data Type="normalizedString"/>
|
||||||
</Column>
|
</Column>
|
||||||
<Column Id="name" Use="required">
|
<Column Id="name" Use="required">
|
||||||
<ShortName>Name</ShortName>
|
<ShortName>Name</ShortName>
|
||||||
<LongName xml:lang="es">Nombre</LongName>
|
<LongName xml:lang="es">Nombre</LongName>
|
||||||
<Data Type="string"/>
|
<Data Type="string"/>
|
||||||
</Column>
|
</Column>
|
||||||
<Key Id="codeKey">
|
<Key Id="codeKey">
|
||||||
<ShortName>CodeKey</ShortName>
|
<ShortName>CodeKey</ShortName>
|
||||||
<ColumnRef Ref="code"/>
|
<ColumnRef Ref="code"/>
|
||||||
</Key>
|
</Key>
|
||||||
</ColumnSet>
|
</ColumnSet>
|
||||||
<SimpleCodeList>
|
<SimpleCodeList>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>01</SimpleValue>
|
<SimpleValue>01</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>IVA</SimpleValue>
|
<SimpleValue>IVA</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>02</SimpleValue>
|
<SimpleValue>02</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>IC</SimpleValue>
|
<SimpleValue>IC</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>03</SimpleValue>
|
<SimpleValue>03</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>ICA</SimpleValue>
|
<SimpleValue>ICA</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>04</SimpleValue>
|
<SimpleValue>04</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>INC</SimpleValue>
|
<SimpleValue>INC</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>05</SimpleValue>
|
<SimpleValue>05</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>ReteIVA</SimpleValue>
|
<SimpleValue>ReteIVA</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>06</SimpleValue>
|
<SimpleValue>06</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>ReteFuente</SimpleValue>
|
<SimpleValue>ReteRenta</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>07</SimpleValue>
|
<SimpleValue>07</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>ReteICA</SimpleValue>
|
<SimpleValue>ReteICA</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>08</SimpleValue>
|
<SimpleValue>08</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>ReteCREE</SimpleValue>
|
<SimpleValue>ReteCREE</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>20</SimpleValue>
|
<SimpleValue>20</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>FtoHorticultura</SimpleValue>
|
<SimpleValue>FtoHorticultura</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>21</SimpleValue>
|
<SimpleValue>21</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>Timbre</SimpleValue>
|
<SimpleValue>Timbre</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>22</SimpleValue>
|
<SimpleValue>22</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>Bolsas</SimpleValue>
|
<SimpleValue>Bolsas</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>23</SimpleValue>
|
<SimpleValue>23</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>INCarbono</SimpleValue>
|
<SimpleValue>INCarbono</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>24</SimpleValue>
|
<SimpleValue>24</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>INCombustibles</SimpleValue>
|
<SimpleValue>INCombustibles</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>25</SimpleValue>
|
<SimpleValue>25</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>Sobretasa Combustibles</SimpleValue>
|
<SimpleValue>Sobretasa Combustibles</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>26</SimpleValue>
|
<SimpleValue>26</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>Sordicom</SimpleValue>
|
<SimpleValue>Sordicom</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>ZZ</SimpleValue>
|
<SimpleValue>30</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
<Value ColumnRef="name">
|
<Value ColumnRef="name">
|
||||||
<SimpleValue>Nombre de la figura tributaria</SimpleValue>
|
<SimpleValue>Impuesto al Consumo de Datos</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
</SimpleCodeList>
|
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>ZZ</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Nombre de la figura tributaria</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
</SimpleCodeList>
|
||||||
</gc:CodeList>
|
</gc:CodeList>
|
||||||
|
|||||||
47
facho/fe/data/dian/codelist/TipoOperacionNCDS-2.1.gc
Normal file
47
facho/fe/data/dian/codelist/TipoOperacionNCDS-2.1.gc
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/">
|
||||||
|
<Identification>
|
||||||
|
<ShortName>TipoOperacion</ShortName>
|
||||||
|
<LongName xml:lang="es">Tipo de operacion</LongName>
|
||||||
|
<Version>1</Version>
|
||||||
|
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoOperacion</CanonicalUri>
|
||||||
|
<CanonicalVersionUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoOperacion-2.1</CanonicalVersionUri>
|
||||||
|
<LocationUri>http://dian.gov.co/ubl/os-ubl-2.0/cl/gc/default/TipoOperacion-2.1.gc</LocationUri>
|
||||||
|
<Agency>
|
||||||
|
<LongName xml:lang="es">DIAN (Dirección de Impuestos y Aduanas Nacionales)</LongName>
|
||||||
|
<Identifier>195</Identifier>
|
||||||
|
</Agency>
|
||||||
|
</Identification>
|
||||||
|
<ColumnSet>
|
||||||
|
<Column Id="code" Use="required">
|
||||||
|
<ShortName>Code</ShortName>
|
||||||
|
<Data Type="normalizedString"/>
|
||||||
|
</Column>
|
||||||
|
<Column Id="name" Use="required">
|
||||||
|
<ShortName>Nombre</ShortName>
|
||||||
|
<Data Type="normalizedString"/>
|
||||||
|
</Column>
|
||||||
|
<Key Id="codeKey">
|
||||||
|
<ShortName>CodeKey</ShortName>
|
||||||
|
<ColumnRef Ref="code"/>
|
||||||
|
</Key>
|
||||||
|
</ColumnSet>
|
||||||
|
<SimpleCodeList>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>10</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Residente</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>11</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>No Residente</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
</SimpleCodeList>
|
||||||
|
</gc:CodeList>
|
||||||
@@ -30,46 +30,6 @@
|
|||||||
</Key>
|
</Key>
|
||||||
</ColumnSet>
|
</ColumnSet>
|
||||||
<SimpleCodeList>
|
<SimpleCodeList>
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-99</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Otro tipo de obligado</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-06</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Ingresos y patrimonio</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-07</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Retención en la fuente a título de renta</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-08</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Retención timbre nacional</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-09</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Retención en la fuente en el impuesto sobre las ventas</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>O-13</SimpleValue>
|
<SimpleValue>O-13</SimpleValue>
|
||||||
@@ -78,14 +38,6 @@
|
|||||||
<SimpleValue>Gran contribuyente</SimpleValue>
|
<SimpleValue>Gran contribuyente</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-14</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Informante de exógena</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>O-15</SimpleValue>
|
<SimpleValue>O-15</SimpleValue>
|
||||||
@@ -94,38 +46,6 @@
|
|||||||
<SimpleValue>Autorretenedor</SimpleValue>
|
<SimpleValue>Autorretenedor</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-16</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Obligación de facturar por ingresos de bienes y/o servicios excluidos</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-17</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Profesionales de compra y venta de divisas</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-19</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Productor y/o exportador de bienes exentos</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-22</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Obligado a cumplir deberes formales a nombre de terceros</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>O-23</SimpleValue>
|
<SimpleValue>O-23</SimpleValue>
|
||||||
@@ -134,62 +54,6 @@
|
|||||||
<SimpleValue>Agente de retención en el impuesto sobre las ventas</SimpleValue>
|
<SimpleValue>Agente de retención en el impuesto sobre las ventas</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-32</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Impuesto Nacional a la Gasolina y al ACPM</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-33</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Impuesto Nacional al consumo</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-34</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Régimen simplificado impuesto nacional consumo rest y bares</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-36</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Establecimiento Permanente</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-37</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Obligado a Facturar Electrónicamente Modelo 2242</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-38</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Facturación Electrónica Voluntaria Modelo 2242</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-39</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Proveedor de Servicios Tecnológicos PST Modelo 2242</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>O-47</SimpleValue>
|
<SimpleValue>O-47</SimpleValue>
|
||||||
@@ -214,782 +78,6 @@
|
|||||||
<SimpleValue>No responsable de IVA</SimpleValue>
|
<SimpleValue>No responsable de IVA</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-52</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Facturador electrónico</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-99</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Otro tipo de obligado</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>R-00-PN</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Clientes del Exterior</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>R-12-PN</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Factor PN</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>R-16-PN</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Mandatario</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>R-25-PN</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Agente Interventor</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>R-99-PN</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>No responsable</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>R-06-PJ</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Apoderado especial</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>R-07-PJ</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Apoderado general</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>R-12-PJ</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Factor</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>R-16-PJ</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Mandatario</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>R-99-PJ</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Otro tipo de responsable</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-01</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Agente de carga internacional</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-02</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Agente marítimo</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-03</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Almacén general de depósito</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-04</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Comercializadora internacional (C.I.)</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-05</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Comerciante de la zona aduanera especial de Inírida, Puerto Carreño, Cumaribo y Primavera</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-06</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Comerciantes de la zona de régimen aduanero especial de Leticia</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-07</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Comerciantes de la zona de régimen aduanero especial de Maicao, Uribia y Manaure</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-08</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Comerciantes de la zona de régimen aduanero especial de Urabá, Tumaco y Guapí</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-09</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Comerciantes del puerto libre de San Andrés, Providencia y Santa Catalina</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-10</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Depósito público de apoyo logístico internacional</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-11</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Depósito privado para procesamiento industrial</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-12</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Depósito privado de transformación o ensamble</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-13</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Depósito franco</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-14</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Depósito privado aeronáutico</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-15</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Depósito privado para distribución internacional</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-16</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Depósito privado de provisiones de a bordo para consumo y para llevar</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-17</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Depósito privado para envíos urgentes</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-18</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Depósito privado</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-19</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Depósito público</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-20</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Depósito público para distribución internacional</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-21</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Exportador de café</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-22</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Exportador</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-23</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Importador</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-24</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Intermediario de tráfico postal y envíos urgentes</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-25</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Operador de transporte multimodal</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-26</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Sociedad de intermediación aduanera</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-27</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Titular de puertos y muelles de servicio público o privado</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-28</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Transportador 263nfor régimen de importación y/o exportación</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-29</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Transportista nacional para operaciones del régimen de tránsito aduanero</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-30</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Usuario comercial zona franca</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-32</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Usuario industrial de bienes zona franca</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-34</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Usuario industrial de servicios zona franca</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-36</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Usuario operador de zona franca</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-37</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Usuario aduanero permanente</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-38</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Usuario altamente exportador</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-39</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Usuario de zonas económicas especiales de exportación</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-40</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Deposito privado de instalaciones industriales</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-41</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Beneficiarios de programas especiales de exportación PEX</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-42</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Depósitos privados para mercancías en tránsito San Andrés</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-43</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Observadores de las operaciones de importación</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-44</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Usuarios sistemas especiales Importación exportación</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-46</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Transportador 263nformac régimen de importación y/o exportación</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-47</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Transportador terrestre régimen de importación y/o exportación</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-48</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Aeropuerto de servicio publico o privado</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-49</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Transportador fluvial régimen de importación</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-50</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Usuario industrial zona franca especial</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-53</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Agencias de aduanas 1</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-54</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Usuario Operador Zona Franca Especial</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-55</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Agencias de aduanas 2</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-56</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Agencias de aduanas 3</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-57</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Agencias de aduanas 4</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-58</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Transportador aéreo nacional</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-60</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Transportador aéreo, marítimo o fluvial modalidad Cabotaje</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-61</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Importador de alimentos de consumo humano y animal</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-62</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Importador Ocasional</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-63</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Importador de maquinaría y sus partes Decreto 2261 de 2012</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-64</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Beneficiario Programa de Fomento Industria Automotriz-PROFIA</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>A-99</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Otro tipo de agente aduanero</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-01</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Agencia</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-02</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Establecimiento de comercio</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-03</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Centro de explotación agrícola</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-04</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Centro de explotación animal</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-05</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Centro de explotación minera</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-06</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Centro de explotación de transformación</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-07</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Centro de explotación de servicios</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-08</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Oficina</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-09</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Sede</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-10</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Sucursal</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-11</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Consultorio</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-12</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Administraciones</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-13</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Seccionales</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-14</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Regionales</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-15</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Intendencias</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-16</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Local o negocio</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-17</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Punto de venta</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-18</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Fábrica</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-19</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Taller</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-20</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Cantera</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-21</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Pozo de Petróleo y Gas</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-22</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Otro lug de tipo de extrac explotación de recursos naturales</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>E-99</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Otro tipo de establecimiento</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-13</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Gran contribuyente</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-15</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Autorretenedor</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-23</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Agente de retención IVA</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
|
||||||
<Value ColumnRef="code">
|
|
||||||
<SimpleValue>O-47</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
<Value ColumnRef="name">
|
|
||||||
<SimpleValue>Régimen simple de tributación</SimpleValue>
|
|
||||||
</Value>
|
|
||||||
</Row>
|
|
||||||
<Row>
|
<Row>
|
||||||
<Value ColumnRef="code">
|
<Value ColumnRef="code">
|
||||||
<SimpleValue>R-99-PN</SimpleValue>
|
<SimpleValue>R-99-PN</SimpleValue>
|
||||||
|
|||||||
@@ -62,5 +62,13 @@
|
|||||||
<SimpleValue>Régimen simple de tributación</SimpleValue>
|
<SimpleValue>Régimen simple de tributación</SimpleValue>
|
||||||
</Value>
|
</Value>
|
||||||
</Row>
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>ZZ</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>No aplica</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
</SimpleCodeList>
|
</SimpleCodeList>
|
||||||
</gc:CodeList>
|
</gc:CodeList>
|
||||||
|
|||||||
156
facho/fe/data/dian/codelist/TipoTrabajador-2.1.gc
Normal file
156
facho/fe/data/dian/codelist/TipoTrabajador-2.1.gc
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
creado por facho, la dian tiene oficial?
|
||||||
|
poblar usando anexo tecnico 5.5.3
|
||||||
|
-->
|
||||||
|
<gc:CodeList xmlns:gc="http://docs.oasis-open.org/codelist/ns/genericode/1.0/">
|
||||||
|
<Identification>
|
||||||
|
<ShortName>TipoTrabajador</ShortName>
|
||||||
|
<LongName xml:lang="es">Tipos de trabajadores</LongName>
|
||||||
|
<Version>1</Version>
|
||||||
|
</Identification>
|
||||||
|
<ColumnSet>
|
||||||
|
<Column Id="code" Use="required">
|
||||||
|
<ShortName>Code</ShortName>
|
||||||
|
<Data Type="normalizedString"/>
|
||||||
|
</Column>
|
||||||
|
<Column Id="name" Use="required">
|
||||||
|
<ShortName>Nombre</ShortName>
|
||||||
|
<Data Type="normalizedString"/>
|
||||||
|
</Column>
|
||||||
|
<Key Id="codeKey">
|
||||||
|
<ShortName>CodeKey</ShortName>
|
||||||
|
<ColumnRef Ref="code"/>
|
||||||
|
</Key>
|
||||||
|
</ColumnSet>
|
||||||
|
<SimpleCodeList>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>01</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Dependiente</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>02</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Servicio domestico</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>04</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Madre comunitaria</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>12</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Aprendices del Sena en etapa lectiva</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>18</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Funcionarios públicos sin tope máximo de ibc</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>19</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Aprendices del SENA en etapa productiva</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>21</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Estudiantes de postgrado en salud</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>22</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Profesor de establecimiento particular</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>23</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Estudiantes aportes solo riesgos laborales</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>30</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Dependiente entidades o universidades públicas con régimen especial en salud</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>31</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Cooperados o pre cooperativas de trabajo asociado</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>47</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Trabajador dependiente de entidad beneficiaria del sistema general de participaciones ‐ aportes patronales</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>51</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Trabajador de tiempo parcial</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>54</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Pre pensionado de entidad en liquidación.</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>56</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Pre pensionado con aporte voluntario a salud</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Value ColumnRef="code">
|
||||||
|
<SimpleValue>58</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
<Value ColumnRef="name">
|
||||||
|
<SimpleValue>Estudiantes de prácticas laborales en el sector público</SimpleValue>
|
||||||
|
</Value>
|
||||||
|
</Row>
|
||||||
|
</SimpleCodeList>
|
||||||
|
</gc:CodeList>
|
||||||
@@ -12,9 +12,6 @@ class CodeList:
|
|||||||
self.short_name = ''
|
self.short_name = ''
|
||||||
self.long_name = ''
|
self.long_name = ''
|
||||||
self.version = 1
|
self.version = 1
|
||||||
self.canonical_uri = ''
|
|
||||||
self.canonical_version_uri = ''
|
|
||||||
self.location_uri = ''
|
|
||||||
|
|
||||||
self.name_column = name_column
|
self.name_column = name_column
|
||||||
self.rows = {}
|
self.rows = {}
|
||||||
@@ -27,9 +24,6 @@ class CodeList:
|
|||||||
self.short_name = tree.find('./Identification/ShortName').text
|
self.short_name = tree.find('./Identification/ShortName').text
|
||||||
self.long_name = tree.find('./Identification/LongName').text
|
self.long_name = tree.find('./Identification/LongName').text
|
||||||
self.version = tree.find('./Identification/Version').text
|
self.version = tree.find('./Identification/Version').text
|
||||||
self.canonical_uri = tree.find('./Identification/CanonicalUri').text
|
|
||||||
self.canonical_version_uri = tree.find('./Identification/CanonicalVersionUri').text
|
|
||||||
self.location_uri = tree.find('./Identification/LocationUri').text
|
|
||||||
|
|
||||||
#obtener registros...
|
#obtener registros...
|
||||||
for row in tree.findall('./SimpleCodeList/Row'):
|
for row in tree.findall('./SimpleCodeList/Row'):
|
||||||
@@ -88,10 +82,16 @@ TipoAmbiente = CodeList(path_for_codelist('TipoAmbiente-2.1.gc'), 'code', 'name'
|
|||||||
TipoDocumento = CodeList(path_for_codelist('TipoDocumento-2.1.gc'), 'code', 'name')
|
TipoDocumento = CodeList(path_for_codelist('TipoDocumento-2.1.gc'), 'code', 'name')
|
||||||
TipoImpuesto = CodeList(path_for_codelist('TipoImpuesto-2.1.gc'), 'code', 'name')\
|
TipoImpuesto = CodeList(path_for_codelist('TipoImpuesto-2.1.gc'), 'code', 'name')\
|
||||||
.update(CodeList(path_for_codelist('TipoImpuesto-2.1.custom.gc'), 'code', 'name'))
|
.update(CodeList(path_for_codelist('TipoImpuesto-2.1.custom.gc'), 'code', 'name'))
|
||||||
|
TarifaImpuesto = CodeList(path_for_codelist('TarifaImpuestoINC-2.1.gc'), 'code', 'name')\
|
||||||
|
.update(CodeList(path_for_codelist('TarifaImpuestoIVA-2.1.gc'), 'code', 'name'))\
|
||||||
|
.update(CodeList(path_for_codelist('TarifaImpuestoReteIVA-2.1.gc'), 'code', 'name'))\
|
||||||
|
.update(CodeList(path_for_codelist('TarifaImpuestoReteRenta-2.1.gc'), 'code', 'name'))
|
||||||
CodigoPrecioReferencia = CodeList(path_for_codelist('CodigoPrecioReferencia-2.1.gc'), 'code', 'name')
|
CodigoPrecioReferencia = CodeList(path_for_codelist('CodigoPrecioReferencia-2.1.gc'), 'code', 'name')
|
||||||
MediosPago = CodeList(path_for_codelist('MediosPago-2.1.gc'), 'code', 'name')
|
MediosPago = CodeList(path_for_codelist('MediosPago-2.1.gc'), 'code', 'name')
|
||||||
|
FormasPago = CodeList(path_for_codelist('FormasPago-2.1.gc'), 'code', 'name')
|
||||||
RegimenFiscal = CodeList(path_for_codelist('RegimenFiscal-2.1.custom.gc'), 'code', 'name')
|
RegimenFiscal = CodeList(path_for_codelist('RegimenFiscal-2.1.custom.gc'), 'code', 'name')
|
||||||
TipoOperacionNC = CodeList(path_for_codelist('TipoOperacionNC-2.1.gc'), 'code', 'name')
|
TipoOperacionNC = CodeList(path_for_codelist('TipoOperacionNC-2.1.gc'), 'code', 'name')
|
||||||
|
TipoOperacionNCDS = CodeList(path_for_codelist('TipoOperacionNCDS-2.1.gc'), 'code', 'name')
|
||||||
TipoOperacionND = CodeList(path_for_codelist('TipoOperacionND-2.1 - copia.gc'), 'code', 'name')
|
TipoOperacionND = CodeList(path_for_codelist('TipoOperacionND-2.1 - copia.gc'), 'code', 'name')
|
||||||
TipoOperacionF = CodeList(path_for_codelist('TipoOperacionF-2.1.gc'), 'code', 'name')\
|
TipoOperacionF = CodeList(path_for_codelist('TipoOperacionF-2.1.gc'), 'code', 'name')\
|
||||||
.update(CodeList(path_for_codelist('TipoOperacionF-2.1.custom.gc'), 'code', 'name'))
|
.update(CodeList(path_for_codelist('TipoOperacionF-2.1.custom.gc'), 'code', 'name'))
|
||||||
@@ -101,3 +101,9 @@ Paises = CodeList(path_for_codelist('Paises-2.1.gc'), 'code', 'name')
|
|||||||
TipoIdFiscal = CodeList(path_for_codelist('TipoIdFiscal-2.1.gc'), 'code', 'name')
|
TipoIdFiscal = CodeList(path_for_codelist('TipoIdFiscal-2.1.gc'), 'code', 'name')
|
||||||
CodigoDescuento = CodeList(path_for_codelist('CodigoDescuento-2.1.gc'), 'code', 'name')
|
CodigoDescuento = CodeList(path_for_codelist('CodigoDescuento-2.1.gc'), 'code', 'name')
|
||||||
UnidadesMedida = CodeList(path_for_codelist('UnidadesMedida-2.1.gc'), 'code', 'name')
|
UnidadesMedida = CodeList(path_for_codelist('UnidadesMedida-2.1.gc'), 'code', 'name')
|
||||||
|
TipoTrabajador = CodeList(path_for_codelist('TipoTrabajador-2.1.gc'), 'code', 'name')
|
||||||
|
SubTipoTrabajador = CodeList(path_for_codelist('SubTipoTrabajador-2.1.gc'), 'code', 'name')
|
||||||
|
TipoContrato = CodeList(path_for_codelist('TipoContrato-2.1.gc'), 'code', 'name')
|
||||||
|
PeriodoNomina = CodeList(path_for_codelist('PeriodoNomina-2.1.gc'), 'code', 'name')
|
||||||
|
TipoMoneda = CodeList(path_for_codelist('TipoMoneda-2.1.gc'), 'code', 'name')
|
||||||
|
IdiomaISO6391 = CodeList(path_for_codelist('Idioma-2.1.gc'), 'iso-639-1', 'name')
|
||||||
|
|||||||
255
facho/fe/fe.py
255
facho/fe/fe.py
@@ -1,6 +1,5 @@
|
|||||||
# This file is part of facho. The COPYRIGHT file at the top level of
|
# This file is part of facho. The COPYRIGHT file at the top level of
|
||||||
# this repository contains the full copyright notices and license terms.
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
from ..facho import FachoXML, FachoXMLExtension, LXMLBuilder
|
from ..facho import FachoXML, FachoXMLExtension, LXMLBuilder
|
||||||
import uuid
|
import uuid
|
||||||
import xmlsig
|
import xmlsig
|
||||||
@@ -8,13 +7,16 @@ import xades
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import OpenSSL
|
import OpenSSL
|
||||||
import zipfile
|
import zipfile
|
||||||
import warnings
|
# import warnings
|
||||||
import hashlib
|
import hashlib
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from .data.dian import codelist
|
from .data.dian import codelist
|
||||||
from . import form
|
from . import form
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from pathlib import Path
|
# from pathlib import Path
|
||||||
|
from dateutil import tz
|
||||||
|
|
||||||
|
from cryptography.hazmat.primitives.serialization import pkcs12
|
||||||
|
|
||||||
AMBIENTE_PRUEBAS = codelist.TipoAmbiente.by_name('Pruebas')['code']
|
AMBIENTE_PRUEBAS = codelist.TipoAmbiente.by_name('Pruebas')['code']
|
||||||
AMBIENTE_PRODUCCION = codelist.TipoAmbiente.by_name('Producción')['code']
|
AMBIENTE_PRODUCCION = codelist.TipoAmbiente.by_name('Producción')['code']
|
||||||
@@ -26,34 +28,53 @@ SCHEME_AGENCY_ATTRS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pwd = Path(__file__).parent
|
|
||||||
# RESOLUCION 0001: pagina 516
|
# RESOLUCION 0001: pagina 516
|
||||||
POLICY_ID = 'file://'+str(pwd)+'/data/dian/politicadefirmav2.pdf'
|
POLICY_ID = 'https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf'
|
||||||
POLICY_NAME = u'Política de firma para facturas electrónicas de la República de Colombia.'
|
POLICY_NAME = u'Política de firma para facturas electrónicas de la República de Colombia.'
|
||||||
|
|
||||||
|
Bogota = tz.gettz('America/Bogota')
|
||||||
|
# NAMESPACES = {
|
||||||
|
# 'atd': 'urn:oasis:names:specification:ubl:schema:xsd:AttachedDocument-2',
|
||||||
|
# 'nomina': 'dian:gov:co:facturaelectronica:NominaIndividual',
|
||||||
|
# 'nominaajuste': 'dian:gov:co:facturaelectronica:NominaIndividualDeAjuste',
|
||||||
|
# 'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1',
|
||||||
|
# 'xs': 'http://www.w3.org/2001/XMLSchema-instance',
|
||||||
|
# 'cac': 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2',
|
||||||
|
# 'cbc': 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
|
||||||
|
# 'cdt': 'urn:DocumentInformation:names:specification:ubl:colombia:schema:xsd:DocumentInformationAggregateComponents-1',
|
||||||
|
# 'clm54217': 'urn:un:unece:uncefact:codelist:specification:54217:2001',
|
||||||
|
# 'clmIANAMIMEMediaType': 'urn:un:unece:uncefact:codelist:specification:IANAMIMEMediaType:2003',
|
||||||
|
# 'ext': 'urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2',
|
||||||
|
# 'qdt': 'urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2',
|
||||||
|
# 'sts': 'dian:gov:co:facturaelectronica:Structures-2-1',
|
||||||
|
# 'udt': 'urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2',
|
||||||
|
# 'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
||||||
|
# 'xades': 'http://uri.etsi.org/01903/v1.3.2#',
|
||||||
|
# 'xades141': 'http://uri.etsi.org/01903/v1.4.1#',
|
||||||
|
# 'ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||||
|
# 'sig': 'http://www.w3.org/2000/09/xmldsig#',
|
||||||
|
# }
|
||||||
|
|
||||||
|
|
||||||
NAMESPACES = {
|
NAMESPACES = {
|
||||||
'facho': 'http://git.disroot.org/Etrivial/facho',
|
|
||||||
'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1',
|
'fe': 'http://www.dian.gov.co/contratos/facturaelectronica/v1',
|
||||||
'cac': 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2',
|
'cac': 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2',
|
||||||
'cbc': 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
|
'cbc': 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
|
||||||
'cdt': 'urn:DocumentInformation:names:specification:ubl:colombia:schema:xsd:DocumentInformationAggregateComponents-1',
|
|
||||||
'clm54217': 'urn:un:unece:uncefact:codelist:specification:54217:2001',
|
|
||||||
'clmIANAMIMEMediaType': 'urn:un:unece:uncefact:codelist:specification:IANAMIMEMediaType:2003',
|
|
||||||
'ext': 'urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2',
|
'ext': 'urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2',
|
||||||
'qdt': 'urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2',
|
'qdt': 'urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2',
|
||||||
'sts': 'dian:gov:co:facturaelectronica:Structures-2-1',
|
'sts': 'dian:gov:co:facturaelectronica:Structures-2-1',
|
||||||
'udt': 'urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2',
|
'udt': 'urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2',
|
||||||
'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
||||||
'xades': 'http://uri.etsi.org/01903/v1.3.2#',
|
|
||||||
'ds': 'http://www.w3.org/2000/09/xmldsig#',
|
'ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||||
'sig': 'http://www.w3.org/2000/09/xmldsig#',
|
'xades': 'http://uri.etsi.org/01903/v1.3.2#',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def fe_from_string(document: str) -> FachoXML:
|
def fe_from_string(document: str) -> FachoXML:
|
||||||
return FeXML.from_string(document)
|
return FeXML.from_string(document)
|
||||||
|
|
||||||
from contextlib import contextmanager
|
|
||||||
|
# from contextlib import contextmanager
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def mock_xades_policy():
|
def mock_xades_policy():
|
||||||
from mock import patch
|
from mock import patch
|
||||||
@@ -61,6 +82,7 @@ def mock_xades_policy():
|
|||||||
with patch('xades.policy.urllib.urlopen') as mock:
|
with patch('xades.policy.urllib.urlopen') as mock:
|
||||||
class UrllibPolicyMock:
|
class UrllibPolicyMock:
|
||||||
def read(self):
|
def read(self):
|
||||||
|
# Usamos contenido de archivo local
|
||||||
cur_dir = os.path.dirname(os.path.abspath(__file__))
|
cur_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
data_dir = os.path.join(cur_dir, 'data', 'dian')
|
data_dir = os.path.join(cur_dir, 'data', 'dian')
|
||||||
policy_file = os.path.join(data_dir, 'politicadefirmav2.pdf')
|
policy_file = os.path.join(data_dir, 'politicadefirmav2.pdf')
|
||||||
@@ -70,31 +92,35 @@ def mock_xades_policy():
|
|||||||
mock.return_value = UrllibPolicyMock()
|
mock.return_value = UrllibPolicyMock()
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
class FeXML(FachoXML):
|
class FeXML(FachoXML):
|
||||||
|
|
||||||
def __init__(self, root, namespace):
|
def __init__(self, root, namespace):
|
||||||
|
# raise Exception(namespace)
|
||||||
super().__init__("{%s}%s" % (namespace, root),
|
super().__init__("{%s}%s" % (namespace, root),
|
||||||
nsmap=NAMESPACES)
|
nsmap=NAMESPACES)
|
||||||
|
|
||||||
self._cn = root.rstrip('/')
|
|
||||||
#self.find_or_create_element(self._cn)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_string(cls, document: str) -> 'FeXML':
|
def from_string(cls, document: str) -> 'FeXML':
|
||||||
return super().from_string(document, namespaces=NAMESPACES)
|
return super().from_string(document, namespaces=NAMESPACES)
|
||||||
|
|
||||||
def tostring(self, **kw):
|
|
||||||
return super().tostring(**kw)\
|
|
||||||
.replace("fe:", "")\
|
|
||||||
.replace("xmlns:fe", "xmlns")
|
|
||||||
|
|
||||||
|
def tostring(self, **kw):
|
||||||
|
# MACHETE(bit4bit) la DIAN espera que la etiqueta raiz no este en un namespace
|
||||||
|
root_namespace = self.root_namespace()
|
||||||
|
root_localname = self.root_localname()
|
||||||
|
xmlns_name = {v: k for k, v in NAMESPACES.items()}[root_namespace]
|
||||||
|
if root_localname == 'Invoice':
|
||||||
|
urn_oasis = 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2'
|
||||||
|
if root_localname == 'CreditNote':
|
||||||
|
urn_oasis = 'urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2'
|
||||||
|
return super().tostring(**kw)\
|
||||||
|
.replace(xmlns_name + ':', '')\
|
||||||
|
.replace('xmlns:'+xmlns_name, 'xmlns')\
|
||||||
|
.replace(root_namespace, urn_oasis)
|
||||||
|
|
||||||
|
|
||||||
class DianXMLExtensionCUDFE(FachoXMLExtension):
|
class DianXMLExtensionCUDFE(FachoXMLExtension):
|
||||||
|
def __init__(self, invoice, tipo_ambiente=AMBIENTE_PRUEBAS):
|
||||||
def __init__(self, invoice, tipo_ambiente = AMBIENTE_PRUEBAS):
|
|
||||||
self.tipo_ambiente = tipo_ambiente
|
self.tipo_ambiente = tipo_ambiente
|
||||||
self.invoice = invoice
|
self.invoice = invoice
|
||||||
|
|
||||||
@@ -119,11 +145,25 @@ class DianXMLExtensionCUDFE(FachoXMLExtension):
|
|||||||
fachoxml.set_element('./cbc:UUID', cufe,
|
fachoxml.set_element('./cbc:UUID', cufe,
|
||||||
schemeID=self.tipo_ambiente,
|
schemeID=self.tipo_ambiente,
|
||||||
schemeName=self.schemeName())
|
schemeName=self.schemeName())
|
||||||
fachoxml.set_element('./cbc:ProfileID', 'DIAN 2.1')
|
|
||||||
fachoxml.set_element('./cbc:ProfileExecutionID', self._tipo_ambiente_int())
|
if self.schemeName() == "CUDS-SHA384":
|
||||||
|
if fachoxml.tag_document() == 'Invoice':
|
||||||
|
fachoxml.set_element('./cbc:ProfileID',
|
||||||
|
'DIAN 2.1: documento soporte en adquisiciones efectuadas a no obligados a facturar.')
|
||||||
|
else:
|
||||||
|
fachoxml.set_element('./cbc:ProfileID',
|
||||||
|
'DIAN 2.1: Nota de ajuste al documento soporte en adquisiciones efectuadas a sujetos no obligados a expedir factura o documento equivalente')
|
||||||
|
else:
|
||||||
|
fachoxml.set_element('./cbc:ProfileID', 'DIAN 2.1: Factura Electrónica de Venta')
|
||||||
|
|
||||||
|
# #DIAN 1.8.-2021: FAD03
|
||||||
|
# fachoxml.set_element('./cbc:ProfileID', 'DIAN 2.1: Factura Electrónica de Venta')
|
||||||
|
fachoxml.set_element(
|
||||||
|
'./cbc:ProfileExecutionID', self._tipo_ambiente_int())
|
||||||
#DIAN 1.7.-2020: FAB36
|
#DIAN 1.7.-2020: FAB36
|
||||||
fachoxml.set_element('./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:QRCode',
|
fachoxml.set_element(
|
||||||
self._get_qrcode(cufe))
|
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:QRCode',
|
||||||
|
self._get_qrcode(cufe))
|
||||||
|
|
||||||
def issue_time(self, datetime_):
|
def issue_time(self, datetime_):
|
||||||
return datetime_.strftime('%H:%M:%S-05:00')
|
return datetime_.strftime('%H:%M:%S-05:00')
|
||||||
@@ -139,7 +179,8 @@ class DianXMLExtensionCUDFE(FachoXMLExtension):
|
|||||||
build_vars['HoraFac'] = self.issue_time(invoice.invoice_issue)
|
build_vars['HoraFac'] = self.issue_time(invoice.invoice_issue)
|
||||||
# PAG 601
|
# PAG 601
|
||||||
build_vars['ValorBruto'] = invoice.invoice_legal_monetary_total.line_extension_amount
|
build_vars['ValorBruto'] = invoice.invoice_legal_monetary_total.line_extension_amount
|
||||||
build_vars['ValorTotalPagar'] = invoice.invoice_legal_monetary_total.payable_amount
|
build_vars['ValorTotalPagar'
|
||||||
|
] = invoice.invoice_legal_monetary_total.payable_amount
|
||||||
ValorImpuestoPara = defaultdict(lambda: form.Amount(0.0))
|
ValorImpuestoPara = defaultdict(lambda: form.Amount(0.0))
|
||||||
build_vars['CodImpuesto1'] = '01'
|
build_vars['CodImpuesto1'] = '01'
|
||||||
build_vars['CodImpuesto2'] = '04'
|
build_vars['CodImpuesto2'] = '04'
|
||||||
@@ -169,7 +210,8 @@ class DianXMLExtensionCUDFE(FachoXMLExtension):
|
|||||||
|
|
||||||
|
|
||||||
class DianXMLExtensionCUFE(DianXMLExtensionCUDFE):
|
class DianXMLExtensionCUFE(DianXMLExtensionCUDFE):
|
||||||
def __init__(self, invoice, clave_tecnica = '', tipo_ambiente = AMBIENTE_PRUEBAS):
|
def __init__(
|
||||||
|
self, invoice, clave_tecnica='', tipo_ambiente=AMBIENTE_PRUEBAS):
|
||||||
self.tipo_ambiente = tipo_ambiente
|
self.tipo_ambiente = tipo_ambiente
|
||||||
self.clave_tecnica = clave_tecnica
|
self.clave_tecnica = clave_tecnica
|
||||||
self.invoice = invoice
|
self.invoice = invoice
|
||||||
@@ -205,6 +247,7 @@ class DianXMLExtensionCUFE(DianXMLExtensionCUDFE):
|
|||||||
'%d' % build_vars['TipoAmb'],
|
'%d' % build_vars['TipoAmb'],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class DianXMLExtensionCUDE(DianXMLExtensionCUDFE):
|
class DianXMLExtensionCUDE(DianXMLExtensionCUDFE):
|
||||||
def __init__(self, invoice, software_pin, tipo_ambiente = AMBIENTE_PRUEBAS):
|
def __init__(self, invoice, software_pin, tipo_ambiente = AMBIENTE_PRUEBAS):
|
||||||
self.tipo_ambiente = tipo_ambiente
|
self.tipo_ambiente = tipo_ambiente
|
||||||
@@ -242,6 +285,41 @@ class DianXMLExtensionCUDE(DianXMLExtensionCUDFE):
|
|||||||
'%d' % build_vars['TipoAmb'],
|
'%d' % build_vars['TipoAmb'],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class DianXMLExtensionCUDS(DianXMLExtensionCUDFE):
|
||||||
|
def __init__(self, invoice, software_pin, tipo_ambiente = AMBIENTE_PRUEBAS):
|
||||||
|
self.tipo_ambiente = tipo_ambiente
|
||||||
|
self.software_pin = software_pin
|
||||||
|
self.invoice = invoice
|
||||||
|
|
||||||
|
def schemeName(self):
|
||||||
|
return 'CUDS-SHA384'
|
||||||
|
|
||||||
|
def buildVars(self):
|
||||||
|
build_vars = super().buildVars()
|
||||||
|
build_vars['Software-PIN'] = str(self.software_pin)
|
||||||
|
return build_vars
|
||||||
|
|
||||||
|
def formatVars(self):
|
||||||
|
build_vars = self.buildVars()
|
||||||
|
CodImpuesto1 = build_vars['CodImpuesto1']
|
||||||
|
CodImpuesto2 = build_vars['CodImpuesto2']
|
||||||
|
CodImpuesto3 = build_vars['CodImpuesto3']
|
||||||
|
return [
|
||||||
|
'%s' % build_vars['NumFac'],
|
||||||
|
'%s' % build_vars['FecFac'],
|
||||||
|
'%s' % build_vars['HoraFac'],
|
||||||
|
form.Amount(build_vars['ValorBruto']).truncate_as_string(2),
|
||||||
|
CodImpuesto1,
|
||||||
|
form.Amount(build_vars['ValorImpuestoPara'].get(CodImpuesto1, 0.0)).truncate_as_string(2),
|
||||||
|
form.Amount(build_vars['ValorTotalPagar']).truncate_as_string(2),
|
||||||
|
'%s' % build_vars['NitOFE'],
|
||||||
|
'%s' % build_vars['NumAdq'],
|
||||||
|
'%s' % build_vars['Software-PIN'],
|
||||||
|
'%d' % build_vars['TipoAmb'],
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class DianXMLExtensionSoftwareProvider(FachoXMLExtension):
|
class DianXMLExtensionSoftwareProvider(FachoXMLExtension):
|
||||||
# RESOLUCION 0004: pagina 108
|
# RESOLUCION 0004: pagina 108
|
||||||
|
|
||||||
@@ -251,7 +329,8 @@ class DianXMLExtensionSoftwareProvider(FachoXMLExtension):
|
|||||||
self.id_software = id_software
|
self.id_software = id_software
|
||||||
|
|
||||||
def build(self, fexml):
|
def build(self, fexml):
|
||||||
software_provider = fexml.fragment('./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:SoftwareProvider')
|
software_provider = fexml.fragment(
|
||||||
|
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:SoftwareProvider')
|
||||||
provider_id_attrs = SCHEME_AGENCY_ATTRS.copy()
|
provider_id_attrs = SCHEME_AGENCY_ATTRS.copy()
|
||||||
provider_id_attrs.update({'schemeID': self.dv})
|
provider_id_attrs.update({'schemeID': self.dv})
|
||||||
#DIAN 1.7.-2020: FAB23
|
#DIAN 1.7.-2020: FAB23
|
||||||
@@ -281,33 +360,36 @@ class DianXMLExtensionSoftwareSecurityCode(FachoXMLExtension):
|
|||||||
|
|
||||||
|
|
||||||
class DianXMLExtensionSigner:
|
class DianXMLExtensionSigner:
|
||||||
|
def __init__(self, pkcs12_path, passphrase=None, localpolicy=True):
|
||||||
def __init__(self, pkcs12_path, passphrase=None, mockpolicy=False):
|
|
||||||
self._pkcs12_data = open(pkcs12_path, 'rb').read()
|
self._pkcs12_data = open(pkcs12_path, 'rb').read()
|
||||||
self._passphrase = None
|
self._passphrase = None
|
||||||
self._mockpolicy = mockpolicy
|
self._localpolicy = localpolicy
|
||||||
if passphrase:
|
if passphrase:
|
||||||
self._passphrase = passphrase.encode('utf-8')
|
self._passphrase = passphrase.encode('utf-8')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_bytes(cls, data, passphrase=None, mockpolicy=False):
|
def from_bytes(cls, data, passphrase=None, localpolicy=True):
|
||||||
self = cls.__new__(cls)
|
self = cls.__new__(cls)
|
||||||
|
|
||||||
self._pkcs12_data = data
|
self._pkcs12_data = data
|
||||||
self._passphrase = None
|
self._passphrase = None
|
||||||
self._mockpolicy = mockpolicy
|
self._localpolicy = localpolicy
|
||||||
if passphrase:
|
if passphrase:
|
||||||
self._passphrase = passphrase.encode('utf-8')
|
self._passphrase = passphrase.encode('utf-8')
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def _element_extension_content(self, fachoxml):
|
||||||
|
return fachoxml.builder.xpath(
|
||||||
|
fachoxml.root,
|
||||||
|
'./ext:UBLExtensions/ext:UBLExtension[2]/ext:ExtensionContent')
|
||||||
|
|
||||||
def sign_xml_string(self, document):
|
def sign_xml_string(self, document):
|
||||||
xml = LXMLBuilder.from_string(document)
|
xml = LXMLBuilder.from_string(document)
|
||||||
signature = self.sign_xml_element(xml)
|
signature = self.sign_xml_element(xml)
|
||||||
|
|
||||||
fachoxml = FachoXML(xml,nsmap=NAMESPACES)
|
fachoxml = FachoXML(xml,nsmap=NAMESPACES)
|
||||||
#DIAN 1.7.-2020: FAB01
|
#DIAN 1.7.-2020: FAB01
|
||||||
extcontent = fachoxml.builder.xpath(fachoxml.root, './ext:UBLExtensions/ext:UBLExtension[2]/ext:ExtensionContent')
|
extcontent = self._element_extension_content(fachoxml)
|
||||||
fachoxml.append_element(extcontent, signature)
|
fachoxml.append_element(extcontent, signature)
|
||||||
|
|
||||||
return fachoxml.tostring(xml_declaration=True, encoding='UTF-8')
|
return fachoxml.tostring(xml_declaration=True, encoding='UTF-8')
|
||||||
@@ -321,7 +403,6 @@ class DianXMLExtensionSigner:
|
|||||||
)
|
)
|
||||||
xml.append(signature)
|
xml.append(signature)
|
||||||
|
|
||||||
|
|
||||||
ref = xmlsig.template.add_reference(
|
ref = xmlsig.template.add_reference(
|
||||||
signature, xmlsig.constants.TransformSha256, uri="", name="xmldsig-%s-ref0" % (id_uuid)
|
signature, xmlsig.constants.TransformSha256, uri="", name="xmldsig-%s-ref0" % (id_uuid)
|
||||||
)
|
)
|
||||||
@@ -329,14 +410,16 @@ class DianXMLExtensionSigner:
|
|||||||
|
|
||||||
id_keyinfo = "xmldsig-%s-KeyInfo" % (id_uuid)
|
id_keyinfo = "xmldsig-%s-KeyInfo" % (id_uuid)
|
||||||
xmlsig.template.add_reference(
|
xmlsig.template.add_reference(
|
||||||
signature, xmlsig.constants.TransformSha256, uri="#%s" % (id_keyinfo), name="xmldsig-%s-ref1" % (id_uuid),
|
signature, xmlsig.constants.TransformSha256, uri="#%s" % (
|
||||||
|
id_keyinfo), name="xmldsig-%s-ref1" % (id_uuid),
|
||||||
)
|
)
|
||||||
ki = xmlsig.template.ensure_key_info(signature, name=id_keyinfo)
|
ki = xmlsig.template.ensure_key_info(signature, name=id_keyinfo)
|
||||||
data = xmlsig.template.add_x509_data(ki)
|
data = xmlsig.template.add_x509_data(ki)
|
||||||
xmlsig.template.x509_data_add_certificate(data)
|
xmlsig.template.x509_data_add_certificate(data)
|
||||||
xmlsig.template.add_key_value(ki)
|
xmlsig.template.add_key_value(ki)
|
||||||
|
|
||||||
qualifying = xades.template.create_qualifying_properties(signature, 'XadesObjects', 'xades')
|
qualifying = xades.template.create_qualifying_properties(
|
||||||
|
signature, 'XadesObjects', 'xades')
|
||||||
xades.utils.ensure_id(qualifying)
|
xades.utils.ensure_id(qualifying)
|
||||||
|
|
||||||
id_props = "xmldsig-%s-signedprops" % (id_uuid)
|
id_props = "xmldsig-%s-signedprops" % (id_uuid)
|
||||||
@@ -344,10 +427,12 @@ class DianXMLExtensionSigner:
|
|||||||
signature, xmlsig.constants.TransformSha256, uri="#%s" % (id_props),
|
signature, xmlsig.constants.TransformSha256, uri="#%s" % (id_props),
|
||||||
uri_type="http://uri.etsi.org/01903#SignedProperties"
|
uri_type="http://uri.etsi.org/01903#SignedProperties"
|
||||||
)
|
)
|
||||||
xmlsig.template.add_transform(props_ref, xmlsig.constants.TransformInclC14N)
|
xmlsig.template.add_transform(
|
||||||
|
props_ref, xmlsig.constants.TransformInclC14N)
|
||||||
|
|
||||||
# TODO assert with http://www.sic.gov.co/hora-legal-colombiana
|
# TODO assert with http://www.sic.gov.co/hora-legal-colombiana
|
||||||
props = xades.template.create_signed_properties(qualifying, name=id_props, datetime=datetime.now())
|
props = xades.template.create_signed_properties(
|
||||||
|
qualifying, name=id_props, datetime=datetime.now(tz=Bogota))
|
||||||
xades.template.add_claimed_role(props, "supplier")
|
xades.template.add_claimed_role(props, "supplier")
|
||||||
|
|
||||||
policy = xades.policy.GenericPolicyId(
|
policy = xades.policy.GenericPolicyId(
|
||||||
@@ -355,48 +440,51 @@ class DianXMLExtensionSigner:
|
|||||||
POLICY_NAME,
|
POLICY_NAME,
|
||||||
xmlsig.constants.TransformSha256)
|
xmlsig.constants.TransformSha256)
|
||||||
ctx = xades.XAdESContext(policy)
|
ctx = xades.XAdESContext(policy)
|
||||||
ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(self._pkcs12_data,
|
ctx.load_pkcs12(pkcs12.load_key_and_certificates(
|
||||||
self._passphrase))
|
self._pkcs12_data,
|
||||||
|
self._passphrase))
|
||||||
|
|
||||||
if self._mockpolicy:
|
# ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(
|
||||||
|
# self._pkcs12_data,
|
||||||
|
# self._passphrase))
|
||||||
|
if self._localpolicy:
|
||||||
with mock_xades_policy():
|
with mock_xades_policy():
|
||||||
ctx.sign(signature)
|
ctx.sign(signature)
|
||||||
ctx.verify(signature)
|
ctx.verify(signature)
|
||||||
else:
|
else:
|
||||||
ctx.sign(signature)
|
ctx.sign(signature)
|
||||||
ctx.verify(signature)
|
ctx.verify(signature)
|
||||||
#xmlsig take parent root
|
# xmlsig take parent root
|
||||||
xml.remove(signature)
|
xml.remove(signature)
|
||||||
return signature
|
return signature
|
||||||
|
|
||||||
def build(self, fachoxml):
|
def build(self, fachoxml):
|
||||||
signature = self.sign_xml_element(fachoxml.root)
|
signature = self.sign_xml_element(fachoxml.root)
|
||||||
extcontent = fachoxml.builder.xpath(fachoxml.root, './ext:UBLExtensions/ext:UBLExtension[2]/ext:ExtensionContent')
|
extcontent = self._element_extension_content(fachoxml)
|
||||||
fachoxml.append_element(extcontent, signature)
|
fachoxml.append_element(extcontent, signature)
|
||||||
|
|
||||||
|
|
||||||
class DianXMLExtensionAuthorizationProvider(FachoXMLExtension):
|
class DianXMLExtensionAuthorizationProvider(FachoXMLExtension):
|
||||||
# RESOLUCION 0004: pagina 176
|
# RESOLUCION 0004: pagina 176
|
||||||
|
|
||||||
def build(self, fexml):
|
def build(self, fexml):
|
||||||
attrs = {'schemeID': '4', 'schemeName': '31'}
|
attrs = {'schemeID': '4', 'schemeName': '31'}
|
||||||
attrs.update(SCHEME_AGENCY_ATTRS)
|
attrs.update(SCHEME_AGENCY_ATTRS)
|
||||||
|
|
||||||
authorization_provider = fexml.fragment('./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:AuthorizationProvider')
|
authorization_provider = fexml.fragment('./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:AuthorizationProvider')
|
||||||
authorization_provider.set_element('./sts:AuthorizationProviderID',
|
authorization_provider.set_element('./sts:AuthorizationProviderID',
|
||||||
'800197268',
|
'800197268',
|
||||||
**attrs)
|
**attrs)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DianXMLExtensionInvoiceSource(FachoXMLExtension):
|
class DianXMLExtensionInvoiceSource(FachoXMLExtension):
|
||||||
# CAB13
|
# CAB13
|
||||||
def build(self, fexml):
|
def build(self, fexml):
|
||||||
dian_path = '/fe:CreditNote/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:InvoiceSource/cbc:IdentificationCode'
|
dian_path = '/fe:CreditNote/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:InvoiceSource/cbc:IdentificationCode'
|
||||||
fexml.set_element(dian_path, 'CO',
|
fexml.set_element(
|
||||||
listAgencyID="6",
|
dian_path, 'CO',
|
||||||
listAgencyName="United Nations Economic Commission for Europe",
|
listAgencyID="6",
|
||||||
listSchemeURI="urn:oasis:names:specification:ubl:codelist:gc:CountryIdentificationCode-2.1")
|
listAgencyName="United Nations Economic Commission for Europe",
|
||||||
|
listSchemeURI="urn:oasis:names:specification:ubl:codelist:gc:CountryIdentificationCode-2.1")
|
||||||
|
|
||||||
|
|
||||||
class DianXMLExtensionInvoiceAuthorization(FachoXMLExtension):
|
class DianXMLExtensionInvoiceAuthorization(FachoXMLExtension):
|
||||||
@@ -426,16 +514,15 @@ class DianXMLExtensionInvoiceAuthorization(FachoXMLExtension):
|
|||||||
invoice_control.set_element('/sts:InvoiceControl/sts:AuthorizedInvoices/sts:To',
|
invoice_control.set_element('/sts:InvoiceControl/sts:AuthorizedInvoices/sts:To',
|
||||||
self.to)
|
self.to)
|
||||||
|
|
||||||
fexml.set_element('./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:InvoiceSource/cbc:IdentificationCode',
|
fexml.set_element(
|
||||||
'CO',
|
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:InvoiceSource/cbc:IdentificationCode',
|
||||||
#DIAN 1.7.-2020: FAB15
|
'CO',
|
||||||
listAgencyID="6",
|
# DIAN 1.7.-2020: FAB15
|
||||||
#DIAN 1.7.-2020: FAB16
|
listAgencyID="6",
|
||||||
listAgencyName="United Nations Economic Commission for Europe",
|
# DIAN 1.7.-2020: FAB16
|
||||||
#DIAN 1.7.-2020: FAB17
|
listAgencyName="United Nations Economic Commission for Europe",
|
||||||
listSchemeURI="urn:oasis:names:specification:ubl:codelist:gc:CountryIdentificationCode-2.1"
|
# DIAN 1.7.-2020: FAB17
|
||||||
)
|
listSchemeURI="urn:oasis:names:specification:ubl:codelist:gc:CountryIdentificationCode-2.1")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DianZIP:
|
class DianZIP:
|
||||||
@@ -444,10 +531,11 @@ class DianZIP:
|
|||||||
MAX_FILES = 50
|
MAX_FILES = 50
|
||||||
|
|
||||||
def __init__(self, file_like):
|
def __init__(self, file_like):
|
||||||
self.zipfile = zipfile.ZipFile(file_like, mode='w', compression=zipfile.ZIP_DEFLATED)
|
self.zipfile = zipfile.ZipFile(
|
||||||
|
file_like, mode='w', compression=zipfile.ZIP_DEFLATED)
|
||||||
self.num_files = 0
|
self.num_files = 0
|
||||||
|
|
||||||
def add_invoice_xml(self, name, xml_data):
|
def add_xml(self, name, xml_data):
|
||||||
self.num_files += 1
|
self.num_files += 1
|
||||||
# TODO cual es la norma para los nombres de archivos?
|
# TODO cual es la norma para los nombres de archivos?
|
||||||
m = hashlib.sha256()
|
m = hashlib.sha256()
|
||||||
@@ -458,7 +546,17 @@ class DianZIP:
|
|||||||
|
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
# DEPRECATED usar add_xml
|
||||||
|
def add_invoice_xml(self, name, xml_data):
|
||||||
|
return self.add_xml(name, xml_data)
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
|
"""
|
||||||
|
Facilita el uso de esta manera:
|
||||||
|
f = open('xxx', 'rb')
|
||||||
|
with DianZIP(f) as zip:
|
||||||
|
zip.add_invoice_xml('name', 'data xml')
|
||||||
|
"""
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, type, value, traceback):
|
def __exit__(self, type, value, traceback):
|
||||||
@@ -467,34 +565,35 @@ class DianZIP:
|
|||||||
|
|
||||||
class DianXMLExtensionSignerVerifier:
|
class DianXMLExtensionSignerVerifier:
|
||||||
|
|
||||||
def __init__(self, pkcs12_path_or_bytes, passphrase=None, mockpolicy=False):
|
def __init__(self, pkcs12_path_or_bytes, passphrase=None, localpolicy=True):
|
||||||
self._pkcs12_path_or_bytes = pkcs12_path_or_bytes
|
self._pkcs12_path_or_bytes = pkcs12_path_or_bytes
|
||||||
self._passphrase = None
|
self._passphrase = None
|
||||||
self._mockpolicy = mockpolicy
|
self._localpolicy = localpolicy
|
||||||
if passphrase:
|
if passphrase:
|
||||||
self._passphrase = passphrase.encode('utf-8')
|
self._passphrase = passphrase.encode('utf-8')
|
||||||
|
|
||||||
def verify_string(self, document):
|
def verify_string(self, document):
|
||||||
|
# Obtener FachoXML
|
||||||
xml = LXMLBuilder.from_string(document)
|
xml = LXMLBuilder.from_string(document)
|
||||||
fachoxml = FachoXML(xml,nsmap=NAMESPACES)
|
fachoxml = FachoXML(xml, nsmap=NAMESPACES)
|
||||||
|
|
||||||
|
# Obtener Signature
|
||||||
signature = fachoxml.builder.xpath(fachoxml.root, '//ds:Signature')
|
signature = fachoxml.builder.xpath(fachoxml.root, '//ds:Signature')
|
||||||
assert signature is not None
|
assert signature is not None
|
||||||
|
|
||||||
|
# Se mueve Signature a elemento raiz para realizar verificaion
|
||||||
signature.getparent().remove(signature)
|
signature.getparent().remove(signature)
|
||||||
fachoxml.root.append(signature)
|
fachoxml.root.append(signature)
|
||||||
|
|
||||||
ctx = xades.XAdESContext()
|
# Verificar archivo usando Signature
|
||||||
|
|
||||||
pkcs12_data = self._pkcs12_path_or_bytes
|
pkcs12_data = self._pkcs12_path_or_bytes
|
||||||
if isinstance(self._pkcs12_path_or_bytes, str):
|
if isinstance(self._pkcs12_path_or_bytes, str):
|
||||||
pkcs12_data = open(self._pkcs12_path_or_bytes, 'rb').read()
|
pkcs12_data = open(self._pkcs12_path_or_bytes, 'rb').read()
|
||||||
|
ctx = xades.XAdESContext()
|
||||||
ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(pkcs12_data,
|
ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(pkcs12_data,
|
||||||
self._passphrase))
|
self._passphrase))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self._mockpolicy:
|
if self._localpolicy:
|
||||||
with mock_xades_policy():
|
with mock_xades_policy():
|
||||||
ctx.verify(signature)
|
ctx.verify(signature)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -1,24 +1,26 @@
|
|||||||
# This file is part of facho. The COPYRIGHT file at the top level of
|
# This file is part of facho. The COPYRIGHT file at the top level of
|
||||||
# this repository contains the full copyright notices and license terms.
|
# this repository contains the full copyright notices and license terms.
|
||||||
|
|
||||||
import hashlib
|
# import hashlib
|
||||||
from functools import reduce
|
# from functools import reduce
|
||||||
import copy
|
# import copy
|
||||||
|
|
||||||
import dataclasses
|
import dataclasses
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, field
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
from collections import defaultdict
|
# from collections import defaultdict
|
||||||
import decimal
|
import decimal
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from ..data.dian import codelist
|
from ..data.dian import codelist
|
||||||
|
|
||||||
DECIMAL_PRECISION = 6
|
DECIMAL_PRECISION = 6
|
||||||
|
|
||||||
|
|
||||||
class AmountCurrencyError(TypeError):
|
class AmountCurrencyError(TypeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Currency:
|
class Currency:
|
||||||
code: str
|
code: str
|
||||||
@@ -29,6 +31,7 @@ class Currency:
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.code
|
return self.code
|
||||||
|
|
||||||
|
|
||||||
class Collection:
|
class Collection:
|
||||||
|
|
||||||
def __init__(self, array):
|
def __init__(self, array):
|
||||||
@@ -45,6 +48,7 @@ class Collection:
|
|||||||
def sum(self):
|
def sum(self):
|
||||||
return sum(self.array)
|
return sum(self.array)
|
||||||
|
|
||||||
|
|
||||||
class AmountCollection(Collection):
|
class AmountCollection(Collection):
|
||||||
|
|
||||||
def sum(self):
|
def sum(self):
|
||||||
@@ -53,10 +57,13 @@ class AmountCollection(Collection):
|
|||||||
total += v
|
total += v
|
||||||
return total
|
return total
|
||||||
|
|
||||||
class Amount:
|
|
||||||
def __init__(self, amount: int or float or str or Amount, currency: Currency = Currency('COP')):
|
|
||||||
|
|
||||||
#DIAN 1.7.-2020: 1.2.3.1
|
class Amount:
|
||||||
|
def __init__(
|
||||||
|
self, amount: typing.Union[int, float, str, "Amount"],
|
||||||
|
currency: Currency = Currency('COP')):
|
||||||
|
|
||||||
|
# DIAN 1.7.-2020: 1.2.3.1
|
||||||
if isinstance(amount, Amount):
|
if isinstance(amount, Amount):
|
||||||
if amount < Amount(0.0):
|
if amount < Amount(0.0):
|
||||||
raise ValueError('amount must be positive >= 0')
|
raise ValueError('amount must be positive >= 0')
|
||||||
@@ -67,14 +74,16 @@ class Amount:
|
|||||||
if float(amount) < 0:
|
if float(amount) < 0:
|
||||||
raise ValueError('amount must be positive >= 0')
|
raise ValueError('amount must be positive >= 0')
|
||||||
|
|
||||||
self.amount = Decimal(amount, decimal.Context(prec=DECIMAL_PRECISION,
|
self.amount = Decimal(
|
||||||
#DIAN 1.7.-2020: 1.2.1.1
|
amount, decimal.Context(
|
||||||
rounding=decimal.ROUND_HALF_EVEN ))
|
prec=DECIMAL_PRECISION,
|
||||||
|
# DIAN 1.7.-2020: 1.2.1.1
|
||||||
|
rounding=decimal.ROUND_HALF_EVEN))
|
||||||
self.currency = currency
|
self.currency = currency
|
||||||
|
|
||||||
def fromNumber(self, val):
|
def fromNumber(self, val):
|
||||||
return Amount(val, currency=self.currency)
|
return Amount(val, currency=self.currency)
|
||||||
|
|
||||||
def round(self, prec):
|
def round(self, prec):
|
||||||
return Amount(round(self.amount, prec), currency=self.currency)
|
return Amount(round(self.amount, prec), currency=self.currency)
|
||||||
|
|
||||||
@@ -92,7 +101,8 @@ class Amount:
|
|||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if not self.is_same_currency(other):
|
if not self.is_same_currency(other):
|
||||||
raise AmountCurrencyError()
|
raise AmountCurrencyError()
|
||||||
return round(self.amount, DECIMAL_PRECISION) == round(other.amount, DECIMAL_PRECISION)
|
return round(self.amount, DECIMAL_PRECISION) == round(
|
||||||
|
other.amount, DECIMAL_PRECISION)
|
||||||
|
|
||||||
def _cast(self, val):
|
def _cast(self, val):
|
||||||
if type(val) in [int, float]:
|
if type(val) in [int, float]:
|
||||||
@@ -100,7 +110,7 @@ class Amount:
|
|||||||
if isinstance(val, Amount):
|
if isinstance(val, Amount):
|
||||||
return val
|
return val
|
||||||
raise TypeError("cant cast to amount")
|
raise TypeError("cant cast to amount")
|
||||||
|
|
||||||
def __add__(self, rother):
|
def __add__(self, rother):
|
||||||
other = self._cast(rother)
|
other = self._cast(rother)
|
||||||
if not self.is_same_currency(other):
|
if not self.is_same_currency(other):
|
||||||
@@ -124,14 +134,14 @@ class Amount:
|
|||||||
|
|
||||||
def truncate_as_string(self, prec):
|
def truncate_as_string(self, prec):
|
||||||
parts = str(self.float()).split('.', 1)
|
parts = str(self.float()).split('.', 1)
|
||||||
return '%s.%s' % (parts[0], parts[1][0:prec].ljust(prec,'0'))
|
return '%s.%s' % (parts[0], parts[1][0:prec].ljust(prec, '0'))
|
||||||
|
|
||||||
def float(self):
|
def float(self):
|
||||||
return float(round(self.amount, DECIMAL_PRECISION))
|
return float(round(self.amount, DECIMAL_PRECISION))
|
||||||
|
|
||||||
|
|
||||||
class Quantity:
|
class Quantity:
|
||||||
|
|
||||||
def __init__(self, val, code):
|
def __init__(self, val, code):
|
||||||
if type(val) not in [float, int]:
|
if type(val) not in [float, int]:
|
||||||
raise ValueError('val expected int or float')
|
raise ValueError('val expected int or float')
|
||||||
@@ -153,6 +163,7 @@ class Quantity:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return str(self)
|
return str(self)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Item:
|
class Item:
|
||||||
scheme_name: str
|
scheme_name: str
|
||||||
@@ -163,10 +174,10 @@ class Item:
|
|||||||
|
|
||||||
|
|
||||||
class StandardItem(Item):
|
class StandardItem(Item):
|
||||||
def __init__(self, id_: str, description: str = ''):
|
def __init__(self, id_: str, description: str = '', name: str = ''):
|
||||||
super().__init__(id=id_,
|
super().__init__(id=id_,
|
||||||
description=description,
|
description=description,
|
||||||
scheme_name='',
|
scheme_name=name,
|
||||||
scheme_id='999',
|
scheme_id='999',
|
||||||
scheme_agency_id='')
|
scheme_agency_id='')
|
||||||
|
|
||||||
@@ -177,9 +188,9 @@ class UNSPSCItem(Item):
|
|||||||
description=description,
|
description=description,
|
||||||
scheme_name='UNSPSC',
|
scheme_name='UNSPSC',
|
||||||
scheme_id='001',
|
scheme_id='001',
|
||||||
scheme_agency_id='10')
|
scheme_agency_id='10')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Country:
|
class Country:
|
||||||
code: str
|
code: str
|
||||||
@@ -190,6 +201,7 @@ class Country:
|
|||||||
raise ValueError("code [%s] not found" % (self.code))
|
raise ValueError("code [%s] not found" % (self.code))
|
||||||
self.name = codelist.Paises[self.code]['name']
|
self.name = codelist.Paises[self.code]['name']
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class CountrySubentity:
|
class CountrySubentity:
|
||||||
code: str
|
code: str
|
||||||
@@ -200,6 +212,7 @@ class CountrySubentity:
|
|||||||
raise ValueError("code [%s] not found" % (self.code))
|
raise ValueError("code [%s] not found" % (self.code))
|
||||||
self.name = codelist.Departamento[self.code]['name']
|
self.name = codelist.Departamento[self.code]['name']
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class City:
|
class City:
|
||||||
code: str
|
code: str
|
||||||
@@ -210,13 +223,22 @@ class City:
|
|||||||
raise ValueError("code [%s] not found" % (self.code))
|
raise ValueError("code [%s] not found" % (self.code))
|
||||||
self.name = codelist.Municipio[self.code]['name']
|
self.name = codelist.Municipio[self.code]['name']
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PostalZone:
|
||||||
|
code: str = ''
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Address:
|
class Address:
|
||||||
name: str
|
name: str
|
||||||
street: str = ''
|
street: str = ''
|
||||||
city: City = City('05001')
|
city: City = field(default_factory=lambda: City('05001'))
|
||||||
country: Country = Country('CO')
|
country: Country = field(default_factory=lambda: Country('CO'))
|
||||||
countrysubentity: CountrySubentity = CountrySubentity('05')
|
countrysubentity: CountrySubentity = field(
|
||||||
|
default_factory=lambda: CountrySubentity('05'))
|
||||||
|
postalzone: PostalZone = field(default_factory=lambda: PostalZone(''))
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PartyIdentification:
|
class PartyIdentification:
|
||||||
@@ -237,6 +259,7 @@ class PartyIdentification:
|
|||||||
if self.type_fiscal not in codelist.TipoIdFiscal:
|
if self.type_fiscal not in codelist.TipoIdFiscal:
|
||||||
raise ValueError("type_fiscal [%s] not found" % (self.type_fiscal))
|
raise ValueError("type_fiscal [%s] not found" % (self.type_fiscal))
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Responsability:
|
class Responsability:
|
||||||
codes: list
|
codes: list
|
||||||
@@ -261,12 +284,12 @@ class TaxScheme:
|
|||||||
code: str
|
code: str
|
||||||
name: str = ''
|
name: str = ''
|
||||||
|
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
if self.code not in codelist.TipoImpuesto:
|
if self.code not in codelist.TipoImpuesto:
|
||||||
raise ValueError("code not found")
|
raise ValueError("code not found")
|
||||||
self.name = codelist.TipoImpuesto[self.code]['name']
|
self.name = codelist.TipoImpuesto[self.code]['name']
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Party:
|
class Party:
|
||||||
name: str
|
name: str
|
||||||
@@ -274,10 +297,10 @@ class Party:
|
|||||||
responsability_code: typing.List[Responsability]
|
responsability_code: typing.List[Responsability]
|
||||||
responsability_regime_code: str
|
responsability_regime_code: str
|
||||||
organization_code: str
|
organization_code: str
|
||||||
tax_scheme: TaxScheme = TaxScheme('01')
|
tax_scheme: TaxScheme = field(default_factory=lambda: TaxScheme('01'))
|
||||||
|
|
||||||
phone: str = ''
|
phone: str = ''
|
||||||
address: Address = Address('')
|
address: Address = field(default_factory=lambda: Address(''))
|
||||||
email: str = ''
|
email: str = ''
|
||||||
legal_name: str = ''
|
legal_name: str = ''
|
||||||
legal_company_ident: str = ''
|
legal_company_ident: str = ''
|
||||||
@@ -305,7 +328,7 @@ class TaxScheme:
|
|||||||
class TaxSubTotal:
|
class TaxSubTotal:
|
||||||
percent: float
|
percent: float
|
||||||
scheme: typing.Optional[TaxScheme] = None
|
scheme: typing.Optional[TaxScheme] = None
|
||||||
tax_amount: Amount = Amount(0.0)
|
tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
|
|
||||||
def calculate(self, invline):
|
def calculate(self, invline):
|
||||||
if self.percent is not None:
|
if self.percent is not None:
|
||||||
@@ -315,12 +338,11 @@ class TaxSubTotal:
|
|||||||
@dataclass
|
@dataclass
|
||||||
class TaxTotal:
|
class TaxTotal:
|
||||||
subtotals: list
|
subtotals: list
|
||||||
tax_amount: Amount = Amount(0.0)
|
tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
taxable_amount: Amount = Amount(0.0)
|
taxable_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
|
|
||||||
def calculate(self, invline):
|
def calculate(self, invline):
|
||||||
self.taxable_amount = invline.total_amount
|
self.taxable_amount = invline.total_amount
|
||||||
|
|
||||||
for subtax in self.subtotals:
|
for subtax in self.subtotals:
|
||||||
subtax.calculate(invline)
|
subtax.calculate(invline)
|
||||||
self.tax_amount += subtax.tax_amount
|
self.tax_amount += subtax.tax_amount
|
||||||
@@ -333,6 +355,40 @@ class TaxTotalOmit(TaxTotal):
|
|||||||
def calculate(self, invline):
|
def calculate(self, invline):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class WithholdingTaxSubTotal:
|
||||||
|
percent: float
|
||||||
|
scheme: typing.Optional[TaxScheme] = None
|
||||||
|
tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
|
|
||||||
|
def calculate(self, invline):
|
||||||
|
if self.percent is not None:
|
||||||
|
self.tax_amount = invline.total_amount * Amount(self.percent / 100)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class WithholdingTaxTotal:
|
||||||
|
subtotals: list
|
||||||
|
tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
|
taxable_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
|
|
||||||
|
def calculate(self, invline):
|
||||||
|
self.taxable_amount = invline.total_amount
|
||||||
|
|
||||||
|
for subtax in self.subtotals:
|
||||||
|
subtax.calculate(invline)
|
||||||
|
self.tax_amount += subtax.tax_amount
|
||||||
|
|
||||||
|
|
||||||
|
class WithholdingTaxTotalOmit(WithholdingTaxTotal):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__([])
|
||||||
|
|
||||||
|
def calculate(self, invline):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Price:
|
class Price:
|
||||||
amount: Amount
|
amount: Amount
|
||||||
@@ -348,6 +404,7 @@ class Price:
|
|||||||
|
|
||||||
self.amount *= self.quantity
|
self.amount *= self.quantity
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PaymentMean:
|
class PaymentMean:
|
||||||
DEBIT = '01'
|
DEBIT = '01'
|
||||||
@@ -365,8 +422,24 @@ class PaymentMean:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class PrePaidPayment:
|
class PrePaidPayment:
|
||||||
#DIAN 1.7.-2020: FBD03
|
# DIAN 1.7.-2020: FBD03
|
||||||
paid_amount: Amount = Amount(0.0)
|
paid_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BillingResponse:
|
||||||
|
id: str
|
||||||
|
code: str
|
||||||
|
description: str
|
||||||
|
|
||||||
|
|
||||||
|
class SupportDocumentCreditNoteResponse(BillingResponse):
|
||||||
|
"""
|
||||||
|
ReferenceID: Identifica la sección del Documento
|
||||||
|
Soporte original a la cual se aplica la corrección.
|
||||||
|
ResponseCode: Código de descripción de la corrección.
|
||||||
|
Description: Descripción de la naturaleza de la corrección.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -375,6 +448,7 @@ class BillingReference:
|
|||||||
uuid: str
|
uuid: str
|
||||||
date: date
|
date: date
|
||||||
|
|
||||||
|
|
||||||
class CreditNoteDocumentReference(BillingReference):
|
class CreditNoteDocumentReference(BillingReference):
|
||||||
"""
|
"""
|
||||||
ident: Prefijo + Numero de la factura relacionada
|
ident: Prefijo + Numero de la factura relacionada
|
||||||
@@ -390,6 +464,7 @@ class DebitNoteDocumentReference(BillingReference):
|
|||||||
date: fecha de emision de la factura relacionada
|
date: fecha de emision de la factura relacionada
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class InvoiceDocumentReference(BillingReference):
|
class InvoiceDocumentReference(BillingReference):
|
||||||
"""
|
"""
|
||||||
ident: Prefijo + Numero de la nota credito relacionada
|
ident: Prefijo + Numero de la nota credito relacionada
|
||||||
@@ -397,6 +472,7 @@ class InvoiceDocumentReference(BillingReference):
|
|||||||
date: fecha de emision de la nota credito relacionada
|
date: fecha de emision de la nota credito relacionada
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class AllowanceChargeReason:
|
class AllowanceChargeReason:
|
||||||
code: str
|
code: str
|
||||||
@@ -409,22 +485,26 @@ class AllowanceChargeReason:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class AllowanceCharge:
|
class AllowanceCharge:
|
||||||
#DIAN 1.7.-2020: FAQ03
|
# DIAN 1.7.-2020: FAQ03
|
||||||
charge_indicator: bool = True
|
charge_indicator: bool = True
|
||||||
amount: Amount = Amount(0.0)
|
amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
reason: AllowanceChargeReason = None
|
reason: AllowanceChargeReason = None
|
||||||
|
|
||||||
#Valor Base para calcular el descuento o el cargo
|
# Valor Base para calcular el descuento o el cargo
|
||||||
base_amount: typing.Optional[Amount] = Amount(0.0)
|
base_amount: typing.Optional[Amount] = field(
|
||||||
|
default_factory=lambda: Amount(0.0))
|
||||||
|
|
||||||
# Porcentaje: Porcentaje que aplicar.
|
# Porcentaje: Porcentaje que aplicar.
|
||||||
multiplier_factor_numeric: Amount = Amount(1.0)
|
multiplier_factor_numeric: Amount = field(
|
||||||
|
default_factory=lambda: Amount(1.0))
|
||||||
|
|
||||||
def isCharge(self):
|
def isCharge(self):
|
||||||
return self.charge_indicator == True
|
charge_indicator = self.charge_indicator is True
|
||||||
|
return charge_indicator
|
||||||
|
|
||||||
def isDiscount(self):
|
def isDiscount(self):
|
||||||
return self.charge_indicator == False
|
charge_indicator = self.charge_indicator is False
|
||||||
|
return charge_indicator
|
||||||
|
|
||||||
def asCharge(self):
|
def asCharge(self):
|
||||||
self.charge_indicator = True
|
self.charge_indicator = True
|
||||||
@@ -438,11 +518,13 @@ class AllowanceCharge:
|
|||||||
def set_base_amount(self, amount):
|
def set_base_amount(self, amount):
|
||||||
self.base_amount = amount
|
self.base_amount = amount
|
||||||
|
|
||||||
|
|
||||||
class AllowanceChargeAsDiscount(AllowanceCharge):
|
class AllowanceChargeAsDiscount(AllowanceCharge):
|
||||||
def __init__(self, amount: Amount = Amount(0.0)):
|
def __init__(self, amount: Amount = Amount(0.0)):
|
||||||
self.charge_indicator = False
|
self.charge_indicator = False
|
||||||
self.amount = amount
|
self.amount = amount
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class InvoiceLine:
|
class InvoiceLine:
|
||||||
# RESOLUCION 0004: pagina 155
|
# RESOLUCION 0004: pagina 155
|
||||||
@@ -455,8 +537,9 @@ class InvoiceLine:
|
|||||||
# la factura y el percent es unico por type_code
|
# la factura y el percent es unico por type_code
|
||||||
# de subtotal
|
# de subtotal
|
||||||
tax: typing.Optional[TaxTotal]
|
tax: typing.Optional[TaxTotal]
|
||||||
|
withholding: typing.Optional[WithholdingTaxTotal]
|
||||||
allowance_charge: typing.List[AllowanceCharge] = dataclasses.field(default_factory=list)
|
allowance_charge: typing.List[AllowanceCharge] = dataclasses.field(
|
||||||
|
default_factory=list)
|
||||||
|
|
||||||
def add_allowance_charge(self, charge):
|
def add_allowance_charge(self, charge):
|
||||||
if not isinstance(charge, AllowanceCharge):
|
if not isinstance(charge, AllowanceCharge):
|
||||||
@@ -467,7 +550,7 @@ class InvoiceLine:
|
|||||||
@property
|
@property
|
||||||
def total_amount_without_charge(self):
|
def total_amount_without_charge(self):
|
||||||
return (self.quantity * self.price.amount)
|
return (self.quantity * self.price.amount)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def total_amount(self):
|
def total_amount(self):
|
||||||
charge = AmountCollection(self.allowance_charge)\
|
charge = AmountCollection(self.allowance_charge)\
|
||||||
@@ -499,8 +582,17 @@ class InvoiceLine:
|
|||||||
def taxable_amount(self):
|
def taxable_amount(self):
|
||||||
return self.tax.taxable_amount
|
return self.tax.taxable_amount
|
||||||
|
|
||||||
|
@property
|
||||||
|
def withholding_amount(self):
|
||||||
|
return self.withholding.tax_amount
|
||||||
|
|
||||||
|
@property
|
||||||
|
def withholding_taxable_amount(self):
|
||||||
|
return self.withholding.taxable_amount
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.tax.calculate(self)
|
self.tax.calculate(self)
|
||||||
|
self.withholding.calculate(self)
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
if not isinstance(self.quantity, Quantity):
|
if not isinstance(self.quantity, Quantity):
|
||||||
@@ -509,18 +601,22 @@ class InvoiceLine:
|
|||||||
if self.tax is None:
|
if self.tax is None:
|
||||||
self.tax = TaxTotalOmit()
|
self.tax = TaxTotalOmit()
|
||||||
|
|
||||||
|
if self.withholding is None:
|
||||||
|
self.withholding = WithholdingTaxTotalOmit()
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class LegalMonetaryTotal:
|
class LegalMonetaryTotal:
|
||||||
line_extension_amount: Amount = Amount(0.0)
|
line_extension_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
tax_exclusive_amount: Amount = Amount(0.0)
|
tax_exclusive_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
tax_inclusive_amount: Amount = Amount(0.0)
|
tax_inclusive_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
charge_total_amount: Amount = Amount(0.0)
|
charge_total_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
allowance_total_amount: Amount = Amount(0.0)
|
allowance_total_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
payable_amount: Amount = Amount(0.0)
|
payable_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
prepaid_amount: Amount = Amount(0.0)
|
prepaid_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
#DIAN 1.7.-2020: FAU14
|
# DIAN 1.7.-2020: FAU14
|
||||||
self.payable_amount = \
|
self.payable_amount = \
|
||||||
self.tax_inclusive_amount \
|
self.tax_inclusive_amount \
|
||||||
+ self.allowance_total_amount \
|
+ self.allowance_total_amount \
|
||||||
@@ -528,22 +624,29 @@ class LegalMonetaryTotal:
|
|||||||
- self.prepaid_amount
|
- self.prepaid_amount
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class NationalSalesInvoiceDocumentType(str):
|
class NationalSalesInvoiceDocumentType(str):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# 6.1.3
|
# 6.1.3
|
||||||
return '01'
|
return '01'
|
||||||
|
|
||||||
|
|
||||||
class CreditNoteDocumentType(str):
|
class CreditNoteDocumentType(str):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# 6.1.3
|
# 6.1.3
|
||||||
return '91'
|
return '91'
|
||||||
|
|
||||||
|
|
||||||
class DebitNoteDocumentType(str):
|
class DebitNoteDocumentType(str):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# 6.1.3
|
# 6.1.3
|
||||||
return '92'
|
return '92'
|
||||||
|
|
||||||
|
|
||||||
|
class CreditNoteSupportDocumentType(str):
|
||||||
|
def __str__(self):
|
||||||
|
return '95'
|
||||||
|
|
||||||
|
|
||||||
class Invoice:
|
class Invoice:
|
||||||
def __init__(self, type_code: str):
|
def __init__(self, type_code: str):
|
||||||
if str(type_code) not in codelist.TipoDocumento:
|
if str(type_code) not in codelist.TipoDocumento:
|
||||||
@@ -563,6 +666,7 @@ class Invoice:
|
|||||||
self.invoice_allowance_charge = []
|
self.invoice_allowance_charge = []
|
||||||
self.invoice_prepaid_payment = []
|
self.invoice_prepaid_payment = []
|
||||||
self.invoice_billing_reference = None
|
self.invoice_billing_reference = None
|
||||||
|
self.invoice_discrepancy_response = None
|
||||||
self.invoice_type_code = str(type_code)
|
self.invoice_type_code = str(type_code)
|
||||||
self.invoice_ident_prefix = None
|
self.invoice_ident_prefix = None
|
||||||
|
|
||||||
@@ -588,7 +692,8 @@ class Invoice:
|
|||||||
if len(prefix) <= 4:
|
if len(prefix) <= 4:
|
||||||
self.invoice_ident_prefix = prefix
|
self.invoice_ident_prefix = prefix
|
||||||
else:
|
else:
|
||||||
raise ValueError('ident prefix failed to get, expected 0 to 4 chars')
|
raise ValueError(
|
||||||
|
'ident prefix failed to get, expected 0 to 4 chars')
|
||||||
|
|
||||||
def set_ident(self, ident: str):
|
def set_ident(self, ident: str):
|
||||||
"""
|
"""
|
||||||
@@ -619,7 +724,7 @@ class Invoice:
|
|||||||
|
|
||||||
def _get_codelist_tipo_operacion(self):
|
def _get_codelist_tipo_operacion(self):
|
||||||
return codelist.TipoOperacionF
|
return codelist.TipoOperacionF
|
||||||
|
|
||||||
def set_operation_type(self, operation):
|
def set_operation_type(self, operation):
|
||||||
if operation not in self._get_codelist_tipo_operacion():
|
if operation not in self._get_codelist_tipo_operacion():
|
||||||
raise ValueError("operation not found")
|
raise ValueError("operation not found")
|
||||||
@@ -638,6 +743,9 @@ class Invoice:
|
|||||||
def set_billing_reference(self, billing_reference: BillingReference):
|
def set_billing_reference(self, billing_reference: BillingReference):
|
||||||
self.invoice_billing_reference = billing_reference
|
self.invoice_billing_reference = billing_reference
|
||||||
|
|
||||||
|
def set_discrepancy_response(self, billing_response: BillingResponse):
|
||||||
|
self.invoice_discrepancy_response = billing_response
|
||||||
|
|
||||||
def accept(self, visitor):
|
def accept(self, visitor):
|
||||||
visitor.visit_payment_mean(self.invoice_payment_mean)
|
visitor.visit_payment_mean(self.invoice_payment_mean)
|
||||||
visitor.visit_customer(self.invoice_customer)
|
visitor.visit_customer(self.invoice_customer)
|
||||||
@@ -649,29 +757,34 @@ class Invoice:
|
|||||||
|
|
||||||
def _calculate_legal_monetary_total(self):
|
def _calculate_legal_monetary_total(self):
|
||||||
for invline in self.invoice_lines:
|
for invline in self.invoice_lines:
|
||||||
self.invoice_legal_monetary_total.line_extension_amount += invline.total_amount
|
self.invoice_legal_monetary_total.line_extension_amount +=\
|
||||||
self.invoice_legal_monetary_total.tax_exclusive_amount += invline.total_tax_exclusive_amount
|
invline.total_amount
|
||||||
#DIAN 1.7.-2020: FAU6
|
self.invoice_legal_monetary_total.tax_exclusive_amount +=\
|
||||||
self.invoice_legal_monetary_total.tax_inclusive_amount += invline.total_tax_inclusive_amount
|
invline.total_tax_exclusive_amount
|
||||||
|
# DIAN 1.7.-2020: FAU6
|
||||||
|
self.invoice_legal_monetary_total.tax_inclusive_amount +=\
|
||||||
|
invline.total_tax_inclusive_amount
|
||||||
|
|
||||||
#DIAN 1.7.-2020: FAU08
|
# DIAN 1.7.-2020: FAU08
|
||||||
self.invoice_legal_monetary_total.allowance_total_amount = AmountCollection(self.invoice_allowance_charge)\
|
self.invoice_legal_monetary_total.allowance_total_amount =\
|
||||||
|
AmountCollection(self.invoice_allowance_charge)\
|
||||||
.filter(lambda charge: charge.isDiscount())\
|
.filter(lambda charge: charge.isDiscount())\
|
||||||
.map(lambda charge: charge.amount)\
|
.map(lambda charge: charge.amount)\
|
||||||
.sum()
|
.sum()
|
||||||
|
|
||||||
#DIAN 1.7.-2020: FAU10
|
# DIAN 1.7.-2020: FAU10
|
||||||
self.invoice_legal_monetary_total.charge_total_amount = AmountCollection(self.invoice_allowance_charge)\
|
self.invoice_legal_monetary_total.charge_total_amount =\
|
||||||
|
AmountCollection(self.invoice_allowance_charge)\
|
||||||
.filter(lambda charge: charge.isCharge())\
|
.filter(lambda charge: charge.isCharge())\
|
||||||
.map(lambda charge: charge.amount)\
|
.map(lambda charge: charge.amount)\
|
||||||
.sum()
|
.sum()
|
||||||
|
|
||||||
#DIAN 1.7.-2020: FAU12
|
# DIAN 1.7.-2020: FAU12
|
||||||
self.invoice_legal_monetary_total.prepaid_amount = AmountCollection(self.invoice_prepaid_payment)\
|
self.invoice_legal_monetary_total.prepaid_amount = AmountCollection(
|
||||||
.map(lambda paid: paid.paid_amount)\
|
self.invoice_prepaid_payment).map(
|
||||||
.sum()
|
lambda paid: paid.paid_amount).sum()
|
||||||
|
|
||||||
#DIAN 1.7.-2020: FAU14
|
# DIAN 1.7.-2020: FAU14
|
||||||
self.invoice_legal_monetary_total.calculate()
|
self.invoice_legal_monetary_total.calculate()
|
||||||
|
|
||||||
def _refresh_charges_base_amount(self):
|
def _refresh_charges_base_amount(self):
|
||||||
@@ -679,18 +792,21 @@ class Invoice:
|
|||||||
for invline in self.invoice_lines:
|
for invline in self.invoice_lines:
|
||||||
if invline.allowance_charge:
|
if invline.allowance_charge:
|
||||||
# TODO actualmente solo uno de los cargos es permitido
|
# TODO actualmente solo uno de los cargos es permitido
|
||||||
raise ValueError('allowance charge in invoice exclude invoice line')
|
raise ValueError(
|
||||||
|
'allowance charge in invoice exclude invoice line')
|
||||||
|
|
||||||
# cargos a nivel de factura
|
# cargos a nivel de factura
|
||||||
for charge in self.invoice_allowance_charge:
|
for charge in self.invoice_allowance_charge:
|
||||||
charge.set_base_amount(self.invoice_legal_monetary_total.line_extension_amount)
|
charge.set_base_amount(
|
||||||
|
self.invoice_legal_monetary_total.line_extension_amount)
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
for invline in self.invoice_lines:
|
for invline in self.invoice_lines:
|
||||||
invline.calculate()
|
invline.calculate()
|
||||||
self._calculate_legal_monetary_total()
|
self._calculate_legal_monetary_total()
|
||||||
self._refresh_charges_base_amount()
|
self._refresh_charges_base_amount()
|
||||||
|
|
||||||
|
|
||||||
class NationalSalesInvoice(Invoice):
|
class NationalSalesInvoice(Invoice):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(NationalSalesInvoiceDocumentType())
|
super().__init__(NationalSalesInvoiceDocumentType())
|
||||||
@@ -706,7 +822,7 @@ class CreditNote(Invoice):
|
|||||||
|
|
||||||
def _get_codelist_tipo_operacion(self):
|
def _get_codelist_tipo_operacion(self):
|
||||||
return codelist.TipoOperacionNC
|
return codelist.TipoOperacionNC
|
||||||
|
|
||||||
def _check_ident_prefix(self, prefix):
|
def _check_ident_prefix(self, prefix):
|
||||||
if len(prefix) != 6:
|
if len(prefix) != 6:
|
||||||
raise ValueError('prefix must be 6 length')
|
raise ValueError('prefix must be 6 length')
|
||||||
@@ -735,3 +851,30 @@ class DebitNote(Invoice):
|
|||||||
if not self.invoice_ident_prefix:
|
if not self.invoice_ident_prefix:
|
||||||
self.invoice_ident_prefix = self.invoice_ident[0:6]
|
self.invoice_ident_prefix = self.invoice_ident[0:6]
|
||||||
|
|
||||||
|
|
||||||
|
class SupportDocument(Invoice):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SupportDocumentCreditNote(SupportDocument):
|
||||||
|
def __init__(
|
||||||
|
self, invoice_document_reference: BillingReference,
|
||||||
|
invoice_discrepancy_response: BillingResponse):
|
||||||
|
super().__init__(CreditNoteSupportDocumentType())
|
||||||
|
|
||||||
|
if not isinstance(invoice_document_reference, BillingReference):
|
||||||
|
raise TypeError('invoice_document_reference invalid type')
|
||||||
|
self.invoice_billing_reference = invoice_document_reference
|
||||||
|
self.invoice_discrepancy_response = invoice_discrepancy_response
|
||||||
|
|
||||||
|
def _get_codelist_tipo_operacion(self):
|
||||||
|
return codelist.TipoOperacionNCDS
|
||||||
|
|
||||||
|
def _check_ident_prefix(self, prefix):
|
||||||
|
if len(prefix) != 6:
|
||||||
|
raise ValueError('prefix must be 6 length')
|
||||||
|
|
||||||
|
def _set_ident_prefix_automatic(self):
|
||||||
|
if not self.invoice_ident_prefix:
|
||||||
|
self.invoice_ident_prefix = self.invoice_ident[0:6]
|
||||||
|
pass
|
||||||
|
|||||||
@@ -2,3 +2,6 @@ from .invoice import *
|
|||||||
from .credit_note import *
|
from .credit_note import *
|
||||||
from .debit_note import *
|
from .debit_note import *
|
||||||
from .utils import *
|
from .utils import *
|
||||||
|
from .attached_document import *
|
||||||
|
from .support_document import *
|
||||||
|
from .support_document_credit_note import *
|
||||||
|
|||||||
15
facho/fe/form_xml/attached_document.py
Normal file
15
facho/fe/form_xml/attached_document.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from .. import fe
|
||||||
|
|
||||||
|
__all__ = ['AttachedDocument']
|
||||||
|
|
||||||
|
|
||||||
|
class AttachedDocument():
|
||||||
|
|
||||||
|
def __init__(self, id):
|
||||||
|
schema =\
|
||||||
|
'urn:oasis:names:specification:ubl:schema:xsd:AttachedDocument-2'
|
||||||
|
self.fexml = fe.FeXML('AttachedDocument', schema)
|
||||||
|
self.fexml.set_element('./cbc:ID', id)
|
||||||
|
|
||||||
|
def toFachoXML(self):
|
||||||
|
return self.fexml
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
from .. import fe
|
# from .. import fe
|
||||||
from ..form import *
|
# from ..form import *
|
||||||
from .invoice import DIANInvoiceXML
|
from .invoice import DIANInvoiceXML
|
||||||
|
|
||||||
__all__ = ['DIANCreditNoteXML']
|
__all__ = ['DIANCreditNoteXML']
|
||||||
|
|
||||||
|
|
||||||
class DIANCreditNoteXML(DIANInvoiceXML):
|
class DIANCreditNoteXML(DIANInvoiceXML):
|
||||||
"""
|
"""
|
||||||
DianInvoiceXML mapea objeto form.Invoice a XML segun
|
DianInvoiceXML mapea objeto form.Invoice a XML segun
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
from .. import fe
|
# from .. import fe
|
||||||
from ..form import *
|
# from ..form import *
|
||||||
from .invoice import DIANInvoiceXML
|
from .invoice import DIANInvoiceXML
|
||||||
|
|
||||||
__all__ = ['DIANDebitNoteXML']
|
__all__ = ['DIANDebitNoteXML']
|
||||||
|
|
||||||
|
|
||||||
class DIANDebitNoteXML(DIANInvoiceXML):
|
class DIANDebitNoteXML(DIANInvoiceXML):
|
||||||
"""
|
"""
|
||||||
DianInvoiceXML mapea objeto form.Invoice a XML segun
|
DianInvoiceXML mapea objeto form.Invoice a XML segun
|
||||||
@@ -19,19 +20,24 @@ class DIANDebitNoteXML(DIANInvoiceXML):
|
|||||||
def tag_document_concilied(fexml):
|
def tag_document_concilied(fexml):
|
||||||
return 'Debited'
|
return 'Debited'
|
||||||
|
|
||||||
#DIAN 1.7.-2020: DAU03
|
# DIAN 1.7.-2020: DAU03
|
||||||
def set_legal_monetary(fexml, invoice):
|
def set_legal_monetary(fexml, invoice):
|
||||||
fexml.set_element_amount('./cac:RequestedMonetaryTotal/cbc:LineExtensionAmount',
|
fexml.set_element_amount(
|
||||||
invoice.invoice_legal_monetary_total.line_extension_amount)
|
'./cac:RequestedMonetaryTotal/cbc:LineExtensionAmount',
|
||||||
|
invoice.invoice_legal_monetary_total.line_extension_amount)
|
||||||
|
|
||||||
fexml.set_element_amount('./cac:RequestedMonetaryTotal/cbc:TaxExclusiveAmount',
|
fexml.set_element_amount(
|
||||||
invoice.invoice_legal_monetary_total.tax_exclusive_amount)
|
'./cac:RequestedMonetaryTotal/cbc:TaxExclusiveAmount',
|
||||||
|
invoice.invoice_legal_monetary_total.tax_exclusive_amount)
|
||||||
|
|
||||||
fexml.set_element_amount('./cac:RequestedMonetaryTotal/cbc:TaxInclusiveAmount',
|
fexml.set_element_amount(
|
||||||
invoice.invoice_legal_monetary_total.tax_inclusive_amount)
|
'./cac:RequestedMonetaryTotal/cbc:TaxInclusiveAmount',
|
||||||
|
invoice.invoice_legal_monetary_total.tax_inclusive_amount)
|
||||||
|
|
||||||
fexml.set_element_amount('./cac:RequestedMonetaryTotal/cbc:ChargeTotalAmount',
|
fexml.set_element_amount(
|
||||||
invoice.invoice_legal_monetary_total.charge_total_amount)
|
'./cac:RequestedMonetaryTotal/cbc:ChargeTotalAmount',
|
||||||
|
invoice.invoice_legal_monetary_total.charge_total_amount)
|
||||||
|
|
||||||
fexml.set_element_amount('./cac:RequestedMonetaryTotal/cbc:PayableAmount',
|
fexml.set_element_amount(
|
||||||
invoice.invoice_legal_monetary_total.payable_amount)
|
'./cac:RequestedMonetaryTotal/cbc:PayableAmount',
|
||||||
|
invoice.invoice_legal_monetary_total.payable_amount)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from .. import fe
|
from .. import fe
|
||||||
from ..form import *
|
from ..form import *
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
__all__ = ['DIANInvoiceXML']
|
__all__ = ['DIANInvoiceXML']
|
||||||
|
|
||||||
@@ -147,7 +148,6 @@ class DIANInvoiceXML(fe.FeXML):
|
|||||||
fexml.set_element('./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme/cbc:ID',
|
fexml.set_element('./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme/cbc:ID',
|
||||||
invoice.invoice_customer.tax_scheme.code)
|
invoice.invoice_customer.tax_scheme.code)
|
||||||
|
|
||||||
|
|
||||||
#DIAN 1.7.-2020: CAJ41
|
#DIAN 1.7.-2020: CAJ41
|
||||||
fexml.set_element('./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme/cbc:Name',
|
fexml.set_element('./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme/cbc:Name',
|
||||||
invoice.invoice_customer.tax_scheme.name)
|
invoice.invoice_customer.tax_scheme.name)
|
||||||
@@ -421,42 +421,55 @@ class DIANInvoiceXML(fe.FeXML):
|
|||||||
|
|
||||||
def set_invoice_totals(fexml, invoice):
|
def set_invoice_totals(fexml, invoice):
|
||||||
tax_amount_for = defaultdict(lambda: defaultdict(lambda: Amount(0.0)))
|
tax_amount_for = defaultdict(lambda: defaultdict(lambda: Amount(0.0)))
|
||||||
|
withholding_amount_for = defaultdict(lambda: defaultdict(lambda: Amount(0.0)))
|
||||||
percent_for = defaultdict(lambda: None)
|
percent_for = defaultdict(lambda: None)
|
||||||
|
|
||||||
#requeridos para CUFE
|
#requeridos para CUFE
|
||||||
#tax_amount_for['01']['tax_amount'] = Amount(0.0)
|
#tax_amount_for['01']['tax_amount'] = Amount(0.0)
|
||||||
#tax_amount_for['01']['taxable_amount'] = Amount(0.0)
|
#tax_amount_for['01']['taxable_amount'] = Amount(0.0)
|
||||||
#DIAN 1.7.-2020: FAS07 => Se debe construir estrategia para su manejo
|
#DIAN 1.7.-2020: FAS07 => Se debe construir estrategia para su manejo
|
||||||
#tax_amount_for['04']['tax_amount'] = 0.0
|
#tax_amount_for['04']['tax_amount'] += 0.0
|
||||||
#tax_amount_for['04']['taxable_amount'] = 0.0
|
#tax_amount_for['04']['taxable_amount'] += 0.0
|
||||||
#tax_amount_for['03']['tax_amount'] = 0.0
|
#tax_amount_for['03']['tax_amount'] += 0.0
|
||||||
#tax_amount_for['03']['taxable_amount'] = 0.0
|
#tax_amount_for['03']['taxable_amount'] += 0.0
|
||||||
|
|
||||||
total_tax_amount = Amount(0.0)
|
total_tax_amount = Amount(0.0)
|
||||||
|
total_withholding_amount = Amount(0.0)
|
||||||
|
|
||||||
for invoice_line in invoice.invoice_lines:
|
for invoice_line in invoice.invoice_lines:
|
||||||
for subtotal in invoice_line.tax.subtotals:
|
for subtotal in invoice_line.tax.subtotals:
|
||||||
if subtotal.scheme is not None:
|
if subtotal.scheme is not None:
|
||||||
tax_amount_for[subtotal.scheme.code]['tax_amount'] += subtotal.tax_amount
|
tax_amount_for[subtotal.scheme.code]['tax_amount'] += subtotal.tax_amount
|
||||||
tax_amount_for[subtotal.scheme.code]['taxable_amount'] += invoice_line.taxable_amount
|
tax_amount_for[subtotal.scheme.code]['taxable_amount'] += invoice_line.taxable_amount
|
||||||
|
tax_amount_for[subtotal.scheme.code]['name'] = subtotal.scheme.name
|
||||||
|
|
||||||
# MACHETE ojo InvoiceLine.tax pasar a Invoice
|
# MACHETE ojo InvoiceLine.tax pasar a Invoice
|
||||||
percent_for[subtotal.scheme.code] = subtotal.percent
|
percent_for[subtotal.scheme.code] = subtotal.percent
|
||||||
|
|
||||||
total_tax_amount += subtotal.tax_amount
|
total_tax_amount += subtotal.tax_amount
|
||||||
|
|
||||||
fexml.placeholder_for('./cac:TaxTotal')
|
for subtotal_withholding in invoice_line.withholding.subtotals:
|
||||||
fexml.set_element_amount('./cac:TaxTotal/cbc:TaxAmount',
|
if subtotal_withholding.scheme is not None:
|
||||||
total_tax_amount)
|
withholding_amount_for[subtotal_withholding.scheme.code]['tax_amount'] += subtotal_withholding.tax_amount
|
||||||
|
withholding_amount_for[subtotal_withholding.scheme.code]['taxable_amount'] += invoice_line.withholding_taxable_amount
|
||||||
|
|
||||||
|
# MACHETE ojo InvoiceLine.tax pasar a Invoice
|
||||||
|
|
||||||
|
percent_for[subtotal_withholding.scheme.code] = subtotal_withholding.percent
|
||||||
|
|
||||||
|
total_withholding_amount += subtotal_withholding.tax_amount
|
||||||
|
|
||||||
|
if total_tax_amount != Amount(0.0):
|
||||||
|
fexml.placeholder_for('./cac:TaxTotal')
|
||||||
|
fexml.set_element_amount('./cac:TaxTotal/cbc:TaxAmount',
|
||||||
|
total_tax_amount)
|
||||||
|
|
||||||
for index, item in enumerate(tax_amount_for.items()):
|
for index, item in enumerate(tax_amount_for.items()):
|
||||||
cod_impuesto, amount_of = item
|
cod_impuesto, amount_of = item
|
||||||
next_append = index > 0
|
next_append = index > 0
|
||||||
|
|
||||||
#DIAN 1.7.-2020: FAS01
|
#DIAN 1.7.-2020: FAS01
|
||||||
line = fexml.fragment('./cac:TaxTotal', append=next_append)
|
line = fexml.fragment('./cac:TaxTotal', append=next_append)
|
||||||
|
|
||||||
#DIAN 1.7.-2020: FAU06
|
#DIAN 1.7.-2020: FAU06
|
||||||
tax_amount = amount_of['tax_amount']
|
tax_amount = amount_of['tax_amount']
|
||||||
fexml.set_element_amount_for(line,
|
fexml.set_element_amount_for(line,
|
||||||
@@ -482,8 +495,48 @@ class DIANInvoiceXML(fe.FeXML):
|
|||||||
if percent_for[cod_impuesto]:
|
if percent_for[cod_impuesto]:
|
||||||
line.set_element('/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent',
|
line.set_element('/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent',
|
||||||
percent_for[cod_impuesto])
|
percent_for[cod_impuesto])
|
||||||
|
|
||||||
line.set_element('/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID',
|
line.set_element('/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID',
|
||||||
cod_impuesto)
|
cod_impuesto)
|
||||||
|
line.set_element('/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name',
|
||||||
|
amount_of['name'])
|
||||||
|
|
||||||
|
for index, item in enumerate(withholding_amount_for.items()):
|
||||||
|
cod_impuesto, amount_of = item
|
||||||
|
next_append = index > 0
|
||||||
|
|
||||||
|
#DIAN 1.7.-2020: FAS01
|
||||||
|
line = fexml.fragment('./cac:WithholdingTaxTotal', append=next_append)
|
||||||
|
#DIAN 1.7.-2020: FAU06
|
||||||
|
tax_amount = amount_of['tax_amount']
|
||||||
|
fexml.set_element_amount_for(line,
|
||||||
|
'/cac:WithholdingTaxTotal/cbc:TaxAmount',
|
||||||
|
tax_amount)
|
||||||
|
|
||||||
|
#DIAN 1.7.-2020: FAS05
|
||||||
|
fexml.set_element_amount_for(line,
|
||||||
|
'/cac:WithholdingTaxTotal/cac:TaxSubtotal/cbc:TaxableAmount',
|
||||||
|
amount_of['taxable_amount'])
|
||||||
|
|
||||||
|
#DIAN 1.7.-2020: FAU06
|
||||||
|
fexml.set_element_amount_for(line,
|
||||||
|
'/cac:WithholdingTaxTotal/cac:TaxSubtotal/cbc:TaxAmount',
|
||||||
|
amount_of['tax_amount'])
|
||||||
|
|
||||||
|
#DIAN 1.7.-2020: FAS07
|
||||||
|
if percent_for[cod_impuesto]:
|
||||||
|
line.set_element('/cac:WithholdingTaxTotal/cac:TaxSubtotal/cbc:Percent',
|
||||||
|
percent_for[cod_impuesto])
|
||||||
|
|
||||||
|
|
||||||
|
if percent_for[cod_impuesto]:
|
||||||
|
line.set_element('/cac:WithholdingTaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent',
|
||||||
|
percent_for[cod_impuesto])
|
||||||
|
|
||||||
|
line.set_element('/cac:WithholdingTaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID',
|
||||||
|
cod_impuesto)
|
||||||
|
line.set_element('/cac:WithholdingTaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name',
|
||||||
|
'ReteRenta')
|
||||||
|
|
||||||
# abstract method
|
# abstract method
|
||||||
def tag_document(fexml):
|
def tag_document(fexml):
|
||||||
@@ -502,7 +555,6 @@ class DIANInvoiceXML(fe.FeXML):
|
|||||||
fexml.set_element_amount_for(line,
|
fexml.set_element_amount_for(line,
|
||||||
'./cac:TaxTotal/cac:TaxSubtotal/cbc:TaxableAmount',
|
'./cac:TaxTotal/cac:TaxSubtotal/cbc:TaxableAmount',
|
||||||
invoice_line.taxable_amount)
|
invoice_line.taxable_amount)
|
||||||
|
|
||||||
for subtotal in invoice_line.tax.subtotals:
|
for subtotal in invoice_line.tax.subtotals:
|
||||||
line.set_element('./cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount', subtotal.tax_amount, currencyID='COP')
|
line.set_element('./cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount', subtotal.tax_amount, currencyID='COP')
|
||||||
|
|
||||||
@@ -514,6 +566,28 @@ class DIANInvoiceXML(fe.FeXML):
|
|||||||
line.set_element('./cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID', subtotal.scheme.code)
|
line.set_element('./cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID', subtotal.scheme.code)
|
||||||
line.set_element('./cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name', subtotal.scheme.name)
|
line.set_element('./cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name', subtotal.scheme.name)
|
||||||
|
|
||||||
|
|
||||||
|
def set_invoice_line_withholding(fexml, line, invoice_line):
|
||||||
|
fexml.set_element_amount_for(line,
|
||||||
|
'./cac:WithholdingTaxTotal/cbc:TaxAmount',
|
||||||
|
invoice_line.withholding_amount)
|
||||||
|
#DIAN 1.7.-2020: FAX05
|
||||||
|
fexml.set_element_amount_for(line,
|
||||||
|
'./cac:WithholdingTaxTotal/cac:TaxSubtotal/cbc:TaxableAmount',
|
||||||
|
invoice_line.withholding_taxable_amount)
|
||||||
|
|
||||||
|
for subtotal in invoice_line.withholding.subtotals:
|
||||||
|
line.set_element('./cac:WithholdingTaxTotal/cac:TaxSubtotal/cbc:TaxAmount', subtotal.tax_amount, currencyID='COP')
|
||||||
|
|
||||||
|
if subtotal.percent is not None:
|
||||||
|
line.set_element('./cac:WithholdingTaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent', '%0.2f' % round(subtotal.percent, 2))
|
||||||
|
|
||||||
|
if subtotal.scheme is not None:
|
||||||
|
#DIAN 1.7.-2020: FAX15
|
||||||
|
line.set_element('./cac:WithholdingTaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID', subtotal.scheme.code)
|
||||||
|
line.set_element('./cac:WithholdingTaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name', subtotal.scheme.name)
|
||||||
|
|
||||||
|
|
||||||
def set_invoice_lines(fexml, invoice):
|
def set_invoice_lines(fexml, invoice):
|
||||||
next_append = False
|
next_append = False
|
||||||
for index, invoice_line in enumerate(invoice.invoice_lines):
|
for index, invoice_line in enumerate(invoice.invoice_lines):
|
||||||
@@ -529,6 +603,9 @@ class DIANInvoiceXML(fe.FeXML):
|
|||||||
if not isinstance(invoice_line.tax, TaxTotalOmit):
|
if not isinstance(invoice_line.tax, TaxTotalOmit):
|
||||||
fexml.set_invoice_line_tax(line, invoice_line)
|
fexml.set_invoice_line_tax(line, invoice_line)
|
||||||
|
|
||||||
|
if not isinstance(invoice_line.withholding, WithholdingTaxTotalOmit):
|
||||||
|
fexml.set_invoice_line_withholding(line, invoice_line)
|
||||||
|
|
||||||
line.set_element('./cac:Item/cbc:Description', invoice_line.item.description)
|
line.set_element('./cac:Item/cbc:Description', invoice_line.item.description)
|
||||||
|
|
||||||
line.set_element('./cac:Item/cac:StandardItemIdentification/cbc:ID',
|
line.set_element('./cac:Item/cac:StandardItemIdentification/cbc:ID',
|
||||||
@@ -546,25 +623,33 @@ class DIANInvoiceXML(fe.FeXML):
|
|||||||
for idx, charge in enumerate(invoice_line.allowance_charge):
|
for idx, charge in enumerate(invoice_line.allowance_charge):
|
||||||
next_append_charge = idx > 0
|
next_append_charge = idx > 0
|
||||||
fexml.append_allowance_charge(line, index + 1, charge, append=next_append_charge)
|
fexml.append_allowance_charge(line, index + 1, charge, append=next_append_charge)
|
||||||
|
|
||||||
def set_allowance_charge(fexml, invoice):
|
def set_allowance_charge(fexml, invoice):
|
||||||
for idx, charge in enumerate(invoice.invoice_allowance_charge):
|
for idx, charge in enumerate(invoice.invoice_allowance_charge):
|
||||||
next_append = idx > 0
|
next_append = idx > 0
|
||||||
fexml.append_allowance_charge(fexml, idx + 1, charge, append=next_append)
|
fexml.append_allowance_charge(
|
||||||
|
fexml, idx + 1, charge, append=next_append)
|
||||||
|
|
||||||
def append_allowance_charge(fexml, parent, idx, charge, append=False):
|
def append_allowance_charge(fexml, parent, idx, charge, append=False):
|
||||||
line = parent.fragment('./cac:AllowanceCharge', append=append)
|
line = parent.fragment('./cac:AllowanceCharge', append=append)
|
||||||
#DIAN 1.7.-2020: FAQ02
|
# DIAN 1.7.-2020: FAQ02
|
||||||
line.set_element('./cbc:ID', idx)
|
line.set_element('./cbc:ID', idx)
|
||||||
#DIAN 1.7.-2020: FAQ03
|
# DIAN 1.7.-2020: FAQ03
|
||||||
line.set_element('./cbc:ChargeIndicator', str(charge.charge_indicator).lower())
|
line.set_element('./cbc:ChargeIndicator', str(
|
||||||
if charge.reason:
|
charge.charge_indicator).lower())
|
||||||
line.set_element('./cbc:AllowanceChargeReasonCode', charge.reason.code)
|
if charge.reason:
|
||||||
line.set_element('./cbc:allowanceChargeReason', charge.reason.reason)
|
line.set_element(
|
||||||
line.set_element('./cbc:MultiplierFactorNumeric', str(round(charge.multiplier_factor_numeric, 2)))
|
'./cbc:AllowanceChargeReasonCode', charge.reason.code)
|
||||||
fexml.set_element_amount_for(line, './cbc:Amount', charge.amount)
|
line.set_element(
|
||||||
fexml.set_element_amount_for(line, './cbc:BaseAmount', charge.base_amount)
|
'./cbc:allowanceChargeReason', charge.reason.reason)
|
||||||
|
line.set_element(
|
||||||
|
'./cbc:MultiplierFactorNumeric', str(
|
||||||
|
round(charge.multiplier_factor_numeric, 2)))
|
||||||
|
fexml.set_element_amount_for(
|
||||||
|
line, './cbc:Amount', charge.amount)
|
||||||
|
fexml.set_element_amount_for(
|
||||||
|
line, './cbc:BaseAmount', charge.base_amount)
|
||||||
|
|
||||||
def attach_invoice(fexml, invoice):
|
def attach_invoice(fexml, invoice):
|
||||||
"""adiciona etiquetas a FEXML y retorna FEXML
|
"""adiciona etiquetas a FEXML y retorna FEXML
|
||||||
en caso de fallar validacion retorna None"""
|
en caso de fallar validacion retorna None"""
|
||||||
@@ -576,7 +661,6 @@ class DIANInvoiceXML(fe.FeXML):
|
|||||||
fexml.placeholder_for('./cbc:ProfileExecutionID')
|
fexml.placeholder_for('./cbc:ProfileExecutionID')
|
||||||
fexml.set_element('./cbc:ID', invoice.invoice_ident)
|
fexml.set_element('./cbc:ID', invoice.invoice_ident)
|
||||||
fexml.placeholder_for('./cbc:UUID')
|
fexml.placeholder_for('./cbc:UUID')
|
||||||
fexml.set_element('./cbc:DocumentCurrencyCode', 'COP')
|
|
||||||
fexml.set_element('./cbc:IssueDate', invoice.invoice_issue.strftime('%Y-%m-%d'))
|
fexml.set_element('./cbc:IssueDate', invoice.invoice_issue.strftime('%Y-%m-%d'))
|
||||||
#DIAN 1.7.-2020: FAD10
|
#DIAN 1.7.-2020: FAD10
|
||||||
fexml.set_element('./cbc:IssueTime', invoice.invoice_issue.strftime('%H:%M:%S-05:00'))
|
fexml.set_element('./cbc:IssueTime', invoice.invoice_issue.strftime('%H:%M:%S-05:00'))
|
||||||
@@ -585,24 +669,25 @@ class DIANInvoiceXML(fe.FeXML):
|
|||||||
listAgencyID='195',
|
listAgencyID='195',
|
||||||
listAgencyName='No matching global declaration available for the validation root',
|
listAgencyName='No matching global declaration available for the validation root',
|
||||||
listURI='http://www.dian.gov.co')
|
listURI='http://www.dian.gov.co')
|
||||||
|
fexml.set_element('./cbc:DocumentCurrencyCode', 'COP')
|
||||||
fexml.set_element('./cbc:LineCountNumeric', len(invoice.invoice_lines))
|
fexml.set_element('./cbc:LineCountNumeric', len(invoice.invoice_lines))
|
||||||
fexml.set_element('./cac:%sPeriod/cbc:StartDate' % (fexml.tag_document()),
|
if fexml.tag_document() == 'Invoice':
|
||||||
invoice.invoice_period_start.strftime('%Y-%m-%d'))
|
fexml.set_element('./cac:%sPeriod/cbc:StartDate' % (
|
||||||
|
fexml.tag_document()),
|
||||||
fexml.set_element('./cac:%sPeriod/cbc:EndDate' % (fexml.tag_document()),
|
invoice.invoice_period_start.strftime('%Y-%m-%d'))
|
||||||
invoice.invoice_period_end.strftime('%Y-%m-%d'))
|
|
||||||
|
|
||||||
|
fexml.set_element('./cac:%sPeriod/cbc:EndDate' % (
|
||||||
|
fexml.tag_document()),
|
||||||
|
invoice.invoice_period_end.strftime('%Y-%m-%d'))
|
||||||
|
fexml.set_billing_reference(invoice)
|
||||||
fexml.customize(invoice)
|
fexml.customize(invoice)
|
||||||
|
|
||||||
fexml.set_supplier(invoice)
|
fexml.set_supplier(invoice)
|
||||||
fexml.set_customer(invoice)
|
fexml.set_customer(invoice)
|
||||||
fexml.set_legal_monetary(invoice)
|
|
||||||
fexml.set_invoice_totals(invoice)
|
|
||||||
fexml.set_invoice_lines(invoice)
|
|
||||||
fexml.set_payment_mean(invoice)
|
fexml.set_payment_mean(invoice)
|
||||||
|
fexml.set_invoice_totals(invoice)
|
||||||
|
fexml.set_legal_monetary(invoice)
|
||||||
|
fexml.set_invoice_lines(invoice)
|
||||||
fexml.set_allowance_charge(invoice)
|
fexml.set_allowance_charge(invoice)
|
||||||
fexml.set_billing_reference(invoice)
|
|
||||||
|
|
||||||
return fexml
|
return fexml
|
||||||
|
|
||||||
def customize(fexml, invoice):
|
def customize(fexml, invoice):
|
||||||
|
|||||||
647
facho/fe/form_xml/support_document.py
Normal file
647
facho/fe/form_xml/support_document.py
Normal file
@@ -0,0 +1,647 @@
|
|||||||
|
from .. import fe
|
||||||
|
from ..form import (
|
||||||
|
Amount, DebitNoteDocumentReference, CreditNoteDocumentReference,
|
||||||
|
InvoiceDocumentReference, TaxTotalOmit, WithholdingTaxTotalOmit
|
||||||
|
)
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
from datetime import datetime
|
||||||
|
# from .attached_document import *
|
||||||
|
|
||||||
|
__all__ = ['DIANSupportDocumentXML']
|
||||||
|
|
||||||
|
|
||||||
|
class DIANSupportDocumentXML(fe.FeXML):
|
||||||
|
"""
|
||||||
|
DianSupportDocumentXML mapea objeto form.Invoice a XML segun
|
||||||
|
lo indicado para él Documento soporte en adquisiciones efectuadas con sujetos no obligados a expedir factura de venta o documento equivalente.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, invoice, tag_document='Invoice'):
|
||||||
|
super().__init__(tag_document, 'http://www.dian.gov.co/contratos/facturaelectronica/v1')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAB03
|
||||||
|
# DIAN 1.1.-2021: NSAB03
|
||||||
|
self.placeholder_for(
|
||||||
|
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:InvoiceControl')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAB13
|
||||||
|
# DIAN 1.1.-2021: NSAB13
|
||||||
|
self.placeholder_for(
|
||||||
|
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:InvoiceSource')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAB18
|
||||||
|
# DIAN 1.1.-2021: NSAB18
|
||||||
|
self.placeholder_for(
|
||||||
|
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:SoftwareProvider')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAB27
|
||||||
|
# DIAN 1.1.-2021: NSAB27
|
||||||
|
self.placeholder_for(
|
||||||
|
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:SoftwareSecurityCode')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAB30 DSAB31
|
||||||
|
# DIAN 1.1.-2021: NSAB30 NSAB31
|
||||||
|
self.placeholder_for(
|
||||||
|
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:AuthorizationProvider/sts:AuthorizationProviderID')
|
||||||
|
|
||||||
|
# ZE02 se requiere existencia para firmar
|
||||||
|
# DIAN 1.1.-2021: DSAA02 DSAB01
|
||||||
|
# DIAN 1.1.-2021: NSAA02 NSAB01
|
||||||
|
ublextension = self.fragment(
|
||||||
|
'./ext:UBLExtensions/ext:UBLExtension', append=True)
|
||||||
|
# DIAN 1.1.-2021: DSAB02
|
||||||
|
# DIAN 1.1.-2021: NSAB02
|
||||||
|
extcontent = ublextension.find_or_create_element(
|
||||||
|
'/ext:UBLExtension/ext:ExtensionContent')
|
||||||
|
self.attach_invoice(invoice)
|
||||||
|
|
||||||
|
def set_supplier(fexml, invoice):
|
||||||
|
# DIAN 1.1.-2021: DSAJ01
|
||||||
|
# DIAN 1.1.-2021: NSAB01
|
||||||
|
fexml.placeholder_for('./cac:AccountingSupplierParty')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ02
|
||||||
|
# DIAN 1.1.-2021: NSAJ02
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cbc:AdditionalAccountID',
|
||||||
|
invoice.invoice_supplier.organization_code)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ07 DSAJ08
|
||||||
|
# DIAN 1.1.-2021: NSAJ07 NSAJ08
|
||||||
|
fexml.placeholder_for(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ09
|
||||||
|
# DIAN 1.1.-2021: NSAJ09
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:ID',
|
||||||
|
invoice.invoice_supplier.address.city.code)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ10
|
||||||
|
# DIAN 1.1.-2021: NSAJ10
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:CityName',
|
||||||
|
invoice.invoice_supplier.address.city.name)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ73
|
||||||
|
# DIAN 1.1.-2021: NSAJ73
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:PostalZone',
|
||||||
|
invoice.invoice_supplier.address.postalzone.code)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ11
|
||||||
|
# DIAN 1.1.-2021: NSAJ11
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:CountrySubentity',
|
||||||
|
invoice.invoice_supplier.address.countrysubentity.name)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ12
|
||||||
|
# DIAN 1.1.-2021: NSAJ12
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cbc:CountrySubentityCode',
|
||||||
|
invoice.invoice_supplier.address.countrysubentity.code)
|
||||||
|
# DIAN 1.1.-2021: NSAJ13 NSAJ14
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cac:AddressLine/cbc:Line',
|
||||||
|
invoice.invoice_supplier.address.street)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ15 DSAJ16
|
||||||
|
# DIAN 1.1.-2021: NSAJ15 NSAJ16
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cac:Country/cbc:IdentificationCode',
|
||||||
|
invoice.invoice_supplier.address.country.code)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ17
|
||||||
|
# DIAN 1.1.-2021: NSAJ17
|
||||||
|
fexml.set_element('./cac:AccountingSupplierParty/cac:Party/cac:PhysicalLocation/cac:Address/cac:Country/cbc:Name',
|
||||||
|
invoice.invoice_supplier.address.country.name,
|
||||||
|
# DIAN 1.1.-2021: DSAJ18
|
||||||
|
# # DIAN 1.1.-2021: NSAJ18
|
||||||
|
languageID='es')
|
||||||
|
|
||||||
|
supplier_company_id_attrs = fe.SCHEME_AGENCY_ATTRS.copy()
|
||||||
|
supplier_company_id_attrs.update(
|
||||||
|
{
|
||||||
|
'schemeID': invoice.invoice_supplier.ident.dv,
|
||||||
|
'schemeName': invoice.invoice_supplier.ident.type_fiscal})
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ19
|
||||||
|
# DIAN 1.1.-2021: NSAJ19
|
||||||
|
fexml.placeholder_for(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ20
|
||||||
|
# DIAN 1.1.-2021: NSAJ20
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:RegistrationName',
|
||||||
|
invoice.invoice_supplier.legal_name)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ21
|
||||||
|
# DIAN 1.1.-2021: NSAJ21
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID',
|
||||||
|
invoice.invoice_supplier.ident,
|
||||||
|
# DIAN 1.1.-2021: DSAJ22 DSAJ23 DSAJ24 DSAJ25
|
||||||
|
# DIAN 1.1.-2021: NSAJ22 NSAJ23 NSAJ24 NSAJ25
|
||||||
|
**supplier_company_id_attrs)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ26
|
||||||
|
# DIAN 1.1.-2021: NSAJ26
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:TaxLevelCode',
|
||||||
|
invoice.invoice_supplier.responsability_code,
|
||||||
|
listName=invoice.invoice_supplier.responsability_regime_code)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ39
|
||||||
|
# DIAN 1.1.-2021: NSAJ39
|
||||||
|
fexml.placeholder_for(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ40
|
||||||
|
# DIAN 1.1.-2021: NSAJ40
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme/cbc:ID',
|
||||||
|
invoice.invoice_customer.tax_scheme.code)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAJ41
|
||||||
|
# DIAN 1.1.-2021: NSAJ41
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme/cbc:Name',
|
||||||
|
invoice.invoice_customer.tax_scheme.name)
|
||||||
|
|
||||||
|
def set_customer(fexml, invoice):
|
||||||
|
# DIAN 1.1.-2021: DSAK01
|
||||||
|
# DIAN 1.1.-2021: NSAK01
|
||||||
|
fexml.placeholder_for('./cac:AccountingCustomerParty')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAK02
|
||||||
|
# DIAN 1.1.-2021: NSAK02
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingCustomerParty/cbc:AdditionalAccountID',
|
||||||
|
invoice.invoice_customer.organization_code)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAK03
|
||||||
|
# DIAN 1.1.-2021: NSAK03
|
||||||
|
fexml.placeholder_for('./cac:AccountingCustomerParty/cac:Party')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAK19
|
||||||
|
# DIAN 1.1.-2021: NSAK19
|
||||||
|
fexml.placeholder_for(
|
||||||
|
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAK20
|
||||||
|
# DIAN 1.1.-2021: NSAK20
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:RegistrationName',
|
||||||
|
invoice.invoice_customer.legal_name)
|
||||||
|
|
||||||
|
customer_company_id_attrs = fe.SCHEME_AGENCY_ATTRS.copy()
|
||||||
|
customer_company_id_attrs.update(
|
||||||
|
{
|
||||||
|
'schemeID': invoice.invoice_customer.ident.dv,
|
||||||
|
'schemeName': invoice.invoice_customer.ident.type_fiscal})
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAK21
|
||||||
|
# DIAN 1.1.-2021: NSAK21
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID',
|
||||||
|
invoice.invoice_customer.ident,
|
||||||
|
# DIAN 1.1.-2021: DSAK22 DSAK23 DSAK24 DSAK25
|
||||||
|
# DIAN 1.1.-2021: NSAK22 NSAK23 NSAK24 NSAK25
|
||||||
|
**customer_company_id_attrs)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAK26
|
||||||
|
# DIAN 1.1.-2021: NSAK26
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cbc:TaxLevelCode',
|
||||||
|
invoice.invoice_customer.responsability_code)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAK39
|
||||||
|
# DIAN 1.1.-2021: NSAK39
|
||||||
|
fexml.placeholder_for(
|
||||||
|
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme')
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAK40
|
||||||
|
# DIAN 1.1.-2021: NSAK40
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme/cbc:ID',
|
||||||
|
invoice.invoice_customer.tax_scheme.code)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAK41
|
||||||
|
# DIAN 1.1.-2021: NSAK41
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:AccountingCustomerParty/cac:Party/cac:PartyTaxScheme/cac:TaxScheme/cbc:Name',
|
||||||
|
invoice.invoice_customer.tax_scheme.name)
|
||||||
|
|
||||||
|
def set_payment_mean(fexml, invoice):
|
||||||
|
payment_mean = invoice.invoice_payment_mean
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAN01 DSAN02
|
||||||
|
# DIAN 1.1.-2021: NSAN02 NSAN02
|
||||||
|
fexml.set_element('./cac:PaymentMeans/cbc:ID', payment_mean.id)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAN03
|
||||||
|
# DIAN 1.1.-2021: NSAN03
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:PaymentMeans/cbc:PaymentMeansCode',
|
||||||
|
payment_mean.code)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAN04
|
||||||
|
# DIAN 1.1.-2021: NSAN04
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:PaymentMeans/cbc:PaymentDueDate',
|
||||||
|
payment_mean.due_at.strftime('%Y-%m-%d'))
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAN05
|
||||||
|
# DIAN 1.1.-2021: NSAN05
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:PaymentMeans/cbc:PaymentID',
|
||||||
|
payment_mean.payment_id)
|
||||||
|
|
||||||
|
def set_element_amount_for(fexml, xml, xpath, amount):
|
||||||
|
if not isinstance(amount, Amount):
|
||||||
|
raise TypeError("amount not is Amount")
|
||||||
|
|
||||||
|
xml.set_element(xpath, amount, currencyID=amount.currency.code)
|
||||||
|
|
||||||
|
def set_element_amount(fexml, xpath, amount):
|
||||||
|
if not isinstance(amount, Amount):
|
||||||
|
raise TypeError("amount not is Amount")
|
||||||
|
|
||||||
|
fexml.set_element(xpath, amount, currencyID=amount.currency.code)
|
||||||
|
|
||||||
|
def set_legal_monetary(fexml, invoice):
|
||||||
|
# DIAN 1.1.-2021: DSAU01 DSAU02 DSAU03
|
||||||
|
# DIAN 1.1.-2021: NSAU01 NSAU02 NSAU03
|
||||||
|
fexml.set_element_amount(
|
||||||
|
'./cac:LegalMonetaryTotal/cbc:LineExtensionAmount',
|
||||||
|
invoice.invoice_legal_monetary_total.line_extension_amount)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAU04 DSAU05
|
||||||
|
# DIAN 1.1.-2021: NSAU04 NSAU05
|
||||||
|
fexml.set_element_amount(
|
||||||
|
'./cac:LegalMonetaryTotal/cbc:TaxExclusiveAmount',
|
||||||
|
invoice.invoice_legal_monetary_total.tax_exclusive_amount)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAU06 DSAU07
|
||||||
|
# DIAN 1.1.-2021: NSAU06 DSAU07
|
||||||
|
fexml.set_element_amount(
|
||||||
|
'./cac:LegalMonetaryTotal/cbc:TaxInclusiveAmount',
|
||||||
|
invoice.invoice_legal_monetary_total.tax_inclusive_amount)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAU10 DSAU11
|
||||||
|
# DIAN 1.1.-2021: NSAU10 DSAU11
|
||||||
|
fexml.set_element_amount(
|
||||||
|
'./cac:LegalMonetaryTotal/cbc:ChargeTotalAmount',
|
||||||
|
invoice.invoice_legal_monetary_total.charge_total_amount)
|
||||||
|
|
||||||
|
# DIAN 1.1.-2021: DSAU14 DSAU15
|
||||||
|
# DIAN 1.1.-2021: NSAU14 DSAU15
|
||||||
|
fexml.set_element_amount(
|
||||||
|
'./cac:LegalMonetaryTotal/cbc:PayableAmount',
|
||||||
|
invoice.invoice_legal_monetary_total.payable_amount)
|
||||||
|
|
||||||
|
def _set_invoice_document_reference(fexml, reference):
|
||||||
|
fexml._do_set_billing_reference(
|
||||||
|
reference, 'cac:InvoiceDocumentReference')
|
||||||
|
|
||||||
|
def _set_credit_note_document_reference(fexml, reference):
|
||||||
|
fexml._do_set_billing_reference(
|
||||||
|
reference, 'cac:CreditNoteDocumentReference')
|
||||||
|
|
||||||
|
def _set_debit_note_document_reference(fexml, reference):
|
||||||
|
fexml._do_set_billing_reference(
|
||||||
|
reference, 'cac:DebitNoteDocumentReference')
|
||||||
|
|
||||||
|
def _do_set_billing_reference(fexml, reference, tag_document):
|
||||||
|
|
||||||
|
if tag_document == 'Invoice':
|
||||||
|
schemeName = 'CUFE-SHA384'
|
||||||
|
else:
|
||||||
|
schemeName = 'CUDS-SHA384'
|
||||||
|
|
||||||
|
fexml.set_element('./cac:BillingReference/%s/cbc:ID' % (tag_document),
|
||||||
|
reference.ident)
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:BillingReference/cac:InvoiceDocumentReference/cbc:UUID',
|
||||||
|
reference.uuid,
|
||||||
|
schemeName=schemeName)
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:BillingReference/cac:InvoiceDocumentReference/cbc:IssueDate',
|
||||||
|
reference.date.strftime("%Y-%m-%d"))
|
||||||
|
|
||||||
|
def set_billing_reference(fexml, invoice):
|
||||||
|
reference = invoice.invoice_billing_reference
|
||||||
|
if reference is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if isinstance(reference, DebitNoteDocumentReference):
|
||||||
|
return fexml._set_debit_note_document_reference(reference)
|
||||||
|
if isinstance(reference, CreditNoteDocumentReference):
|
||||||
|
return fexml._set_credit_note_document_reference(reference)
|
||||||
|
|
||||||
|
if isinstance(reference, InvoiceDocumentReference):
|
||||||
|
return fexml._set_invoice_document_reference(reference)
|
||||||
|
|
||||||
|
def set_discrepancy_response(fexml, invoice):
|
||||||
|
reference = invoice.invoice_discrepancy_response
|
||||||
|
if reference is None:
|
||||||
|
return
|
||||||
|
if isinstance(reference, DebitNoteDocumentReference):
|
||||||
|
return fexml._set_debit_note_document_reference(reference)
|
||||||
|
if isinstance(reference, CreditNoteDocumentReference):
|
||||||
|
return fexml._set_credit_note_document_reference(reference)
|
||||||
|
|
||||||
|
if isinstance(reference, InvoiceDocumentReference):
|
||||||
|
return fexml._set_invoice_document_reference(reference)
|
||||||
|
|
||||||
|
fexml.set_element('./cac:DiscrepancyResponse/cbc:ReferenceID',
|
||||||
|
reference.id)
|
||||||
|
fexml.set_element('./cac:DiscrepancyResponse/cbc:ResponseCode',
|
||||||
|
reference.code)
|
||||||
|
fexml.set_element('./cac:DiscrepancyResponse/cbc:Description',
|
||||||
|
reference.description)
|
||||||
|
|
||||||
|
def set_invoice_totals(fexml, invoice):
|
||||||
|
tax_amount_for = defaultdict(lambda: defaultdict(lambda: Amount(0.0)))
|
||||||
|
percent_for = defaultdict(lambda: None)
|
||||||
|
|
||||||
|
total_tax_amount = Amount(0.0)
|
||||||
|
|
||||||
|
for invoice_line in invoice.invoice_lines:
|
||||||
|
for subtotal in invoice_line.tax.subtotals:
|
||||||
|
if subtotal.scheme is not None:
|
||||||
|
tax_amount_for[
|
||||||
|
subtotal.scheme.code][
|
||||||
|
'tax_amount'] += subtotal.tax_amount
|
||||||
|
tax_amount_for[subtotal.scheme.code][
|
||||||
|
'taxable_amount'] += invoice_line.taxable_amount
|
||||||
|
|
||||||
|
# MACHETE ojo InvoiceLine.tax pasar a Invoice
|
||||||
|
percent_for[subtotal.scheme.code] = subtotal.percent
|
||||||
|
|
||||||
|
total_tax_amount += subtotal.tax_amount
|
||||||
|
|
||||||
|
if total_tax_amount != Amount(0.0):
|
||||||
|
fexml.placeholder_for('./cac:TaxTotal')
|
||||||
|
fexml.set_element_amount('./cac:TaxTotal/cbc:TaxAmount',
|
||||||
|
total_tax_amount)
|
||||||
|
|
||||||
|
for index, item in enumerate(tax_amount_for.items()):
|
||||||
|
cod_impuesto, amount_of = item
|
||||||
|
next_append = index > 0
|
||||||
|
|
||||||
|
# DIAN 1.7.-2020: FAS01
|
||||||
|
line = fexml.fragment('./cac:TaxTotal', append=next_append)
|
||||||
|
# DIAN 1.7.-2020: FAU06
|
||||||
|
tax_amount = amount_of['tax_amount']
|
||||||
|
fexml.set_element_amount_for(line,
|
||||||
|
'/cac:TaxTotal/cbc:TaxAmount',
|
||||||
|
tax_amount)
|
||||||
|
|
||||||
|
# DIAN 1.7.-2020: FAS05
|
||||||
|
fexml.set_element_amount_for(
|
||||||
|
line,
|
||||||
|
'/cac:TaxTotal/cac:TaxSubtotal/cbc:TaxableAmount',
|
||||||
|
amount_of['taxable_amount'])
|
||||||
|
|
||||||
|
# DIAN 1.7.-2020: FAU06
|
||||||
|
fexml.set_element_amount_for(
|
||||||
|
line,
|
||||||
|
'/cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount',
|
||||||
|
amount_of['tax_amount'])
|
||||||
|
|
||||||
|
# DIAN 1.7.-2020: FAS07
|
||||||
|
if percent_for[cod_impuesto]:
|
||||||
|
line.set_element('/cac:TaxTotal/cac:TaxSubtotal/cbc:Percent',
|
||||||
|
percent_for[cod_impuesto])
|
||||||
|
|
||||||
|
if percent_for[cod_impuesto]:
|
||||||
|
line.set_element(
|
||||||
|
'/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent',
|
||||||
|
percent_for[cod_impuesto])
|
||||||
|
|
||||||
|
line.set_element(
|
||||||
|
'/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID',
|
||||||
|
cod_impuesto)
|
||||||
|
line.set_element(
|
||||||
|
'/cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name', 'IVA')
|
||||||
|
|
||||||
|
# abstract method
|
||||||
|
|
||||||
|
def tag_document(fexml):
|
||||||
|
return 'Invoice'
|
||||||
|
|
||||||
|
# abstract method
|
||||||
|
def tag_document_concilied(fexml):
|
||||||
|
return 'Invoiced'
|
||||||
|
|
||||||
|
def set_invoice_line_withholding(fexml, line, invoice_line):
|
||||||
|
fexml.set_element_amount_for(line,
|
||||||
|
'./cac:WithholdingTaxTotal/cbc:TaxAmount',
|
||||||
|
invoice_line.withholding_amount)
|
||||||
|
# DIAN 1.7.-2020: FAX05
|
||||||
|
fexml.set_element_amount_for(
|
||||||
|
line,
|
||||||
|
'./cac:WithholdingTaxTotal/cac:TaxSubtotal/cbc:TaxableAmount',
|
||||||
|
invoice_line.withholding_taxable_amount)
|
||||||
|
|
||||||
|
for subtotal in invoice_line.withholding.subtotals:
|
||||||
|
line.set_element(
|
||||||
|
'./cac:WithholdingTaxTotal/cac:TaxSubtotal/cbc:TaxAmount',
|
||||||
|
subtotal.tax_amount,
|
||||||
|
currencyID='COP')
|
||||||
|
|
||||||
|
if subtotal.percent is not None:
|
||||||
|
line.set_element(
|
||||||
|
'./cac:WithholdingTaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent',
|
||||||
|
'%0.2f' %
|
||||||
|
round(
|
||||||
|
subtotal.percent,
|
||||||
|
2))
|
||||||
|
|
||||||
|
if subtotal.scheme is not None:
|
||||||
|
# DIAN 1.7.-2020: FAX15
|
||||||
|
line.set_element(
|
||||||
|
'./cac:WithholdingTaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID',
|
||||||
|
subtotal.scheme.code)
|
||||||
|
line.set_element(
|
||||||
|
'./cac:WithholdingTaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name',
|
||||||
|
subtotal.scheme.name)
|
||||||
|
|
||||||
|
def set_invoice_line_tax(fexml, line, invoice_line):
|
||||||
|
fexml.set_element_amount_for(line,
|
||||||
|
'./cac:TaxTotal/cbc:TaxAmount',
|
||||||
|
invoice_line.tax_amount)
|
||||||
|
|
||||||
|
# DIAN 1.7.-2020: FAX05
|
||||||
|
fexml.set_element_amount_for(
|
||||||
|
line,
|
||||||
|
'./cac:TaxTotal/cac:TaxSubtotal/cbc:TaxableAmount',
|
||||||
|
invoice_line.taxable_amount)
|
||||||
|
for subtotal in invoice_line.tax.subtotals:
|
||||||
|
line.set_element(
|
||||||
|
'./cac:TaxTotal/cac:TaxSubtotal/cbc:TaxAmount',
|
||||||
|
subtotal.tax_amount,
|
||||||
|
currencyID='COP')
|
||||||
|
|
||||||
|
if subtotal.percent is not None:
|
||||||
|
line.set_element(
|
||||||
|
'./cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cbc:Percent',
|
||||||
|
'%0.2f' %
|
||||||
|
round(
|
||||||
|
subtotal.percent,
|
||||||
|
2))
|
||||||
|
|
||||||
|
if subtotal.scheme is not None:
|
||||||
|
# DIAN 1.7.-2020: FAX15
|
||||||
|
line.set_element(
|
||||||
|
'./cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:ID',
|
||||||
|
subtotal.scheme.code)
|
||||||
|
line.set_element(
|
||||||
|
'./cac:TaxTotal/cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name',
|
||||||
|
subtotal.scheme.name)
|
||||||
|
|
||||||
|
def set_invoice_lines(fexml, invoice):
|
||||||
|
next_append = False
|
||||||
|
for index, invoice_line in enumerate(invoice.invoice_lines):
|
||||||
|
line = fexml.fragment(
|
||||||
|
'./cac:%sLine' %
|
||||||
|
(fexml.tag_document()),
|
||||||
|
append=next_append)
|
||||||
|
next_append = True
|
||||||
|
|
||||||
|
line.set_element('./cbc:ID', index + 1)
|
||||||
|
line.set_element(
|
||||||
|
'./cbc:%sQuantity' %
|
||||||
|
(fexml.tag_document_concilied()),
|
||||||
|
invoice_line.quantity,
|
||||||
|
unitCode='NAR')
|
||||||
|
fexml.set_element_amount_for(line,
|
||||||
|
'./cbc:LineExtensionAmount',
|
||||||
|
invoice_line.total_amount)
|
||||||
|
|
||||||
|
period = line.fragment('./cac:InvoicePeriod')
|
||||||
|
period.set_element('./cbc:StartDate',
|
||||||
|
datetime.now().strftime('%Y-%m-%d'))
|
||||||
|
period.set_element(
|
||||||
|
'./cbc:DescriptionCode', '1')
|
||||||
|
period.set_element('./cbc:Description',
|
||||||
|
'Por operación')
|
||||||
|
|
||||||
|
if not isinstance(invoice_line.tax, TaxTotalOmit):
|
||||||
|
fexml.set_invoice_line_tax(line, invoice_line)
|
||||||
|
|
||||||
|
if not isinstance(
|
||||||
|
invoice_line.withholding,
|
||||||
|
WithholdingTaxTotalOmit):
|
||||||
|
fexml.set_invoice_line_withholding(line, invoice_line)
|
||||||
|
|
||||||
|
line.set_element(
|
||||||
|
'./cac:Item/cbc:Description',
|
||||||
|
invoice_line.item.description)
|
||||||
|
|
||||||
|
line.set_element(
|
||||||
|
'./cac:Item/cac:StandardItemIdentification/cbc:ID',
|
||||||
|
invoice_line.item.id,
|
||||||
|
schemeID=invoice_line.item.scheme_id,
|
||||||
|
schemeName=invoice_line.item.scheme_name,
|
||||||
|
schemeAgencyID=invoice_line.item.scheme_agency_id)
|
||||||
|
|
||||||
|
line.set_element(
|
||||||
|
'./cac:Price/cbc:PriceAmount',
|
||||||
|
invoice_line.price.amount,
|
||||||
|
currencyID=invoice_line.price.amount.currency.code)
|
||||||
|
# DIAN 1.7.-2020: FBB04
|
||||||
|
line.set_element('./cac:Price/cbc:BaseQuantity',
|
||||||
|
invoice_line.quantity,
|
||||||
|
unitCode=invoice_line.quantity.code)
|
||||||
|
|
||||||
|
for idx, charge in enumerate(invoice_line.allowance_charge):
|
||||||
|
next_append_charge = idx > 0
|
||||||
|
fexml.append_allowance_charge(
|
||||||
|
line, index + 1, charge, append=next_append_charge)
|
||||||
|
|
||||||
|
def set_allowance_charge(fexml, invoice):
|
||||||
|
for idx, charge in enumerate(invoice.invoice_allowance_charge):
|
||||||
|
next_append = idx > 0
|
||||||
|
fexml.append_allowance_charge(
|
||||||
|
fexml, idx + 1, charge, append=next_append)
|
||||||
|
|
||||||
|
def append_allowance_charge(fexml, parent, idx, charge, append=False):
|
||||||
|
line = parent.fragment('./cac:AllowanceCharge', append=append)
|
||||||
|
# DIAN 1.7.-2020: FAQ02
|
||||||
|
line.set_element('./cbc:ID', idx)
|
||||||
|
# DIAN 1.7.-2020: FAQ03
|
||||||
|
line.set_element('./cbc:ChargeIndicator',
|
||||||
|
str(charge.charge_indicator).lower())
|
||||||
|
if charge.reason:
|
||||||
|
line.set_element(
|
||||||
|
'./cbc:AllowanceChargeReasonCode',
|
||||||
|
charge.reason.code)
|
||||||
|
line.set_element(
|
||||||
|
'./cbc:allowanceChargeReason',
|
||||||
|
charge.reason.reason)
|
||||||
|
line.set_element('./cbc:MultiplierFactorNumeric',
|
||||||
|
str(round(charge.multiplier_factor_numeric, 2)))
|
||||||
|
fexml.set_element_amount_for(line, './cbc:Amount', charge.amount)
|
||||||
|
fexml.set_element_amount_for(
|
||||||
|
line, './cbc:BaseAmount', charge.base_amount)
|
||||||
|
|
||||||
|
def attach_invoice(fexml, invoice):
|
||||||
|
"""adiciona etiquetas a FEXML y retorna FEXML
|
||||||
|
en caso de fallar validacion retorna None"""
|
||||||
|
|
||||||
|
fexml.placeholder_for('./ext:UBLExtensions')
|
||||||
|
fexml.set_element('./cbc:UBLVersionID', 'UBL 2.1')
|
||||||
|
fexml.set_element(
|
||||||
|
'./cbc:CustomizationID',
|
||||||
|
invoice.invoice_operation_type)
|
||||||
|
fexml.placeholder_for('./cbc:ProfileID')
|
||||||
|
fexml.placeholder_for('./cbc:ProfileExecutionID')
|
||||||
|
fexml.set_element('./cbc:ID', invoice.invoice_ident)
|
||||||
|
fexml.placeholder_for('./cbc:UUID')
|
||||||
|
fexml.set_element('./cbc:DocumentCurrencyCode', 'COP')
|
||||||
|
fexml.set_element(
|
||||||
|
'./cbc:IssueDate',
|
||||||
|
invoice.invoice_issue.strftime('%Y-%m-%d'))
|
||||||
|
# DIAN 1.7.-2020: FAD10
|
||||||
|
fexml.set_element(
|
||||||
|
'./cbc:IssueTime',
|
||||||
|
invoice.invoice_issue.strftime('%H:%M:%S-05:00'))
|
||||||
|
fexml.set_element(
|
||||||
|
'./cbc:%sTypeCode' %
|
||||||
|
(fexml.tag_document()),
|
||||||
|
invoice.invoice_type_code,
|
||||||
|
listAgencyID='195',
|
||||||
|
listAgencyName='No matching global declaration available for the validation root',
|
||||||
|
listURI='http://www.dian.gov.co')
|
||||||
|
fexml.set_element('./cbc:LineCountNumeric', len(invoice.invoice_lines))
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:%sPeriod/cbc:StartDate' %
|
||||||
|
(fexml.tag_document()),
|
||||||
|
invoice.invoice_period_start.strftime('%Y-%m-%d'))
|
||||||
|
|
||||||
|
fexml.set_element(
|
||||||
|
'./cac:%sPeriod/cbc:EndDate' %
|
||||||
|
(fexml.tag_document()),
|
||||||
|
invoice.invoice_period_end.strftime('%Y-%m-%d'))
|
||||||
|
|
||||||
|
fexml.customize(invoice)
|
||||||
|
|
||||||
|
fexml.set_supplier(invoice)
|
||||||
|
fexml.set_customer(invoice)
|
||||||
|
fexml.set_legal_monetary(invoice)
|
||||||
|
fexml.set_invoice_totals(invoice)
|
||||||
|
fexml.set_invoice_lines(invoice)
|
||||||
|
fexml.set_payment_mean(invoice)
|
||||||
|
fexml.set_allowance_charge(invoice)
|
||||||
|
fexml.set_discrepancy_response(invoice)
|
||||||
|
fexml.set_billing_reference(invoice)
|
||||||
|
|
||||||
|
return fexml
|
||||||
|
|
||||||
|
def customize(fexml, invoice):
|
||||||
|
"""adiciona etiquetas a FEXML y retorna FEXML
|
||||||
|
en caso de fallar validacion retorna None"""
|
||||||
25
facho/fe/form_xml/support_document_credit_note.py
Normal file
25
facho/fe/form_xml/support_document_credit_note.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# from .. import fe
|
||||||
|
# from ..form import *
|
||||||
|
from .support_document import DIANSupportDocumentXML
|
||||||
|
|
||||||
|
__all__ = ['DIANSupportDocumentCreditNoteXML']
|
||||||
|
|
||||||
|
|
||||||
|
class DIANSupportDocumentCreditNoteXML(DIANSupportDocumentXML):
|
||||||
|
"""
|
||||||
|
DianInvoiceXML mapea objeto form.Invoice a XML segun
|
||||||
|
lo indicado para la facturacion electronica.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, invoice):
|
||||||
|
super(
|
||||||
|
DIANSupportDocumentCreditNoteXML,
|
||||||
|
self).__init__(
|
||||||
|
invoice,
|
||||||
|
'CreditNote')
|
||||||
|
|
||||||
|
def tag_document(fexml):
|
||||||
|
return 'CreditNote'
|
||||||
|
|
||||||
|
def tag_document_concilied(fexml):
|
||||||
|
return 'Credited'
|
||||||
@@ -2,14 +2,30 @@ from .. import fe
|
|||||||
|
|
||||||
__all__ = ['DIANWrite', 'DIANWriteSigned']
|
__all__ = ['DIANWrite', 'DIANWriteSigned']
|
||||||
|
|
||||||
|
|
||||||
def DIANWrite(xml, filename):
|
def DIANWrite(xml, filename):
|
||||||
document = xml.tostring(xml_declaration=True, encoding='UTF-8')
|
document = xml.tostring(xml_declaration=True, encoding='UTF-8')
|
||||||
with open(filename, 'w') as f:
|
with open(filename, 'w') as f:
|
||||||
f.write(document)
|
f.write(document)
|
||||||
|
|
||||||
|
|
||||||
def DIANWriteSigned(xml, filename, private_key, passphrase, use_cache_policy=False):
|
def DIANWriteSigned(
|
||||||
document = xml.tostring(xml_declaration=True, encoding='UTF-8').encode('utf-8')
|
xml,
|
||||||
signer = fe.DianXMLExtensionSigner(private_key, passphrase=passphrase, mockpolicy=use_cache_policy)
|
filename,
|
||||||
|
private_key,
|
||||||
|
passphrase,
|
||||||
|
use_cache_policy=False,
|
||||||
|
dian_signer=None):
|
||||||
|
document = xml.tostring(
|
||||||
|
xml_declaration=True,
|
||||||
|
encoding='UTF-8').encode('utf-8')
|
||||||
|
if dian_signer is None:
|
||||||
|
dian_signer = fe.DianXMLExtensionSigner
|
||||||
|
|
||||||
|
signer = dian_signer(
|
||||||
|
private_key,
|
||||||
|
passphrase=passphrase,
|
||||||
|
localpolicy=use_cache_policy)
|
||||||
|
|
||||||
with open(filename, 'w') as f:
|
with open(filename, 'w') as f:
|
||||||
f.write(signer.sign_xml_string(document))
|
f.write(signer.sign_xml_string(document))
|
||||||
|
|||||||
651
facho/fe/nomina/__init__.py
Normal file
651
facho/fe/nomina/__init__.py
Normal file
@@ -0,0 +1,651 @@
|
|||||||
|
#
|
||||||
|
# Para esta implementacion se usa BDD
|
||||||
|
# ver **test_nomina.py**.
|
||||||
|
#
|
||||||
|
# La idea en general es validar comportamiento desde el XML,
|
||||||
|
# creando las estructuras minimas necesaras.
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from datetime import datetime
|
||||||
|
import hashlib
|
||||||
|
import typing
|
||||||
|
|
||||||
|
from .. import fe
|
||||||
|
from .. import form
|
||||||
|
from ..data.dian import codelist
|
||||||
|
|
||||||
|
from .devengado import *
|
||||||
|
from .deduccion import *
|
||||||
|
from .trabajador import *
|
||||||
|
from .empleador import *
|
||||||
|
from .pago import *
|
||||||
|
from .lugar import Lugar
|
||||||
|
|
||||||
|
from .amount import Amount
|
||||||
|
from .exception import *
|
||||||
|
|
||||||
|
class Fecha:
|
||||||
|
def __init__(self, fecha):
|
||||||
|
try:
|
||||||
|
datetime.strptime(fecha, "%Y-%m-%d")
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError("fecha debe ser formato YYYY-MM-DD")
|
||||||
|
self.value = fecha
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def cast(cls, data, optional=False):
|
||||||
|
if isinstance(data, str):
|
||||||
|
return cls(data)
|
||||||
|
elif isinstance(data, cls):
|
||||||
|
return data
|
||||||
|
elif data is None and optional:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
raise ValueError('no se logra hacer casting a Fecha')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
class FechaPago(Fecha):
|
||||||
|
def apply(self, fragment):
|
||||||
|
fragment.set_element('./FechaPago', self.value)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Novedad:
|
||||||
|
# cune de nomina a relacionar
|
||||||
|
# NIE204
|
||||||
|
cune: str
|
||||||
|
# NIE199
|
||||||
|
activa: bool = False
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
if self.cune != "":
|
||||||
|
fragment.set_attributes('./Novedad',
|
||||||
|
CUNENov=self.cune,
|
||||||
|
)
|
||||||
|
|
||||||
|
def post_apply(self, fexml, scopexml, fragment):
|
||||||
|
scopexml.set_element('./Novedad', self.activa)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class NumeroSecuencia:
|
||||||
|
consecutivo: int
|
||||||
|
prefijo: str
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
numero = f"{self.prefijo}{self.consecutivo}"
|
||||||
|
fragment.set_attributes('./NumeroSecuenciaXML',
|
||||||
|
# NIE010
|
||||||
|
Prefijo=self.prefijo,
|
||||||
|
# NIE011
|
||||||
|
Consecutivo=self.consecutivo,
|
||||||
|
# NIE012
|
||||||
|
Numero = numero)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Periodo:
|
||||||
|
fecha_ingreso: typing.Union[str, Fecha]
|
||||||
|
fecha_liquidacion_inicio: typing.Union[str, Fecha]
|
||||||
|
fecha_liquidacion_fin: typing.Union[str, Fecha]
|
||||||
|
fecha_generacion: typing.Union[str, Fecha]
|
||||||
|
|
||||||
|
tiempo_laborado: int = 1
|
||||||
|
fecha_retiro: typing.Union[str, Fecha] = None
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
self.fecha_ingreso = Fecha.cast(self.fecha_ingreso)
|
||||||
|
self.fecha_liquidacion_inicio = Fecha.cast(self.fecha_liquidacion_inicio)
|
||||||
|
self.fecha_liquidacion_fin = Fecha.cast(self.fecha_liquidacion_fin)
|
||||||
|
self.fecha_retiro = Fecha.cast(self.fecha_retiro, optional=True)
|
||||||
|
|
||||||
|
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:
|
||||||
|
razon_social: str
|
||||||
|
nit: str
|
||||||
|
dv: int
|
||||||
|
software_id: str
|
||||||
|
software_pin: str
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
fragment.set_attributes('./ProveedorXML',
|
||||||
|
# NIE017
|
||||||
|
NIT=self.nit,
|
||||||
|
# NIE018
|
||||||
|
DV=self.dv,
|
||||||
|
# NIE019
|
||||||
|
SoftwareID=self.software_id,
|
||||||
|
|
||||||
|
SoftwareSC=None,
|
||||||
|
# NIE025
|
||||||
|
RazonSocial=self.razon_social
|
||||||
|
)
|
||||||
|
|
||||||
|
def post_apply(self, fexml, scopexml, fragment):
|
||||||
|
cune_xpath = scopexml.xpath_from_root('/InformacionGeneral')
|
||||||
|
cune = fexml.get_element_attribute(cune_xpath, 'CUNE')
|
||||||
|
|
||||||
|
ambiente = fexml.get_element_attribute(scopexml.xpath_from_root('/InformacionGeneral'), 'Ambiente')
|
||||||
|
codigo_qr = f"https://catalogo-vpfe.dian.gov.co/document/searchqr?documentkey={cune}"
|
||||||
|
|
||||||
|
if InformacionGeneral.AMBIENTE_PRUEBAS == ambiente:
|
||||||
|
codigo_qr = f"https://catalogo-vpfe-hab.dian.gov.co/document/searchqr?documentkey={cune}"
|
||||||
|
elif ambiente is None:
|
||||||
|
raise RuntimeError('fail to get InformacionGeneral/@Ambiente')
|
||||||
|
|
||||||
|
scopexml.set_element('./CodigoQR', codigo_qr)
|
||||||
|
|
||||||
|
# NIE020
|
||||||
|
software_code = self._software_security_code(fexml, scopexml)
|
||||||
|
fexml.set_attributes(scopexml.xpath_from_root('/ProveedorXML'), SoftwareSC=software_code)
|
||||||
|
|
||||||
|
def _software_security_code(self, fexml, scopexml):
|
||||||
|
|
||||||
|
|
||||||
|
# 8.2
|
||||||
|
numero = fexml.get_element_attribute(scopexml.xpath_from_root('/NumeroSecuenciaXML'), 'Numero')
|
||||||
|
if numero is None:
|
||||||
|
raise RuntimeError('fallo obtener NumeroSequenciaXML/@Numero')
|
||||||
|
|
||||||
|
id_software = self.software_id
|
||||||
|
software_pin = self.software_pin
|
||||||
|
|
||||||
|
code = "".join([id_software, software_pin, numero])
|
||||||
|
|
||||||
|
fexml.set_attributes(scopexml.xpath_from_root('/ProveedorXML'))
|
||||||
|
h = hashlib.sha384()
|
||||||
|
h.update(code.encode('utf-8'))
|
||||||
|
return h.hexdigest()
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Metadata:
|
||||||
|
novedad: Novedad
|
||||||
|
secuencia: NumeroSecuencia
|
||||||
|
# NIE013, NIE014, NIE015, NIE016
|
||||||
|
lugar_generacion: Lugar
|
||||||
|
proveedor: Proveedor
|
||||||
|
|
||||||
|
def apply(self, novedad, numero_secuencia_xml, lugar_generacion_xml, proveedor_xml):
|
||||||
|
if novedad:
|
||||||
|
self.novedad.apply(novedad)
|
||||||
|
self.secuencia.apply(numero_secuencia_xml)
|
||||||
|
self.lugar_generacion.apply(lugar_generacion_xml, './LugarGeneracionXML')
|
||||||
|
self.proveedor.apply(proveedor_xml)
|
||||||
|
|
||||||
|
def post_apply(self, fexml, scopexml, novedad, numero_secuencia_xml, lugar_generacion_xml, proveedor_xml):
|
||||||
|
self.proveedor.post_apply(fexml, scopexml, proveedor_xml)
|
||||||
|
if novedad:
|
||||||
|
self.novedad.post_apply(fexml, scopexml, proveedor_xml)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PeriodoNomina:
|
||||||
|
code: str
|
||||||
|
name: str = ''
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if self.code not in codelist.PeriodoNomina:
|
||||||
|
raise ValueError("code [%s] not found" % (self.code))
|
||||||
|
self.name = codelist.PeriodoNomina[self.code]['name']
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TipoMoneda:
|
||||||
|
code: str
|
||||||
|
name: str = ''
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if self.code not in codelist.TipoMoneda:
|
||||||
|
raise ValueError("code [%s] not found" % (self.code))
|
||||||
|
self.name = codelist.TipoMoneda[self.code]['name']
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class InformacionGeneral:
|
||||||
|
@dataclass
|
||||||
|
class TIPO_AMBIENTE:
|
||||||
|
valor: str
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.valor == str(other)
|
||||||
|
|
||||||
|
# TABLA 5.1.1
|
||||||
|
@dataclass
|
||||||
|
class AMBIENTE_PRODUCCION(TIPO_AMBIENTE):
|
||||||
|
valor: str = '1'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
self.valor
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class AMBIENTE_PRUEBAS(TIPO_AMBIENTE):
|
||||||
|
valor: str = '2'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
self.valor
|
||||||
|
|
||||||
|
# TABLA 5.5.7
|
||||||
|
@dataclass
|
||||||
|
class TIPO_XML:
|
||||||
|
valor: str
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.valor == str(other)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TIPO_XML_NORMAL(TIPO_XML):
|
||||||
|
valor: str = '102'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
self.valor
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class TIPO_XML_AJUSTES(TIPO_XML):
|
||||||
|
valor: str = '103'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
self.valor
|
||||||
|
|
||||||
|
fecha_generacion: typing.Union[str, Fecha]
|
||||||
|
hora_generacion: str
|
||||||
|
periodo_nomina: PeriodoNomina
|
||||||
|
tipo_moneda: TipoMoneda
|
||||||
|
tipo_ambiente: TIPO_AMBIENTE
|
||||||
|
tipo_xml: TIPO_XML
|
||||||
|
software_pin: str
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
self.fecha_generacion = Fecha.cast(self.fecha_generacion)
|
||||||
|
|
||||||
|
def apply(self, fragment, version):
|
||||||
|
fragment.set_attributes('./InformacionGeneral',
|
||||||
|
# NIE022
|
||||||
|
Version = version,
|
||||||
|
# NIE023
|
||||||
|
Ambiente = self.tipo_ambiente.valor,
|
||||||
|
# NIE202
|
||||||
|
# TABLA 5.5.2
|
||||||
|
# TODO(bit4bit) solo NominaIndividual
|
||||||
|
TipoXML = self.tipo_xml.valor,
|
||||||
|
# NIE024
|
||||||
|
CUNE = None,
|
||||||
|
# NIE025
|
||||||
|
EncripCUNE = 'CUNE-SHA384',
|
||||||
|
# NIE026
|
||||||
|
FechaGen = self.fecha_generacion,
|
||||||
|
# NIE027
|
||||||
|
HoraGen = self.hora_generacion,
|
||||||
|
# NIE029
|
||||||
|
PeriodoNomina = self.periodo_nomina.code,
|
||||||
|
# NIE030
|
||||||
|
TipoMoneda = self.tipo_moneda.code,
|
||||||
|
TRM = 0
|
||||||
|
# TODO(bit4bit) resto...
|
||||||
|
# .....
|
||||||
|
)
|
||||||
|
|
||||||
|
def post_apply(self, fexml, scopexml, fragment):
|
||||||
|
# generar cune
|
||||||
|
# ver 8.1.1.1
|
||||||
|
xpaths = [
|
||||||
|
scopexml.xpath_from_root('/NumeroSecuenciaXML/@Numero'),
|
||||||
|
scopexml.xpath_from_root('/InformacionGeneral/@FechaGen'),
|
||||||
|
scopexml.xpath_from_root('/InformacionGeneral/@HoraGen'),
|
||||||
|
scopexml.xpath_from_root('/DevengadosTotal'),
|
||||||
|
scopexml.xpath_from_root('/DeduccionesTotal'),
|
||||||
|
scopexml.xpath_from_root('/ComprobanteTotal'),
|
||||||
|
scopexml.xpath_from_root('/Empleador/@NIT'),
|
||||||
|
scopexml.xpath_from_root('/Trabajador/@NumeroDocumento'),
|
||||||
|
scopexml.xpath_from_root('/InformacionGeneral/@TipoXML'),
|
||||||
|
tuple([self.software_pin]),
|
||||||
|
scopexml.xpath_from_root('/InformacionGeneral/@Ambiente')
|
||||||
|
]
|
||||||
|
|
||||||
|
campos = fexml.get_elements_text_or_attributes(xpaths)
|
||||||
|
|
||||||
|
cune = "".join(campos)
|
||||||
|
|
||||||
|
h = hashlib.sha384()
|
||||||
|
h.update(cune.encode('utf-8'))
|
||||||
|
cune_hash = h.hexdigest()
|
||||||
|
|
||||||
|
fragment.set_attributes(
|
||||||
|
'./InformacionGeneral',
|
||||||
|
# NIE024
|
||||||
|
CUNE = cune_hash
|
||||||
|
)
|
||||||
|
|
||||||
|
class DianXMLExtensionSigner(fe.DianXMLExtensionSigner):
|
||||||
|
|
||||||
|
def __init__(self, pkcs12_path, passphrase=None, localpolicy=True):
|
||||||
|
super().__init__(pkcs12_path, passphrase=passphrase, localpolicy=localpolicy)
|
||||||
|
|
||||||
|
def _element_extension_content(self, fachoxml):
|
||||||
|
return fachoxml.builder.xpath(fachoxml.root, './ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent')
|
||||||
|
|
||||||
|
|
||||||
|
class DIANNominaXML:
|
||||||
|
def __init__(self, tag_document, xpath_ajuste=None, schemaLocation=None, namespace_ajuste=None):
|
||||||
|
self.informacion_general_version = None
|
||||||
|
|
||||||
|
self.tag_document = tag_document
|
||||||
|
|
||||||
|
if namespace_ajuste:
|
||||||
|
self.fexml = fe.FeXML(tag_document, namespace_ajuste)
|
||||||
|
else:
|
||||||
|
self.fexml = fe.FeXML(tag_document, 'dian:gov:co:facturaelectronica:NominaIndividual')
|
||||||
|
|
||||||
|
self.fexml.root.set("SchemaLocation", "")
|
||||||
|
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')
|
||||||
|
self.fexml.placeholder_for('./TipoNota', optional=True)
|
||||||
|
|
||||||
|
self.root_fragment = self.fexml
|
||||||
|
if xpath_ajuste is not None:
|
||||||
|
self.root_fragment = self.fexml.fragment(xpath_ajuste)
|
||||||
|
self.root_fragment.placeholder_for('./ReemplazandoPredecesor', optional=True)
|
||||||
|
self.root_fragment.placeholder_for('./EliminandoPredecesor', optional=True)
|
||||||
|
if not namespace_ajuste:
|
||||||
|
self.root_fragment.placeholder_for('./Novedad', optional=False)
|
||||||
|
self.root_fragment.placeholder_for('./Periodo')
|
||||||
|
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)
|
||||||
|
if not namespace_ajuste:
|
||||||
|
self.novedad = self.root_fragment.fragment('./Novedad')
|
||||||
|
else:
|
||||||
|
self.novedad = None
|
||||||
|
self.informacion_general_xml = self.root_fragment.fragment('./InformacionGeneral')
|
||||||
|
self.periodo_xml = self.root_fragment.fragment('./Periodo')
|
||||||
|
self.fecha_pagos_xml = self.root_fragment.fragment('./FechasPagos')
|
||||||
|
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')
|
||||||
|
self.empleador = self.root_fragment.fragment('./Empleador')
|
||||||
|
self.trabajador = self.root_fragment.fragment('./Trabajador')
|
||||||
|
self.pago_xml = self.root_fragment.fragment('./Pago')
|
||||||
|
self.devengados = self.root_fragment.fragment('./Devengados')
|
||||||
|
self.deducciones = self.root_fragment.fragment('./Deducciones')
|
||||||
|
|
||||||
|
self.informacion_general = None
|
||||||
|
self.metadata = None
|
||||||
|
|
||||||
|
def asignar_metadata(self, metadata):
|
||||||
|
if not isinstance(metadata, Metadata):
|
||||||
|
raise ValueError('se espera tipo Metadata')
|
||||||
|
self.metadata = metadata
|
||||||
|
|
||||||
|
self.metadata.apply(self.novedad, self.numero_secuencia_xml, self.lugar_generacion_xml, self.proveedor_xml)
|
||||||
|
|
||||||
|
def asignar_informacion_general(self, general):
|
||||||
|
if not isinstance(general, InformacionGeneral):
|
||||||
|
raise ValueError('se espera tipo InformacionGeneral')
|
||||||
|
self.informacion_general = general
|
||||||
|
self.informacion_general.apply(self.informacion_general_xml, self.informacion_general_version)
|
||||||
|
|
||||||
|
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, data):
|
||||||
|
if isinstance(data, str):
|
||||||
|
fecha = FechaPago(data)
|
||||||
|
elif isinstance(data, FechaPago):
|
||||||
|
fecha = data
|
||||||
|
|
||||||
|
fecha.apply(self.fecha_pagos_xml)
|
||||||
|
|
||||||
|
def asignar_empleador(self, empleador):
|
||||||
|
if not isinstance(empleador, Empleador):
|
||||||
|
raise ValueError('se espera tipo Empleador')
|
||||||
|
empleador.apply(self.empleador)
|
||||||
|
|
||||||
|
def asignar_trabajador(self, trabajador):
|
||||||
|
if not isinstance(trabajador, Trabajador):
|
||||||
|
raise ValueError('se espera tipo Trabajador')
|
||||||
|
trabajador.apply(self.trabajador)
|
||||||
|
|
||||||
|
def adicionar_devengado(self, devengado):
|
||||||
|
if not isinstance(devengado, Devengado):
|
||||||
|
raise ValueError('se espera tipo Devengado')
|
||||||
|
|
||||||
|
devengado.apply(self.devengados)
|
||||||
|
|
||||||
|
def adicionar_deduccion(self, deduccion):
|
||||||
|
if not isinstance(deduccion, Deduccion):
|
||||||
|
raise ValueError('se espera tipo Devengado')
|
||||||
|
|
||||||
|
deduccion.apply(self.deducciones)
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
"""
|
||||||
|
Valida requisitos segun anexo tecnico
|
||||||
|
"""
|
||||||
|
errors = []
|
||||||
|
|
||||||
|
def check_element(xpath, msg):
|
||||||
|
if not self.fexml.exist_element(xpath):
|
||||||
|
errors.append(DIANNominaIndividualError(msg))
|
||||||
|
|
||||||
|
def check_attribute(xpath, key, msg):
|
||||||
|
err = DIANNominaIndividualError(msg)
|
||||||
|
elem = self.fexml.get_element(xpath)
|
||||||
|
|
||||||
|
if elem is None:
|
||||||
|
return errors.append(err)
|
||||||
|
|
||||||
|
if elem.get(key, None) is None:
|
||||||
|
return errors.append(err)
|
||||||
|
|
||||||
|
check_attribute(
|
||||||
|
self.fexml.xpath_from_root('/Periodo'),
|
||||||
|
'FechaIngreso',
|
||||||
|
'se requiere Periodo')
|
||||||
|
|
||||||
|
check_element(
|
||||||
|
self.fexml.xpath_from_root('/Pago'),
|
||||||
|
'se requiere Pago'
|
||||||
|
)
|
||||||
|
|
||||||
|
check_element(
|
||||||
|
self.fexml.xpath_from_root('/Devengados/Basico'),
|
||||||
|
'se requiere DevengadoBasico'
|
||||||
|
)
|
||||||
|
|
||||||
|
check_element(
|
||||||
|
self.fexml.xpath_from_root('/Deducciones/Salud'),
|
||||||
|
'se requiere DeduccionSalud'
|
||||||
|
)
|
||||||
|
|
||||||
|
check_element(
|
||||||
|
self.fexml.xpath_from_root('/Deducciones/FondoPension'),
|
||||||
|
'se requiere DeduccionFondoPension'
|
||||||
|
)
|
||||||
|
|
||||||
|
return errors
|
||||||
|
|
||||||
|
def informacion_general(self):
|
||||||
|
xpath = self.root_fragment.xpath_from_root('/InformacionGeneral')
|
||||||
|
return {
|
||||||
|
'cune': self.fexml.get_element_attribute(cune_xpath, 'CUNE'),
|
||||||
|
'fecha_generacion': self.fexml.get_element_attribute(xpath, 'FechaGen'),
|
||||||
|
'numero': self.fexml.get_element_attribute(self.root_fragment('/NumeroSecuenciaXML', 'Numero'))
|
||||||
|
}
|
||||||
|
|
||||||
|
def toFachoXML(self):
|
||||||
|
self._devengados_total()
|
||||||
|
self._deducciones_total()
|
||||||
|
self._comprobante_total()
|
||||||
|
|
||||||
|
if self.informacion_general is not None:
|
||||||
|
#TODO(bit4bit) acoplamiento temporal
|
||||||
|
# es importante el orden de ejecucion
|
||||||
|
|
||||||
|
self.informacion_general.post_apply(self.fexml, self.root_fragment, self.informacion_general_xml)
|
||||||
|
|
||||||
|
if self.metadata is not None:
|
||||||
|
self.metadata.post_apply(self.fexml, self.root_fragment, self.novedad, self.numero_secuencia_xml, self.lugar_generacion_xml, self.proveedor_xml)
|
||||||
|
|
||||||
|
return self.fexml
|
||||||
|
|
||||||
|
def _comprobante_total(self):
|
||||||
|
devengados_total = self.root_fragment.get_element_text_or_attribute('./DevengadosTotal', '0.0')
|
||||||
|
deducciones_total = self.root_fragment.get_element_text_or_attribute('./DeduccionesTotal', '0.0')
|
||||||
|
|
||||||
|
comprobante_total = Amount(devengados_total) - Amount(deducciones_total)
|
||||||
|
|
||||||
|
self.root_fragment.set_element('./ComprobanteTotal', str(round(comprobante_total, 2)))
|
||||||
|
|
||||||
|
def _deducciones_total(self):
|
||||||
|
xpaths = [
|
||||||
|
self.root_fragment.xpath_from_root('/Deducciones/Salud/@Deduccion'),
|
||||||
|
self.root_fragment.xpath_from_root('/Deducciones/FondoPension/@Deduccion')
|
||||||
|
]
|
||||||
|
deducciones = map(lambda valor: Amount(valor),
|
||||||
|
self._values_of_xpaths(xpaths))
|
||||||
|
|
||||||
|
deducciones_total = Amount(0.0)
|
||||||
|
|
||||||
|
for deduccion in deducciones:
|
||||||
|
deducciones_total += deduccion
|
||||||
|
|
||||||
|
self.root_fragment.set_element('./DeduccionesTotal', str(round(deducciones_total, 2)))
|
||||||
|
|
||||||
|
def _devengados_total(self):
|
||||||
|
xpaths = [
|
||||||
|
self.root_fragment.xpath_from_root('/Devengados/Basico/@SueldoTrabajado'),
|
||||||
|
self.root_fragment.xpath_from_root('/Devengados/Transporte/@AuxilioTransporte'),
|
||||||
|
self.root_fragment.xpath_from_root('/Devengados/Transporte/@ViaticoManuAlojS'),
|
||||||
|
self.root_fragment.xpath_from_root('/Devengados/Transporte/@ViaticoManuAlojNS')
|
||||||
|
]
|
||||||
|
devengados = map(lambda valor: Amount(valor),
|
||||||
|
self._values_of_xpaths(xpaths))
|
||||||
|
|
||||||
|
devengados_total = Amount(0.0)
|
||||||
|
for devengado in devengados:
|
||||||
|
devengados_total += devengado
|
||||||
|
# TODO(bit4bit) nque valor va redondeado?
|
||||||
|
# NIE186
|
||||||
|
self.root_fragment.set_element('./Redondeo', str(round(0,2)))
|
||||||
|
self.root_fragment.set_element('./DevengadosTotal', str(round(devengados_total,2)))
|
||||||
|
|
||||||
|
def _values_of_xpaths(self, xpaths):
|
||||||
|
xpaths_values_of_values = map(lambda val: self.fexml.get_element_text_or_attribute(val, multiple=True), xpaths)
|
||||||
|
xpaths_values = []
|
||||||
|
# toda esta carreta para hacer un aplano de lista
|
||||||
|
for xpath_values in xpaths_values_of_values:
|
||||||
|
if xpath_values is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for xpath_value in xpath_values:
|
||||||
|
xpaths_values.append(xpath_value)
|
||||||
|
|
||||||
|
return filter(lambda val: val is not None, xpaths_values)
|
||||||
|
|
||||||
|
class DIANNominaIndividual(DIANNominaXML):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
schema = "dian:gov:co:facturaelectronica:NominaIndividual NominaIndividualElectronicaXSD.xsd"
|
||||||
|
|
||||||
|
super().__init__('NominaIndividual', schemaLocation=schema)
|
||||||
|
self.informacion_general_version = 'V1.0: Documento Soporte de Pago de Nómina Electrónica'
|
||||||
|
|
||||||
|
# TODO(bit4bit) confirmar que no tienen en comun con NominaIndividual
|
||||||
|
class DIANNominaIndividualDeAjuste(DIANNominaXML):
|
||||||
|
|
||||||
|
class Reemplazar(DIANNominaXML):
|
||||||
|
@dataclass
|
||||||
|
class Predecesor:
|
||||||
|
numero: str
|
||||||
|
cune: str
|
||||||
|
fecha_generacion: str
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
# NIAE214
|
||||||
|
fragment.set_element('./TipoNota', '1')
|
||||||
|
fragment.set_element('./Reemplazar/ReemplazandoPredecesor', None,
|
||||||
|
# NIAE090
|
||||||
|
NumeroPred = self.numero,
|
||||||
|
# NIAE191
|
||||||
|
CUNEPred = self.cune,
|
||||||
|
# NIAE192
|
||||||
|
FechaGenPred = self.fecha_generacion
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
schema = "dian:gov:co:facturaelectronica:NominaIndividualDeAjuste NominaIndividualDeAjusteElectronicaXSD.xsd"
|
||||||
|
|
||||||
|
super().__init__('NominaIndividualDeAjuste', './Reemplazar', schemaLocation=schema, namespace_ajuste='dian:gov:co:facturaelectronica:NominaIndividualDeAjuste')
|
||||||
|
|
||||||
|
self.informacion_general_version = 'V1.0: Nota de Ajuste de Documento Soporte de Pago de Nómina Electrónica'
|
||||||
|
|
||||||
|
def asignar_predecesor(self, predecesor):
|
||||||
|
if not isinstance(predecesor, self.Predecesor):
|
||||||
|
raise ValueError("se espera tipo Predecesor")
|
||||||
|
predecesor.apply(self.fexml)
|
||||||
|
|
||||||
|
|
||||||
|
class Eliminar(DIANNominaXML):
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Predecesor:
|
||||||
|
numero: str
|
||||||
|
cune: str
|
||||||
|
fecha_generacion: str
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
fragment.set_element('./TipoNota', '2')
|
||||||
|
fragment.set_element('./Eliminar/EliminandoPredecesor', None,
|
||||||
|
# NIAE090
|
||||||
|
NumeroPred = self.numero,
|
||||||
|
# NIAE191
|
||||||
|
CUNEPred = self.cune,
|
||||||
|
# NIAE192
|
||||||
|
FechaGenPred = self.fecha_generacion
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
schema = "dian:gov:co:facturaelectronica:NominaIndividualDeAjuste NominaIndividualDeAjusteElectronicaXSD.xsd"
|
||||||
|
super().__init__('NominaIndividualDeAjuste', './Eliminar', schemaLocation=schema, namespace_ajuste='dian:gov:co:facturaelectronica:NominaIndividualDeAjuste')
|
||||||
|
|
||||||
|
self.informacion_general_version = "V1.0: Nota de Ajuste de Documento Soporte de Pago de Nómina Electrónica"
|
||||||
|
|
||||||
|
def asignar_predecesor(self, predecesor):
|
||||||
|
if not isinstance(predecesor, self.Predecesor):
|
||||||
|
raise ValueError("se espera tipo Eliminar.Predecesor")
|
||||||
|
predecesor.apply(self.fexml)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__('NominaIndividualDeAjuste')
|
||||||
|
|
||||||
4
facho/fe/nomina/amount.py
Normal file
4
facho/fe/nomina/amount.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from .. import form
|
||||||
|
|
||||||
|
class Amount(form.Amount):
|
||||||
|
pass
|
||||||
3
facho/fe/nomina/deduccion/README.md
Normal file
3
facho/fe/nomina/deduccion/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# contributing
|
||||||
|
|
||||||
|
crear nuevo objeto de valor y exportar en **__init__.py** atributo **__all__**.
|
||||||
13
facho/fe/nomina/deduccion/__init__.py
Normal file
13
facho/fe/nomina/deduccion/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#
|
||||||
|
# al crear objetos de valor
|
||||||
|
# se debe exportar en __all__
|
||||||
|
|
||||||
|
from .deduccion import *
|
||||||
|
from .salud import *
|
||||||
|
from .fondo_pension import *
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'Deduccion',
|
||||||
|
'DeduccionSalud',
|
||||||
|
'DeduccionFondoPension'
|
||||||
|
]
|
||||||
2
facho/fe/nomina/deduccion/deduccion.py
Normal file
2
facho/fe/nomina/deduccion/deduccion.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
class Deduccion:
|
||||||
|
pass
|
||||||
18
facho/fe/nomina/deduccion/fondo_pension.py
Normal file
18
facho/fe/nomina/deduccion/fondo_pension.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from ..amount import Amount
|
||||||
|
from .deduccion import Deduccion
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DeduccionFondoPension(Deduccion):
|
||||||
|
porcentaje: Amount
|
||||||
|
deduccion: Amount
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
fragment.set_element('./FondoPension', None,
|
||||||
|
append_ = True,
|
||||||
|
# NIE164
|
||||||
|
Porcentaje = str(round(self.porcentaje, 2)),
|
||||||
|
# NIE166
|
||||||
|
Deduccion = self.deduccion
|
||||||
|
)
|
||||||
19
facho/fe/nomina/deduccion/salud.py
Normal file
19
facho/fe/nomina/deduccion/salud.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from ..amount import Amount
|
||||||
|
from .deduccion import Deduccion
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DeduccionSalud(Deduccion):
|
||||||
|
porcentaje: Amount
|
||||||
|
deduccion: Amount
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
fragment.set_element('./Salud', None,
|
||||||
|
append_ = True,
|
||||||
|
# NIE161
|
||||||
|
Porcentaje = str(round(self.porcentaje, 2)),
|
||||||
|
# NIE163
|
||||||
|
Deduccion = self.deduccion
|
||||||
|
)
|
||||||
|
|
||||||
4
facho/fe/nomina/departamento.py
Normal file
4
facho/fe/nomina/departamento.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from .. import form
|
||||||
|
|
||||||
|
class Departamento(form.CountrySubentity):
|
||||||
|
pass
|
||||||
3
facho/fe/nomina/devengado/README.md
Normal file
3
facho/fe/nomina/devengado/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# contributing
|
||||||
|
|
||||||
|
crear nuevo objeto de valor y exportar en **__init__.py** atributo **__all__**.
|
||||||
19
facho/fe/nomina/devengado/__init__.py
Normal file
19
facho/fe/nomina/devengado/__init__.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
from .basico import *
|
||||||
|
from .transporte import *
|
||||||
|
from .devengado import *
|
||||||
|
from .horas_extras import *
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'Devengado',
|
||||||
|
'DevengadoBasico',
|
||||||
|
'DevengadoTransporte',
|
||||||
|
'DevengadoHoraExtra',
|
||||||
|
'DevengadoHorasExtrasDiarias',
|
||||||
|
'DevengadoHorasExtrasNocturnas',
|
||||||
|
'DevengadoHorasRecargoNocturno',
|
||||||
|
'DevengadoHorasExtrasDiariasDominicalesYFestivos',
|
||||||
|
'DevengadoHorasRecargoDiariasDominicalesYFestivos',
|
||||||
|
'DevengadoHorasExtrasNocturnasDominicalesYFestivos',
|
||||||
|
'DevengadoHorasRecargoNocturnoDominicalesYFestivos'
|
||||||
|
]
|
||||||
20
facho/fe/nomina/devengado/basico.py
Normal file
20
facho/fe/nomina/devengado/basico.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from ..amount import Amount
|
||||||
|
from .devengado import Devengado
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DevengadoBasico(Devengado):
|
||||||
|
dias_trabajados: int
|
||||||
|
sueldo_trabajado: Amount
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
fragment.find_or_create_element('./Basico')
|
||||||
|
|
||||||
|
fragment.set_attributes('/Basico',
|
||||||
|
# NIE069
|
||||||
|
DiasTrabajados = str(self.dias_trabajados),
|
||||||
|
# NIE070
|
||||||
|
SueldoTrabajado = round(self.sueldo_trabajado, 2)
|
||||||
|
)
|
||||||
2
facho/fe/nomina/devengado/devengado.py
Normal file
2
facho/fe/nomina/devengado/devengado.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
class Devengado:
|
||||||
|
pass
|
||||||
93
facho/fe/nomina/devengado/horas_extras.py
Normal file
93
facho/fe/nomina/devengado/horas_extras.py
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from ..amount import Amount
|
||||||
|
from .devengado import Devengado
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DevengadoHoraExtra:
|
||||||
|
hora_inicio: str
|
||||||
|
hora_fin: str
|
||||||
|
cantidad: int
|
||||||
|
porcentaje: Amount
|
||||||
|
pago: Amount
|
||||||
|
|
||||||
|
def apply(self, child_path, fragment):
|
||||||
|
fragment.set_element(child_path, None,
|
||||||
|
append_=True,
|
||||||
|
# NIE074
|
||||||
|
HoraInicio=self.hora_inicio,
|
||||||
|
# NIE075
|
||||||
|
HoraFin=self.hora_fin,
|
||||||
|
# NIE076
|
||||||
|
Cantidad=self.cantidad,
|
||||||
|
# NIE077
|
||||||
|
Porcentaje=str(round(self.porcentaje, 2)),
|
||||||
|
# NIE078
|
||||||
|
Pago=str(round(self.pago, 2)))
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DevengadoHorasExtrasDiarias(Devengado):
|
||||||
|
horas_extras: List[DevengadoHoraExtra]
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
hora_extra_xml = fragment.fragment('./HEDs')
|
||||||
|
for hora_extra in self.horas_extras:
|
||||||
|
hora_extra.apply('./HED', hora_extra_xml)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DevengadoHorasExtrasNocturnas(Devengado):
|
||||||
|
horas_extras: List[DevengadoHoraExtra]
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
hora_extra_xml = fragment.fragment('./HENs')
|
||||||
|
for hora_extra in self.horas_extras:
|
||||||
|
hora_extra.apply('./HEN', hora_extra_xml)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DevengadoHorasRecargoNocturno(Devengado):
|
||||||
|
horas_extras: List[DevengadoHoraExtra]
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
hora_extra_xml = fragment.fragment('./HRNs')
|
||||||
|
for hora_extra in self.horas_extras:
|
||||||
|
hora_extra.apply('./HRN', hora_extra_xml)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DevengadoHorasExtrasDiariasDominicalesYFestivos(Devengado):
|
||||||
|
horas_extras: List[DevengadoHoraExtra]
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
hora_extra_xml = fragment.fragment('./HEDDFs')
|
||||||
|
for hora_extra in self.horas_extras:
|
||||||
|
hora_extra.apply('./HEDDF', hora_extra_xml)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DevengadoHorasRecargoDiariasDominicalesYFestivos(Devengado):
|
||||||
|
horas_extras: List[DevengadoHoraExtra]
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
hora_extra_xml = fragment.fragment('./HRDDFs')
|
||||||
|
for hora_extra in self.horas_extras:
|
||||||
|
hora_extra.apply('./HRDDF', hora_extra_xml)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DevengadoHorasExtrasNocturnasDominicalesYFestivos(Devengado):
|
||||||
|
horas_extras: List[DevengadoHoraExtra]
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
hora_extra_xml = fragment.fragment('./HENDFs')
|
||||||
|
for hora_extra in self.horas_extras:
|
||||||
|
hora_extra.apply('./HENDF', hora_extra_xml)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DevengadoHorasRecargoNocturnoDominicalesYFestivos(Devengado):
|
||||||
|
horas_extras: List[DevengadoHoraExtra]
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
hora_extra_xml = fragment.fragment('./HRNDFs')
|
||||||
|
for hora_extra in self.horas_extras:
|
||||||
|
hora_extra.apply('./HRNDF', hora_extra_xml)
|
||||||
21
facho/fe/nomina/devengado/transporte.py
Normal file
21
facho/fe/nomina/devengado/transporte.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from ..amount import Amount
|
||||||
|
from .devengado import Devengado
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class DevengadoTransporte(Devengado):
|
||||||
|
auxilio_transporte: Amount = None
|
||||||
|
viatico_manutencion: Amount = None
|
||||||
|
viatico_manutencion_no_salarial: Amount = None
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
fragment.set_element('./Transporte', None,
|
||||||
|
append_ = True,
|
||||||
|
# NIE071
|
||||||
|
AuxilioTransporte = self.auxilio_transporte,
|
||||||
|
# NIE072
|
||||||
|
ViaticoManuAlojS = self.viatico_manutencion,
|
||||||
|
# NIE073
|
||||||
|
ViaticoManuAlojNS = self.viatico_manutencion_no_salarial
|
||||||
|
)
|
||||||
35
facho/fe/nomina/empleador/__init__.py
Normal file
35
facho/fe/nomina/empleador/__init__.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from ..pais import Pais
|
||||||
|
from ..departamento import Departamento
|
||||||
|
from ..municipio import Municipio
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Empleador:
|
||||||
|
razon_social: str
|
||||||
|
nit: str
|
||||||
|
dv: str
|
||||||
|
pais: Pais
|
||||||
|
departamento: Departamento
|
||||||
|
municipio: Municipio
|
||||||
|
direccion: str
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
fragment.set_attributes('./Empleador',
|
||||||
|
# NIE033
|
||||||
|
NIT = self.nit,
|
||||||
|
# NIE034
|
||||||
|
DV = self.dv,
|
||||||
|
# NIE035
|
||||||
|
Pais = self.pais.code,
|
||||||
|
# NIE036
|
||||||
|
DepartamentoEstado = self.departamento.code,
|
||||||
|
# NIE037
|
||||||
|
MunicipioCiudad = self.municipio.code,
|
||||||
|
# NIE038
|
||||||
|
Direccion = self.direccion,
|
||||||
|
|
||||||
|
RazonSocial=self.razon_social
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
2
facho/fe/nomina/exception.py
Normal file
2
facho/fe/nomina/exception.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
class DIANNominaIndividualError(Exception):
|
||||||
|
pass
|
||||||
155
facho/fe/nomina/hablitacion.py
Normal file
155
facho/fe/nomina/hablitacion.py
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from facho import fe
|
||||||
|
|
||||||
|
class Habilitacion:
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Metadata:
|
||||||
|
software_pin: str
|
||||||
|
software_id: str
|
||||||
|
nit: str
|
||||||
|
dv: str
|
||||||
|
|
||||||
|
def __init__(self, metadata):
|
||||||
|
self.metadata = metadata
|
||||||
|
|
||||||
|
def generar(self, zipname, fecha):
|
||||||
|
nominas = []
|
||||||
|
dianzip = fe.DianZIP(open(zipname, 'w'))
|
||||||
|
|
||||||
|
fechabase = datetime.datetime.now()
|
||||||
|
consecutivo = 0
|
||||||
|
for _ in range(1, 11):
|
||||||
|
consecutivo += 1
|
||||||
|
fechabase += datetime.timedelta(days=1)
|
||||||
|
nomina = self._crear_nomina_individual()
|
||||||
|
|
||||||
|
# pag 96
|
||||||
|
nombre = "nie%010d%s%08x.xml" % (int(self.nit), fecha.strftime('%s'), consecutivo)
|
||||||
|
|
||||||
|
def _crear_nomina_individual_reemplazar(self, nomina, fechabase):
|
||||||
|
metadata = self.metadata
|
||||||
|
|
||||||
|
fecha = fechabase.strftime('%Y-%m-%d')
|
||||||
|
|
||||||
|
nomina_ajuste = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
|
||||||
|
self._poblar_nomina(nomina_ajuste, metadata, fecha, prefijo='R')
|
||||||
|
informacion_general = nomina.informacion_general()
|
||||||
|
|
||||||
|
|
||||||
|
def _poblar_nomina(self, nomina, metadata, fecha, prefijo='N', consecutivo='0001'):
|
||||||
|
nomina.asignar_fecha_pago(fecha)
|
||||||
|
|
||||||
|
nomina.asignar_metadata(fe.nomina.Metadata(
|
||||||
|
secuencia=fe.nomina.NumeroSecuencia(
|
||||||
|
prefijo=prefijo,
|
||||||
|
consecutivo=consecutivo
|
||||||
|
),
|
||||||
|
lugar_generacion=fe.nomina.Lugar(
|
||||||
|
pais = fe.nomina.Pais(
|
||||||
|
code = 'CO'
|
||||||
|
),
|
||||||
|
departamento = fe.nomina.Departamento(
|
||||||
|
code = '05'
|
||||||
|
),
|
||||||
|
municipio = fe.nomina.Municipio(
|
||||||
|
code = '05001'
|
||||||
|
),
|
||||||
|
),
|
||||||
|
proveedor=fe.nomina.Proveedor(
|
||||||
|
nit=metadata.nit,
|
||||||
|
dv=metadata.dv,
|
||||||
|
software_id=metadata.software_id,
|
||||||
|
software_pin=metadata.software_pin
|
||||||
|
)
|
||||||
|
))
|
||||||
|
|
||||||
|
nomina.asignar_periodo(fe.nomina.Periodo(
|
||||||
|
fecha_ingreso=fecha,
|
||||||
|
fecha_liquidacion_inicio=fecha,
|
||||||
|
fecha_liquidacion_fin=fecha,
|
||||||
|
fecha_generacion=fecha,
|
||||||
|
))
|
||||||
|
|
||||||
|
nomina.asignar_informacion_general(fe.nomina.InformacionGeneral(
|
||||||
|
fecha_generacion = fecha,
|
||||||
|
hora_generacion = '20:09:00-05:00',
|
||||||
|
tipo_ambiente = fe.nomina.InformacionGeneral.AMBIENTE_PRUEBAS,
|
||||||
|
software_pin = metadata.software_pin,
|
||||||
|
periodo_nomina = fe.nomina.PeriodoNomina(code='1'),
|
||||||
|
tipo_moneda = fe.nomina.TipoMoneda(code='COP')
|
||||||
|
))
|
||||||
|
|
||||||
|
nomina.asignar_pago(fe.nomina.Pago(
|
||||||
|
forma=fe.nomina.FormaPago(
|
||||||
|
code='1',
|
||||||
|
),
|
||||||
|
metodo=fe.nomina.MetodoPago(
|
||||||
|
code='10'
|
||||||
|
)
|
||||||
|
))
|
||||||
|
nomina.asignar_empleador(fe.nomina.Empleador(
|
||||||
|
nit = metadata.nit,
|
||||||
|
dv = '0',
|
||||||
|
pais = fe.nomina.Pais(
|
||||||
|
code = 'CO'
|
||||||
|
),
|
||||||
|
departamento = fe.nomina.Departamento(
|
||||||
|
code = '05'
|
||||||
|
),
|
||||||
|
municipio = fe.nomina.Municipio(
|
||||||
|
code = '05001'
|
||||||
|
),
|
||||||
|
direccion = 'calle etrivial'
|
||||||
|
))
|
||||||
|
|
||||||
|
nomina.asignar_trabajador(fe.nomina.Trabajador(
|
||||||
|
tipo_contrato = fe.nomina.TipoContrato(
|
||||||
|
code = '1'
|
||||||
|
),
|
||||||
|
alto_riesgo = False,
|
||||||
|
tipo_documento = fe.nomina.TipoDocumento(
|
||||||
|
code = '11'
|
||||||
|
),
|
||||||
|
primer_apellido = 'gnu',
|
||||||
|
segundo_apellido = 'emacs',
|
||||||
|
primer_nombre = 'facho',
|
||||||
|
lugar_trabajo = fe.nomina.LugarTrabajo(
|
||||||
|
pais = fe.nomina.Pais(code='CO'),
|
||||||
|
departamento = fe.nomina.Departamento(code='05'),
|
||||||
|
municipio = fe.nomina.Municipio(code='05001'),
|
||||||
|
direccion = 'calle facho'
|
||||||
|
),
|
||||||
|
numero_documento = metadata.nit,
|
||||||
|
tipo = fe.nomina.TipoTrabajador(
|
||||||
|
code = '01'
|
||||||
|
),
|
||||||
|
salario_integral = True,
|
||||||
|
sueldo = fe.nomina.Amount(1_500_000)
|
||||||
|
))
|
||||||
|
|
||||||
|
nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
|
||||||
|
dias_trabajados = 60,
|
||||||
|
sueldo_trabajado = fe.nomina.Amount(3_500_000)
|
||||||
|
))
|
||||||
|
|
||||||
|
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||||
|
porcentaje = fe.nomina.Amount(19),
|
||||||
|
deduccion = fe.nomina.Amount(1_000_000)
|
||||||
|
))
|
||||||
|
|
||||||
|
nomina.adicionar_deduccion(fe.nomina.DeduccionFondoPension(
|
||||||
|
porcentaje=fe.nomina.Amount(1),
|
||||||
|
deduccion=fe.nomina.Amount(10)
|
||||||
|
))
|
||||||
|
|
||||||
|
def _crear_nomina_individual(self, fechabase):
|
||||||
|
metadata = self.metadata
|
||||||
|
|
||||||
|
fecha = fechabase.strftime('%Y-%m-%d')
|
||||||
|
|
||||||
|
nomina = fe.nomina.DIANNominaIndividual()
|
||||||
|
self._poblar_nomina(nomina, metadata, fecha)
|
||||||
|
|
||||||
25
facho/fe/nomina/lugar.py
Normal file
25
facho/fe/nomina/lugar.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from .pais import Pais
|
||||||
|
from .departamento import Departamento
|
||||||
|
from .municipio import Municipio
|
||||||
|
from facho.fe.data.dian import codelist
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Lugar:
|
||||||
|
pais: Pais
|
||||||
|
departamento: Departamento
|
||||||
|
municipio: Municipio
|
||||||
|
idioma: str = 'es'
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if self.idioma not in codelist.IdiomaISO6391:
|
||||||
|
raise ValueError("idioma [%s] not found" % (self.code))
|
||||||
|
codelist.IdiomaISO6391[self.idioma]['iso-639-1']
|
||||||
|
|
||||||
|
def apply(self, fragment, root):
|
||||||
|
fragment.set_attributes(root,
|
||||||
|
Pais=self.pais.code,
|
||||||
|
DepartamentoEstado=self.departamento.code,
|
||||||
|
MunicipioCiudad=self.municipio.code,
|
||||||
|
Idioma=self.idioma)
|
||||||
5
facho/fe/nomina/municipio.py
Normal file
5
facho/fe/nomina/municipio.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
from .. import form
|
||||||
|
|
||||||
|
class Municipio(form.City):
|
||||||
|
pass
|
||||||
|
|
||||||
16
facho/fe/nomina/pago/__init__.py
Normal file
16
facho/fe/nomina/pago/__init__.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from .forma_pago import FormaPago
|
||||||
|
from .metodo_pago import MetodoPago
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Pago:
|
||||||
|
forma: FormaPago
|
||||||
|
metodo: MetodoPago
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
fragment.set_attributes('./Pago',
|
||||||
|
# NIE064
|
||||||
|
Forma = self.forma.code,
|
||||||
|
# NIE065
|
||||||
|
Metodo = self.metodo.code)
|
||||||
13
facho/fe/nomina/pago/forma_pago.py
Normal file
13
facho/fe/nomina/pago/forma_pago.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from facho.fe.data.dian import codelist
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class FormaPago:
|
||||||
|
code: str
|
||||||
|
name: str = ''
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if self.code not in codelist.FormasPago:
|
||||||
|
raise ValueError("code [%s] not found" % (self.code))
|
||||||
|
self.name = codelist.FormasPago[self.code]['name']
|
||||||
14
facho/fe/nomina/pago/metodo_pago.py
Normal file
14
facho/fe/nomina/pago/metodo_pago.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from facho.fe.data.dian import codelist
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MetodoPago:
|
||||||
|
code: str
|
||||||
|
name: str = ''
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
if self.code not in codelist.MediosPago:
|
||||||
|
raise ValueError("code [%s] not found" % (self.code))
|
||||||
|
self.name = codelist.MediosPago[self.code]['name']
|
||||||
|
|
||||||
4
facho/fe/nomina/pais.py
Normal file
4
facho/fe/nomina/pais.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
from .. import form
|
||||||
|
|
||||||
|
class Pais(form.Country):
|
||||||
|
pass
|
||||||
73
facho/fe/nomina/trabajador/__init__.py
Normal file
73
facho/fe/nomina/trabajador/__init__.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
from dataclasses import dataclass, field
|
||||||
|
|
||||||
|
from ..amount import Amount
|
||||||
|
|
||||||
|
from .tipo_contrato import *
|
||||||
|
from .tipo_documento import *
|
||||||
|
from .lugar_trabajo import *
|
||||||
|
from .tipo_trabajador import *
|
||||||
|
from .sub_tipo_trabajador import *
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Trabajador:
|
||||||
|
tipo_contrato: TipoContrato
|
||||||
|
tipo_documento: TipoDocumento
|
||||||
|
numero_documento: str
|
||||||
|
|
||||||
|
primer_apellido: str
|
||||||
|
segundo_apellido: str
|
||||||
|
primer_nombre: str
|
||||||
|
|
||||||
|
lugar_trabajo: LugarTrabajo
|
||||||
|
alto_riesgo: bool
|
||||||
|
salario_integral: bool
|
||||||
|
sueldo: Amount
|
||||||
|
|
||||||
|
tipo: TipoTrabajador
|
||||||
|
|
||||||
|
codigo_trabajador: str = None
|
||||||
|
otros_nombres: str = None
|
||||||
|
sub_tipo: SubTipoTrabajador = field(default_factory=lambda: SubTipoTrabajador(code='00'))
|
||||||
|
|
||||||
|
def apply(self, fragment):
|
||||||
|
fragment.set_attributes('./Trabajador',
|
||||||
|
# NIE041
|
||||||
|
TipoTrabajador = self.tipo.code,
|
||||||
|
# NIE042
|
||||||
|
SubTipoTrabajador = self.sub_tipo.code,
|
||||||
|
# NIE043
|
||||||
|
AltoRiesgoPension = str(self.alto_riesgo).lower(),
|
||||||
|
# NIE044
|
||||||
|
TipoDocumento = self.tipo_documento.code,
|
||||||
|
# NIE045
|
||||||
|
NumeroDocumento = self.numero_documento,
|
||||||
|
# NIE046
|
||||||
|
PrimerApellido = self.primer_apellido,
|
||||||
|
# NIE047
|
||||||
|
SegundoApellido = self.segundo_apellido,
|
||||||
|
# NIE048
|
||||||
|
PrimerNombre = self.primer_nombre,
|
||||||
|
# NIE049
|
||||||
|
OtrosNombres = self.otros_nombres,
|
||||||
|
# NIE050
|
||||||
|
LugarTrabajoPais = self.lugar_trabajo.pais.code,
|
||||||
|
|
||||||
|
# NIE051
|
||||||
|
LugarTrabajoDepartamentoEstado = self.lugar_trabajo.departamento.code,
|
||||||
|
|
||||||
|
# NIE052
|
||||||
|
LugarTrabajoMunicipioCiudad = self.lugar_trabajo.municipio.code,
|
||||||
|
|
||||||
|
# NIE053
|
||||||
|
LugarTrabajoDireccion = self.lugar_trabajo.direccion,
|
||||||
|
# NIE056
|
||||||
|
SalarioIntegral = str(self.salario_integral).lower(),
|
||||||
|
# NIE061
|
||||||
|
TipoContrato = self.tipo_contrato.code,
|
||||||
|
# NIE062
|
||||||
|
Sueldo = str(self.sueldo),
|
||||||
|
# NIE063
|
||||||
|
CodigoTrabajador = self.codigo_trabajador
|
||||||
|
)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user