Compare commits
3 Commits
main
...
NominaHabi
Author | SHA1 | Date | |
---|---|---|---|
e539f1e0a7 | |||
7972a3f59c | |||
20d8f4284f |
@ -94,14 +94,6 @@ Ready to contribute? Here's how to set up `facho` for local development.
|
||||
|
||||
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
|
||||
-----------------------
|
||||
|
||||
|
35
Dockerfile
35
Dockerfile
@ -1,24 +1,17 @@
|
||||
# DERIVADO DE https://alextereshenkov.github.io/run-python-tests-with-tox-in-docker.html
|
||||
FROM ubuntu:24.04
|
||||
FROM ubuntu:18.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 \
|
||||
python3.7 python3.7-distutils python3.7-dev \
|
||||
python3.8 python3.8-distutils python3.8-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 \
|
||||
&& python3 get-pip.py pip==21.3 \
|
||||
&& python3.7 get-pip.py pip==21.3 \
|
||||
&& python3.8 get-pip.py pip==21.3 \
|
||||
&& rm get-pip.py
|
||||
|
||||
RUN apt-get install -y --no-install-recommends \
|
||||
@ -27,14 +20,12 @@ RUN apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
zip
|
||||
|
||||
RUN python3.9 --version
|
||||
RUN python3.10 --version
|
||||
RUN python3.11 --version
|
||||
RUN python3.12 --version
|
||||
RUN python3.6 --version
|
||||
RUN python3.7 --version
|
||||
RUN python3.8 --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.6 install setuptools setuptools-rust
|
||||
RUN pip3.7 install setuptools setuptools-rust
|
||||
RUN pip3.8 install setuptools setuptools-rust
|
||||
|
||||
RUN pip3 install tox pytest --break-system-packages
|
||||
RUN pip3 install tox pytest
|
||||
|
@ -11,11 +11,14 @@
|
||||
dev-setup:
|
||||
docker build -t facho .
|
||||
|
||||
py-develop:
|
||||
docker run -t -v $(PWD):/app -w /app facho sh -c 'python3.7 setup.py develop --user'
|
||||
|
||||
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'
|
||||
docker run -t -v $(PWD):/app -w /app facho sh -c 'cd /app; python3.7 setup.py test'
|
||||
|
||||
tox:
|
||||
docker run -it -v $(PWD)/:/app -w /app facho tox
|
||||
|
@ -14,7 +14,7 @@ from facho.fe import fe
|
||||
from datetime import datetime, date
|
||||
|
||||
# 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
|
||||
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
|
||||
@ -36,7 +36,6 @@ def extensions(inv):
|
||||
'SETP', 990000000, 995000000)#del SET de pruebas
|
||||
return [security_code, authorization_provider, cufe, software_provider, inv_authorization]
|
||||
|
||||
|
||||
def invoice():
|
||||
# factura de venta nacional
|
||||
inv = form.Invoice('01')
|
||||
@ -50,17 +49,16 @@ def invoice():
|
||||
inv.set_operation_type('10')
|
||||
inv.set_supplier(form.Party(
|
||||
legal_name = 'Nombre registrado de la empresa',
|
||||
name='Nombre comercial o él mismo nombre registrado',
|
||||
ident=form.PartyIdentification(
|
||||
'nit_empresa', 'digito_verificación', '31'),
|
||||
name = 'Nombre comercial o él mismo nombre registrado',
|
||||
ident = form.PartyIdentification('nit_empresa', 'digito_verificación', '31'),
|
||||
# obligaciones del contribuyente ver DIAN:FAK26
|
||||
responsability_code=form.Responsability(['ZZ', 'O-14', 'O-48']),
|
||||
responsability_code = form.Responsability(['O-07', 'O-14', 'O-48']),
|
||||
# ver DIAN:FAJ28
|
||||
responsability_regime_code='48',
|
||||
responsability_regime_code = '48',
|
||||
# tipo de organizacion juridica ver DIAN:6.2.3
|
||||
organization_code='1',
|
||||
email="correoempresa@correoempresa.correo",
|
||||
address=form.Address(
|
||||
organization_code = '1',
|
||||
email = "correoempresa@correoempresa.correo",
|
||||
address = form.Address(
|
||||
'', '', form.City('05001', 'Medellín'),
|
||||
form.Country('CO', 'Colombia'),
|
||||
form.CountrySubentity('05', 'Antioquia')),
|
||||
@ -78,43 +76,42 @@ def invoice():
|
||||
'', '', form.City('05001', 'Medellín'),
|
||||
form.Country('CO', 'Colombia'),
|
||||
form.CountrySubentity('05', 'Antioquia')),
|
||||
# tax_scheme = form.TaxScheme('01', 'IVA')
|
||||
#tax_scheme = form.TaxScheme('01', 'IVA')
|
||||
))
|
||||
# asignar metodo de pago
|
||||
inv.set_payment_mean(form.PaymentMean(
|
||||
# metodo de pago ver DIAN:3.4.1
|
||||
id='1',
|
||||
# codigocorrespondientealmediodepagoverDIAN:3.4.2
|
||||
code='20',
|
||||
# fechadevencimientodelafactura
|
||||
due_at=datetime.now(),
|
||||
# identificadornumerico
|
||||
payment_id='2'
|
||||
id = '1',
|
||||
# codigo correspondiente al medio de pago ver DIAN:3.4.2
|
||||
code = '20',
|
||||
# fecha de vencimiento de la factura
|
||||
due_at = datetime.now(),
|
||||
# identificador numerico
|
||||
payment_id = '2'
|
||||
))
|
||||
# adicionar una linea al documento
|
||||
inv.add_invoice_line(
|
||||
form.InvoiceLine(
|
||||
quantity=form.Quantity(int(20.5), '94'),
|
||||
# item general de codigo 999
|
||||
description='productO3',
|
||||
sitem=form.StandardItem('test', 9999),
|
||||
price=form.Price(
|
||||
# precio base del item (sin iva)
|
||||
amount=form.Amount(200.00),
|
||||
# ver DIAN:6.3.5.1
|
||||
type_code='01',
|
||||
type='x'
|
||||
),
|
||||
tax=form.TaxTotal(
|
||||
subtotals=[
|
||||
form.TaxSubTotal(
|
||||
percent=19.00,
|
||||
scheme=form.TaxScheme('01')
|
||||
)]
|
||||
)
|
||||
))
|
||||
inv.add_invoice_line(form.InvoiceLine(
|
||||
quantity = form.Quantity(int(20.5), '94'),
|
||||
# item general de codigo 999
|
||||
description = 'productO3',
|
||||
item = form.StandardItem('test', 9999),
|
||||
price = form.Price(
|
||||
# precio base del item (sin iva)
|
||||
amount = form.Amount(200.00),
|
||||
# ver DIAN:6.3.5.1
|
||||
type_code = '01',
|
||||
type = 'x'
|
||||
),
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
percent = 19.00,
|
||||
scheme=form.TaxScheme('01')
|
||||
)
|
||||
]
|
||||
)
|
||||
))
|
||||
return inv
|
||||
|
||||
|
||||
def document_xml():
|
||||
return form_xml.DIANInvoiceXML
|
||||
|
123
examples/habilitacion/N000001.py
Normal file
123
examples/habilitacion/N000001.py
Normal file
@ -0,0 +1,123 @@
|
||||
|
||||
from facho import fe
|
||||
|
||||
SOFTWARE_PIN='20234'
|
||||
SOFTWARE_ID='100b0d10-0ca0-4ad4-a894-b704a568cbf3'
|
||||
NIT='901575528'
|
||||
DV='2'
|
||||
|
||||
def extensions(nomina):
|
||||
return []
|
||||
|
||||
def nomina():
|
||||
nomina = fe.nomina.DIANNominaIndividual()
|
||||
|
||||
nomina.asignar_fecha_pago('2024-04-30')
|
||||
|
||||
nomina.asignar_metadata(fe.nomina.Metadata(
|
||||
novedad=fe.nomina.Novedad(value='false'),
|
||||
secuencia=fe.nomina.NumeroSecuencia(
|
||||
prefijo='N',
|
||||
consecutivo='000001'
|
||||
),
|
||||
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(
|
||||
razon_social='BICI PIZZA S.A.S',
|
||||
nit=NIT,
|
||||
dv=DV,
|
||||
software_id=SOFTWARE_ID,
|
||||
software_pin=SOFTWARE_PIN
|
||||
)
|
||||
))
|
||||
|
||||
nomina.asignar_periodo(fe.nomina.Periodo(
|
||||
fecha_ingreso= '2022-01-05',
|
||||
fecha_liquidacion_inicio='2024-04-01',
|
||||
fecha_liquidacion_fin='2024-04-30',
|
||||
fecha_generacion='2024-04-30'
|
||||
))
|
||||
|
||||
nomina.asignar_informacion_general(fe.nomina.InformacionGeneral(
|
||||
fecha_generacion = '2024-04-30',
|
||||
hora_generacion = '08:01:00-05:00',
|
||||
tipo_ambiente = fe.nomina.InformacionGeneral.AMBIENTE_PRUEBAS,
|
||||
software_pin = 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(
|
||||
razon_social='BICI PIZZA S.A.S',
|
||||
nit = NIT,
|
||||
dv = DV,
|
||||
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 = 'GONZALEZ',
|
||||
segundo_apellido = '',
|
||||
primer_nombre = 'JUAN',
|
||||
lugar_trabajo = fe.nomina.LugarTrabajo(
|
||||
pais = fe.nomina.Pais(code='CO'),
|
||||
departamento = fe.nomina.Departamento(code='05'),
|
||||
municipio = fe.nomina.Municipio(code='05001'),
|
||||
direccion = 'CL 35C 102-17 BL 7 AP 101'
|
||||
),
|
||||
numero_documento = NIT,
|
||||
tipo = fe.nomina.TipoTrabajador(
|
||||
code = '01'
|
||||
),
|
||||
salario_integral = False,
|
||||
sueldo = fe.nomina.Amount(2400000)
|
||||
))
|
||||
|
||||
nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
|
||||
dias_trabajados = 30,
|
||||
sueldo_trabajado = fe.nomina.Amount(2400000)
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||
porcentaje = fe.nomina.Amount(4),
|
||||
deduccion = fe.nomina.Amount(96000)
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionFondoPension(
|
||||
porcentaje=fe.nomina.Amount(4),
|
||||
deduccion = fe.nomina.Amount(96000)
|
||||
))
|
||||
return nomina
|
||||
|
89
examples/habilitacion/N000001.xml
Normal file
89
examples/habilitacion/N000001.xml
Normal file
@ -0,0 +1,89 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<NominaIndividual xmlns:atd="urn:oasis:names:specification:ubl:schema:xsd:AttachedDocument-2" xmlns="dian:gov:co:facturaelectronica:NominaIndividual" xmlns:fe="http://www.dian.gov.co/contratos/facturaelectronica/v1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" 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="dian:gov:co:facturaelectronica:Structures-2-1" 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:xades141="http://uri.etsi.org/01903/v1.4.1#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:sig="http://www.w3.org/2000/09/xmldsig#" SchemaLocation="" xsi:schemaLocation="dian:gov:co:facturaelectronica:NominaIndividual NominaIndividualElectronicaXSD.xsd"><ext:UBLExtensions><ext:UBLExtension><ext:ExtensionContent><ds:Signature Id="xmlsig-2e62ccd5-82d2-4922-90a0-31af30fc44c0">
|
||||
<ds:SignedInfo>
|
||||
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
||||
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
|
||||
<ds:Reference Id="xmldsig-2e62ccd5-82d2-4922-90a0-31af30fc44c0-ref0" URI="">
|
||||
<ds:Transforms>
|
||||
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
||||
</ds:Transforms>
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||
<ds:DigestValue>HS3rmJgPKyCNLNO3TXfP0s1zIGvJTjq40JfMm/muHLA=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
<ds:Reference Id="xmldsig-2e62ccd5-82d2-4922-90a0-31af30fc44c0-ref1" URI="#xmldsig-2e62ccd5-82d2-4922-90a0-31af30fc44c0-KeyInfo">
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||
<ds:DigestValue>88R+0zjb6NIUiHhT8EE1ale8bO+TR6SSQBtVQUYkZ6c=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
<ds:Reference URI="#xmldsig-2e62ccd5-82d2-4922-90a0-31af30fc44c0-signedprops" Type="http://uri.etsi.org/01903#SignedProperties">
|
||||
<ds:Transforms>
|
||||
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
||||
</ds:Transforms>
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||
<ds:DigestValue>QF0d+RznylwnbFaGclqPWLndUo35HVDouEYoS1wfVO8=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
</ds:SignedInfo>
|
||||
<ds:SignatureValue>0JBFsBhyo4r/9m5vuBXbKirHOgniDNeGW3RNXpCE/sgXvrV3E4K8/M4HeO0VYtM0
|
||||
G4bHvvkP2NCkdrKgZ9gB+XG8E/rEmJnwKpHm2kaNnpM1pYGoqBNWpqCa5FnUsEk4
|
||||
c4BmBaKjmBSUrz+2JoOg1RKaaJumqGWm83IjWWJq9b4l40imL0XIgoTmWUtIGOA0
|
||||
swm5rokLFldHv9T9CQvuYqCQIb6GAb2HB/GzNcPVO6quCqNVI6K9+Zh6vNpWpnCW
|
||||
crP8iCn4T3jo2PxU56dwA63xOtkTdYWphaGL4J63flsZysPQ817uuHV/XLu1VwHE
|
||||
cBpcTWyXL9LB7rgqrVSIzw==</ds:SignatureValue>
|
||||
<ds:KeyInfo Id="xmldsig-2e62ccd5-82d2-4922-90a0-31af30fc44c0-KeyInfo">
|
||||
<ds:X509Data>
|
||||
<ds:X509Certificate>MIIH8TCCBdmgAwIBAgIIQxaPJd4YTlMwDQYJKoZIhvcNAQELBQAwgbYxIzAhBgkq
|
||||
hkiG9w0BCQEWFGluZm9AYW5kZXNzY2QuY29tLmNvMSYwJAYDVQQDEx1DQSBBTkRF
|
||||
UyBTQ0QgUy5BLiBDbGFzZSBJSSB2MzEwMC4GA1UECxMnRGl2aXNpb24gZGUgY2Vy
|
||||
dGlmaWNhY2lvbiBlbnRpZGFkIGZpbmFsMRIwEAYDVQQKEwlBbmRlcyBTQ0QxFDAS
|
||||
BgNVBAcTC0JvZ290YSBELkMuMQswCQYDVQQGEwJDTzAeFw0yNDA1MTYwNTAwMDBa
|
||||
Fw0yNTA1MTYwNDU5MDBaMIIBQDEtMCsGA1UECRMkVFYgNDYgQyA0MiBFU1RFIDc4
|
||||
OSBDT1JSIFNBTlRBIEVMRU5BMSIwIAYJKoZIhvcNAQkBFhNiaWNpcGl6emFAZ21h
|
||||
aWwuY29tMRowGAYDVQQDExFCSUNJIFBJWlpBIFMuQS5TLjETMBEGA1UEBRMKOTAx
|
||||
NTc1NTI4MjE2MDQGA1UEDBMtRW1pc29yIEZhY3R1cmEgRWxlY3Ryb25pY2EgLSBQ
|
||||
ZXJzb25hIEp1cmlkaWNhMTswOQYDVQQLEzJFbWl0aWRvIHBvciBBbmRlcyBTQ0Qg
|
||||
QWMgMjYgNjkgQyAwMyBUb3JyZSBCIE9mIDcwMTEQMA4GA1UEChMHR0VSRU5URTES
|
||||
MBAGA1UEBwwJTUVERUxMw41OMRIwEAYDVQQIEwlBTlRJT1FVSUExCzAJBgNVBAYT
|
||||
AkNPMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5J1O+4ZedrSBUsb+
|
||||
9tjNPHI9RGeIJcJl3Wc/208OqMYcCwGLUkrYBgH78E7IayD5/wra04OU57cS1/+/
|
||||
yBUWYR60oqkaH2/8OXkJMqmjisVM/b58m7zyMw4TAF8N/PbswnrKukFU2acxISwT
|
||||
Lu36HC4hshWw8bEGP54szvv1xnwqcOAWNBCxcBuc9k1JD+SIiqqPwHKh+6EDIoou
|
||||
jo0H15w3rAxkHQRvYe6/IrpvH2sqJl1I3dLv0iqy9+d2l891KBA9Yebdw7m/+ufu
|
||||
+eqs+0zKrwV6QLhRFmceHzEkPMTFepc2COGf80OUNbI6WWnspvDK97D8YG0MeifP
|
||||
YveIPwIDAQABo4ICdDCCAnAwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRA/iZp
|
||||
RzInMtGsIcgu7M+N1TVo6DBvBggrBgEFBQcBAQRjMGEwNgYIKwYBBQUHMAKGKmh0
|
||||
dHA6Ly9jZXJ0cy5hbmRlc3NjZC5jb20uY28vQ2xhc2VJSXYzLmNydDAnBggrBgEF
|
||||
BQcwAYYbaHR0cDovL29jc3AuYW5kZXNzY2QuY29tLmNvMB4GA1UdEQQXMBWBE2Jp
|
||||
Y2lwaXp6YUBnbWFpbC5jb20wggEjBgNVHSAEggEaMIIBFjCBwQYNKwYBBAGB9EgB
|
||||
AgYIADCBrzCBrAYIKwYBBQUHAgIwgZ8MgZxMYSB1dGlsaXphY2nDs24gZGUgZXN0
|
||||
ZSBjZXJ0aWZpY2FkbyBlc3TDoSBzdWpldGEgYSBsYSBQQyBkZSBGYWN0dXJhY2nD
|
||||
s24gRWxlY3Ryw7NuaWNhIHkgRFBDIGVzdGFibGVjaWRhcyBwb3IgQW5kZXMgU0NE
|
||||
LiBDw7NkaWdvIGRlIEFjcmVkaXRhY2nDs246IDE2LUVDRC0wMDQwUAYNKwYBBAGB
|
||||
9EgBAQEKADA/MD0GCCsGAQUFBwIBFjFodHRwczovL3d3dy5hbmRlc3NjZC5jb20u
|
||||
Y28vZG9jcy9EUENfQW5kZXNTQ0QucGRmMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr
|
||||
BgEFBQcDBDA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vY3JsLmFuZGVzc2NkLmNv
|
||||
bS5jby9DbGFzZUlJdjMuY3JsMB0GA1UdDgQWBBRKPoh3BJM7SxEL0UXkSne2MyFO
|
||||
jjAOBgNVHQ8BAf8EBAMCBeAwDQYJKoZIhvcNAQELBQADggIBAA6Zzor3kpJ6vNKv
|
||||
TAeHaMfmJ/PaghQ1+Lab7Pwk+lsPsMETFu/IpEK5qij2bV54UNnqyLYOZtIbnWTG
|
||||
qgT7QxQvy+/of/I3zzF+kH4/Lp2TSlHaDEb/airCZ3I2G23M9iaZzSwYuOsOaGwp
|
||||
4ovkXlYwQ7FVNfIIoAq95m9cBAigb06bRIlVBVTQq44hQFQQG6aSIT7SSPtCwPhB
|
||||
5CJzG09pmgbxizqN/yxdjWdfW6Av79dh6K4uQT++Vtyp5DuAkmfn0ehayrUbDLkH
|
||||
9jQFF128U5pnOPfKWf22acXqQBapesUSV/HZUZ3PXoWeHWXcMdz0azxOEunS4+px
|
||||
fs5UzInRAmEcYwJHqJT3irFz+J2RsZ0WnJHrTGqFoXniQQH8QbCHehDTGN7/v/v1
|
||||
LQBr5PQBnSEWhmrQ9uFrwPyMMg3yd+L75TaHLZ0MTSVezAG52oM9jBiU5tYXkSio
|
||||
EfPdIsGlG74BybULGSG2OlTINlblj/lj7pL67V+gY9EGN1zzNKL5sW4YXlXewa6K
|
||||
dTpLmmzWzI8Cm+tOuuJDSHSwMjn525O+Z/oyKLjdQdyfg1KnZYwNZFpMmCwfP5nd
|
||||
cm4F7Anzb9HX9ciluAxc6as9TsNoDDTSAGPuUr0QvXqXd9ZCgXdNzdFeiaYknLP5
|
||||
hT4f5CoO2M8qcG+CH7HnkaOHrSuK</ds:X509Certificate>
|
||||
</ds:X509Data>
|
||||
<ds:KeyValue>
|
||||
<ds:RSAKeyValue>
|
||||
<ds:Modulus>5J1O+4ZedrSBUsb+9tjNPHI9RGeIJcJl3Wc/208OqMYcCwGLUkrYBgH78E7IayD5
|
||||
/wra04OU57cS1/+/yBUWYR60oqkaH2/8OXkJMqmjisVM/b58m7zyMw4TAF8N/Pbs
|
||||
wnrKukFU2acxISwTLu36HC4hshWw8bEGP54szvv1xnwqcOAWNBCxcBuc9k1JD+SI
|
||||
iqqPwHKh+6EDIooujo0H15w3rAxkHQRvYe6/IrpvH2sqJl1I3dLv0iqy9+d2l891
|
||||
KBA9Yebdw7m/+ufu+eqs+0zKrwV6QLhRFmceHzEkPMTFepc2COGf80OUNbI6WWns
|
||||
pvDK97D8YG0MeifPYveIPw==</ds:Modulus>
|
||||
<ds:Exponent>AQAB</ds:Exponent>
|
||||
</ds:RSAKeyValue>
|
||||
</ds:KeyValue>
|
||||
</ds:KeyInfo>
|
||||
<ds:Object><xades:QualifyingProperties Target="#xmlsig-2e62ccd5-82d2-4922-90a0-31af30fc44c0" Id="XadesObjects"><xades:SignedProperties Id="xmldsig-2e62ccd5-82d2-4922-90a0-31af30fc44c0-signedprops"><xades:SignedSignatureProperties><xades:SigningTime>2025-03-16T16:49:57.777363</xades:SigningTime><xades:SigningCertificate><xades:Cert><xades:CertDigest><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>YcIPspAVFcNg+B/galYrdCLYvLIEwFI4KWdSzcuupPY=</ds:DigestValue></xades:CertDigest><xades:IssuerSerial><ds:X509IssuerName>C=CO, L=Bogota D.C., O=Andes SCD, OU=Division de certificacion entidad final, CN=CA ANDES SCD S.A. Clase II v3, OID.1.2.840.113549.1.9.1=info@andesscd.com.co</ds:X509IssuerName><ds:X509SerialNumber>4834208642831502931</ds:X509SerialNumber></xades:IssuerSerial></xades:Cert></xades:SigningCertificate><xades:SignaturePolicyIdentifier><xades:SignaturePolicyId><xades:SigPolicyId><xades:Identifier>https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf</xades:Identifier><xades:Description>Política de firma para facturas electrónicas de la República de Colombia.</xades:Description></xades:SigPolicyId><xades:SigPolicyHash><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>dMoMvtcG5aIzgYo0tIsSQeVJBDnUnfSOfBpxXrmor0Y=</ds:DigestValue></xades:SigPolicyHash></xades:SignaturePolicyId></xades:SignaturePolicyIdentifier><xades:SignerRole><xades:ClaimedRoles><xades:ClaimedRole>supplier</xades:ClaimedRole></xades:ClaimedRoles></xades:SignerRole></xades:SignedSignatureProperties></xades:SignedProperties></xades:QualifyingProperties></ds:Object></ds:Signature></ext:ExtensionContent></ext:UBLExtension></ext:UBLExtensions><Novedad CUNENov="false">false</Novedad><Periodo FechaIngreso="2022-01-05" FechaLiquidacionInicio="2024-04-01" FechaLiquidacionFin="2024-04-30" TiempoLaborado="1" FechaGen="2024-04-30"/><NumeroSecuenciaXML Prefijo="N" Consecutivo="000001" Numero="N000001"/><LugarGeneracionXML Pais="CO" DepartamentoEstado="05" MunicipioCiudad="05001" Idioma="es"/><ProveedorXML NIT="901575528" DV="2" SoftwareID="100b0d10-0ca0-4ad4-a894-b704a568cbf3" RazonSocial="BICI PIZZA S.A.S" SoftwareSC="277c710304542320e15609646371219dc9ac3edd9c73adc0a278a355fbef97609bb7e451b92900b517044443f6ae1838"/><CodigoQR>https://catalogo-vpfe-hab.dian.gov.co/document/searchqr?documentkey=f498037db4d2f7c42224fbdc958d031927f17f0ad4e4c1f4a3e85d6363d68f3f951860873e6899937c080f03b0bd0ceb</CodigoQR><InformacionGeneral Version="V1.0: Documento Soporte de Pago de Nómina Electrónica" Ambiente="2" TipoXML="102" EncripCUNE="CUNE-SHA384" FechaGen="2024-04-30" HoraGen="08:01:00-05:00" PeriodoNomina="1" TipoMoneda="COP" TRM="0" CUNE="f498037db4d2f7c42224fbdc958d031927f17f0ad4e4c1f4a3e85d6363d68f3f951860873e6899937c080f03b0bd0ceb"/><Empleador NIT="901575528" DV="2" Pais="CO" DepartamentoEstado="05" MunicipioCiudad="05001" Direccion="calle etrivial" RazonSocial="BICI PIZZA S.A.S"/><Trabajador TipoTrabajador="01" SubTipoTrabajador="00" AltoRiesgoPension="false" TipoDocumento="11" NumeroDocumento="901575528" PrimerApellido="GONZALEZ" SegundoApellido="" PrimerNombre="JUAN" LugarTrabajoPais="CO" LugarTrabajoDepartamentoEstado="05" LugarTrabajoMunicipioCiudad="05001" LugarTrabajoDireccion="CL 35C 102-17 BL 7 AP 101" SalarioIntegral="false" TipoContrato="1" Sueldo="2400000.0"/><Pago Forma="1" Metodo="10"/><FechasPagos><FechaPago>2024-04-30</FechaPago></FechasPagos><Devengados><Basico DiasTrabajados="30" SueldoTrabajado="2400000.00"/></Devengados><Deducciones><Salud Porcentaje="4.00" Deduccion="96000.0"/><FondoPension Porcentaje="4.00" Deduccion="96000.0"/></Deducciones><Redondeo>0</Redondeo><DevengadosTotal>2400000.00</DevengadosTotal><DeduccionesTotal>192000.00</DeduccionesTotal><ComprobanteTotal>2208000.00</ComprobanteTotal></NominaIndividual>
|
BIN
examples/habilitacion/N000001.zip
Normal file
BIN
examples/habilitacion/N000001.zip
Normal file
Binary file not shown.
123
examples/habilitacion/N000002.py
Normal file
123
examples/habilitacion/N000002.py
Normal file
@ -0,0 +1,123 @@
|
||||
|
||||
from facho import fe
|
||||
|
||||
SOFTWARE_PIN='20234'
|
||||
SOFTWARE_ID='100b0d10-0ca0-4ad4-a894-b704a568cbf3'
|
||||
NIT='901575528'
|
||||
DV='2'
|
||||
|
||||
def extensions(nomina):
|
||||
return []
|
||||
|
||||
def nomina():
|
||||
nomina = fe.nomina.DIANNominaIndividual()
|
||||
|
||||
nomina.asignar_fecha_pago('2024-04-30')
|
||||
|
||||
nomina.asignar_metadata(fe.nomina.Metadata(
|
||||
novedad=fe.nomina.Novedad(value='false'),
|
||||
secuencia=fe.nomina.NumeroSecuencia(
|
||||
prefijo='N',
|
||||
consecutivo='000002'
|
||||
),
|
||||
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(
|
||||
razon_social='BICI PIZZA S.A.S',
|
||||
nit=NIT,
|
||||
dv=DV,
|
||||
software_id=SOFTWARE_ID,
|
||||
software_pin=SOFTWARE_PIN
|
||||
)
|
||||
))
|
||||
|
||||
nomina.asignar_periodo(fe.nomina.Periodo(
|
||||
fecha_ingreso= '2022-09-05',
|
||||
fecha_liquidacion_inicio='2024-04-01',
|
||||
fecha_liquidacion_fin='2024-04-30',
|
||||
fecha_generacion='2024-04-30'
|
||||
))
|
||||
|
||||
nomina.asignar_informacion_general(fe.nomina.InformacionGeneral(
|
||||
fecha_generacion = '2024-04-30',
|
||||
hora_generacion = '08:01:00-05:00',
|
||||
tipo_ambiente = fe.nomina.InformacionGeneral.AMBIENTE_PRUEBAS,
|
||||
software_pin = 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(
|
||||
razon_social='BICI PIZZA S.A.S',
|
||||
nit = NIT,
|
||||
dv = DV,
|
||||
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 = 'GIRALDO',
|
||||
segundo_apellido = '',
|
||||
primer_nombre = 'VIVIANA',
|
||||
lugar_trabajo = fe.nomina.LugarTrabajo(
|
||||
pais = fe.nomina.Pais(code='CO'),
|
||||
departamento = fe.nomina.Departamento(code='05'),
|
||||
municipio = fe.nomina.Municipio(code='05001'),
|
||||
direccion = 'CL 35C 102-17 BL 7 AP 101'
|
||||
),
|
||||
numero_documento = NIT,
|
||||
tipo = fe.nomina.TipoTrabajador(
|
||||
code = '01'
|
||||
),
|
||||
salario_integral = False,
|
||||
sueldo = fe.nomina.Amount(1160000)
|
||||
))
|
||||
|
||||
nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
|
||||
dias_trabajados = 30,
|
||||
sueldo_trabajado = fe.nomina.Amount(1160000)
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||
porcentaje = fe.nomina.Amount(4),
|
||||
deduccion = fe.nomina.Amount(46400)
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionFondoPension(
|
||||
porcentaje=fe.nomina.Amount(4),
|
||||
deduccion = fe.nomina.Amount(46400)
|
||||
))
|
||||
return nomina
|
||||
|
89
examples/habilitacion/N000002.xml
Normal file
89
examples/habilitacion/N000002.xml
Normal file
@ -0,0 +1,89 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<NominaIndividual xmlns:atd="urn:oasis:names:specification:ubl:schema:xsd:AttachedDocument-2" xmlns="dian:gov:co:facturaelectronica:NominaIndividual" xmlns:fe="http://www.dian.gov.co/contratos/facturaelectronica/v1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" 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="dian:gov:co:facturaelectronica:Structures-2-1" 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:xades141="http://uri.etsi.org/01903/v1.4.1#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:sig="http://www.w3.org/2000/09/xmldsig#" SchemaLocation="" xsi:schemaLocation="dian:gov:co:facturaelectronica:NominaIndividual NominaIndividualElectronicaXSD.xsd"><ext:UBLExtensions><ext:UBLExtension><ext:ExtensionContent><ds:Signature Id="xmlsig-bd7246f2-0f63-4a0a-822b-f59be349b7df">
|
||||
<ds:SignedInfo>
|
||||
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
||||
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
|
||||
<ds:Reference Id="xmldsig-bd7246f2-0f63-4a0a-822b-f59be349b7df-ref0" URI="">
|
||||
<ds:Transforms>
|
||||
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
||||
</ds:Transforms>
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||
<ds:DigestValue>OZ66ZARE1QPKfYYk+BdiEnO0675e7p00fGwhb/Iyd5s=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
<ds:Reference Id="xmldsig-bd7246f2-0f63-4a0a-822b-f59be349b7df-ref1" URI="#xmldsig-bd7246f2-0f63-4a0a-822b-f59be349b7df-KeyInfo">
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||
<ds:DigestValue>jZRqaYdQrLDYoqJmrKrLoO2ZHlGX1Xo5IpGFAznaQnI=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
<ds:Reference URI="#xmldsig-bd7246f2-0f63-4a0a-822b-f59be349b7df-signedprops" Type="http://uri.etsi.org/01903#SignedProperties">
|
||||
<ds:Transforms>
|
||||
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
||||
</ds:Transforms>
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||
<ds:DigestValue>XNMT1fgTLgeuUDfYH//8aY/TqzhsRcScSySL/6nKwxE=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
</ds:SignedInfo>
|
||||
<ds:SignatureValue>fHBH/GVqHYi8iFbtTUwLUaVerZjfoj64Toq5jE+qi/HLmwhtDCAK2V/ISn0VDxpJ
|
||||
3QrAqWw/VjTFEqWmRV7mCxybM98A/+5yeWbvDkG2eY5fUOUHin9+oomysY8cwLjA
|
||||
joXsvjEJlM1YIndzWG/Dryr14Hcax6ItVSaopA+1BpUoFn/5jWwZXsbmq0jHDjsI
|
||||
Vyk1WpZzYwmM/aGZg7gj/pR7kZZOnv4d3L/MnFP6vJRdRNtRwO73wBd5lYGU1KaB
|
||||
iTimrV2gBwg0+o5bqloSaQEtqV87adJG0h3eosSiIhrG9rc9rOpvqqq7tG2nAxRx
|
||||
NyPM8gwuKoaoU9ogvRsqHQ==</ds:SignatureValue>
|
||||
<ds:KeyInfo Id="xmldsig-bd7246f2-0f63-4a0a-822b-f59be349b7df-KeyInfo">
|
||||
<ds:X509Data>
|
||||
<ds:X509Certificate>MIIH8TCCBdmgAwIBAgIIQxaPJd4YTlMwDQYJKoZIhvcNAQELBQAwgbYxIzAhBgkq
|
||||
hkiG9w0BCQEWFGluZm9AYW5kZXNzY2QuY29tLmNvMSYwJAYDVQQDEx1DQSBBTkRF
|
||||
UyBTQ0QgUy5BLiBDbGFzZSBJSSB2MzEwMC4GA1UECxMnRGl2aXNpb24gZGUgY2Vy
|
||||
dGlmaWNhY2lvbiBlbnRpZGFkIGZpbmFsMRIwEAYDVQQKEwlBbmRlcyBTQ0QxFDAS
|
||||
BgNVBAcTC0JvZ290YSBELkMuMQswCQYDVQQGEwJDTzAeFw0yNDA1MTYwNTAwMDBa
|
||||
Fw0yNTA1MTYwNDU5MDBaMIIBQDEtMCsGA1UECRMkVFYgNDYgQyA0MiBFU1RFIDc4
|
||||
OSBDT1JSIFNBTlRBIEVMRU5BMSIwIAYJKoZIhvcNAQkBFhNiaWNpcGl6emFAZ21h
|
||||
aWwuY29tMRowGAYDVQQDExFCSUNJIFBJWlpBIFMuQS5TLjETMBEGA1UEBRMKOTAx
|
||||
NTc1NTI4MjE2MDQGA1UEDBMtRW1pc29yIEZhY3R1cmEgRWxlY3Ryb25pY2EgLSBQ
|
||||
ZXJzb25hIEp1cmlkaWNhMTswOQYDVQQLEzJFbWl0aWRvIHBvciBBbmRlcyBTQ0Qg
|
||||
QWMgMjYgNjkgQyAwMyBUb3JyZSBCIE9mIDcwMTEQMA4GA1UEChMHR0VSRU5URTES
|
||||
MBAGA1UEBwwJTUVERUxMw41OMRIwEAYDVQQIEwlBTlRJT1FVSUExCzAJBgNVBAYT
|
||||
AkNPMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5J1O+4ZedrSBUsb+
|
||||
9tjNPHI9RGeIJcJl3Wc/208OqMYcCwGLUkrYBgH78E7IayD5/wra04OU57cS1/+/
|
||||
yBUWYR60oqkaH2/8OXkJMqmjisVM/b58m7zyMw4TAF8N/PbswnrKukFU2acxISwT
|
||||
Lu36HC4hshWw8bEGP54szvv1xnwqcOAWNBCxcBuc9k1JD+SIiqqPwHKh+6EDIoou
|
||||
jo0H15w3rAxkHQRvYe6/IrpvH2sqJl1I3dLv0iqy9+d2l891KBA9Yebdw7m/+ufu
|
||||
+eqs+0zKrwV6QLhRFmceHzEkPMTFepc2COGf80OUNbI6WWnspvDK97D8YG0MeifP
|
||||
YveIPwIDAQABo4ICdDCCAnAwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRA/iZp
|
||||
RzInMtGsIcgu7M+N1TVo6DBvBggrBgEFBQcBAQRjMGEwNgYIKwYBBQUHMAKGKmh0
|
||||
dHA6Ly9jZXJ0cy5hbmRlc3NjZC5jb20uY28vQ2xhc2VJSXYzLmNydDAnBggrBgEF
|
||||
BQcwAYYbaHR0cDovL29jc3AuYW5kZXNzY2QuY29tLmNvMB4GA1UdEQQXMBWBE2Jp
|
||||
Y2lwaXp6YUBnbWFpbC5jb20wggEjBgNVHSAEggEaMIIBFjCBwQYNKwYBBAGB9EgB
|
||||
AgYIADCBrzCBrAYIKwYBBQUHAgIwgZ8MgZxMYSB1dGlsaXphY2nDs24gZGUgZXN0
|
||||
ZSBjZXJ0aWZpY2FkbyBlc3TDoSBzdWpldGEgYSBsYSBQQyBkZSBGYWN0dXJhY2nD
|
||||
s24gRWxlY3Ryw7NuaWNhIHkgRFBDIGVzdGFibGVjaWRhcyBwb3IgQW5kZXMgU0NE
|
||||
LiBDw7NkaWdvIGRlIEFjcmVkaXRhY2nDs246IDE2LUVDRC0wMDQwUAYNKwYBBAGB
|
||||
9EgBAQEKADA/MD0GCCsGAQUFBwIBFjFodHRwczovL3d3dy5hbmRlc3NjZC5jb20u
|
||||
Y28vZG9jcy9EUENfQW5kZXNTQ0QucGRmMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr
|
||||
BgEFBQcDBDA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vY3JsLmFuZGVzc2NkLmNv
|
||||
bS5jby9DbGFzZUlJdjMuY3JsMB0GA1UdDgQWBBRKPoh3BJM7SxEL0UXkSne2MyFO
|
||||
jjAOBgNVHQ8BAf8EBAMCBeAwDQYJKoZIhvcNAQELBQADggIBAA6Zzor3kpJ6vNKv
|
||||
TAeHaMfmJ/PaghQ1+Lab7Pwk+lsPsMETFu/IpEK5qij2bV54UNnqyLYOZtIbnWTG
|
||||
qgT7QxQvy+/of/I3zzF+kH4/Lp2TSlHaDEb/airCZ3I2G23M9iaZzSwYuOsOaGwp
|
||||
4ovkXlYwQ7FVNfIIoAq95m9cBAigb06bRIlVBVTQq44hQFQQG6aSIT7SSPtCwPhB
|
||||
5CJzG09pmgbxizqN/yxdjWdfW6Av79dh6K4uQT++Vtyp5DuAkmfn0ehayrUbDLkH
|
||||
9jQFF128U5pnOPfKWf22acXqQBapesUSV/HZUZ3PXoWeHWXcMdz0azxOEunS4+px
|
||||
fs5UzInRAmEcYwJHqJT3irFz+J2RsZ0WnJHrTGqFoXniQQH8QbCHehDTGN7/v/v1
|
||||
LQBr5PQBnSEWhmrQ9uFrwPyMMg3yd+L75TaHLZ0MTSVezAG52oM9jBiU5tYXkSio
|
||||
EfPdIsGlG74BybULGSG2OlTINlblj/lj7pL67V+gY9EGN1zzNKL5sW4YXlXewa6K
|
||||
dTpLmmzWzI8Cm+tOuuJDSHSwMjn525O+Z/oyKLjdQdyfg1KnZYwNZFpMmCwfP5nd
|
||||
cm4F7Anzb9HX9ciluAxc6as9TsNoDDTSAGPuUr0QvXqXd9ZCgXdNzdFeiaYknLP5
|
||||
hT4f5CoO2M8qcG+CH7HnkaOHrSuK</ds:X509Certificate>
|
||||
</ds:X509Data>
|
||||
<ds:KeyValue>
|
||||
<ds:RSAKeyValue>
|
||||
<ds:Modulus>5J1O+4ZedrSBUsb+9tjNPHI9RGeIJcJl3Wc/208OqMYcCwGLUkrYBgH78E7IayD5
|
||||
/wra04OU57cS1/+/yBUWYR60oqkaH2/8OXkJMqmjisVM/b58m7zyMw4TAF8N/Pbs
|
||||
wnrKukFU2acxISwTLu36HC4hshWw8bEGP54szvv1xnwqcOAWNBCxcBuc9k1JD+SI
|
||||
iqqPwHKh+6EDIooujo0H15w3rAxkHQRvYe6/IrpvH2sqJl1I3dLv0iqy9+d2l891
|
||||
KBA9Yebdw7m/+ufu+eqs+0zKrwV6QLhRFmceHzEkPMTFepc2COGf80OUNbI6WWns
|
||||
pvDK97D8YG0MeifPYveIPw==</ds:Modulus>
|
||||
<ds:Exponent>AQAB</ds:Exponent>
|
||||
</ds:RSAKeyValue>
|
||||
</ds:KeyValue>
|
||||
</ds:KeyInfo>
|
||||
<ds:Object><xades:QualifyingProperties Target="#xmlsig-bd7246f2-0f63-4a0a-822b-f59be349b7df" Id="XadesObjects"><xades:SignedProperties Id="xmldsig-bd7246f2-0f63-4a0a-822b-f59be349b7df-signedprops"><xades:SignedSignatureProperties><xades:SigningTime>2025-03-16T16:50:01.250573</xades:SigningTime><xades:SigningCertificate><xades:Cert><xades:CertDigest><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>YcIPspAVFcNg+B/galYrdCLYvLIEwFI4KWdSzcuupPY=</ds:DigestValue></xades:CertDigest><xades:IssuerSerial><ds:X509IssuerName>C=CO, L=Bogota D.C., O=Andes SCD, OU=Division de certificacion entidad final, CN=CA ANDES SCD S.A. Clase II v3, OID.1.2.840.113549.1.9.1=info@andesscd.com.co</ds:X509IssuerName><ds:X509SerialNumber>4834208642831502931</ds:X509SerialNumber></xades:IssuerSerial></xades:Cert></xades:SigningCertificate><xades:SignaturePolicyIdentifier><xades:SignaturePolicyId><xades:SigPolicyId><xades:Identifier>https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf</xades:Identifier><xades:Description>Política de firma para facturas electrónicas de la República de Colombia.</xades:Description></xades:SigPolicyId><xades:SigPolicyHash><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>dMoMvtcG5aIzgYo0tIsSQeVJBDnUnfSOfBpxXrmor0Y=</ds:DigestValue></xades:SigPolicyHash></xades:SignaturePolicyId></xades:SignaturePolicyIdentifier><xades:SignerRole><xades:ClaimedRoles><xades:ClaimedRole>supplier</xades:ClaimedRole></xades:ClaimedRoles></xades:SignerRole></xades:SignedSignatureProperties></xades:SignedProperties></xades:QualifyingProperties></ds:Object></ds:Signature></ext:ExtensionContent></ext:UBLExtension></ext:UBLExtensions><Novedad CUNENov="false">false</Novedad><Periodo FechaIngreso="2022-09-05" FechaLiquidacionInicio="2024-04-01" FechaLiquidacionFin="2024-04-30" TiempoLaborado="1" FechaGen="2024-04-30"/><NumeroSecuenciaXML Prefijo="N" Consecutivo="000002" Numero="N000002"/><LugarGeneracionXML Pais="CO" DepartamentoEstado="05" MunicipioCiudad="05001" Idioma="es"/><ProveedorXML NIT="901575528" DV="2" SoftwareID="100b0d10-0ca0-4ad4-a894-b704a568cbf3" RazonSocial="BICI PIZZA S.A.S" SoftwareSC="067c1069842576f1f954d3540d9f75a214e2a63219f36f4f25465e26958c10d2c9e222076635379bd7f61ca0459c87e9"/><CodigoQR>https://catalogo-vpfe-hab.dian.gov.co/document/searchqr?documentkey=cb2e6968a811c661ebdc8b8cd19a323ca05471c2fe3c3b1cfb5275379d7df94d6c22f9405d732295e805095e366a99fa</CodigoQR><InformacionGeneral Version="V1.0: Documento Soporte de Pago de Nómina Electrónica" Ambiente="2" TipoXML="102" EncripCUNE="CUNE-SHA384" FechaGen="2024-04-30" HoraGen="08:01:00-05:00" PeriodoNomina="1" TipoMoneda="COP" TRM="0" CUNE="cb2e6968a811c661ebdc8b8cd19a323ca05471c2fe3c3b1cfb5275379d7df94d6c22f9405d732295e805095e366a99fa"/><Empleador NIT="901575528" DV="2" Pais="CO" DepartamentoEstado="05" MunicipioCiudad="05001" Direccion="calle etrivial" RazonSocial="BICI PIZZA S.A.S"/><Trabajador TipoTrabajador="01" SubTipoTrabajador="00" AltoRiesgoPension="false" TipoDocumento="11" NumeroDocumento="901575528" PrimerApellido="GIRALDO" SegundoApellido="" PrimerNombre="VIVIANA" LugarTrabajoPais="CO" LugarTrabajoDepartamentoEstado="05" LugarTrabajoMunicipioCiudad="05001" LugarTrabajoDireccion="CL 35C 102-17 BL 7 AP 101" SalarioIntegral="false" TipoContrato="1" Sueldo="1160000.0"/><Pago Forma="1" Metodo="10"/><FechasPagos><FechaPago>2024-04-30</FechaPago></FechasPagos><Devengados><Basico DiasTrabajados="30" SueldoTrabajado="1160000.00"/></Devengados><Deducciones><Salud Porcentaje="4.00" Deduccion="46400.0"/><FondoPension Porcentaje="4.00" Deduccion="46400.0"/></Deducciones><Redondeo>0</Redondeo><DevengadosTotal>1160000.00</DevengadosTotal><DeduccionesTotal>92800.00</DeduccionesTotal><ComprobanteTotal>1067200.00</ComprobanteTotal></NominaIndividual>
|
BIN
examples/habilitacion/N000002.zip
Normal file
BIN
examples/habilitacion/N000002.zip
Normal file
Binary file not shown.
123
examples/habilitacion/N000003.py
Normal file
123
examples/habilitacion/N000003.py
Normal file
@ -0,0 +1,123 @@
|
||||
|
||||
from facho import fe
|
||||
|
||||
SOFTWARE_PIN='20234'
|
||||
SOFTWARE_ID='100b0d10-0ca0-4ad4-a894-b704a568cbf3'
|
||||
NIT='901575528'
|
||||
DV='2'
|
||||
|
||||
def extensions(nomina):
|
||||
return []
|
||||
|
||||
def nomina():
|
||||
nomina = fe.nomina.DIANNominaIndividual()
|
||||
|
||||
nomina.asignar_fecha_pago('2024-04-30')
|
||||
|
||||
nomina.asignar_metadata(fe.nomina.Metadata(
|
||||
novedad=fe.nomina.Novedad(value='false'),
|
||||
secuencia=fe.nomina.NumeroSecuencia(
|
||||
prefijo='N',
|
||||
consecutivo='000003'
|
||||
),
|
||||
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(
|
||||
razon_social='BICI PIZZA S.A.S',
|
||||
nit=NIT,
|
||||
dv=DV,
|
||||
software_id=SOFTWARE_ID,
|
||||
software_pin=SOFTWARE_PIN
|
||||
)
|
||||
))
|
||||
|
||||
nomina.asignar_periodo(fe.nomina.Periodo(
|
||||
fecha_ingreso= '2022-01-05',
|
||||
fecha_liquidacion_inicio='2024-04-01',
|
||||
fecha_liquidacion_fin='2024-04-30',
|
||||
fecha_generacion='2024-04-30'
|
||||
))
|
||||
|
||||
nomina.asignar_informacion_general(fe.nomina.InformacionGeneral(
|
||||
fecha_generacion = '2024-04-30',
|
||||
hora_generacion = '08:01:00-05:00',
|
||||
tipo_ambiente = fe.nomina.InformacionGeneral.AMBIENTE_PRUEBAS,
|
||||
software_pin = 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(
|
||||
razon_social='BICI PIZZA S.A.S',
|
||||
nit = NIT,
|
||||
dv = DV,
|
||||
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 = 'GONZALEZ',
|
||||
segundo_apellido = '',
|
||||
primer_nombre = 'JUAN',
|
||||
lugar_trabajo = fe.nomina.LugarTrabajo(
|
||||
pais = fe.nomina.Pais(code='CO'),
|
||||
departamento = fe.nomina.Departamento(code='05'),
|
||||
municipio = fe.nomina.Municipio(code='05001'),
|
||||
direccion = 'CL 35C 102-17 BL 7 AP 101'
|
||||
),
|
||||
numero_documento = NIT,
|
||||
tipo = fe.nomina.TipoTrabajador(
|
||||
code = '01'
|
||||
),
|
||||
salario_integral = False,
|
||||
sueldo = fe.nomina.Amount(2400000)
|
||||
))
|
||||
|
||||
nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
|
||||
dias_trabajados = 30,
|
||||
sueldo_trabajado = fe.nomina.Amount(2400000)
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||
porcentaje = fe.nomina.Amount(4),
|
||||
deduccion = fe.nomina.Amount(96000)
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionFondoPension(
|
||||
porcentaje=fe.nomina.Amount(4),
|
||||
deduccion = fe.nomina.Amount(96000)
|
||||
))
|
||||
return nomina
|
||||
|
89
examples/habilitacion/N000003.xml
Normal file
89
examples/habilitacion/N000003.xml
Normal file
@ -0,0 +1,89 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<NominaIndividual xmlns:atd="urn:oasis:names:specification:ubl:schema:xsd:AttachedDocument-2" xmlns="dian:gov:co:facturaelectronica:NominaIndividual" xmlns:fe="http://www.dian.gov.co/contratos/facturaelectronica/v1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" 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="dian:gov:co:facturaelectronica:Structures-2-1" 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:xades141="http://uri.etsi.org/01903/v1.4.1#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:sig="http://www.w3.org/2000/09/xmldsig#" SchemaLocation="" xsi:schemaLocation="dian:gov:co:facturaelectronica:NominaIndividual NominaIndividualElectronicaXSD.xsd"><ext:UBLExtensions><ext:UBLExtension><ext:ExtensionContent><ds:Signature Id="xmlsig-135b3cc1-1d1c-4ddd-a4c0-704a880a352b">
|
||||
<ds:SignedInfo>
|
||||
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
||||
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
|
||||
<ds:Reference Id="xmldsig-135b3cc1-1d1c-4ddd-a4c0-704a880a352b-ref0" URI="">
|
||||
<ds:Transforms>
|
||||
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
||||
</ds:Transforms>
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||
<ds:DigestValue>mf3prH7SIB1Df0Z/nOPdRGG0DKXP8oCra41918zaCyg=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
<ds:Reference Id="xmldsig-135b3cc1-1d1c-4ddd-a4c0-704a880a352b-ref1" URI="#xmldsig-135b3cc1-1d1c-4ddd-a4c0-704a880a352b-KeyInfo">
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||
<ds:DigestValue>H3dF/siCNdG6iSy15jUQct1k4qswXBZToWJH6tsptpk=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
<ds:Reference URI="#xmldsig-135b3cc1-1d1c-4ddd-a4c0-704a880a352b-signedprops" Type="http://uri.etsi.org/01903#SignedProperties">
|
||||
<ds:Transforms>
|
||||
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
||||
</ds:Transforms>
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||
<ds:DigestValue>IqiqJKHTI0OAWva1xZ+ZOk9ooGkzEa4hReQCr4/W778=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
</ds:SignedInfo>
|
||||
<ds:SignatureValue>Nv0nFvZ4Y3KIaPODEiOFgThDYb+DNKlJrRUAOrIxcNvtotpK7Y91JnYbUgFvl28b
|
||||
Z5V/catUMyOclGDjPzslTBcHXExleb5eIgUB8URdNvdrB78iXFUOfPc+ESFomru8
|
||||
jyPX9cZw24ZYBmQqqusvqIkf/tIARFGZ+7AzXkp28dBRFyWtgjESn60DIrFjm9x5
|
||||
Pthv1K95gytjrrpwvdk77KN4uumlCbGoc2Pizbj+ufijbnxEPDS7fS7RR0Qv9uz/
|
||||
2X7znR10TK8+gwMz7AVRYQi90ZbhOadxf3j+HVAlHtw+JHbrPSC+7xBOiPPStY6o
|
||||
6TkQU+ZMpz2IUovjqREXow==</ds:SignatureValue>
|
||||
<ds:KeyInfo Id="xmldsig-135b3cc1-1d1c-4ddd-a4c0-704a880a352b-KeyInfo">
|
||||
<ds:X509Data>
|
||||
<ds:X509Certificate>MIIH8TCCBdmgAwIBAgIIQxaPJd4YTlMwDQYJKoZIhvcNAQELBQAwgbYxIzAhBgkq
|
||||
hkiG9w0BCQEWFGluZm9AYW5kZXNzY2QuY29tLmNvMSYwJAYDVQQDEx1DQSBBTkRF
|
||||
UyBTQ0QgUy5BLiBDbGFzZSBJSSB2MzEwMC4GA1UECxMnRGl2aXNpb24gZGUgY2Vy
|
||||
dGlmaWNhY2lvbiBlbnRpZGFkIGZpbmFsMRIwEAYDVQQKEwlBbmRlcyBTQ0QxFDAS
|
||||
BgNVBAcTC0JvZ290YSBELkMuMQswCQYDVQQGEwJDTzAeFw0yNDA1MTYwNTAwMDBa
|
||||
Fw0yNTA1MTYwNDU5MDBaMIIBQDEtMCsGA1UECRMkVFYgNDYgQyA0MiBFU1RFIDc4
|
||||
OSBDT1JSIFNBTlRBIEVMRU5BMSIwIAYJKoZIhvcNAQkBFhNiaWNpcGl6emFAZ21h
|
||||
aWwuY29tMRowGAYDVQQDExFCSUNJIFBJWlpBIFMuQS5TLjETMBEGA1UEBRMKOTAx
|
||||
NTc1NTI4MjE2MDQGA1UEDBMtRW1pc29yIEZhY3R1cmEgRWxlY3Ryb25pY2EgLSBQ
|
||||
ZXJzb25hIEp1cmlkaWNhMTswOQYDVQQLEzJFbWl0aWRvIHBvciBBbmRlcyBTQ0Qg
|
||||
QWMgMjYgNjkgQyAwMyBUb3JyZSBCIE9mIDcwMTEQMA4GA1UEChMHR0VSRU5URTES
|
||||
MBAGA1UEBwwJTUVERUxMw41OMRIwEAYDVQQIEwlBTlRJT1FVSUExCzAJBgNVBAYT
|
||||
AkNPMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5J1O+4ZedrSBUsb+
|
||||
9tjNPHI9RGeIJcJl3Wc/208OqMYcCwGLUkrYBgH78E7IayD5/wra04OU57cS1/+/
|
||||
yBUWYR60oqkaH2/8OXkJMqmjisVM/b58m7zyMw4TAF8N/PbswnrKukFU2acxISwT
|
||||
Lu36HC4hshWw8bEGP54szvv1xnwqcOAWNBCxcBuc9k1JD+SIiqqPwHKh+6EDIoou
|
||||
jo0H15w3rAxkHQRvYe6/IrpvH2sqJl1I3dLv0iqy9+d2l891KBA9Yebdw7m/+ufu
|
||||
+eqs+0zKrwV6QLhRFmceHzEkPMTFepc2COGf80OUNbI6WWnspvDK97D8YG0MeifP
|
||||
YveIPwIDAQABo4ICdDCCAnAwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRA/iZp
|
||||
RzInMtGsIcgu7M+N1TVo6DBvBggrBgEFBQcBAQRjMGEwNgYIKwYBBQUHMAKGKmh0
|
||||
dHA6Ly9jZXJ0cy5hbmRlc3NjZC5jb20uY28vQ2xhc2VJSXYzLmNydDAnBggrBgEF
|
||||
BQcwAYYbaHR0cDovL29jc3AuYW5kZXNzY2QuY29tLmNvMB4GA1UdEQQXMBWBE2Jp
|
||||
Y2lwaXp6YUBnbWFpbC5jb20wggEjBgNVHSAEggEaMIIBFjCBwQYNKwYBBAGB9EgB
|
||||
AgYIADCBrzCBrAYIKwYBBQUHAgIwgZ8MgZxMYSB1dGlsaXphY2nDs24gZGUgZXN0
|
||||
ZSBjZXJ0aWZpY2FkbyBlc3TDoSBzdWpldGEgYSBsYSBQQyBkZSBGYWN0dXJhY2nD
|
||||
s24gRWxlY3Ryw7NuaWNhIHkgRFBDIGVzdGFibGVjaWRhcyBwb3IgQW5kZXMgU0NE
|
||||
LiBDw7NkaWdvIGRlIEFjcmVkaXRhY2nDs246IDE2LUVDRC0wMDQwUAYNKwYBBAGB
|
||||
9EgBAQEKADA/MD0GCCsGAQUFBwIBFjFodHRwczovL3d3dy5hbmRlc3NjZC5jb20u
|
||||
Y28vZG9jcy9EUENfQW5kZXNTQ0QucGRmMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr
|
||||
BgEFBQcDBDA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vY3JsLmFuZGVzc2NkLmNv
|
||||
bS5jby9DbGFzZUlJdjMuY3JsMB0GA1UdDgQWBBRKPoh3BJM7SxEL0UXkSne2MyFO
|
||||
jjAOBgNVHQ8BAf8EBAMCBeAwDQYJKoZIhvcNAQELBQADggIBAA6Zzor3kpJ6vNKv
|
||||
TAeHaMfmJ/PaghQ1+Lab7Pwk+lsPsMETFu/IpEK5qij2bV54UNnqyLYOZtIbnWTG
|
||||
qgT7QxQvy+/of/I3zzF+kH4/Lp2TSlHaDEb/airCZ3I2G23M9iaZzSwYuOsOaGwp
|
||||
4ovkXlYwQ7FVNfIIoAq95m9cBAigb06bRIlVBVTQq44hQFQQG6aSIT7SSPtCwPhB
|
||||
5CJzG09pmgbxizqN/yxdjWdfW6Av79dh6K4uQT++Vtyp5DuAkmfn0ehayrUbDLkH
|
||||
9jQFF128U5pnOPfKWf22acXqQBapesUSV/HZUZ3PXoWeHWXcMdz0azxOEunS4+px
|
||||
fs5UzInRAmEcYwJHqJT3irFz+J2RsZ0WnJHrTGqFoXniQQH8QbCHehDTGN7/v/v1
|
||||
LQBr5PQBnSEWhmrQ9uFrwPyMMg3yd+L75TaHLZ0MTSVezAG52oM9jBiU5tYXkSio
|
||||
EfPdIsGlG74BybULGSG2OlTINlblj/lj7pL67V+gY9EGN1zzNKL5sW4YXlXewa6K
|
||||
dTpLmmzWzI8Cm+tOuuJDSHSwMjn525O+Z/oyKLjdQdyfg1KnZYwNZFpMmCwfP5nd
|
||||
cm4F7Anzb9HX9ciluAxc6as9TsNoDDTSAGPuUr0QvXqXd9ZCgXdNzdFeiaYknLP5
|
||||
hT4f5CoO2M8qcG+CH7HnkaOHrSuK</ds:X509Certificate>
|
||||
</ds:X509Data>
|
||||
<ds:KeyValue>
|
||||
<ds:RSAKeyValue>
|
||||
<ds:Modulus>5J1O+4ZedrSBUsb+9tjNPHI9RGeIJcJl3Wc/208OqMYcCwGLUkrYBgH78E7IayD5
|
||||
/wra04OU57cS1/+/yBUWYR60oqkaH2/8OXkJMqmjisVM/b58m7zyMw4TAF8N/Pbs
|
||||
wnrKukFU2acxISwTLu36HC4hshWw8bEGP54szvv1xnwqcOAWNBCxcBuc9k1JD+SI
|
||||
iqqPwHKh+6EDIooujo0H15w3rAxkHQRvYe6/IrpvH2sqJl1I3dLv0iqy9+d2l891
|
||||
KBA9Yebdw7m/+ufu+eqs+0zKrwV6QLhRFmceHzEkPMTFepc2COGf80OUNbI6WWns
|
||||
pvDK97D8YG0MeifPYveIPw==</ds:Modulus>
|
||||
<ds:Exponent>AQAB</ds:Exponent>
|
||||
</ds:RSAKeyValue>
|
||||
</ds:KeyValue>
|
||||
</ds:KeyInfo>
|
||||
<ds:Object><xades:QualifyingProperties Target="#xmlsig-135b3cc1-1d1c-4ddd-a4c0-704a880a352b" Id="XadesObjects"><xades:SignedProperties Id="xmldsig-135b3cc1-1d1c-4ddd-a4c0-704a880a352b-signedprops"><xades:SignedSignatureProperties><xades:SigningTime>2025-03-16T16:51:23.354553</xades:SigningTime><xades:SigningCertificate><xades:Cert><xades:CertDigest><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>YcIPspAVFcNg+B/galYrdCLYvLIEwFI4KWdSzcuupPY=</ds:DigestValue></xades:CertDigest><xades:IssuerSerial><ds:X509IssuerName>C=CO, L=Bogota D.C., O=Andes SCD, OU=Division de certificacion entidad final, CN=CA ANDES SCD S.A. Clase II v3, OID.1.2.840.113549.1.9.1=info@andesscd.com.co</ds:X509IssuerName><ds:X509SerialNumber>4834208642831502931</ds:X509SerialNumber></xades:IssuerSerial></xades:Cert></xades:SigningCertificate><xades:SignaturePolicyIdentifier><xades:SignaturePolicyId><xades:SigPolicyId><xades:Identifier>https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf</xades:Identifier><xades:Description>Política de firma para facturas electrónicas de la República de Colombia.</xades:Description></xades:SigPolicyId><xades:SigPolicyHash><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>dMoMvtcG5aIzgYo0tIsSQeVJBDnUnfSOfBpxXrmor0Y=</ds:DigestValue></xades:SigPolicyHash></xades:SignaturePolicyId></xades:SignaturePolicyIdentifier><xades:SignerRole><xades:ClaimedRoles><xades:ClaimedRole>supplier</xades:ClaimedRole></xades:ClaimedRoles></xades:SignerRole></xades:SignedSignatureProperties></xades:SignedProperties></xades:QualifyingProperties></ds:Object></ds:Signature></ext:ExtensionContent></ext:UBLExtension></ext:UBLExtensions><Novedad CUNENov="false">false</Novedad><Periodo FechaIngreso="2022-01-05" FechaLiquidacionInicio="2024-04-01" FechaLiquidacionFin="2024-04-30" TiempoLaborado="1" FechaGen="2024-04-30"/><NumeroSecuenciaXML Prefijo="N" Consecutivo="000003" Numero="N000003"/><LugarGeneracionXML Pais="CO" DepartamentoEstado="05" MunicipioCiudad="05001" Idioma="es"/><ProveedorXML NIT="901575528" DV="2" SoftwareID="100b0d10-0ca0-4ad4-a894-b704a568cbf3" RazonSocial="BICI PIZZA S.A.S" SoftwareSC="23bd3a3e925c4cdf6c4b99c1eda9e64846526241a263b86f3ffc9673d91020625812ef6abdcf93b4c326b7b65999d6c1"/><CodigoQR>https://catalogo-vpfe-hab.dian.gov.co/document/searchqr?documentkey=beae68d136b80593b01b5cd7594bc86cc2f6ffd17d0238e5842e29ef6dfde62d26cb959764b6bf0943e73149596bfec0</CodigoQR><InformacionGeneral Version="V1.0: Documento Soporte de Pago de Nómina Electrónica" Ambiente="2" TipoXML="102" EncripCUNE="CUNE-SHA384" FechaGen="2024-04-30" HoraGen="08:01:00-05:00" PeriodoNomina="1" TipoMoneda="COP" TRM="0" CUNE="beae68d136b80593b01b5cd7594bc86cc2f6ffd17d0238e5842e29ef6dfde62d26cb959764b6bf0943e73149596bfec0"/><Empleador NIT="901575528" DV="2" Pais="CO" DepartamentoEstado="05" MunicipioCiudad="05001" Direccion="calle etrivial" RazonSocial="BICI PIZZA S.A.S"/><Trabajador TipoTrabajador="01" SubTipoTrabajador="00" AltoRiesgoPension="false" TipoDocumento="11" NumeroDocumento="901575528" PrimerApellido="GONZALEZ" SegundoApellido="" PrimerNombre="JUAN" LugarTrabajoPais="CO" LugarTrabajoDepartamentoEstado="05" LugarTrabajoMunicipioCiudad="05001" LugarTrabajoDireccion="CL 35C 102-17 BL 7 AP 101" SalarioIntegral="false" TipoContrato="1" Sueldo="2400000.0"/><Pago Forma="1" Metodo="10"/><FechasPagos><FechaPago>2024-04-30</FechaPago></FechasPagos><Devengados><Basico DiasTrabajados="30" SueldoTrabajado="2400000.00"/></Devengados><Deducciones><Salud Porcentaje="4.00" Deduccion="96000.0"/><FondoPension Porcentaje="4.00" Deduccion="96000.0"/></Deducciones><Redondeo>0</Redondeo><DevengadosTotal>2400000.00</DevengadosTotal><DeduccionesTotal>192000.00</DeduccionesTotal><ComprobanteTotal>2208000.00</ComprobanteTotal></NominaIndividual>
|
BIN
examples/habilitacion/N000003.zip
Normal file
BIN
examples/habilitacion/N000003.zip
Normal file
Binary file not shown.
123
examples/habilitacion/N000004.py
Normal file
123
examples/habilitacion/N000004.py
Normal file
@ -0,0 +1,123 @@
|
||||
|
||||
from facho import fe
|
||||
|
||||
SOFTWARE_PIN='20234'
|
||||
SOFTWARE_ID='100b0d10-0ca0-4ad4-a894-b704a568cbf3'
|
||||
NIT='901575528'
|
||||
DV='2'
|
||||
|
||||
def extensions(nomina):
|
||||
return []
|
||||
|
||||
def nomina():
|
||||
nomina = fe.nomina.DIANNominaIndividual()
|
||||
|
||||
nomina.asignar_fecha_pago('2024-04-30')
|
||||
|
||||
nomina.asignar_metadata(fe.nomina.Metadata(
|
||||
novedad=fe.nomina.Novedad(value='false'),
|
||||
secuencia=fe.nomina.NumeroSecuencia(
|
||||
prefijo='N',
|
||||
consecutivo='000004'
|
||||
),
|
||||
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(
|
||||
razon_social='BICI PIZZA S.A.S',
|
||||
nit=NIT,
|
||||
dv=DV,
|
||||
software_id=SOFTWARE_ID,
|
||||
software_pin=SOFTWARE_PIN
|
||||
)
|
||||
))
|
||||
|
||||
nomina.asignar_periodo(fe.nomina.Periodo(
|
||||
fecha_ingreso= '2022-09-05',
|
||||
fecha_liquidacion_inicio='2024-04-01',
|
||||
fecha_liquidacion_fin='2024-04-30',
|
||||
fecha_generacion='2024-04-30'
|
||||
))
|
||||
|
||||
nomina.asignar_informacion_general(fe.nomina.InformacionGeneral(
|
||||
fecha_generacion = '2024-04-30',
|
||||
hora_generacion = '08:01:00-05:00',
|
||||
tipo_ambiente = fe.nomina.InformacionGeneral.AMBIENTE_PRUEBAS,
|
||||
software_pin = 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(
|
||||
razon_social='BICI PIZZA S.A.S',
|
||||
nit = NIT,
|
||||
dv = DV,
|
||||
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 = 'GIRALDO',
|
||||
segundo_apellido = '',
|
||||
primer_nombre = 'VIVIANA',
|
||||
lugar_trabajo = fe.nomina.LugarTrabajo(
|
||||
pais = fe.nomina.Pais(code='CO'),
|
||||
departamento = fe.nomina.Departamento(code='05'),
|
||||
municipio = fe.nomina.Municipio(code='05001'),
|
||||
direccion = 'CL 35C 102-17 BL 7 AP 101'
|
||||
),
|
||||
numero_documento = NIT,
|
||||
tipo = fe.nomina.TipoTrabajador(
|
||||
code = '01'
|
||||
),
|
||||
salario_integral = False,
|
||||
sueldo = fe.nomina.Amount(1160000)
|
||||
))
|
||||
|
||||
nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
|
||||
dias_trabajados = 30,
|
||||
sueldo_trabajado = fe.nomina.Amount(1160000)
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||
porcentaje = fe.nomina.Amount(4),
|
||||
deduccion = fe.nomina.Amount(46400)
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionFondoPension(
|
||||
porcentaje=fe.nomina.Amount(4),
|
||||
deduccion = fe.nomina.Amount(46400)
|
||||
))
|
||||
return nomina
|
||||
|
89
examples/habilitacion/N000004.xml
Normal file
89
examples/habilitacion/N000004.xml
Normal file
@ -0,0 +1,89 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<NominaIndividual xmlns:atd="urn:oasis:names:specification:ubl:schema:xsd:AttachedDocument-2" xmlns="dian:gov:co:facturaelectronica:NominaIndividual" xmlns:fe="http://www.dian.gov.co/contratos/facturaelectronica/v1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" 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="dian:gov:co:facturaelectronica:Structures-2-1" 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:xades141="http://uri.etsi.org/01903/v1.4.1#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:sig="http://www.w3.org/2000/09/xmldsig#" SchemaLocation="" xsi:schemaLocation="dian:gov:co:facturaelectronica:NominaIndividual NominaIndividualElectronicaXSD.xsd"><ext:UBLExtensions><ext:UBLExtension><ext:ExtensionContent><ds:Signature Id="xmlsig-bf43fedd-6780-438f-afe3-ac062d8b8072">
|
||||
<ds:SignedInfo>
|
||||
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
||||
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
|
||||
<ds:Reference Id="xmldsig-bf43fedd-6780-438f-afe3-ac062d8b8072-ref0" URI="">
|
||||
<ds:Transforms>
|
||||
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
||||
</ds:Transforms>
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||
<ds:DigestValue>ZAE71pLQXXnN5+540pnkxH5ALNBQcecMdLWFKTKby0g=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
<ds:Reference Id="xmldsig-bf43fedd-6780-438f-afe3-ac062d8b8072-ref1" URI="#xmldsig-bf43fedd-6780-438f-afe3-ac062d8b8072-KeyInfo">
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||
<ds:DigestValue>kNyh65TH4KfF6wqRoy1duEawgkvOlr2rYLCNfdTfK1c=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
<ds:Reference URI="#xmldsig-bf43fedd-6780-438f-afe3-ac062d8b8072-signedprops" Type="http://uri.etsi.org/01903#SignedProperties">
|
||||
<ds:Transforms>
|
||||
<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
||||
</ds:Transforms>
|
||||
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
|
||||
<ds:DigestValue>BoPBi5C0tXfV04cf74M4jktBxf9eVsXk5IWqGdeOSHw=</ds:DigestValue>
|
||||
</ds:Reference>
|
||||
</ds:SignedInfo>
|
||||
<ds:SignatureValue>pw5WDlbd4GhnSAJKlTEDjsb1+VAVtyyXWA/isvGz4LHY5n1Fm4hiN7fD3JIrfOBj
|
||||
z/tUfROLzbbywUnVklfaDri6txZlFFwa9SY8MO38bgE0HUxGq5khb/4uzktGRInp
|
||||
H3i0TG5i42YB83PQItSLiEgPWqGVolj5sWfUqD81Ck4CvgtKuZgnn9JPLgP0sjjT
|
||||
BUjKcMt4K+ZLvXumehKKCzEbtoaa5DHKUrpuCU2giGMMPElwaTulFA5kNLBnAk2n
|
||||
HBCiIq+YZ2C3BqE+WQptcQDIObmEnRURvvUTB64gCh4Tigmq6vnv/dMPWmQvohmp
|
||||
ETIZDwU0/xdGcUK7Ujyl4g==</ds:SignatureValue>
|
||||
<ds:KeyInfo Id="xmldsig-bf43fedd-6780-438f-afe3-ac062d8b8072-KeyInfo">
|
||||
<ds:X509Data>
|
||||
<ds:X509Certificate>MIIH8TCCBdmgAwIBAgIIQxaPJd4YTlMwDQYJKoZIhvcNAQELBQAwgbYxIzAhBgkq
|
||||
hkiG9w0BCQEWFGluZm9AYW5kZXNzY2QuY29tLmNvMSYwJAYDVQQDEx1DQSBBTkRF
|
||||
UyBTQ0QgUy5BLiBDbGFzZSBJSSB2MzEwMC4GA1UECxMnRGl2aXNpb24gZGUgY2Vy
|
||||
dGlmaWNhY2lvbiBlbnRpZGFkIGZpbmFsMRIwEAYDVQQKEwlBbmRlcyBTQ0QxFDAS
|
||||
BgNVBAcTC0JvZ290YSBELkMuMQswCQYDVQQGEwJDTzAeFw0yNDA1MTYwNTAwMDBa
|
||||
Fw0yNTA1MTYwNDU5MDBaMIIBQDEtMCsGA1UECRMkVFYgNDYgQyA0MiBFU1RFIDc4
|
||||
OSBDT1JSIFNBTlRBIEVMRU5BMSIwIAYJKoZIhvcNAQkBFhNiaWNpcGl6emFAZ21h
|
||||
aWwuY29tMRowGAYDVQQDExFCSUNJIFBJWlpBIFMuQS5TLjETMBEGA1UEBRMKOTAx
|
||||
NTc1NTI4MjE2MDQGA1UEDBMtRW1pc29yIEZhY3R1cmEgRWxlY3Ryb25pY2EgLSBQ
|
||||
ZXJzb25hIEp1cmlkaWNhMTswOQYDVQQLEzJFbWl0aWRvIHBvciBBbmRlcyBTQ0Qg
|
||||
QWMgMjYgNjkgQyAwMyBUb3JyZSBCIE9mIDcwMTEQMA4GA1UEChMHR0VSRU5URTES
|
||||
MBAGA1UEBwwJTUVERUxMw41OMRIwEAYDVQQIEwlBTlRJT1FVSUExCzAJBgNVBAYT
|
||||
AkNPMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5J1O+4ZedrSBUsb+
|
||||
9tjNPHI9RGeIJcJl3Wc/208OqMYcCwGLUkrYBgH78E7IayD5/wra04OU57cS1/+/
|
||||
yBUWYR60oqkaH2/8OXkJMqmjisVM/b58m7zyMw4TAF8N/PbswnrKukFU2acxISwT
|
||||
Lu36HC4hshWw8bEGP54szvv1xnwqcOAWNBCxcBuc9k1JD+SIiqqPwHKh+6EDIoou
|
||||
jo0H15w3rAxkHQRvYe6/IrpvH2sqJl1I3dLv0iqy9+d2l891KBA9Yebdw7m/+ufu
|
||||
+eqs+0zKrwV6QLhRFmceHzEkPMTFepc2COGf80OUNbI6WWnspvDK97D8YG0MeifP
|
||||
YveIPwIDAQABo4ICdDCCAnAwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRA/iZp
|
||||
RzInMtGsIcgu7M+N1TVo6DBvBggrBgEFBQcBAQRjMGEwNgYIKwYBBQUHMAKGKmh0
|
||||
dHA6Ly9jZXJ0cy5hbmRlc3NjZC5jb20uY28vQ2xhc2VJSXYzLmNydDAnBggrBgEF
|
||||
BQcwAYYbaHR0cDovL29jc3AuYW5kZXNzY2QuY29tLmNvMB4GA1UdEQQXMBWBE2Jp
|
||||
Y2lwaXp6YUBnbWFpbC5jb20wggEjBgNVHSAEggEaMIIBFjCBwQYNKwYBBAGB9EgB
|
||||
AgYIADCBrzCBrAYIKwYBBQUHAgIwgZ8MgZxMYSB1dGlsaXphY2nDs24gZGUgZXN0
|
||||
ZSBjZXJ0aWZpY2FkbyBlc3TDoSBzdWpldGEgYSBsYSBQQyBkZSBGYWN0dXJhY2nD
|
||||
s24gRWxlY3Ryw7NuaWNhIHkgRFBDIGVzdGFibGVjaWRhcyBwb3IgQW5kZXMgU0NE
|
||||
LiBDw7NkaWdvIGRlIEFjcmVkaXRhY2nDs246IDE2LUVDRC0wMDQwUAYNKwYBBAGB
|
||||
9EgBAQEKADA/MD0GCCsGAQUFBwIBFjFodHRwczovL3d3dy5hbmRlc3NjZC5jb20u
|
||||
Y28vZG9jcy9EUENfQW5kZXNTQ0QucGRmMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr
|
||||
BgEFBQcDBDA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vY3JsLmFuZGVzc2NkLmNv
|
||||
bS5jby9DbGFzZUlJdjMuY3JsMB0GA1UdDgQWBBRKPoh3BJM7SxEL0UXkSne2MyFO
|
||||
jjAOBgNVHQ8BAf8EBAMCBeAwDQYJKoZIhvcNAQELBQADggIBAA6Zzor3kpJ6vNKv
|
||||
TAeHaMfmJ/PaghQ1+Lab7Pwk+lsPsMETFu/IpEK5qij2bV54UNnqyLYOZtIbnWTG
|
||||
qgT7QxQvy+/of/I3zzF+kH4/Lp2TSlHaDEb/airCZ3I2G23M9iaZzSwYuOsOaGwp
|
||||
4ovkXlYwQ7FVNfIIoAq95m9cBAigb06bRIlVBVTQq44hQFQQG6aSIT7SSPtCwPhB
|
||||
5CJzG09pmgbxizqN/yxdjWdfW6Av79dh6K4uQT++Vtyp5DuAkmfn0ehayrUbDLkH
|
||||
9jQFF128U5pnOPfKWf22acXqQBapesUSV/HZUZ3PXoWeHWXcMdz0azxOEunS4+px
|
||||
fs5UzInRAmEcYwJHqJT3irFz+J2RsZ0WnJHrTGqFoXniQQH8QbCHehDTGN7/v/v1
|
||||
LQBr5PQBnSEWhmrQ9uFrwPyMMg3yd+L75TaHLZ0MTSVezAG52oM9jBiU5tYXkSio
|
||||
EfPdIsGlG74BybULGSG2OlTINlblj/lj7pL67V+gY9EGN1zzNKL5sW4YXlXewa6K
|
||||
dTpLmmzWzI8Cm+tOuuJDSHSwMjn525O+Z/oyKLjdQdyfg1KnZYwNZFpMmCwfP5nd
|
||||
cm4F7Anzb9HX9ciluAxc6as9TsNoDDTSAGPuUr0QvXqXd9ZCgXdNzdFeiaYknLP5
|
||||
hT4f5CoO2M8qcG+CH7HnkaOHrSuK</ds:X509Certificate>
|
||||
</ds:X509Data>
|
||||
<ds:KeyValue>
|
||||
<ds:RSAKeyValue>
|
||||
<ds:Modulus>5J1O+4ZedrSBUsb+9tjNPHI9RGeIJcJl3Wc/208OqMYcCwGLUkrYBgH78E7IayD5
|
||||
/wra04OU57cS1/+/yBUWYR60oqkaH2/8OXkJMqmjisVM/b58m7zyMw4TAF8N/Pbs
|
||||
wnrKukFU2acxISwTLu36HC4hshWw8bEGP54szvv1xnwqcOAWNBCxcBuc9k1JD+SI
|
||||
iqqPwHKh+6EDIooujo0H15w3rAxkHQRvYe6/IrpvH2sqJl1I3dLv0iqy9+d2l891
|
||||
KBA9Yebdw7m/+ufu+eqs+0zKrwV6QLhRFmceHzEkPMTFepc2COGf80OUNbI6WWns
|
||||
pvDK97D8YG0MeifPYveIPw==</ds:Modulus>
|
||||
<ds:Exponent>AQAB</ds:Exponent>
|
||||
</ds:RSAKeyValue>
|
||||
</ds:KeyValue>
|
||||
</ds:KeyInfo>
|
||||
<ds:Object><xades:QualifyingProperties Target="#xmlsig-bf43fedd-6780-438f-afe3-ac062d8b8072" Id="XadesObjects"><xades:SignedProperties Id="xmldsig-bf43fedd-6780-438f-afe3-ac062d8b8072-signedprops"><xades:SignedSignatureProperties><xades:SigningTime>2025-03-16T16:51:26.699846</xades:SigningTime><xades:SigningCertificate><xades:Cert><xades:CertDigest><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>YcIPspAVFcNg+B/galYrdCLYvLIEwFI4KWdSzcuupPY=</ds:DigestValue></xades:CertDigest><xades:IssuerSerial><ds:X509IssuerName>C=CO, L=Bogota D.C., O=Andes SCD, OU=Division de certificacion entidad final, CN=CA ANDES SCD S.A. Clase II v3, OID.1.2.840.113549.1.9.1=info@andesscd.com.co</ds:X509IssuerName><ds:X509SerialNumber>4834208642831502931</ds:X509SerialNumber></xades:IssuerSerial></xades:Cert></xades:SigningCertificate><xades:SignaturePolicyIdentifier><xades:SignaturePolicyId><xades:SigPolicyId><xades:Identifier>https://facturaelectronica.dian.gov.co/politicadefirma/v2/politicadefirmav2.pdf</xades:Identifier><xades:Description>Política de firma para facturas electrónicas de la República de Colombia.</xades:Description></xades:SigPolicyId><xades:SigPolicyHash><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>dMoMvtcG5aIzgYo0tIsSQeVJBDnUnfSOfBpxXrmor0Y=</ds:DigestValue></xades:SigPolicyHash></xades:SignaturePolicyId></xades:SignaturePolicyIdentifier><xades:SignerRole><xades:ClaimedRoles><xades:ClaimedRole>supplier</xades:ClaimedRole></xades:ClaimedRoles></xades:SignerRole></xades:SignedSignatureProperties></xades:SignedProperties></xades:QualifyingProperties></ds:Object></ds:Signature></ext:ExtensionContent></ext:UBLExtension></ext:UBLExtensions><Novedad CUNENov="false">false</Novedad><Periodo FechaIngreso="2022-09-05" FechaLiquidacionInicio="2024-04-01" FechaLiquidacionFin="2024-04-30" TiempoLaborado="1" FechaGen="2024-04-30"/><NumeroSecuenciaXML Prefijo="N" Consecutivo="000004" Numero="N000004"/><LugarGeneracionXML Pais="CO" DepartamentoEstado="05" MunicipioCiudad="05001" Idioma="es"/><ProveedorXML NIT="901575528" DV="2" SoftwareID="100b0d10-0ca0-4ad4-a894-b704a568cbf3" RazonSocial="BICI PIZZA S.A.S" SoftwareSC="61d2d18fc61f70cff4f5c5c2a5e17e5c904bf42179a8118242e994b40c22ef203741568ee51d94b81a7fbde4ea6a79aa"/><CodigoQR>https://catalogo-vpfe-hab.dian.gov.co/document/searchqr?documentkey=40d20d7af2d7ee471909e62fcb4beef7de82494e6c8df4e8349ca33a1246dea601b4cc9035e18972e853ecd435799eaa</CodigoQR><InformacionGeneral Version="V1.0: Documento Soporte de Pago de Nómina Electrónica" Ambiente="2" TipoXML="102" EncripCUNE="CUNE-SHA384" FechaGen="2024-04-30" HoraGen="08:01:00-05:00" PeriodoNomina="1" TipoMoneda="COP" TRM="0" CUNE="40d20d7af2d7ee471909e62fcb4beef7de82494e6c8df4e8349ca33a1246dea601b4cc9035e18972e853ecd435799eaa"/><Empleador NIT="901575528" DV="2" Pais="CO" DepartamentoEstado="05" MunicipioCiudad="05001" Direccion="calle etrivial" RazonSocial="BICI PIZZA S.A.S"/><Trabajador TipoTrabajador="01" SubTipoTrabajador="00" AltoRiesgoPension="false" TipoDocumento="11" NumeroDocumento="901575528" PrimerApellido="GIRALDO" SegundoApellido="" PrimerNombre="VIVIANA" LugarTrabajoPais="CO" LugarTrabajoDepartamentoEstado="05" LugarTrabajoMunicipioCiudad="05001" LugarTrabajoDireccion="CL 35C 102-17 BL 7 AP 101" SalarioIntegral="false" TipoContrato="1" Sueldo="1160000.0"/><Pago Forma="1" Metodo="10"/><FechasPagos><FechaPago>2024-04-30</FechaPago></FechasPagos><Devengados><Basico DiasTrabajados="30" SueldoTrabajado="1160000.00"/></Devengados><Deducciones><Salud Porcentaje="4.00" Deduccion="46400.0"/><FondoPension Porcentaje="4.00" Deduccion="46400.0"/></Deducciones><Redondeo>0</Redondeo><DevengadosTotal>1160000.00</DevengadosTotal><DeduccionesTotal>92800.00</DeduccionesTotal><ComprobanteTotal>1067200.00</ComprobanteTotal></NominaIndividual>
|
BIN
examples/habilitacion/N000004.zip
Normal file
BIN
examples/habilitacion/N000004.zip
Normal file
Binary file not shown.
@ -1,127 +1,109 @@
|
||||
# importar libreria de modelos
|
||||
from facho import fe, form_xml
|
||||
import facho.fe.form as form
|
||||
import datetime
|
||||
|
||||
PRIVATE_KEY_PATH = 'ruta a mi llave privada'
|
||||
PRIVATE_PASSPHRASE = 'clave de la llave privada'
|
||||
import facho.fe.form_xml
|
||||
|
||||
PRIVATE_KEY_PATH='ruta a mi llave privada'
|
||||
PRIVATE_PASSPHRASE='clave de la llave privada'
|
||||
|
||||
# consultar las extensiones necesarias
|
||||
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()
|
||||
cufe = fe.DianXMLExtensionCUFE(
|
||||
inv, fe.DianXMLExtensionCUFE.AMBIENTE_PRUEBAS,
|
||||
'clave tecnica')
|
||||
cufe = fe.DianXMLExtensionCUFE(inv, fe.DianXMLExtensionCUFE.AMBIENTE_PRUEBAS,
|
||||
'clave tecnica')
|
||||
nit = form.PartyIdentification('nit', '5', '31')
|
||||
software_provider = fe.DianXMLExtensionSoftwareProvider(
|
||||
nit, nit.dv, 'id software')
|
||||
inv_authorization = fe.DianXMLExtensionInvoiceAuthorization(
|
||||
'invoice autorization',
|
||||
datetime(2019, 1, 19),
|
||||
datetime(2030, 1, 19),
|
||||
'SETP', 990000001, 995000000)
|
||||
return [
|
||||
security_code,
|
||||
authorization_provider,
|
||||
cufe, software_provider,
|
||||
inv_authorization
|
||||
]
|
||||
|
||||
software_provider = fe.DianXMLExtensionSoftwareProvider(nit, nit.dv, 'id software')
|
||||
inv_authorization = fe.DianXMLExtensionInvoiceAuthorization('invoice autorization',
|
||||
datetime(2019, 1, 19),
|
||||
datetime(2030, 1, 19),
|
||||
'SETP', 990000001, 995000000)
|
||||
return [security_code, authorization_provider, cufe, software_provider, inv_authorization]
|
||||
|
||||
# generar documento desde modelo a ruta indicada
|
||||
def generate_document(invoice, filepath):
|
||||
xml = form_xml.DIANInvoiceXML(invoice)
|
||||
for extension in extensions(invoice):
|
||||
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
|
||||
# ...
|
||||
|
||||
# factura de venta nacional
|
||||
inv = form.NationalSalesInvoice()
|
||||
|
||||
# asignar periodo de facturacion
|
||||
inv.set_period(datetime.now(), datetime.now())
|
||||
|
||||
# asignar fecha de emision de la factura
|
||||
|
||||
inv.set_issue(datetime.now())
|
||||
# asignar prefijo y numero del documento
|
||||
|
||||
inv.set_ident('SETP990003033')
|
||||
# asignar tipo de operacion ver DIAN:6.1.5
|
||||
inv.set_operation_type('10')
|
||||
|
||||
# asignar proveedor
|
||||
inv.set_supplier(form.Party(
|
||||
legal_name='FACHOSOS',
|
||||
name='FACHOSOS',
|
||||
ident=form.PartyIdentification('900579212', '5', '31'),
|
||||
legal_name = 'FACHO SOS',
|
||||
name = 'FACHO SOS',
|
||||
ident = form.PartyIdentification('900579212', '5', '31'),
|
||||
# obligaciones del contribuyente ver DIAN:FAK26
|
||||
responsability_code=form.Responsability(['ZZ', 'O-09', 'O-14', 'O-48']),
|
||||
responsability_code = form.Responsability(['O-07', 'O-09', 'O-14', 'O-48']),
|
||||
# ver DIAN:FAJ28
|
||||
responsability_regime_code='48',
|
||||
responsability_regime_code = '48',
|
||||
# tipo de organizacion juridica ver DIAN:6.2.3
|
||||
organization_code='1',
|
||||
email="sdds@sd.com",
|
||||
address=form.Address(
|
||||
name='',
|
||||
street='',
|
||||
city=form.City('05001', 'Medellín'),
|
||||
country=form.Country('CO', 'Colombia'),
|
||||
countrysubentity=form.CountrySubentity('05', 'Antioquia'))
|
||||
organization_code = '1',
|
||||
email = "sdds@sd.com",
|
||||
address = form.Address(
|
||||
name = '',
|
||||
street = '',
|
||||
city = form.City('05001', 'Medellín'),
|
||||
country = form.Country('CO', 'Colombia'),
|
||||
countrysubentity = form.CountrySubentity('05', 'Antioquia'))
|
||||
))
|
||||
|
||||
inv.set_customer(form.Party(
|
||||
legal_name='facho-customer',
|
||||
name='facho-customer',
|
||||
ident=form.PartyIdentification('999999999', '', '13'),
|
||||
responsability_code=form.Responsability(['R-99-PN']),
|
||||
responsability_regime_code='49',
|
||||
organization_code='2',
|
||||
email="sdds@sd.com",
|
||||
address=form.Address(
|
||||
name='',
|
||||
street='',
|
||||
city=form.City('05001', 'Medellín'),
|
||||
country=form.Country('CO', 'Colombia'),
|
||||
countrysubentity=form.CountrySubentity('05', 'Antioquia'))
|
||||
legal_name = 'facho-customer',
|
||||
name = 'facho-customer',
|
||||
ident = form.PartyIdentification('999999999', '', '13'),
|
||||
responsability_code = form.Responsability(['R-99-PN']),
|
||||
responsability_regime_code = '49',
|
||||
organization_code = '2',
|
||||
email = "sdds@sd.com",
|
||||
address = form.Address(
|
||||
name = '',
|
||||
street = '',
|
||||
city = form.City('05001', 'Medellín'),
|
||||
country = form.Country('CO', 'Colombia'),
|
||||
countrysubentity = form.CountrySubentity('05', 'Antioquia'))
|
||||
))
|
||||
# asignar metodo de pago
|
||||
inv.set_payment_mean(form.PaymentMean(
|
||||
# metodo de pago ver DIAN:3.4.1
|
||||
id='1',
|
||||
id = '1',
|
||||
# codigo correspondiente al medio de pago ver DIAN:3.4.2
|
||||
code='10',
|
||||
code = '10',
|
||||
# fecha de vencimiento de la factura
|
||||
due_at=datetime.now(),
|
||||
due_at = datetime.now(),
|
||||
|
||||
# identificador numerico
|
||||
payment_id='1'
|
||||
payment_id = '1'
|
||||
))
|
||||
# adicionar una linea al documento
|
||||
inv.add_invoice_line(form.InvoiceLine(
|
||||
quantity=form.Quantity(1, '94'),
|
||||
description='producto facho',
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto facho',
|
||||
# item general de codigo 999
|
||||
item=form.StandardItem('test', 9999),
|
||||
price=form.Price(
|
||||
item = form.StandardItem('test', 9999),
|
||||
price = form.Price(
|
||||
# precio base del tiem
|
||||
amount=form.Amount(100.00),
|
||||
amount = form.Amount(100.00),
|
||||
# ver DIAN:6.3.5.1
|
||||
type_code='01',
|
||||
type='x'
|
||||
type_code = '01',
|
||||
type = 'x'
|
||||
),
|
||||
tax=form.TaxTotal(
|
||||
subtotals=[
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
percent=19.00,
|
||||
)]
|
||||
percent = 19.00,
|
||||
)
|
||||
]
|
||||
)
|
||||
))
|
||||
|
||||
|
@ -76,7 +76,7 @@
|
||||
<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>
|
||||
<cbc:TaxLevelCode listName="48">O-07;O-09;O-14;O-48</cbc:TaxLevelCode>
|
||||
<cac:TaxScheme/>
|
||||
</cac:PartyTaxScheme>
|
||||
<cac:Contact>
|
||||
|
@ -259,14 +259,14 @@ def generate_invoice(private_key, passphrase, scriptname, generate=False, ssl=Tr
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
import facho.fe.form as form
|
||||
from facho.fe.form_xml import DIANInvoiceXML, DIANWriteSigned, DIANWrite, DIANSupportDocumentXML
|
||||
from facho.fe.form_xml import DIANInvoiceXML, DIANWriteSigned,DIANWrite
|
||||
from facho import fe
|
||||
|
||||
try:
|
||||
invoice_xml = module.document_xml()
|
||||
except AttributeError:
|
||||
#invoice_xml = DIANInvoiceXML
|
||||
invoice_xml = DIANSupportDocumentXML
|
||||
invoice_xml = DIANInvoiceXML
|
||||
|
||||
print("Using document xml:", invoice_xml)
|
||||
invoice = module.invoice()
|
||||
invoice.calculate()
|
||||
|
@ -1,11 +1,12 @@
|
||||
# This file is part of facho. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from lxml import etree
|
||||
from lxml.etree import Element, tostring
|
||||
from lxml.etree import Element, SubElement, tostring
|
||||
import re
|
||||
from collections import defaultdict
|
||||
from copy import deepcopy
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
class FachoValueInvalid(Exception):
|
||||
def __init__(self, xpath):
|
||||
@ -31,10 +32,7 @@ class LXMLBuilder:
|
||||
|
||||
def __init__(self, nsmap):
|
||||
self.nsmap = nsmap
|
||||
self._re_node_expr = \
|
||||
re.compile(
|
||||
r'^(?P<path>((?P<ns>\w+):)?(?P<tag>[a-zA-Z0-9_-]+))'
|
||||
r'(?P<attrs>\[.+\])?')
|
||||
self._re_node_expr = re.compile(r'^(?P<path>((?P<ns>\w+):)?(?P<tag>[a-zA-Z0-9_-]+))(?P<attrs>\[.+\])?')
|
||||
self._re_attrs = re.compile(r'(\w+)\s*=\s*\"?(\w+)\"?')
|
||||
|
||||
def match_expression(self, node_expr):
|
||||
@ -123,7 +121,7 @@ class LXMLBuilder:
|
||||
elem.attrib[key] = value
|
||||
|
||||
@classmethod
|
||||
def remove_attributes(cls, elem, keys, exclude=[]):
|
||||
def remove_attributes(cls, elem, keys, exclude = []):
|
||||
for key in keys:
|
||||
if key in exclude:
|
||||
continue
|
||||
@ -145,8 +143,7 @@ class LXMLBuilder:
|
||||
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']:
|
||||
if is_optional and el.getchildren() == [] and el.keys() == ['facho_optional']:
|
||||
el.getparent().remove(el)
|
||||
|
||||
return tostring(elem, **attrs).decode('utf-8')
|
||||
@ -156,15 +153,14 @@ class FachoXML:
|
||||
"""
|
||||
Decora XML con funciones de consulta XPATH de un solo elemento
|
||||
"""
|
||||
def __init__(self, root, builder=None, nsmap=None, fragment_prefix='',
|
||||
fragment_root_element=None):
|
||||
def __init__(self, root, builder=None, nsmap=None, fragment_prefix='',fragment_root_element=None):
|
||||
if builder is None:
|
||||
self.builder = LXMLBuilder(nsmap)
|
||||
else:
|
||||
self.builder = builder
|
||||
|
||||
self.nsmap = nsmap
|
||||
|
||||
|
||||
if isinstance(root, str):
|
||||
self.root = self.builder.build_element_from_string(root, nsmap)
|
||||
else:
|
||||
@ -181,22 +177,16 @@ class FachoXML:
|
||||
xml = LXMLBuilder.from_string(document)
|
||||
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):
|
||||
# elem = self.find_or_create_element(xpath, append=append)
|
||||
# self.builder.append(elem, new_elem)
|
||||
#elem = self.find_or_create_element(xpath, append=append)
|
||||
#self.builder.append(elem, new_elem)
|
||||
self.builder.append(elem, new_elem)
|
||||
|
||||
def add_extension(self, extension):
|
||||
extension.build(self)
|
||||
|
||||
def fragment(
|
||||
self, xpath, append=False, append_not_exists=False):
|
||||
|
||||
def fragment(self, xpath, append=False, append_not_exists=False):
|
||||
nodes = xpath.split('/')
|
||||
nodes.pop()
|
||||
root_prefix = '/'.join(nodes)
|
||||
@ -206,9 +196,7 @@ class FachoXML:
|
||||
|
||||
if parent is None:
|
||||
parent = self.find_or_create_element(xpath, append=append)
|
||||
return FachoXML(
|
||||
parent, nsmap=self.nsmap, fragment_prefix=root_prefix,
|
||||
fragment_root_element=self.root)
|
||||
return FachoXML(parent, nsmap=self.nsmap, fragment_prefix=root_prefix, fragment_root_element=self.root)
|
||||
|
||||
def register_alias_xpath(self, alias, xpath):
|
||||
self.xpath_for[alias] = xpath
|
||||
@ -244,8 +232,7 @@ class FachoXML:
|
||||
"""
|
||||
xpath = self._path_xpath_for(xpath)
|
||||
node_paths = xpath.split('/')
|
||||
# remove empty /
|
||||
node_paths.pop(0)
|
||||
node_paths.pop(0) #remove empty /
|
||||
root_tag = node_paths.pop(0)
|
||||
|
||||
root_node = self.builder.build_from_expression(root_tag)
|
||||
@ -253,10 +240,10 @@ class FachoXML:
|
||||
# restaurar ya que no es la raiz y asignar actual como raiz
|
||||
node_paths.insert(0, root_tag)
|
||||
root_node = self.root
|
||||
|
||||
|
||||
if not self.builder.same_tag(root_node.tag, self.root.tag):
|
||||
raise ValueError('xpath %s must be absolute to /%s' % (
|
||||
xpath, self.root.tag))
|
||||
|
||||
raise ValueError('xpath %s must be absolute to /%s' % (xpath, self.root.tag))
|
||||
|
||||
# crea jerarquia segun xpath indicado
|
||||
parent = None
|
||||
@ -266,8 +253,8 @@ class FachoXML:
|
||||
for node_path in node_paths:
|
||||
node_expr = self.builder.match_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
|
||||
if child is not None:
|
||||
@ -278,12 +265,11 @@ class FachoXML:
|
||||
|
||||
node_expr = self.builder.match_expression(node_tag)
|
||||
node = self.builder.build_from_expression(node_tag)
|
||||
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
|
||||
if child is not None:
|
||||
current_elem = child
|
||||
|
||||
|
||||
if parent == current_elem:
|
||||
self.builder.append(parent, node)
|
||||
return node
|
||||
@ -300,10 +286,9 @@ class FachoXML:
|
||||
self.builder.append(parent, node)
|
||||
return node
|
||||
|
||||
if self.builder.is_attribute(
|
||||
last_slibing, 'facho_placeholder', 'True'):
|
||||
if self.builder.is_attribute(last_slibing, 'facho_placeholder', 'True'):
|
||||
self._remove_facho_attributes(last_slibing)
|
||||
return last_slibing
|
||||
return last_slibing
|
||||
self.builder.append_next(last_slibing, node)
|
||||
return node
|
||||
|
||||
@ -314,8 +299,7 @@ class FachoXML:
|
||||
self._remove_facho_attributes(current_elem)
|
||||
return current_elem
|
||||
|
||||
def set_element_validator(
|
||||
self, xpath, validator=False):
|
||||
def set_element_validator(self, xpath, validator = False):
|
||||
"""
|
||||
validador al asignar contenido a xpath indicado
|
||||
|
||||
@ -328,9 +312,8 @@ class FachoXML:
|
||||
self._validators[key] = lambda v, attrs: True
|
||||
else:
|
||||
self._validators[key] = validator
|
||||
|
||||
def set_element(
|
||||
self, xpath, content, **attrs):
|
||||
|
||||
def set_element(self, xpath, content, **attrs):
|
||||
"""
|
||||
asigna contenido ubicado por ruta tipo XPATH.
|
||||
@param xpath ruta tipo XPATH
|
||||
@ -372,8 +355,7 @@ class FachoXML:
|
||||
self.builder.set_attribute(elem, k, str(v))
|
||||
return self
|
||||
|
||||
def get_element_attribute(
|
||||
self, xpath, attribute, multiple=False):
|
||||
def get_element_attribute(self, xpath, attribute, multiple=False):
|
||||
elem = self.get_element(xpath, multiple=multiple)
|
||||
|
||||
if elem is None:
|
||||
@ -410,16 +392,14 @@ class FachoXML:
|
||||
return None
|
||||
return format_(text)
|
||||
|
||||
def get_element_text_or_attribute(
|
||||
self, xpath, default=None, multiple=False, raise_on_fail=False):
|
||||
def get_element_text_or_attribute(self, xpath, default=None, multiple=False, raise_on_fail=False):
|
||||
parts = xpath.split('/')
|
||||
is_attribute = parts[-1].startswith('@')
|
||||
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)
|
||||
val = self.get_element_attribute(element_path, attribute_name, multiple=multiple)
|
||||
if val is None:
|
||||
return default
|
||||
return val
|
||||
@ -452,8 +432,7 @@ class FachoXML:
|
||||
if isinstance(xpath, tuple):
|
||||
val = xpath[0]
|
||||
else:
|
||||
val = self.get_element_text_or_attribute(
|
||||
xpath, raise_on_fail=raise_on_fail)
|
||||
val = self.get_element_text_or_attribute(xpath, raise_on_fail=raise_on_fail)
|
||||
vals.append(val)
|
||||
return vals
|
||||
|
||||
@ -475,8 +454,7 @@ class FachoXML:
|
||||
return True
|
||||
|
||||
def _remove_facho_attributes(self, elem):
|
||||
self.builder.remove_attributes(
|
||||
elem, ['facho_optional', 'facho_placeholder'])
|
||||
self.builder.remove_attributes(elem, ['facho_optional', 'facho_placeholder'])
|
||||
|
||||
def tostring(self, **kw):
|
||||
return self.builder.tostring(self.root, **kw)
|
||||
@ -488,17 +466,15 @@ class FachoXML:
|
||||
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('/')
|
||||
new_xpath = '/' + ns + etree.QName(root).localname + '/' + etree.QName(self.root).localname + '/' + xpath.lstrip('/')
|
||||
else:
|
||||
new_xpath = '/' + ns + etree.QName(root).localname + '/' + \
|
||||
xpath.lstrip('/')
|
||||
new_xpath = '/' + ns + etree.QName(root).localname + '/' + xpath.lstrip('/')
|
||||
return new_xpath
|
||||
|
||||
def __str__(self):
|
||||
|
@ -5,7 +5,6 @@ from .fe import DianXMLExtensionSigner
|
||||
from .fe import DianXMLExtensionSoftwareSecurityCode
|
||||
from .fe import DianXMLExtensionCUFE
|
||||
from .fe import DianXMLExtensionCUDE
|
||||
from .fe import DianXMLExtensionCUDS
|
||||
from .fe import DianXMLExtensionInvoiceAuthorization
|
||||
from .fe import DianXMLExtensionSoftwareProvider
|
||||
from .fe import DianXMLExtensionAuthorizationProvider
|
||||
|
@ -234,10 +234,9 @@ def _append_timestamp(security, expires_dt=None):
|
||||
if expires_dt is None:
|
||||
expires_dt = timedelta(seconds=6000)
|
||||
|
||||
timestamp = datetime.now()
|
||||
etimestamp = utils.WSU.Timestamp({'{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Id': utils.get_unique_id()})
|
||||
etimestamp.append(utils.WSU.Created(get_timestamp(timestamp=timestamp)))
|
||||
etimestamp.append(utils.WSU.Expires(get_timestamp(timestamp=timestamp, delta=expires_dt)))
|
||||
etimestamp.append(utils.WSU.Created(get_timestamp()))
|
||||
etimestamp.append(utils.WSU.Expires(get_timestamp(delta=expires_dt)))
|
||||
security.insert(0, etimestamp)
|
||||
if etree.LXML_VERSION[:2] >= (3, 5):
|
||||
etree.cleanup_namespaces(security,
|
||||
|
@ -1,61 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 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/">
|
||||
<Identification>
|
||||
<ShortName>TarifaImpuestos</ShortName>
|
||||
<LongName xml:lang="es">Tarifas por Impuesto</LongName>
|
||||
<Version>1</Version>
|
||||
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TarifaImpuestos</CanonicalUri>
|
||||
<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>
|
||||
<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>
|
||||
<LongName xml:lang="es">Codigo Comun</LongName>
|
||||
<Data Type="normalizedString"/>
|
||||
</Column>
|
||||
<Column Id="name" Use="required">
|
||||
<ShortName>Name</ShortName>
|
||||
<LongName xml:lang="es">Nombre</LongName>
|
||||
<Data Type="string"/>
|
||||
</Column>
|
||||
<Column Id="description" Use="required">
|
||||
<ShortName>Description</ShortName>
|
||||
<LongName xml:lang="es">Descripcion</LongName>
|
||||
<Data Type="string"/>
|
||||
</Column>
|
||||
<Key Id="codeKey">
|
||||
<ShortName>CodeKey</ShortName>
|
||||
<ColumnRef Ref="code"/>
|
||||
</Key>
|
||||
</ColumnSet>
|
||||
<SimpleCodeList>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>15.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteIVA</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>ReteIVA</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<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>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 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/">
|
||||
<Identification>
|
||||
<ShortName>TarifaImpuestos</ShortName>
|
||||
<LongName xml:lang="es">Tarifas por Impuesto</LongName>
|
||||
<Version>1</Version>
|
||||
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TarifaImpuestos</CanonicalUri>
|
||||
<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>
|
||||
<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>
|
||||
<LongName xml:lang="es">Codigo Comun</LongName>
|
||||
<Data Type="normalizedString"/>
|
||||
</Column>
|
||||
<Column Id="name" Use="required">
|
||||
<ShortName>Name</ShortName>
|
||||
<LongName xml:lang="es">Nombre</LongName>
|
||||
<Data Type="string"/>
|
||||
</Column>
|
||||
<Column Id="description" Use="required">
|
||||
<ShortName>Description</ShortName>
|
||||
<LongName xml:lang="es">Descripcion</LongName>
|
||||
<Data Type="string"/>
|
||||
</Column>
|
||||
<Key Id="codeKey">
|
||||
<ShortName>CodeKey</ShortName>
|
||||
<ColumnRef Ref="code"/>
|
||||
</Key>
|
||||
</ColumnSet>
|
||||
<SimpleCodeList>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>15.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteIVA</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>ReteIVA</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
</SimpleCodeList>
|
||||
</gc:CodeList>
|
||||
|
@ -1,100 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 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/">
|
||||
<Identification>
|
||||
<ShortName>TipoDocumento</ShortName>
|
||||
<LongName xml:lang="es">Tipo de Documento</LongName>
|
||||
<Version>1</Version>
|
||||
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoDocumento</CanonicalUri>
|
||||
<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>
|
||||
<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>
|
||||
<LongName xml:lang="es">Codigo Comun</LongName>
|
||||
<Data Type="normalizedString"/>
|
||||
</Column>
|
||||
<Column Id="name" Use="required">
|
||||
<ShortName>Name</ShortName>
|
||||
<LongName xml:lang="es">Nombre</LongName>
|
||||
<Data Type="string"/>
|
||||
</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>Factura electrónica de Venta</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Tipos de factura</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>02</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Factura electrónica de venta con propósito de exportación</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Tipos de factura</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>03</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Factura de talonario o papel con numeración de contingencia.</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Tipos de factura</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>04</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Factura electrónica de Venta por Contingencia DIAN</SimpleValue>
|
||||
</Value>
|
||||
<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>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 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/">
|
||||
<Identification>
|
||||
<ShortName>TipoDocumento</ShortName>
|
||||
<LongName xml:lang="es">Tipo de Documento</LongName>
|
||||
<Version>1</Version>
|
||||
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoDocumento</CanonicalUri>
|
||||
<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>
|
||||
<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>
|
||||
<LongName xml:lang="es">Codigo Comun</LongName>
|
||||
<Data Type="normalizedString"/>
|
||||
</Column>
|
||||
<Column Id="name" Use="required">
|
||||
<ShortName>Name</ShortName>
|
||||
<LongName xml:lang="es">Nombre</LongName>
|
||||
<Data Type="string"/>
|
||||
</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>Factura de Venta Nacional</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>02</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Factura de Exportación </SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>03</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Factura de Contingencia</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>91</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Nota Crédito</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>92</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Nota Débito</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
</SimpleCodeList>
|
||||
</gc:CodeList>
|
||||
|
@ -1,171 +1,162 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 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/">
|
||||
<Identification>
|
||||
<ShortName>TipoImpuesto</ShortName>
|
||||
<LongName xml:lang="es">Tipo de Tributos</LongName>
|
||||
<Version>1</Version>
|
||||
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoImpuesto</CanonicalUri>
|
||||
<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>
|
||||
<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>
|
||||
<LongName xml:lang="es">Codigo Comun</LongName>
|
||||
<Data Type="normalizedString"/>
|
||||
</Column>
|
||||
<Column Id="name" Use="required">
|
||||
<ShortName>Name</ShortName>
|
||||
<LongName xml:lang="es">Nombre</LongName>
|
||||
<Data Type="string"/>
|
||||
</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>IVA</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>02</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>IC</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>03</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ICA</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>04</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>INC</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>05</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteIVA</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>06</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteRenta</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>07</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteICA</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>08</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteCREE</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>20</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>FtoHorticultura</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>21</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Timbre</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>22</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Bolsas</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>23</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>INCarbono</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>24</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>INCombustibles</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>25</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Sobretasa Combustibles</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>26</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Sordicom</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>30</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Impuesto al Consumo de Datos</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>ZZ</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Nombre de la figura tributaria</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
</SimpleCodeList>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 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/">
|
||||
<Identification>
|
||||
<ShortName>TipoImpuesto</ShortName>
|
||||
<LongName xml:lang="es">Tipo de Tributos</LongName>
|
||||
<Version>1</Version>
|
||||
<CanonicalUri>urn:dian:names:especificacion:ubl:listacodigos:gc:TipoImpuesto</CanonicalUri>
|
||||
<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>
|
||||
<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>
|
||||
<LongName xml:lang="es">Codigo Comun</LongName>
|
||||
<Data Type="normalizedString"/>
|
||||
</Column>
|
||||
<Column Id="name" Use="required">
|
||||
<ShortName>Name</ShortName>
|
||||
<LongName xml:lang="es">Nombre</LongName>
|
||||
<Data Type="string"/>
|
||||
</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>IVA</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>02</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>IC</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>03</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ICA</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>04</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>INC</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>05</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteIVA</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>06</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>07</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteICA</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>08</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteCREE</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>20</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>FtoHorticultura</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>21</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Timbre</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>22</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Bolsas</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>23</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>INCarbono</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>24</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>INCombustibles</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>25</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Sobretasa Combustibles</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>26</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Sordicom</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>ZZ</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Nombre de la figura tributaria</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
</SimpleCodeList>
|
||||
</gc:CodeList>
|
||||
|
@ -1,47 +0,0 @@
|
||||
<?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,6 +30,46 @@
|
||||
</Key>
|
||||
</ColumnSet>
|
||||
<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>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>O-13</SimpleValue>
|
||||
@ -38,6 +78,14 @@
|
||||
<SimpleValue>Gran contribuyente</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>O-14</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Informante de exógena</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>O-15</SimpleValue>
|
||||
@ -46,6 +94,38 @@
|
||||
<SimpleValue>Autorretenedor</SimpleValue>
|
||||
</Value>
|
||||
</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>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>O-23</SimpleValue>
|
||||
@ -54,6 +134,62 @@
|
||||
<SimpleValue>Agente de retención en el impuesto sobre las ventas</SimpleValue>
|
||||
</Value>
|
||||
</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>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>O-47</SimpleValue>
|
||||
@ -78,6 +214,782 @@
|
||||
<SimpleValue>No responsable de IVA</SimpleValue>
|
||||
</Value>
|
||||
</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>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>R-99-PN</SimpleValue>
|
||||
|
@ -62,13 +62,5 @@
|
||||
<SimpleValue>Régimen simple de tributación</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>ZZ</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>No aplica</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
</SimpleCodeList>
|
||||
</gc:CodeList>
|
||||
|
@ -82,16 +82,11 @@ TipoAmbiente = CodeList(path_for_codelist('TipoAmbiente-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')\
|
||||
.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')
|
||||
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')
|
||||
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')
|
||||
TipoOperacionF = CodeList(path_for_codelist('TipoOperacionF-2.1.gc'), 'code', 'name')\
|
||||
.update(CodeList(path_for_codelist('TipoOperacionF-2.1.custom.gc'), 'code', 'name'))
|
||||
|
210
facho/fe/fe.py
210
facho/fe/fe.py
@ -1,5 +1,6 @@
|
||||
# This file is part of facho. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from ..facho import FachoXML, FachoXMLExtension, LXMLBuilder
|
||||
import uuid
|
||||
import xmlsig
|
||||
@ -7,16 +8,13 @@ import xades
|
||||
from datetime import datetime
|
||||
import OpenSSL
|
||||
import zipfile
|
||||
# import warnings
|
||||
import warnings
|
||||
import hashlib
|
||||
from contextlib import contextmanager
|
||||
from .data.dian import codelist
|
||||
from . import form
|
||||
from collections import defaultdict
|
||||
# from pathlib import Path
|
||||
from dateutil import tz
|
||||
|
||||
from cryptography.hazmat.primitives.serialization import pkcs12
|
||||
from pathlib import Path
|
||||
|
||||
AMBIENTE_PRUEBAS = codelist.TipoAmbiente.by_name('Pruebas')['code']
|
||||
AMBIENTE_PRODUCCION = codelist.TipoAmbiente.by_name('Producción')['code']
|
||||
@ -32,51 +30,32 @@ SCHEME_AGENCY_ATTRS = {
|
||||
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.'
|
||||
|
||||
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 = {
|
||||
'apr': 'urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2',
|
||||
'atd': 'urn:oasis:names:specification:ubl:schema:xsd:AttachedDocument-2',
|
||||
'no': 'dian:gov:co:facturaelectronica:NominaIndividual',
|
||||
'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',
|
||||
'udt': 'urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2',
|
||||
'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
'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#',
|
||||
}
|
||||
|
||||
|
||||
def fe_from_string(document: str) -> FachoXML:
|
||||
return FeXML.from_string(document)
|
||||
|
||||
|
||||
# from contextlib import contextmanager
|
||||
from contextlib import contextmanager
|
||||
@contextmanager
|
||||
def mock_xades_policy():
|
||||
from mock import patch
|
||||
@ -94,39 +73,29 @@ def mock_xades_policy():
|
||||
mock.return_value = UrllibPolicyMock()
|
||||
yield
|
||||
|
||||
|
||||
|
||||
class FeXML(FachoXML):
|
||||
|
||||
def __init__(self, root, namespace):
|
||||
# raise Exception(namespace)
|
||||
|
||||
super().__init__("{%s}%s" % (namespace, root),
|
||||
nsmap=NAMESPACES)
|
||||
|
||||
@classmethod
|
||||
def from_string(cls, document: str) -> 'FeXML':
|
||||
return super().from_string(document, namespaces=NAMESPACES)
|
||||
|
||||
|
||||
def tostring(self, **kw):
|
||||
# MACHETE(bit4bit) la DIAN espera que la etiqueta raiz no este en un namespace
|
||||
urn_oasis = {
|
||||
'AttachedDocument': 'urn:oasis:names:specification:ubl:schema:xsd:AttachedDocument-2',
|
||||
'Invoice': 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2',
|
||||
'CreditNote': 'urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2',
|
||||
'ApplicationResponse': 'urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2'
|
||||
}
|
||||
|
||||
root_namespace = self.root_namespace()
|
||||
root_localname = self.root_localname()
|
||||
xmlns_name = {v: k for k, v in NAMESPACES.items()}[root_namespace]
|
||||
|
||||
return super().tostring(**kw)\
|
||||
.replace(xmlns_name + ':', '')\
|
||||
.replace('xmlns:'+xmlns_name, 'xmlns')\
|
||||
.replace(root_namespace, urn_oasis[root_localname])
|
||||
.replace("fe:", "")\
|
||||
.replace("xmlns:no", "xmlns")\
|
||||
.replace("change", "xsi:schemaLocation")
|
||||
|
||||
|
||||
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.invoice = invoice
|
||||
|
||||
@ -151,25 +120,12 @@ class DianXMLExtensionCUDFE(FachoXMLExtension):
|
||||
fachoxml.set_element('./cbc:UUID', cufe,
|
||||
schemeID=self.tipo_ambiente,
|
||||
schemeName=self.schemeName())
|
||||
|
||||
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.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
|
||||
fachoxml.set_element(
|
||||
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:QRCode',
|
||||
self._get_qrcode(cufe))
|
||||
fachoxml.set_element('./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:QRCode',
|
||||
self._get_qrcode(cufe))
|
||||
|
||||
def issue_time(self, datetime_):
|
||||
return datetime_.strftime('%H:%M:%S-05:00')
|
||||
@ -185,8 +141,7 @@ class DianXMLExtensionCUDFE(FachoXMLExtension):
|
||||
build_vars['HoraFac'] = self.issue_time(invoice.invoice_issue)
|
||||
# PAG 601
|
||||
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))
|
||||
build_vars['CodImpuesto1'] = '01'
|
||||
build_vars['CodImpuesto2'] = '04'
|
||||
@ -216,8 +171,7 @@ class DianXMLExtensionCUDFE(FachoXMLExtension):
|
||||
|
||||
|
||||
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.clave_tecnica = clave_tecnica
|
||||
self.invoice = invoice
|
||||
@ -253,7 +207,6 @@ class DianXMLExtensionCUFE(DianXMLExtensionCUDFE):
|
||||
'%d' % build_vars['TipoAmb'],
|
||||
]
|
||||
|
||||
|
||||
class DianXMLExtensionCUDE(DianXMLExtensionCUDFE):
|
||||
def __init__(self, invoice, software_pin, tipo_ambiente = AMBIENTE_PRUEBAS):
|
||||
self.tipo_ambiente = tipo_ambiente
|
||||
@ -291,41 +244,6 @@ class DianXMLExtensionCUDE(DianXMLExtensionCUDFE):
|
||||
'%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):
|
||||
# RESOLUCION 0004: pagina 108
|
||||
|
||||
@ -335,8 +253,7 @@ class DianXMLExtensionSoftwareProvider(FachoXMLExtension):
|
||||
self.id_software = id_software
|
||||
|
||||
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.update({'schemeID': self.dv})
|
||||
#DIAN 1.7.-2020: FAB23
|
||||
@ -366,6 +283,7 @@ class DianXMLExtensionSoftwareSecurityCode(FachoXMLExtension):
|
||||
|
||||
|
||||
class DianXMLExtensionSigner:
|
||||
|
||||
def __init__(self, pkcs12_path, passphrase=None, localpolicy=True):
|
||||
self._pkcs12_data = open(pkcs12_path, 'rb').read()
|
||||
self._passphrase = None
|
||||
@ -376,18 +294,17 @@ class DianXMLExtensionSigner:
|
||||
@classmethod
|
||||
def from_bytes(cls, data, passphrase=None, localpolicy=True):
|
||||
self = cls.__new__(cls)
|
||||
|
||||
self._pkcs12_data = data
|
||||
self._passphrase = None
|
||||
self._localpolicy = localpolicy
|
||||
if passphrase:
|
||||
self._passphrase = passphrase.encode('utf-8')
|
||||
|
||||
|
||||
return self
|
||||
|
||||
def _element_extension_content(self, fachoxml):
|
||||
return fachoxml.builder.xpath(
|
||||
fachoxml.root,
|
||||
'./ext:UBLExtensions/ext:UBLExtension[2]/ext:ExtensionContent')
|
||||
return fachoxml.builder.xpath(fachoxml.root, './ext:UBLExtensions/ext:UBLExtension[2]/ext:ExtensionContent')
|
||||
|
||||
def sign_xml_string(self, document):
|
||||
xml = LXMLBuilder.from_string(document)
|
||||
@ -409,6 +326,7 @@ class DianXMLExtensionSigner:
|
||||
)
|
||||
xml.append(signature)
|
||||
|
||||
|
||||
ref = xmlsig.template.add_reference(
|
||||
signature, xmlsig.constants.TransformSha256, uri="", name="xmldsig-%s-ref0" % (id_uuid)
|
||||
)
|
||||
@ -416,16 +334,14 @@ class DianXMLExtensionSigner:
|
||||
|
||||
id_keyinfo = "xmldsig-%s-KeyInfo" % (id_uuid)
|
||||
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)
|
||||
data = xmlsig.template.add_x509_data(ki)
|
||||
xmlsig.template.x509_data_add_certificate(data)
|
||||
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)
|
||||
|
||||
id_props = "xmldsig-%s-signedprops" % (id_uuid)
|
||||
@ -433,12 +349,10 @@ class DianXMLExtensionSigner:
|
||||
signature, xmlsig.constants.TransformSha256, uri="#%s" % (id_props),
|
||||
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
|
||||
props = xades.template.create_signed_properties(
|
||||
qualifying, name=id_props, datetime=datetime.now(tz=Bogota))
|
||||
props = xades.template.create_signed_properties(qualifying, name=id_props, datetime=datetime.now())
|
||||
xades.template.add_claimed_role(props, "supplier")
|
||||
|
||||
policy = xades.policy.GenericPolicyId(
|
||||
@ -446,13 +360,9 @@ class DianXMLExtensionSigner:
|
||||
POLICY_NAME,
|
||||
xmlsig.constants.TransformSha256)
|
||||
ctx = xades.XAdESContext(policy)
|
||||
ctx.load_pkcs12(pkcs12.load_key_and_certificates(
|
||||
self._pkcs12_data,
|
||||
self._passphrase))
|
||||
ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(self._pkcs12_data,
|
||||
self._passphrase))
|
||||
|
||||
# ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(
|
||||
# self._pkcs12_data,
|
||||
# self._passphrase))
|
||||
if self._localpolicy:
|
||||
with mock_xades_policy():
|
||||
ctx.sign(signature)
|
||||
@ -460,7 +370,7 @@ class DianXMLExtensionSigner:
|
||||
else:
|
||||
ctx.sign(signature)
|
||||
ctx.verify(signature)
|
||||
# xmlsig take parent root
|
||||
#xmlsig take parent root
|
||||
xml.remove(signature)
|
||||
return signature
|
||||
|
||||
@ -469,28 +379,29 @@ class DianXMLExtensionSigner:
|
||||
extcontent = self._element_extension_content(fachoxml)
|
||||
fachoxml.append_element(extcontent, signature)
|
||||
|
||||
|
||||
|
||||
class DianXMLExtensionAuthorizationProvider(FachoXMLExtension):
|
||||
# RESOLUCION 0004: pagina 176
|
||||
|
||||
def build(self, fexml):
|
||||
attrs = {'schemeID': '4', 'schemeName': '31'}
|
||||
attrs.update(SCHEME_AGENCY_ATTRS)
|
||||
|
||||
authorization_provider = fexml.fragment('./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:AuthorizationProvider')
|
||||
authorization_provider.set_element('./sts:AuthorizationProviderID',
|
||||
'800197268',
|
||||
**attrs)
|
||||
|
||||
|
||||
|
||||
class DianXMLExtensionInvoiceSource(FachoXMLExtension):
|
||||
# CAB13
|
||||
def build(self, fexml):
|
||||
dian_path = '/fe:CreditNote/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:InvoiceSource/cbc:IdentificationCode'
|
||||
fexml.set_element(
|
||||
dian_path, 'CO',
|
||||
listAgencyID="6",
|
||||
listAgencyName="United Nations Economic Commission for Europe",
|
||||
listSchemeURI="urn:oasis:names:specification:ubl:codelist:gc:CountryIdentificationCode-2.1")
|
||||
fexml.set_element(dian_path, 'CO',
|
||||
listAgencyID="6",
|
||||
listAgencyName="United Nations Economic Commission for Europe",
|
||||
listSchemeURI="urn:oasis:names:specification:ubl:codelist:gc:CountryIdentificationCode-2.1")
|
||||
|
||||
|
||||
class DianXMLExtensionInvoiceAuthorization(FachoXMLExtension):
|
||||
@ -520,15 +431,16 @@ class DianXMLExtensionInvoiceAuthorization(FachoXMLExtension):
|
||||
invoice_control.set_element('/sts:InvoiceControl/sts:AuthorizedInvoices/sts:To',
|
||||
self.to)
|
||||
|
||||
fexml.set_element(
|
||||
'./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:InvoiceSource/cbc:IdentificationCode',
|
||||
'CO',
|
||||
# DIAN 1.7.-2020: FAB15
|
||||
listAgencyID="6",
|
||||
# DIAN 1.7.-2020: FAB16
|
||||
listAgencyName="United Nations Economic Commission for Europe",
|
||||
# DIAN 1.7.-2020: FAB17
|
||||
listSchemeURI="urn:oasis:names:specification:ubl:codelist:gc:CountryIdentificationCode-2.1")
|
||||
fexml.set_element('./ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent/sts:DianExtensions/sts:InvoiceSource/cbc:IdentificationCode',
|
||||
'CO',
|
||||
#DIAN 1.7.-2020: FAB15
|
||||
listAgencyID="6",
|
||||
#DIAN 1.7.-2020: FAB16
|
||||
listAgencyName="United Nations Economic Commission for Europe",
|
||||
#DIAN 1.7.-2020: FAB17
|
||||
listSchemeURI="urn:oasis:names:specification:ubl:codelist:gc:CountryIdentificationCode-2.1"
|
||||
)
|
||||
|
||||
|
||||
|
||||
class DianZIP:
|
||||
@ -537,8 +449,7 @@ class DianZIP:
|
||||
MAX_FILES = 50
|
||||
|
||||
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
|
||||
|
||||
def add_xml(self, name, xml_data):
|
||||
@ -559,6 +470,7 @@ class DianZIP:
|
||||
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')
|
||||
@ -581,7 +493,7 @@ class DianXMLExtensionSignerVerifier:
|
||||
def verify_string(self, document):
|
||||
# Obtener FachoXML
|
||||
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')
|
||||
|
@ -1,26 +1,24 @@
|
||||
# This file is part of facho. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
# import hashlib
|
||||
# from functools import reduce
|
||||
# import copy
|
||||
|
||||
import hashlib
|
||||
from functools import reduce
|
||||
import copy
|
||||
import dataclasses
|
||||
from dataclasses import dataclass, field
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, date
|
||||
# from collections import defaultdict
|
||||
from collections import defaultdict
|
||||
import decimal
|
||||
from decimal import Decimal
|
||||
import typing
|
||||
|
||||
from ..data.dian import codelist
|
||||
|
||||
DECIMAL_PRECISION = 6
|
||||
|
||||
|
||||
class AmountCurrencyError(TypeError):
|
||||
pass
|
||||
|
||||
|
||||
@dataclass
|
||||
class Currency:
|
||||
code: str
|
||||
@ -31,7 +29,6 @@ class Currency:
|
||||
def __str__(self):
|
||||
return self.code
|
||||
|
||||
|
||||
class Collection:
|
||||
|
||||
def __init__(self, array):
|
||||
@ -48,7 +45,6 @@ class Collection:
|
||||
def sum(self):
|
||||
return sum(self.array)
|
||||
|
||||
|
||||
class AmountCollection(Collection):
|
||||
|
||||
def sum(self):
|
||||
@ -57,13 +53,10 @@ class AmountCollection(Collection):
|
||||
total += v
|
||||
return total
|
||||
|
||||
|
||||
class Amount:
|
||||
def __init__(
|
||||
self, amount: typing.Union[int, float, str, "Amount"],
|
||||
currency: Currency = Currency('COP')):
|
||||
def __init__(self, amount: int or float or str or Amount, currency: Currency = Currency('COP')):
|
||||
|
||||
# DIAN 1.7.-2020: 1.2.3.1
|
||||
#DIAN 1.7.-2020: 1.2.3.1
|
||||
if isinstance(amount, Amount):
|
||||
if amount < Amount(0.0):
|
||||
raise ValueError('amount must be positive >= 0')
|
||||
@ -74,16 +67,14 @@ class Amount:
|
||||
if float(amount) < 0:
|
||||
raise ValueError('amount must be positive >= 0')
|
||||
|
||||
self.amount = Decimal(
|
||||
amount, decimal.Context(
|
||||
prec=DECIMAL_PRECISION,
|
||||
# DIAN 1.7.-2020: 1.2.1.1
|
||||
rounding=decimal.ROUND_HALF_EVEN))
|
||||
self.amount = Decimal(amount, decimal.Context(prec=DECIMAL_PRECISION,
|
||||
#DIAN 1.7.-2020: 1.2.1.1
|
||||
rounding=decimal.ROUND_HALF_EVEN ))
|
||||
self.currency = currency
|
||||
|
||||
def fromNumber(self, val):
|
||||
return Amount(val, currency=self.currency)
|
||||
|
||||
|
||||
def round(self, prec):
|
||||
return Amount(round(self.amount, prec), currency=self.currency)
|
||||
|
||||
@ -101,8 +92,7 @@ class Amount:
|
||||
def __eq__(self, other):
|
||||
if not self.is_same_currency(other):
|
||||
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):
|
||||
if type(val) in [int, float]:
|
||||
@ -110,7 +100,7 @@ class Amount:
|
||||
if isinstance(val, Amount):
|
||||
return val
|
||||
raise TypeError("cant cast to amount")
|
||||
|
||||
|
||||
def __add__(self, rother):
|
||||
other = self._cast(rother)
|
||||
if not self.is_same_currency(other):
|
||||
@ -134,14 +124,14 @@ class Amount:
|
||||
|
||||
def truncate_as_string(self, prec):
|
||||
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):
|
||||
return float(round(self.amount, DECIMAL_PRECISION))
|
||||
|
||||
|
||||
|
||||
class Quantity:
|
||||
|
||||
|
||||
def __init__(self, val, code):
|
||||
if type(val) not in [float, int]:
|
||||
raise ValueError('val expected int or float')
|
||||
@ -163,7 +153,6 @@ class Quantity:
|
||||
def __repr__(self):
|
||||
return str(self)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Item:
|
||||
scheme_name: str
|
||||
@ -174,10 +163,10 @@ class Item:
|
||||
|
||||
|
||||
class StandardItem(Item):
|
||||
def __init__(self, id_: str, description: str = '', name: str = ''):
|
||||
def __init__(self, id_: str, description: str = ''):
|
||||
super().__init__(id=id_,
|
||||
description=description,
|
||||
scheme_name=name,
|
||||
scheme_name='',
|
||||
scheme_id='999',
|
||||
scheme_agency_id='')
|
||||
|
||||
@ -188,9 +177,9 @@ class UNSPSCItem(Item):
|
||||
description=description,
|
||||
scheme_name='UNSPSC',
|
||||
scheme_id='001',
|
||||
scheme_agency_id='10')
|
||||
|
||||
scheme_agency_id='10')
|
||||
|
||||
|
||||
@dataclass
|
||||
class Country:
|
||||
code: str
|
||||
@ -201,7 +190,6 @@ class Country:
|
||||
raise ValueError("code [%s] not found" % (self.code))
|
||||
self.name = codelist.Paises[self.code]['name']
|
||||
|
||||
|
||||
@dataclass
|
||||
class CountrySubentity:
|
||||
code: str
|
||||
@ -212,7 +200,6 @@ class CountrySubentity:
|
||||
raise ValueError("code [%s] not found" % (self.code))
|
||||
self.name = codelist.Departamento[self.code]['name']
|
||||
|
||||
|
||||
@dataclass
|
||||
class City:
|
||||
code: str
|
||||
@ -223,22 +210,13 @@ class City:
|
||||
raise ValueError("code [%s] not found" % (self.code))
|
||||
self.name = codelist.Municipio[self.code]['name']
|
||||
|
||||
|
||||
@dataclass
|
||||
class PostalZone:
|
||||
code: str = ''
|
||||
|
||||
|
||||
@dataclass
|
||||
class Address:
|
||||
name: str
|
||||
street: str = ''
|
||||
city: City = field(default_factory=lambda: City('05001'))
|
||||
country: Country = field(default_factory=lambda: Country('CO'))
|
||||
countrysubentity: CountrySubentity = field(
|
||||
default_factory=lambda: CountrySubentity('05'))
|
||||
postalzone: PostalZone = field(default_factory=lambda: PostalZone(''))
|
||||
|
||||
city: City = City('05001')
|
||||
country: Country = Country('CO')
|
||||
countrysubentity: CountrySubentity = CountrySubentity('05')
|
||||
|
||||
@dataclass
|
||||
class PartyIdentification:
|
||||
@ -259,7 +237,6 @@ class PartyIdentification:
|
||||
if self.type_fiscal not in codelist.TipoIdFiscal:
|
||||
raise ValueError("type_fiscal [%s] not found" % (self.type_fiscal))
|
||||
|
||||
|
||||
@dataclass
|
||||
class Responsability:
|
||||
codes: list
|
||||
@ -284,12 +261,12 @@ class TaxScheme:
|
||||
code: str
|
||||
name: str = ''
|
||||
|
||||
|
||||
def __post_init__(self):
|
||||
if self.code not in codelist.TipoImpuesto:
|
||||
raise ValueError("code not found")
|
||||
self.name = codelist.TipoImpuesto[self.code]['name']
|
||||
|
||||
|
||||
@dataclass
|
||||
class Party:
|
||||
name: str
|
||||
@ -297,10 +274,10 @@ class Party:
|
||||
responsability_code: typing.List[Responsability]
|
||||
responsability_regime_code: str
|
||||
organization_code: str
|
||||
tax_scheme: TaxScheme = field(default_factory=lambda: TaxScheme('01'))
|
||||
tax_scheme: TaxScheme = TaxScheme('01')
|
||||
|
||||
phone: str = ''
|
||||
address: Address = field(default_factory=lambda: Address(''))
|
||||
address: Address = Address('')
|
||||
email: str = ''
|
||||
legal_name: str = ''
|
||||
legal_company_ident: str = ''
|
||||
@ -328,7 +305,7 @@ class TaxScheme:
|
||||
class TaxSubTotal:
|
||||
percent: float
|
||||
scheme: typing.Optional[TaxScheme] = None
|
||||
tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||
tax_amount: Amount = Amount(0.0)
|
||||
|
||||
def calculate(self, invline):
|
||||
if self.percent is not None:
|
||||
@ -338,11 +315,12 @@ class TaxSubTotal:
|
||||
@dataclass
|
||||
class TaxTotal:
|
||||
subtotals: list
|
||||
tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||
taxable_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||
tax_amount: Amount = Amount(0.0)
|
||||
taxable_amount: Amount = 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
|
||||
@ -355,40 +333,6 @@ class TaxTotalOmit(TaxTotal):
|
||||
def calculate(self, invline):
|
||||
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
|
||||
class Price:
|
||||
amount: Amount
|
||||
@ -404,7 +348,6 @@ class Price:
|
||||
|
||||
self.amount *= self.quantity
|
||||
|
||||
|
||||
@dataclass
|
||||
class PaymentMean:
|
||||
DEBIT = '01'
|
||||
@ -422,24 +365,8 @@ class PaymentMean:
|
||||
|
||||
@dataclass
|
||||
class PrePaidPayment:
|
||||
# DIAN 1.7.-2020: FBD03
|
||||
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.
|
||||
"""
|
||||
#DIAN 1.7.-2020: FBD03
|
||||
paid_amount: Amount = Amount(0.0)
|
||||
|
||||
|
||||
@dataclass
|
||||
@ -448,7 +375,6 @@ class BillingReference:
|
||||
uuid: str
|
||||
date: date
|
||||
|
||||
|
||||
class CreditNoteDocumentReference(BillingReference):
|
||||
"""
|
||||
ident: Prefijo + Numero de la factura relacionada
|
||||
@ -464,7 +390,6 @@ class DebitNoteDocumentReference(BillingReference):
|
||||
date: fecha de emision de la factura relacionada
|
||||
"""
|
||||
|
||||
|
||||
class InvoiceDocumentReference(BillingReference):
|
||||
"""
|
||||
ident: Prefijo + Numero de la nota credito relacionada
|
||||
@ -472,7 +397,6 @@ class InvoiceDocumentReference(BillingReference):
|
||||
date: fecha de emision de la nota credito relacionada
|
||||
"""
|
||||
|
||||
|
||||
@dataclass
|
||||
class AllowanceChargeReason:
|
||||
code: str
|
||||
@ -485,26 +409,22 @@ class AllowanceChargeReason:
|
||||
|
||||
@dataclass
|
||||
class AllowanceCharge:
|
||||
# DIAN 1.7.-2020: FAQ03
|
||||
#DIAN 1.7.-2020: FAQ03
|
||||
charge_indicator: bool = True
|
||||
amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||
amount: Amount = Amount(0.0)
|
||||
reason: AllowanceChargeReason = None
|
||||
|
||||
# Valor Base para calcular el descuento o el cargo
|
||||
base_amount: typing.Optional[Amount] = field(
|
||||
default_factory=lambda: Amount(0.0))
|
||||
|
||||
#Valor Base para calcular el descuento o el cargo
|
||||
base_amount: typing.Optional[Amount] = Amount(0.0)
|
||||
|
||||
# Porcentaje: Porcentaje que aplicar.
|
||||
multiplier_factor_numeric: Amount = field(
|
||||
default_factory=lambda: Amount(1.0))
|
||||
|
||||
multiplier_factor_numeric: Amount = Amount(1.0)
|
||||
|
||||
def isCharge(self):
|
||||
charge_indicator = self.charge_indicator is True
|
||||
return charge_indicator
|
||||
return self.charge_indicator == True
|
||||
|
||||
def isDiscount(self):
|
||||
charge_indicator = self.charge_indicator is False
|
||||
return charge_indicator
|
||||
return self.charge_indicator == False
|
||||
|
||||
def asCharge(self):
|
||||
self.charge_indicator = True
|
||||
@ -518,13 +438,11 @@ class AllowanceCharge:
|
||||
def set_base_amount(self, amount):
|
||||
self.base_amount = amount
|
||||
|
||||
|
||||
class AllowanceChargeAsDiscount(AllowanceCharge):
|
||||
def __init__(self, amount: Amount = Amount(0.0)):
|
||||
self.charge_indicator = False
|
||||
self.amount = amount
|
||||
|
||||
|
||||
@dataclass
|
||||
class InvoiceLine:
|
||||
# RESOLUCION 0004: pagina 155
|
||||
@ -537,9 +455,8 @@ class InvoiceLine:
|
||||
# la factura y el percent es unico por type_code
|
||||
# de subtotal
|
||||
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):
|
||||
if not isinstance(charge, AllowanceCharge):
|
||||
@ -550,7 +467,7 @@ class InvoiceLine:
|
||||
@property
|
||||
def total_amount_without_charge(self):
|
||||
return (self.quantity * self.price.amount)
|
||||
|
||||
|
||||
@property
|
||||
def total_amount(self):
|
||||
charge = AmountCollection(self.allowance_charge)\
|
||||
@ -582,17 +499,8 @@ class InvoiceLine:
|
||||
def taxable_amount(self):
|
||||
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):
|
||||
self.tax.calculate(self)
|
||||
self.withholding.calculate(self)
|
||||
|
||||
def __post_init__(self):
|
||||
if not isinstance(self.quantity, Quantity):
|
||||
@ -601,22 +509,18 @@ class InvoiceLine:
|
||||
if self.tax is None:
|
||||
self.tax = TaxTotalOmit()
|
||||
|
||||
if self.withholding is None:
|
||||
self.withholding = WithholdingTaxTotalOmit()
|
||||
|
||||
|
||||
@dataclass
|
||||
class LegalMonetaryTotal:
|
||||
line_extension_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||
tax_exclusive_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||
tax_inclusive_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||
charge_total_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||
allowance_total_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||
payable_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||
prepaid_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||
line_extension_amount: Amount = Amount(0.0)
|
||||
tax_exclusive_amount: Amount = Amount(0.0)
|
||||
tax_inclusive_amount: Amount = Amount(0.0)
|
||||
charge_total_amount: Amount = Amount(0.0)
|
||||
allowance_total_amount: Amount = Amount(0.0)
|
||||
payable_amount: Amount = Amount(0.0)
|
||||
prepaid_amount: Amount = Amount(0.0)
|
||||
|
||||
def calculate(self):
|
||||
# DIAN 1.7.-2020: FAU14
|
||||
#DIAN 1.7.-2020: FAU14
|
||||
self.payable_amount = \
|
||||
self.tax_inclusive_amount \
|
||||
+ self.allowance_total_amount \
|
||||
@ -624,29 +528,22 @@ class LegalMonetaryTotal:
|
||||
- self.prepaid_amount
|
||||
|
||||
|
||||
|
||||
class NationalSalesInvoiceDocumentType(str):
|
||||
def __str__(self):
|
||||
# 6.1.3
|
||||
return '01'
|
||||
|
||||
|
||||
class CreditNoteDocumentType(str):
|
||||
def __str__(self):
|
||||
# 6.1.3
|
||||
return '91'
|
||||
|
||||
|
||||
class DebitNoteDocumentType(str):
|
||||
def __str__(self):
|
||||
# 6.1.3
|
||||
return '92'
|
||||
|
||||
|
||||
class CreditNoteSupportDocumentType(str):
|
||||
def __str__(self):
|
||||
return '95'
|
||||
|
||||
|
||||
class Invoice:
|
||||
def __init__(self, type_code: str):
|
||||
if str(type_code) not in codelist.TipoDocumento:
|
||||
@ -666,7 +563,6 @@ class Invoice:
|
||||
self.invoice_allowance_charge = []
|
||||
self.invoice_prepaid_payment = []
|
||||
self.invoice_billing_reference = None
|
||||
self.invoice_discrepancy_response = None
|
||||
self.invoice_type_code = str(type_code)
|
||||
self.invoice_ident_prefix = None
|
||||
|
||||
@ -692,8 +588,7 @@ class Invoice:
|
||||
if len(prefix) <= 4:
|
||||
self.invoice_ident_prefix = prefix
|
||||
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):
|
||||
"""
|
||||
@ -724,7 +619,7 @@ class Invoice:
|
||||
|
||||
def _get_codelist_tipo_operacion(self):
|
||||
return codelist.TipoOperacionF
|
||||
|
||||
|
||||
def set_operation_type(self, operation):
|
||||
if operation not in self._get_codelist_tipo_operacion():
|
||||
raise ValueError("operation not found")
|
||||
@ -743,9 +638,6 @@ class Invoice:
|
||||
def set_billing_reference(self, billing_reference: BillingReference):
|
||||
self.invoice_billing_reference = billing_reference
|
||||
|
||||
def set_discrepancy_response(self, billing_response: BillingResponse):
|
||||
self.invoice_discrepancy_response = billing_response
|
||||
|
||||
def accept(self, visitor):
|
||||
visitor.visit_payment_mean(self.invoice_payment_mean)
|
||||
visitor.visit_customer(self.invoice_customer)
|
||||
@ -757,34 +649,29 @@ class Invoice:
|
||||
|
||||
def _calculate_legal_monetary_total(self):
|
||||
for invline in self.invoice_lines:
|
||||
self.invoice_legal_monetary_total.line_extension_amount +=\
|
||||
invline.total_amount
|
||||
self.invoice_legal_monetary_total.tax_exclusive_amount +=\
|
||||
invline.total_tax_exclusive_amount
|
||||
# DIAN 1.7.-2020: FAU6
|
||||
self.invoice_legal_monetary_total.tax_inclusive_amount +=\
|
||||
invline.total_tax_inclusive_amount
|
||||
self.invoice_legal_monetary_total.line_extension_amount += invline.total_amount
|
||||
self.invoice_legal_monetary_total.tax_exclusive_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
|
||||
self.invoice_legal_monetary_total.allowance_total_amount =\
|
||||
AmountCollection(self.invoice_allowance_charge)\
|
||||
#DIAN 1.7.-2020: FAU08
|
||||
self.invoice_legal_monetary_total.allowance_total_amount = AmountCollection(self.invoice_allowance_charge)\
|
||||
.filter(lambda charge: charge.isDiscount())\
|
||||
.map(lambda charge: charge.amount)\
|
||||
.sum()
|
||||
|
||||
# DIAN 1.7.-2020: FAU10
|
||||
self.invoice_legal_monetary_total.charge_total_amount =\
|
||||
AmountCollection(self.invoice_allowance_charge)\
|
||||
#DIAN 1.7.-2020: FAU10
|
||||
self.invoice_legal_monetary_total.charge_total_amount = AmountCollection(self.invoice_allowance_charge)\
|
||||
.filter(lambda charge: charge.isCharge())\
|
||||
.map(lambda charge: charge.amount)\
|
||||
.sum()
|
||||
|
||||
# DIAN 1.7.-2020: FAU12
|
||||
self.invoice_legal_monetary_total.prepaid_amount = AmountCollection(
|
||||
self.invoice_prepaid_payment).map(
|
||||
lambda paid: paid.paid_amount).sum()
|
||||
#DIAN 1.7.-2020: FAU12
|
||||
self.invoice_legal_monetary_total.prepaid_amount = AmountCollection(self.invoice_prepaid_payment)\
|
||||
.map(lambda paid: paid.paid_amount)\
|
||||
.sum()
|
||||
|
||||
# DIAN 1.7.-2020: FAU14
|
||||
#DIAN 1.7.-2020: FAU14
|
||||
self.invoice_legal_monetary_total.calculate()
|
||||
|
||||
def _refresh_charges_base_amount(self):
|
||||
@ -792,21 +679,18 @@ class Invoice:
|
||||
for invline in self.invoice_lines:
|
||||
if invline.allowance_charge:
|
||||
# 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
|
||||
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):
|
||||
for invline in self.invoice_lines:
|
||||
invline.calculate()
|
||||
self._calculate_legal_monetary_total()
|
||||
self._refresh_charges_base_amount()
|
||||
|
||||
|
||||
class NationalSalesInvoice(Invoice):
|
||||
def __init__(self):
|
||||
super().__init__(NationalSalesInvoiceDocumentType())
|
||||
@ -822,7 +706,7 @@ class CreditNote(Invoice):
|
||||
|
||||
def _get_codelist_tipo_operacion(self):
|
||||
return codelist.TipoOperacionNC
|
||||
|
||||
|
||||
def _check_ident_prefix(self, prefix):
|
||||
if len(prefix) != 6:
|
||||
raise ValueError('prefix must be 6 length')
|
||||
@ -851,30 +735,3 @@ class DebitNote(Invoice):
|
||||
if not self.invoice_ident_prefix:
|
||||
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,7 +2,4 @@ from .invoice import *
|
||||
from .credit_note import *
|
||||
from .debit_note import *
|
||||
from .utils import *
|
||||
from .support_document import *
|
||||
from .support_document_credit_note import *
|
||||
from .attached_document import *
|
||||
from .application_response import *
|
||||
|
@ -1,177 +0,0 @@
|
||||
from .. import fe
|
||||
|
||||
__all__ = ['ApplicationResponse']
|
||||
|
||||
|
||||
class ApplicationResponse:
|
||||
|
||||
def __init__(self, invoice, tag_document='ApplicationResponse'):
|
||||
self.schema =\
|
||||
'urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2'
|
||||
self.tag_document = tag_document
|
||||
self.invoice = invoice
|
||||
self.fexml = fe.FeXML(
|
||||
self.tag_document, self.schema)
|
||||
self.application_response = self.application_response()
|
||||
|
||||
def application_response(self):
|
||||
# DIAN 1.9.-2023: AE02
|
||||
self.fexml.set_element(
|
||||
'./cbc:UBLVersionID', 'UBL 2.1')
|
||||
|
||||
# DIAN 1.9.-2023: AE03
|
||||
self.fexml.set_element(
|
||||
'./cbc:CustomizationID', 'Documentos adjuntos')
|
||||
|
||||
# DIAN 1.9.-2023: AE04
|
||||
self.fexml.set_element(
|
||||
'./cbc:ProfileID', 'DIAN 2.1')
|
||||
|
||||
# DIAN 1.9.-2023: AE04a
|
||||
self.fexml.set_element(
|
||||
'./cbc:ProfileExecutionID', '1')
|
||||
|
||||
self.fexml.set_element(
|
||||
'./cbc:ID', '1')
|
||||
|
||||
self.fexml.set_element(
|
||||
'./cbc:UUID', '1', schemeName="CUDE-SHA384")
|
||||
|
||||
self.fexml.set_element(
|
||||
'./cbc:IssueDate',
|
||||
self.invoice.invoice_issue.strftime('%Y-%m-%d'))
|
||||
|
||||
# DIAN 1.9.-2023: AE06
|
||||
self.fexml.set_element(
|
||||
'./cbc:IssueTime', self.invoice.invoice_issue.strftime(
|
||||
'%H:%M:%S-05:00'))
|
||||
|
||||
self.set_sender_party()
|
||||
self.set_receiver_party()
|
||||
self.set_document_response()
|
||||
|
||||
def set_sender_party(self):
|
||||
# DIAN 1.9.-2023: AE09
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:SenderParty')
|
||||
# DIAN 1.9.-2023: AE10
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme')
|
||||
# DIAN 1.9.-2023: AE11
|
||||
self.fexml.set_element(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme/cbc:RegistrationName',
|
||||
self.invoice.invoice_supplier.name)
|
||||
# DIAN 1.9.-2023: AE12
|
||||
# DIAN 1.9.-2023: AE13
|
||||
# DIAN 1.9.-2023: AE14
|
||||
# DIAN 1.9.-2023: AE15
|
||||
self.fexml.set_element(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme/cbc:CompanyID',
|
||||
self.invoice.invoice_supplier.ident,
|
||||
schemeAgencyID='195',
|
||||
schemeID=self.invoice.invoice_supplier.ident.dv,
|
||||
schemeName=self.invoice.invoice_supplier.ident.type_fiscal)
|
||||
|
||||
# DIAN 1.9.-2023: AE16
|
||||
self.fexml.set_element(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme/cbc:TaxLevelCode',
|
||||
self.invoice.invoice_supplier.responsability_code)
|
||||
|
||||
# DIAN 1.9.-2023: AE18
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme/cac:TaxScheme')
|
||||
|
||||
# DIAN 1.9.-2023: AE19
|
||||
self.fexml.set_element(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme/cac:TaxScheme/cbc:ID',
|
||||
self.invoice.invoice_supplier.tax_scheme.code)
|
||||
|
||||
# DIAN 1.9.-2023: AE20
|
||||
self.fexml.set_element(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme/cac:TaxScheme/cbc:Name',
|
||||
self.invoice.invoice_supplier.tax_scheme.name)
|
||||
|
||||
def set_receiver_party(self):
|
||||
# DIAN 1.9.-2023: AE21
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:ReceiverParty')
|
||||
# DIAN 1.9.-2023: AE22
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme')
|
||||
# DIAN 1.9.-2023: AE23
|
||||
self.fexml.set_element(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme/cbc:RegistrationName',
|
||||
self.invoice.invoice_customer.name)
|
||||
# DIAN 1.9.-2023: AE24
|
||||
# DIAN 1.9.-2023: AE25
|
||||
# DIAN 1.9.-2023: AE26
|
||||
# DIAN 1.9.-2023: AE27
|
||||
self.fexml.set_element(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme/cbc:CompanyID',
|
||||
self.invoice.invoice_customer.ident,
|
||||
schemeAgencyID='195',
|
||||
schemeID=self.invoice.invoice_customer.ident.dv,
|
||||
schemeName=self.invoice.invoice_customer.ident.type_fiscal)
|
||||
# DIAN 1.9.-2023: AE28
|
||||
self.fexml.set_element(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme/cbc:TaxLevelCode',
|
||||
self.invoice.invoice_customer.responsability_code)
|
||||
# DIAN 1.9.-2023: AE30
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme/cac:TaxScheme')
|
||||
# DIAN 1.9.-2023: AE31
|
||||
self.fexml.set_element(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme/cac:TaxScheme/cbc:ID',
|
||||
self.invoice.invoice_customer.tax_scheme.code)
|
||||
# DIAN 1.9.-2023: AE32
|
||||
self.fexml.set_element(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme/cac:TaxScheme/cbc:Name',
|
||||
self.invoice.invoice_customer.tax_scheme.name)
|
||||
|
||||
def set_document_response(self):
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:DocumentResponse')
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:DocumentResponse/cac:Response')
|
||||
self.fexml.set_element(
|
||||
'./cac:DocumentResponse/cac:Response/cbc:ResponseCode',
|
||||
'02')
|
||||
self.fexml.set_element(
|
||||
'./cac:DocumentResponse/cac:Response/cbc:Description',
|
||||
'Documento validado por la DIAN')
|
||||
self.set_documnent_reference()
|
||||
|
||||
def set_documnent_reference(self):
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:DocumentResponse/cac:DocumentReference')
|
||||
self.fexml.set_element(
|
||||
'./cac:DocumentResponse/cac:DocumentReference/cbc:ID',
|
||||
'FESS19566058')
|
||||
self.fexml.set_element(
|
||||
'./cac:DocumentResponse/cac:DocumentReference/cbc:UUID',
|
||||
'f51ee529aabd19d10e39444f2f593b94d56d5885fbf433faf718d53a7e968f64bf54a6ee43c6a2df842771b54a6aae1a',
|
||||
schemeName="CUFE-SHA384")
|
||||
self.set_response_lines()
|
||||
|
||||
def set_response_lines(self):
|
||||
lines = [{
|
||||
'LineID': '1',
|
||||
'ResponseCode': '0000',
|
||||
'Description': '0',
|
||||
}]
|
||||
|
||||
for line in lines:
|
||||
self.fexml.set_element(
|
||||
'./cac:DocumentResponse/cac:LineResponse/cac:LineReference/cbc:LineID', line[
|
||||
'LineID'])
|
||||
self.fexml.set_element(
|
||||
'./cac:DocumentResponse/cac:LineResponse/cac:Response/cbc:ResponseCode', line[
|
||||
'ResponseCode'])
|
||||
self.fexml.set_element(
|
||||
'./cac:DocumentResponse/cac:LineResponse/cac:Response/cbc:Description', line[
|
||||
'Description'])
|
||||
|
||||
|
||||
|
||||
def toFachoXML(self):
|
||||
return self.fexml
|
@ -1,227 +1,14 @@
|
||||
from .. import fe
|
||||
from .application_response import ApplicationResponse
|
||||
|
||||
__all__ = ['AttachedDocument']
|
||||
|
||||
|
||||
class AttachedDocument():
|
||||
|
||||
def __init__(self, invoice, DIANInvoiceXML, id):
|
||||
self.schema =\
|
||||
'urn:oasis:names:specification:ubl:schema:xsd:AttachedDocument-2'
|
||||
self.id = id
|
||||
self.invoice = invoice
|
||||
self.DIANInvoiceXML = DIANInvoiceXML
|
||||
self.attached_document_invoice = self.attached_document_invoice()
|
||||
|
||||
def attached_document_invoice(self):
|
||||
self.fexml = fe.FeXML(
|
||||
'AttachedDocument', self.schema)
|
||||
|
||||
# DIAN 1.9.-2023: AE02
|
||||
self.fexml.set_element(
|
||||
'./cbc:UBLVersionID', 'UBL 2.1')
|
||||
|
||||
# DIAN 1.9.-2023: AE03
|
||||
self.fexml.set_element(
|
||||
'./cbc:CustomizationID', 'Documentos adjuntos')
|
||||
|
||||
# DIAN 1.9.-2023: AE04
|
||||
self.fexml.set_element(
|
||||
'./cbc:ProfileID', 'Factura Electrónica de Venta')
|
||||
|
||||
# DIAN 1.9.-2023: AE04a
|
||||
self.fexml.set_element(
|
||||
'./cbc:ProfileExecutionID', '1')
|
||||
|
||||
# DIAN 1.9.-2023: AE04b
|
||||
self.fexml.set_element(
|
||||
'./cbc:ID', self.id)
|
||||
|
||||
# DIAN 1.9.-2023: AE05
|
||||
self.fexml.set_element(
|
||||
'./cbc:IssueDate',
|
||||
self.invoice.invoice_issue.strftime('%Y-%m-%d'))
|
||||
|
||||
# DIAN 1.9.-2023: AE06
|
||||
self.fexml.set_element(
|
||||
'./cbc:IssueTime', self.invoice.invoice_issue.strftime(
|
||||
'%H:%M:%S-05:00'))
|
||||
|
||||
# DIAN 1.9.-2023: AE08
|
||||
self.fexml.set_element(
|
||||
'./cbc:DocumentType', 'Contenedor de Factura Electrónica')
|
||||
|
||||
# DIAN 1.9.-2023: AE08a
|
||||
self.fexml.set_element(
|
||||
'./cbc:ParentDocumentID', self.invoice.invoice_ident)
|
||||
|
||||
# DIAN 1.9.-2023: AE09
|
||||
self.set_sender_party()
|
||||
|
||||
# DIAN 1.9.-2023: AE20
|
||||
self.set_receiver_party()
|
||||
# DIAN 1.9.-2023: AE33
|
||||
self.set_attachment()
|
||||
self.set_parent_document_line_reference()
|
||||
|
||||
def set_sender_party(self):
|
||||
# DIAN 1.9.-2023: AE09
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:SenderParty')
|
||||
# DIAN 1.9.-2023: AE10
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme')
|
||||
# DIAN 1.9.-2023: AE11
|
||||
self.fexml.set_element(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme/cbc:RegistrationName',
|
||||
self.invoice.invoice_supplier.name)
|
||||
# DIAN 1.9.-2023: AE12
|
||||
# DIAN 1.9.-2023: AE13
|
||||
# DIAN 1.9.-2023: AE14
|
||||
# DIAN 1.9.-2023: AE15
|
||||
self.fexml.set_element(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme/cbc:CompanyID',
|
||||
self.invoice.invoice_supplier.ident,
|
||||
schemeAgencyID='195',
|
||||
schemeID=self.invoice.invoice_supplier.ident.dv,
|
||||
schemeName=self.invoice.invoice_supplier.ident.type_fiscal)
|
||||
|
||||
# DIAN 1.9.-2023: AE16
|
||||
self.fexml.set_element(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme/cbc:TaxLevelCode',
|
||||
self.invoice.invoice_supplier.responsability_code)
|
||||
|
||||
# DIAN 1.9.-2023: AE18
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme/cac:TaxScheme')
|
||||
|
||||
# DIAN 1.9.-2023: AE19
|
||||
self.fexml.set_element(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme/cac:TaxScheme/cbc:ID',
|
||||
self.invoice.invoice_supplier.tax_scheme.code)
|
||||
|
||||
# DIAN 1.9.-2023: AE20
|
||||
self.fexml.set_element(
|
||||
'./cac:SenderParty/cac:PartyTaxScheme/cac:TaxScheme/cbc:Name',
|
||||
self.invoice.invoice_supplier.tax_scheme.name)
|
||||
|
||||
def set_receiver_party(self):
|
||||
# DIAN 1.9.-2023: AE21
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:ReceiverParty')
|
||||
# DIAN 1.9.-2023: AE22
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme')
|
||||
# DIAN 1.9.-2023: AE23
|
||||
self.fexml.set_element(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme/cbc:RegistrationName',
|
||||
self.invoice.invoice_customer.name)
|
||||
# DIAN 1.9.-2023: AE24
|
||||
# DIAN 1.9.-2023: AE25
|
||||
# DIAN 1.9.-2023: AE26
|
||||
# DIAN 1.9.-2023: AE27
|
||||
self.fexml.set_element(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme/cbc:CompanyID',
|
||||
self.invoice.invoice_customer.ident,
|
||||
schemeAgencyID='195',
|
||||
schemeID=self.invoice.invoice_customer.ident.dv,
|
||||
schemeName=self.invoice.invoice_customer.ident.type_fiscal)
|
||||
# DIAN 1.9.-2023: AE28
|
||||
self.fexml.set_element(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme/cbc:TaxLevelCode',
|
||||
self.invoice.invoice_customer.responsability_code)
|
||||
# DIAN 1.9.-2023: AE30
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme/cac:TaxScheme')
|
||||
# DIAN 1.9.-2023: AE31
|
||||
self.fexml.set_element(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme/cac:TaxScheme/cbc:ID',
|
||||
self.invoice.invoice_customer.tax_scheme.code)
|
||||
# DIAN 1.9.-2023: AE32
|
||||
self.fexml.set_element(
|
||||
'./cac:ReceiverParty/cac:PartyTaxScheme/cac:TaxScheme/cbc:Name',
|
||||
self.invoice.invoice_customer.tax_scheme.name)
|
||||
|
||||
def set_attachment(self):
|
||||
# DIAN 1.9.-2023: AE33
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:Attachment')
|
||||
# DIAN 1.9.-2023: AE34
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:Attachment/cac:ExternalReference')
|
||||
# DIAN 1.9.-2023: AE35
|
||||
self.fexml.set_element(
|
||||
'./cac:Attachment/cac:ExternalReference/cbc:MimeCode',
|
||||
'text/xml')
|
||||
# DIAN 1.9.-2023: AE36
|
||||
self.fexml.set_element(
|
||||
'./cac:Attachment/cac:ExternalReference/cbc:EncodingCode',
|
||||
'UTF-8')
|
||||
# DIAN 1.9.-2023: AE37
|
||||
self.fexml.set_element(
|
||||
'./cac:Attachment/cac:ExternalReference/cbc:Description',
|
||||
self._build_attachment(self.DIANInvoiceXML)
|
||||
)
|
||||
|
||||
def set_parent_document_line_reference(self):
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:ParentDocumentLineReference')
|
||||
self.fexml.set_element(
|
||||
'./cac:ParentDocumentLineReference/cbc:LineID', 1)
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference')
|
||||
self.fexml.set_element(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cbc:ID',
|
||||
'1234')
|
||||
self.fexml.set_element(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cbc:UUID',
|
||||
'1234',
|
||||
schemeName="CUFE-SHA384")
|
||||
self.fexml.set_element(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cbc:IssueDate',
|
||||
'2024-11-28')
|
||||
self.fexml.set_element(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cbc:DocumentType',
|
||||
'ApplicationResponse')
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cac:Attachment')
|
||||
self.fexml.set_element(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cac:Attachment/cac:ExternalReference/cbc:MimeCode',
|
||||
'text/xml')
|
||||
self.fexml.set_element(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cac:Attachment/cac:ExternalReference/cbc:EncodingCode',
|
||||
'UTF-8')
|
||||
|
||||
application_response = ApplicationResponse(
|
||||
self.invoice).toFachoXML()
|
||||
|
||||
self.fexml.set_element(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cac:Attachment/cac:ExternalReference/cbc:Description',
|
||||
self._build_attachment(application_response))
|
||||
self.fexml.placeholder_for(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cac:ResultOfVerification')
|
||||
self.fexml.set_element(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cac:ResultOfVerification/cbc:ValidatorID',
|
||||
'Unidad Especial Dirección de Impuestos y Aduanas Nacionales')
|
||||
self.fexml.set_element(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cac:ResultOfVerification/cbc:ValidationResultCode',
|
||||
'02')
|
||||
self.fexml.set_element(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cac:ResultOfVerification/cbc:ValidationDate',
|
||||
'2024-11-28')
|
||||
self.fexml.set_element(
|
||||
'./cac:ParentDocumentLineReference/cac:DocumentReference/cac:ResultOfVerification/cbc:ValidationTime',
|
||||
'10:35:11-05:00')
|
||||
|
||||
def _build_attachment(self, DIANInvoiceXML):
|
||||
document = (
|
||||
'<?xml version="1.0" encoding="UTF-8" standalone="no"?>'
|
||||
) + DIANInvoiceXML.tostring()
|
||||
attachment = "<![CDATA[{}]]>".format(
|
||||
document)
|
||||
|
||||
return attachment
|
||||
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,10 +1,9 @@
|
||||
# from .. import fe
|
||||
# from ..form import *
|
||||
from .. import fe
|
||||
from ..form import *
|
||||
from .invoice import DIANInvoiceXML
|
||||
|
||||
__all__ = ['DIANCreditNoteXML']
|
||||
|
||||
|
||||
class DIANCreditNoteXML(DIANInvoiceXML):
|
||||
"""
|
||||
DianInvoiceXML mapea objeto form.Invoice a XML segun
|
||||
|
@ -1,10 +1,9 @@
|
||||
# from .. import fe
|
||||
# from ..form import *
|
||||
from .. import fe
|
||||
from ..form import *
|
||||
from .invoice import DIANInvoiceXML
|
||||
|
||||
__all__ = ['DIANDebitNoteXML']
|
||||
|
||||
|
||||
class DIANDebitNoteXML(DIANInvoiceXML):
|
||||
"""
|
||||
DianInvoiceXML mapea objeto form.Invoice a XML segun
|
||||
@ -20,24 +19,19 @@ class DIANDebitNoteXML(DIANInvoiceXML):
|
||||
def tag_document_concilied(fexml):
|
||||
return 'Debited'
|
||||
|
||||
# DIAN 1.7.-2020: DAU03
|
||||
#DIAN 1.7.-2020: DAU03
|
||||
def set_legal_monetary(fexml, invoice):
|
||||
fexml.set_element_amount(
|
||||
'./cac:RequestedMonetaryTotal/cbc:LineExtensionAmount',
|
||||
invoice.invoice_legal_monetary_total.line_extension_amount)
|
||||
fexml.set_element_amount('./cac:RequestedMonetaryTotal/cbc:LineExtensionAmount',
|
||||
invoice.invoice_legal_monetary_total.line_extension_amount)
|
||||
|
||||
fexml.set_element_amount(
|
||||
'./cac:RequestedMonetaryTotal/cbc:TaxExclusiveAmount',
|
||||
invoice.invoice_legal_monetary_total.tax_exclusive_amount)
|
||||
fexml.set_element_amount('./cac:RequestedMonetaryTotal/cbc:TaxExclusiveAmount',
|
||||
invoice.invoice_legal_monetary_total.tax_exclusive_amount)
|
||||
|
||||
fexml.set_element_amount(
|
||||
'./cac:RequestedMonetaryTotal/cbc:TaxInclusiveAmount',
|
||||
invoice.invoice_legal_monetary_total.tax_inclusive_amount)
|
||||
fexml.set_element_amount('./cac:RequestedMonetaryTotal/cbc:TaxInclusiveAmount',
|
||||
invoice.invoice_legal_monetary_total.tax_inclusive_amount)
|
||||
|
||||
fexml.set_element_amount(
|
||||
'./cac:RequestedMonetaryTotal/cbc:ChargeTotalAmount',
|
||||
invoice.invoice_legal_monetary_total.charge_total_amount)
|
||||
fexml.set_element_amount('./cac:RequestedMonetaryTotal/cbc:ChargeTotalAmount',
|
||||
invoice.invoice_legal_monetary_total.charge_total_amount)
|
||||
|
||||
fexml.set_element_amount(
|
||||
'./cac:RequestedMonetaryTotal/cbc:PayableAmount',
|
||||
invoice.invoice_legal_monetary_total.payable_amount)
|
||||
fexml.set_element_amount('./cac:RequestedMonetaryTotal/cbc:PayableAmount',
|
||||
invoice.invoice_legal_monetary_total.payable_amount)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,647 +0,0 @@
|
||||
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"""
|
@ -1,25 +0,0 @@
|
||||
# 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,30 +2,18 @@ from .. import fe
|
||||
|
||||
__all__ = ['DIANWrite', 'DIANWriteSigned']
|
||||
|
||||
|
||||
def DIANWrite(xml, filename):
|
||||
document = xml.tostring(xml_declaration=True, encoding='UTF-8')
|
||||
with open(filename, 'w') as f:
|
||||
f.write(document)
|
||||
|
||||
|
||||
def DIANWriteSigned(
|
||||
xml,
|
||||
filename,
|
||||
private_key,
|
||||
passphrase,
|
||||
use_cache_policy=False,
|
||||
dian_signer=None):
|
||||
document = xml.tostring(
|
||||
xml_declaration=True,
|
||||
encoding='UTF-8').encode('utf-8')
|
||||
|
||||
def DIANWriteSigned(xml, 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)
|
||||
signer = dian_signer(private_key, passphrase=passphrase, localpolicy=use_cache_policy)
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
f.write(signer.sign_xml_string(document))
|
||||
|
@ -53,20 +53,14 @@ class FechaPago(Fecha):
|
||||
|
||||
@dataclass
|
||||
class Novedad:
|
||||
# cune de nomina a relacionar
|
||||
# NIE204
|
||||
cune: str
|
||||
# NIE199
|
||||
activa: bool = False
|
||||
value: False
|
||||
|
||||
def apply(self, fragment):
|
||||
if self.cune != "":
|
||||
fragment.set_attributes('./Novedad',
|
||||
CUNENov=self.cune,
|
||||
)
|
||||
|
||||
fragment.set_attributes('./Novedad',
|
||||
CUNENov=self.value,
|
||||
)
|
||||
def post_apply(self, fexml, scopexml, fragment):
|
||||
scopexml.set_element('./Novedad', self.activa)
|
||||
scopexml.set_element('./Novedad', "false")
|
||||
|
||||
|
||||
@dataclass
|
||||
@ -144,12 +138,13 @@ class Proveedor:
|
||||
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:
|
||||
if InformacionGeneral.AMBIENTE_PRUEBAS.same(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)
|
||||
scopexml.set_element('./Novedad', "false")
|
||||
|
||||
# NIE020
|
||||
software_code = self._software_security_code(fexml, scopexml)
|
||||
@ -182,16 +177,14 @@ class Metadata:
|
||||
proveedor: Proveedor
|
||||
|
||||
def apply(self, novedad, numero_secuencia_xml, lugar_generacion_xml, proveedor_xml):
|
||||
if novedad:
|
||||
self.novedad.apply(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)
|
||||
self.novedad.post_apply(fexml, scopexml, proveedor_xml)
|
||||
|
||||
@dataclass
|
||||
class PeriodoNomina:
|
||||
@ -219,8 +212,9 @@ class InformacionGeneral:
|
||||
class TIPO_AMBIENTE:
|
||||
valor: str
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.valor == str(other)
|
||||
@classmethod
|
||||
def same(cls, value):
|
||||
return cls.valor == str(value)
|
||||
|
||||
# TABLA 5.1.1
|
||||
@dataclass
|
||||
@ -234,28 +228,6 @@ class InformacionGeneral:
|
||||
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
|
||||
|
||||
@ -264,7 +236,6 @@ class InformacionGeneral:
|
||||
periodo_nomina: PeriodoNomina
|
||||
tipo_moneda: TipoMoneda
|
||||
tipo_ambiente: TIPO_AMBIENTE
|
||||
tipo_xml: TIPO_XML
|
||||
software_pin: str
|
||||
|
||||
def __post_init__(self):
|
||||
@ -279,7 +250,7 @@ class InformacionGeneral:
|
||||
# NIE202
|
||||
# TABLA 5.5.2
|
||||
# TODO(bit4bit) solo NominaIndividual
|
||||
TipoXML = self.tipo_xml.valor,
|
||||
TipoXML = '102',
|
||||
# NIE024
|
||||
CUNE = None,
|
||||
# NIE025
|
||||
@ -338,18 +309,15 @@ class DianXMLExtensionSigner(fe.DianXMLExtensionSigner):
|
||||
|
||||
|
||||
class DIANNominaXML:
|
||||
def __init__(self, tag_document, xpath_ajuste=None, schemaLocation=None, namespace_ajuste=None):
|
||||
def __init__(self, tag_document, xpath_ajuste=None,schemaLocation=None):
|
||||
self.informacion_general_version = None
|
||||
|
||||
self.tag_document = tag_document
|
||||
self.fexml = fe.FeXML(tag_document, 'http://www.dian.gov.co/contratos/facturaelectronica/v1')
|
||||
|
||||
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)
|
||||
if schemaLocation is not None:
|
||||
self.fexml.root.set("SchemaLocation", "")
|
||||
self.fexml.root.set("change", schemaLocation)
|
||||
|
||||
# layout, la dian requiere que los elementos
|
||||
# esten ordenados segun el anexo tecnico
|
||||
@ -361,8 +329,7 @@ class DIANNominaXML:
|
||||
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('./Novedad', optional=False)
|
||||
self.root_fragment.placeholder_for('./Periodo')
|
||||
self.root_fragment.placeholder_for('./NumeroSecuenciaXML')
|
||||
self.root_fragment.placeholder_for('./LugarGeneracionXML')
|
||||
@ -375,10 +342,8 @@ class DIANNominaXML:
|
||||
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.novedad = self.root_fragment.fragment('./Novedad')
|
||||
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')
|
||||
@ -398,7 +363,6 @@ class DIANNominaXML:
|
||||
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):
|
||||
@ -555,8 +519,6 @@ class DIANNominaXML:
|
||||
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)))
|
||||
|
||||
@ -592,8 +554,6 @@ class DIANNominaIndividualDeAjuste(DIANNominaXML):
|
||||
fecha_generacion: str
|
||||
|
||||
def apply(self, fragment):
|
||||
# NIAE214
|
||||
fragment.set_element('./TipoNota', '1')
|
||||
fragment.set_element('./Reemplazar/ReemplazandoPredecesor', None,
|
||||
# NIAE090
|
||||
NumeroPred = self.numero,
|
||||
@ -604,11 +564,9 @@ class DIANNominaIndividualDeAjuste(DIANNominaXML):
|
||||
)
|
||||
|
||||
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'
|
||||
super().__init__('NominaIndividualDeAjuste', './Reemplazar')
|
||||
# NIAE214
|
||||
self.root_fragment.set_element('./TipoNota', '1')
|
||||
|
||||
def asignar_predecesor(self, predecesor):
|
||||
if not isinstance(predecesor, self.Predecesor):
|
||||
@ -625,7 +583,6 @@ class DIANNominaIndividualDeAjuste(DIANNominaXML):
|
||||
fecha_generacion: str
|
||||
|
||||
def apply(self, fragment):
|
||||
fragment.set_element('./TipoNota', '2')
|
||||
fragment.set_element('./Eliminar/EliminandoPredecesor', None,
|
||||
# NIAE090
|
||||
NumeroPred = self.numero,
|
||||
@ -636,9 +593,9 @@ class DIANNominaIndividualDeAjuste(DIANNominaXML):
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
schema = "dian:gov:co:facturaelectronica:NominaIndividualDeAjuste NominaIndividualDeAjusteElectronicaXSD.xsd"
|
||||
super().__init__('NominaIndividualDeAjuste', './Eliminar', schemaLocation=schema, namespace_ajuste='dian:gov:co:facturaelectronica:NominaIndividualDeAjuste')
|
||||
super().__init__('NominaIndividualDeAjuste', './Eliminar')
|
||||
|
||||
self.root_fragment.set_element('./TipoNota', '2')
|
||||
self.informacion_general_version = "V1.0: Nota de Ajuste de Documento Soporte de Pago de Nómina Electrónica"
|
||||
|
||||
def asignar_predecesor(self, predecesor):
|
||||
|
@ -1,4 +1,4 @@
|
||||
from dataclasses import dataclass, field
|
||||
from dataclasses import dataclass
|
||||
|
||||
from ..amount import Amount
|
||||
|
||||
@ -29,7 +29,7 @@ class Trabajador:
|
||||
|
||||
codigo_trabajador: str = None
|
||||
otros_nombres: str = None
|
||||
sub_tipo: SubTipoTrabajador = field(default_factory=lambda: SubTipoTrabajador(code='00'))
|
||||
sub_tipo: SubTipoTrabajador = SubTipoTrabajador(code='00')
|
||||
|
||||
def apply(self, fragment):
|
||||
fragment.set_attributes('./Trabajador',
|
||||
|
@ -1,17 +0,0 @@
|
||||
attrs==22.1.0
|
||||
distlib==0.3.6
|
||||
filelock==3.8.0
|
||||
iniconfig==1.1.1
|
||||
packaging==21.3
|
||||
platformdirs==2.5.2
|
||||
pluggy==1.0.0
|
||||
py==1.11.0
|
||||
pyparsing==3.0.9
|
||||
pytest==7.1.3
|
||||
semantic-version==2.10.0
|
||||
setuptools-rust==1.5.2
|
||||
six==1.16.0
|
||||
tomli==2.0.1
|
||||
tox==3.26.0
|
||||
typing_extensions==4.4.0
|
||||
virtualenv==20.16.5
|
3
scrips/nomina.csv
Normal file
3
scrips/nomina.csv
Normal file
@ -0,0 +1,3 @@
|
||||
P,#,Nombre,P_Apellido,S_Apellido,Cédula,Dirección,Salario,Días,Salud,Pension,Aux Transpo,Sueldo,Fecha_pago,Fecha_Ingreso,Fecha_inicio,Fecha_fin,Fecha_generación,hora_generacion
|
||||
N,000005,JUAN,GONZALEZ,CARDONA,71380802,CL 35C 102-17 BL 7 AP 101,2400000,30,96000,96000,140606,2400000,2024-04-30,2022-01-05,2024-04-01,2024-04-30,2024-04-30,08:01:00
|
||||
N,000006,VIVIANA,GIRALDO,VASQUEZ,32257132,CL 35C 102-17 BL 7 AP 101,1160000,30,46400,46400,140606,1160000,2024-04-30,2022-09-05,2024-04-01,2024-04-30,2024-04-30,08:01:00
|
|
177
scrips/nomina.sh
Normal file
177
scrips/nomina.sh
Normal file
@ -0,0 +1,177 @@
|
||||
#!/bin/bash
|
||||
|
||||
SOFTWARE_PIN='20234'
|
||||
SOFTWARE_ID='100b0d10-0ca0-4ad4-a894-b704a568cbf3'
|
||||
NIT='901575528'
|
||||
DV='2'
|
||||
TIPO_AMBIENTE='AMBIENTE_PRUEBAS'
|
||||
RAZON_SOCIAL='BICI PIZZA S.A.S'
|
||||
SET_PRUEBAS='be4d232c-9c7b-4542-b24d-6044c4e316ce'
|
||||
PASSPHARASE='7U3XbtZ76W'
|
||||
#La ruta donde se encuentren estos archivos
|
||||
LLAVE_PRIVADA='privada.pem'
|
||||
LLAVE_PUBLICA='publica.pem'
|
||||
CERTIFICADO='Certificado.pfx'
|
||||
HABILITACION='True'
|
||||
ARCHIVO_CSV='nomina.csv'
|
||||
|
||||
IFS=,
|
||||
while read line; do
|
||||
|
||||
field=( $line )
|
||||
|
||||
Prefijo=${field[0]}
|
||||
Numero=${field[1]}
|
||||
Nombre=${field[2]}
|
||||
P_Apellido=${field[3]}
|
||||
S_Apellifo=${field[4]}
|
||||
Cedula=${field[5]}
|
||||
Direccion=${field[6]}
|
||||
Salario=${field[7]}
|
||||
Sueldo=${field[12]}
|
||||
Dias=${field[8]}
|
||||
Salud=${field[9]}
|
||||
Pension=${field[10]}
|
||||
AuxTp=${field[11]}
|
||||
Pago=${field[13]}
|
||||
Ingreso=${field[14]}
|
||||
Inicio=${field[15]}
|
||||
Fin=${field[16]}
|
||||
Generacion=${field[17]}
|
||||
Hora=${field[18]}
|
||||
|
||||
echo "
|
||||
from facho import fe
|
||||
|
||||
SOFTWARE_PIN='${SOFTWARE_PIN}'
|
||||
SOFTWARE_ID='${SOFTWARE_ID}'
|
||||
NIT='${NIT}'
|
||||
DV='${DV}'
|
||||
|
||||
def extensions(nomina):
|
||||
return []
|
||||
|
||||
def nomina():
|
||||
nomina = fe.nomina.DIANNominaIndividual()
|
||||
|
||||
nomina.asignar_fecha_pago('${Pago}')
|
||||
|
||||
nomina.asignar_metadata(fe.nomina.Metadata(
|
||||
novedad=fe.nomina.Novedad(value='false'),
|
||||
secuencia=fe.nomina.NumeroSecuencia(
|
||||
prefijo='${Prefijo}',
|
||||
consecutivo='${Numero}'
|
||||
),
|
||||
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(
|
||||
razon_social='${RAZON_SOCIAL}',
|
||||
nit=NIT,
|
||||
dv=DV,
|
||||
software_id=SOFTWARE_ID,
|
||||
software_pin=SOFTWARE_PIN
|
||||
)
|
||||
))
|
||||
|
||||
nomina.asignar_periodo(fe.nomina.Periodo(
|
||||
fecha_ingreso= '${Ingreso}',
|
||||
fecha_liquidacion_inicio='${Inicio}',
|
||||
fecha_liquidacion_fin='${Fin}',
|
||||
fecha_generacion='${Generacion}'
|
||||
))
|
||||
|
||||
nomina.asignar_informacion_general(fe.nomina.InformacionGeneral(
|
||||
fecha_generacion = '${Generacion}',
|
||||
hora_generacion = '${Hora}-05:00',
|
||||
tipo_ambiente = fe.nomina.InformacionGeneral.${TIPO_AMBIENTE},
|
||||
software_pin = 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(
|
||||
razon_social='${RAZON_SOCIAL}',
|
||||
nit = NIT,
|
||||
dv = DV,
|
||||
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 = '${P_Apellido}',
|
||||
segundo_apellido = '${S_Apellido}',
|
||||
primer_nombre = '${Nombre}',
|
||||
lugar_trabajo = fe.nomina.LugarTrabajo(
|
||||
pais = fe.nomina.Pais(code='CO'),
|
||||
departamento = fe.nomina.Departamento(code='05'),
|
||||
municipio = fe.nomina.Municipio(code='05001'),
|
||||
direccion = '${Direccion}'
|
||||
),
|
||||
numero_documento = NIT,
|
||||
tipo = fe.nomina.TipoTrabajador(
|
||||
code = '01'
|
||||
),
|
||||
salario_integral = False,
|
||||
sueldo = fe.nomina.Amount(${Sueldo})
|
||||
))
|
||||
|
||||
nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
|
||||
dias_trabajados = ${field[8]},
|
||||
sueldo_trabajado = fe.nomina.Amount(${Salario})
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||
porcentaje = fe.nomina.Amount(4),
|
||||
deduccion = fe.nomina.Amount(${Salud})
|
||||
))
|
||||
|
||||
nomina.adicionar_deduccion(fe.nomina.DeduccionFondoPension(
|
||||
porcentaje=fe.nomina.Amount(4),
|
||||
deduccion = fe.nomina.Amount(${Pension})
|
||||
))
|
||||
return nomina
|
||||
" > "${Prefijo}${Numero}".py
|
||||
facho generate-nomina --private-key ${CERTIFICADO} --passphrase ${PASSPHARASE} --use-cache-policy --sign "${field[0]}${field[1]}".py "${Prefijo}${Numero}".xml
|
||||
CUNE=`grep -oP "<CodigoQR>(.*)</CodigoQR>" "${Prefijo}${Numero}".xml | sed -n 's/.*documentkey=\([^<]*\)<\/CodigoQR>.*/\1/p'`
|
||||
zip "${field[0]}${field[1]}".zip "${field[0]}${field[1]}".xml
|
||||
if [ "$HABILITACION" == "True" ];then
|
||||
facho soap-send-test-set-async --private-key ${LLAVE_PRIVADA} --public-key ${LLAVE_PUBLICA} --habilitacion --password ${PASSPHARASE} --test-setid ${SET_PRUEBAS} "${field[0]}${field[1]}".xml "${field[0]}${field[1]}".zip
|
||||
else
|
||||
facho soap-send-nomina-sync --private-key ${LLAVE_PRIVADA} --public-key ${LLAVE_PUBLICA} --password ${PASSPHARASE} "${field[0]}${field[1]}".xml "${field[0]}${field[1]}".zip --produccion
|
||||
fi
|
||||
|
||||
|
||||
done < ${ARCHIVO_CSV}
|
||||
|
@ -22,4 +22,4 @@ exclude = docs
|
||||
test = pytest
|
||||
|
||||
[tool:pytest]
|
||||
addopts = --ignore=setup.py
|
||||
collect_ignore = ['setup.py']
|
||||
|
51
setup.py
51
setup.py
@ -13,36 +13,19 @@ with open('README.rst') as readme_file:
|
||||
with open('HISTORY.rst') as history_file:
|
||||
history = history_file.read()
|
||||
|
||||
requirements = ['Click>=8.1.7',
|
||||
'zeep==4.2.1',
|
||||
'lxml==5.2.2',
|
||||
'cryptography==3.3.2',
|
||||
'pyOpenSSL==20.0.1',
|
||||
'xmlsig==0.1.7',
|
||||
'xades==1.0.0',
|
||||
'xmlsec==1.3.14',
|
||||
'python-dateutil==2.9.0.post0',
|
||||
# usamos esta dependencia en runtime
|
||||
# para forzar uso de policy_id de archivo local
|
||||
'mock>=5.1.0',
|
||||
'xmlschema>=3.0.0']
|
||||
|
||||
"""
|
||||
Listado de Versiones Anteriores
|
||||
requirements = ['Click>=6.0',
|
||||
'zeep==4.0.0',
|
||||
'lxml==4.6.3',
|
||||
'cryptography==3.3.2',
|
||||
'pyOpenSSL==20.0.1',
|
||||
'xmlsig==0.1.7',
|
||||
'xades==0.2.2',
|
||||
'xmlsec==1.3.12',
|
||||
# usamos esta dependencia en runtime
|
||||
# para forzar uso de policy_id de archivo local
|
||||
'mock>=2.0.0',
|
||||
'xmlschema>=1.8']
|
||||
|
||||
"""
|
||||
requirements = ['Click>=8.1.7',
|
||||
'zeep==4.2.1',
|
||||
'lxml==5.2.2',
|
||||
'cryptography==3.3.2',
|
||||
'pyOpenSSL==20.0.1',
|
||||
'xmlsig==0.1.7',
|
||||
'xades==1.0.0',
|
||||
'xmlsec==1.3.14',
|
||||
'python-dateutil==2.9.0.post0',
|
||||
# usamos esta dependencia en runtime
|
||||
# para forzar uso de policy_id de archivo local
|
||||
'mock>=5.1.0',
|
||||
'xmlschema>=3.0.0' ]
|
||||
|
||||
setup_requirements = ['pytest-runner', ]
|
||||
|
||||
@ -57,10 +40,10 @@ setup(
|
||||
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
|
||||
'Natural Language :: English',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.9',
|
||||
'Programming Language :: Python :: 3.10',
|
||||
'Programming Language :: Python :: 3.11',
|
||||
'Programming Language :: Python :: 3.12',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
],
|
||||
description="Facturacion Electronica Colombia",
|
||||
entry_points={
|
||||
|
@ -1 +0,0 @@
|
||||
907e4444decc9e59c160a2fb3b6659b33dc5b632a5008922b9a62f83f757b1c448e47f5867f2b50dbdb96f48c7681168
|
@ -4,32 +4,30 @@ from datetime import datetime
|
||||
|
||||
@pytest.fixture
|
||||
def simple_debit_note_without_lines():
|
||||
inv = form.DebitNote(form.InvoiceDocumentReference(
|
||||
'1234', 'xx', datetime.now()))
|
||||
inv = form.DebitNote(form.InvoiceDocumentReference('1234', 'xx', datetime.now()))
|
||||
inv.set_period(datetime.now(), datetime.now())
|
||||
inv.set_issue(datetime.now())
|
||||
inv.set_ident('ABC123')
|
||||
inv.set_operation_type('30')
|
||||
inv.set_payment_mean(form.PaymentMean(
|
||||
form.PaymentMean.DEBIT, '41', datetime.now(), '1234'))
|
||||
inv.set_payment_mean(form.PaymentMean(form.PaymentMean.DEBIT, '41', datetime.now(), '1234'))
|
||||
inv.set_supplier(form.Party(
|
||||
name='facho-supplier',
|
||||
ident=form.PartyIdentification('123', '', '31'),
|
||||
responsability_code = form.Responsability(['ZZ']),
|
||||
responsability_regime_code='48',
|
||||
organization_code='1',
|
||||
address=form.Address(
|
||||
name = 'facho-supplier',
|
||||
ident = form.PartyIdentification('123','', '31'),
|
||||
responsability_code = form.Responsability(['O-07']),
|
||||
responsability_regime_code = '48',
|
||||
organization_code = '1',
|
||||
address = form.Address(
|
||||
'', '', form.City('05001', 'Medellín'),
|
||||
form.Country('CO', 'Colombia'),
|
||||
form.CountrySubentity('05', 'Antioquia'))
|
||||
))
|
||||
inv.set_customer(form.Party(
|
||||
name='facho-customer',
|
||||
ident=form.PartyIdentification('321', '', '31'),
|
||||
responsability_code=form.Responsability(['ZZ']),
|
||||
responsability_regime_code='48',
|
||||
organization_code='1',
|
||||
address=form.Address(
|
||||
name = 'facho-customer',
|
||||
ident = form.PartyIdentification('321', '', '31'),
|
||||
responsability_code = form.Responsability(['O-07']),
|
||||
responsability_regime_code = '48',
|
||||
organization_code = '1',
|
||||
address = form.Address(
|
||||
'', '', form.City('05001', 'Medellín'),
|
||||
form.Country('CO', 'Colombia'),
|
||||
form.CountrySubentity('05', 'Antioquia'))
|
||||
@ -47,7 +45,7 @@ def simple_credit_note_without_lines():
|
||||
inv.set_supplier(form.Party(
|
||||
name = 'facho-supplier',
|
||||
ident = form.PartyIdentification('123','', '31'),
|
||||
responsability_code = form.Responsability(['ZZ']),
|
||||
responsability_code = form.Responsability(['O-07']),
|
||||
responsability_regime_code = '48',
|
||||
organization_code = '1',
|
||||
address = form.Address(
|
||||
@ -58,7 +56,7 @@ def simple_credit_note_without_lines():
|
||||
inv.set_customer(form.Party(
|
||||
name = 'facho-customer',
|
||||
ident = form.PartyIdentification('321', '', '31'),
|
||||
responsability_code = form.Responsability(['ZZ']),
|
||||
responsability_code = form.Responsability(['O-07']),
|
||||
responsability_regime_code = '48',
|
||||
organization_code = '1',
|
||||
address = form.Address(
|
||||
@ -79,7 +77,7 @@ def simple_invoice_without_lines():
|
||||
inv.set_supplier(form.Party(
|
||||
name = 'facho-supplier',
|
||||
ident = form.PartyIdentification('123','', '31'),
|
||||
responsability_code = form.Responsability(['ZZ']),
|
||||
responsability_code = form.Responsability(['O-07']),
|
||||
responsability_regime_code = '48',
|
||||
organization_code = '1',
|
||||
address = form.Address(
|
||||
@ -90,7 +88,7 @@ def simple_invoice_without_lines():
|
||||
inv.set_customer(form.Party(
|
||||
name = 'facho-customer',
|
||||
ident = form.PartyIdentification('321', '', '31'),
|
||||
responsability_code = form.Responsability(['ZZ']),
|
||||
responsability_code = form.Responsability(['O-07']),
|
||||
responsability_regime_code = '48',
|
||||
organization_code = '1',
|
||||
address = form.Address(
|
||||
@ -100,7 +98,6 @@ def simple_invoice_without_lines():
|
||||
))
|
||||
return inv
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def simple_invoice():
|
||||
inv = form.NationalSalesInvoice()
|
||||
@ -112,7 +109,7 @@ def simple_invoice():
|
||||
inv.set_supplier(form.Party(
|
||||
name = 'facho-supplier',
|
||||
ident = form.PartyIdentification('123','', '31'),
|
||||
responsability_code = form.Responsability(['ZZ']),
|
||||
responsability_code = form.Responsability(['O-07']),
|
||||
responsability_regime_code = '48',
|
||||
organization_code = '1',
|
||||
address = form.Address(
|
||||
@ -123,7 +120,7 @@ def simple_invoice():
|
||||
inv.set_customer(form.Party(
|
||||
name = 'facho-customer',
|
||||
ident = form.PartyIdentification('321','', '31'),
|
||||
responsability_code = form.Responsability(['ZZ']),
|
||||
responsability_code = form.Responsability(['O-07']),
|
||||
responsability_regime_code = '48',
|
||||
organization_code = '1',
|
||||
address = form.Address(
|
||||
@ -131,20 +128,19 @@ def simple_invoice():
|
||||
form.Country('CO', 'Colombia'),
|
||||
form.CountrySubentity('05', 'Antioquia'))
|
||||
))
|
||||
|
||||
inv.add_invoice_line(form.InvoiceLine(
|
||||
quantity=form.Quantity(1, '94'),
|
||||
description='productofacho',
|
||||
item=form.StandardItem(9999),
|
||||
price=form.Price(form.Amount(100.0),'01',''),
|
||||
tax=form.TaxTotal(
|
||||
tax_amount=form.Amount(0.0),
|
||||
taxable_amount=form.Amount(0.0),
|
||||
subtotals=[
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto facho',
|
||||
item = form.StandardItem( 9999),
|
||||
price = form.Price(form.Amount(100.0), '01', ''),
|
||||
tax = form.TaxTotal(
|
||||
tax_amount = form.Amount(0.0),
|
||||
taxable_amount = form.Amount(0.0),
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
percent=19.0,
|
||||
)]),
|
||||
withholding=form.WithholdingTaxTotal(
|
||||
subtotals=[])
|
||||
percent = 19.0,
|
||||
)
|
||||
]
|
||||
)
|
||||
))
|
||||
return inv
|
||||
|
@ -1,21 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# This file is part of facho. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
import pytest
|
||||
from facho.fe import form_xml
|
||||
from fixtures import simple_invoice
|
||||
|
||||
simple_invoice = simple_invoice
|
||||
|
||||
|
||||
def test_application_response(simple_invoice):
|
||||
|
||||
doc = form_xml.ApplicationResponse(simple_invoice)
|
||||
xml = doc.toFachoXML()
|
||||
|
||||
with open("application_response.xml", "w") as fh:
|
||||
fh.write(xml.tostring())
|
||||
# raise Exception(xml.tostring())
|
||||
# assert xml.get_element_text(
|
||||
# './apr:ApplicationResponse')
|
@ -2,124 +2,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# This file is part of facho. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
# from datetime import datetime
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
from facho.fe import form_xml
|
||||
from datetime import datetime
|
||||
|
||||
import helpers
|
||||
from fixtures import simple_invoice
|
||||
|
||||
simple_invoice = simple_invoice
|
||||
|
||||
def test_xml_with_required_elements(simple_invoice):
|
||||
|
||||
xml_header = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'
|
||||
DIANInvoiceXML = form_xml.DIANInvoiceXML(
|
||||
simple_invoice)
|
||||
|
||||
doc = form_xml.AttachedDocument(
|
||||
simple_invoice,
|
||||
DIANInvoiceXML,
|
||||
id='123')
|
||||
def test_xml_with_required_elements():
|
||||
doc = form_xml.AttachedDocument(id='123')
|
||||
|
||||
xml = doc.toFachoXML()
|
||||
|
||||
DIANInvoiceXML = form_xml.DIANInvoiceXML(
|
||||
simple_invoice, 'Invoice').attach_invoice
|
||||
|
||||
ApplicationResponse = xml_header + form_xml.ApplicationResponse(simple_invoice).toFachoXML().tostring()
|
||||
|
||||
attached_document = xml_header + DIANInvoiceXML.tostring()
|
||||
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cbc:UBLVersionID') == 'UBL 2.1'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cbc:CustomizationID') == 'Documentos adjuntos'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cbc:ProfileID') == 'Factura Electrónica de Venta'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cbc:ProfileExecutionID') == '1'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cbc:ID') == '123'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cbc:IssueDate') == str(datetime.today().date())
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cbc:IssueTime') == datetime.today(
|
||||
).time().strftime(
|
||||
'%H:%M:%S-05:00')
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cbc:DocumentType'
|
||||
) == 'Contenedor de Factura Electrónica'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cbc:ParentDocumentID'
|
||||
) == 'ABC123'
|
||||
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:SenderParty/cac:PartyTaxScheme/cbc:RegistrationName'
|
||||
) == 'facho-supplier'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:SenderParty/cac:PartyTaxScheme/cbc:CompanyID'
|
||||
) == '123'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:SenderParty/cac:PartyTaxScheme/cbc:TaxLevelCode'
|
||||
) == 'ZZ'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:SenderParty/cac:PartyTaxScheme/cac:TaxScheme/cbc:ID'
|
||||
) == '01'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:SenderParty/cac:PartyTaxScheme/cac:TaxScheme/cbc:Name'
|
||||
) == 'IVA'
|
||||
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ReceiverParty/cac:PartyTaxScheme/cbc:RegistrationName'
|
||||
) == 'facho-customer'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ReceiverParty/cac:PartyTaxScheme/cbc:CompanyID'
|
||||
) == '321'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ReceiverParty/cac:PartyTaxScheme/cbc:TaxLevelCode'
|
||||
) == 'ZZ'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ReceiverParty/cac:PartyTaxScheme/cac:TaxScheme/cbc:ID'
|
||||
) == '01'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ReceiverParty/cac:PartyTaxScheme/cac:TaxScheme/cbc:Name'
|
||||
) == 'IVA'
|
||||
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:Attachment/cac:ExternalReference/cbc:MimeCode'
|
||||
) == "text/xml"
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:Attachment/cac:ExternalReference/cbc:EncodingCode'
|
||||
) == "UTF-8"
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:Attachment/cac:ExternalReference/cbc:Description'
|
||||
) == "<![CDATA[{}]]>".format(attached_document)
|
||||
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ParentDocumentLineReference/cbc:LineID'
|
||||
) == '1'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ParentDocumentLineReference/cac:DocumentReference/cbc:ID'
|
||||
) == '1234'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ParentDocumentLineReference/cac:DocumentReference/cbc:UUID'
|
||||
) == '1234'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ParentDocumentLineReference/cac:DocumentReference/cbc:IssueDate'
|
||||
) == '2024-11-28'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ParentDocumentLineReference/cac:DocumentReference/cbc:DocumentType'
|
||||
) == 'ApplicationResponse'
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ParentDocumentLineReference/cac:DocumentReference/cac:Attachment/cac:ExternalReference/cbc:MimeCode'
|
||||
) == 'text/xml'
|
||||
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ParentDocumentLineReference/cac:DocumentReference/cac:Attachment/cac:ExternalReference/cbc:EncodingCode'
|
||||
) == "UTF-8"
|
||||
|
||||
assert xml.get_element_text(
|
||||
'/atd:AttachedDocument/cac:ParentDocumentLineReference/cac:DocumentReference/cac:Attachment/cac:ExternalReference/cbc:Description'
|
||||
) == "<![CDATA[{}]]>".format(ApplicationResponse)
|
||||
assert xml.get_element_text('/atd:AttachedDocument/cbc:ID') == '123'
|
||||
|
||||
|
@ -4,26 +4,21 @@
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
"""Tests for `facho` package."""
|
||||
from facho.fe.data.dian import codelist
|
||||
|
||||
import pytest
|
||||
from facho.fe.data.dian import codelist
|
||||
|
||||
def test_tiporesponsabilidad():
|
||||
assert codelist.TipoResponsabilidad.short_name == 'TipoResponsabilidad'
|
||||
assert codelist.TipoResponsabilidad.by_name(
|
||||
'Autorretenedor')['name'] == 'Autorretenedor'
|
||||
|
||||
assert codelist.TipoResponsabilidad.by_name('Autorretenedor')['name'] == 'Autorretenedor'
|
||||
|
||||
def test_tipoorganizacion():
|
||||
assert codelist.TipoOrganizacion.short_name == 'TipoOrganizacion'
|
||||
assert codelist.TipoOrganizacion.by_name(
|
||||
'Persona Natural')['name'] == 'Persona Natural'
|
||||
|
||||
assert codelist.TipoOrganizacion.by_name('Persona Natural')['name'] == 'Persona Natural'
|
||||
|
||||
def test_tipodocumento():
|
||||
assert codelist.TipoDocumento.short_name == 'TipoDocumento'
|
||||
assert codelist.TipoDocumento.by_name(
|
||||
'Factura electrónica de Venta')['code'] == '01'
|
||||
|
||||
assert codelist.TipoDocumento.by_name('Factura de Venta Nacional')['code'] == '01'
|
||||
|
||||
def test_departamento():
|
||||
assert codelist.Departamento['05']['name'] == 'Antioquia'
|
||||
|
@ -5,15 +5,15 @@
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from facho import fe
|
||||
|
||||
|
||||
import helpers
|
||||
|
||||
|
||||
def test_xmlsigned_build(monkeypatch):
|
||||
# openssl req -x509 -sha256 -nodes -subj "/CN=test" -days 1 -newkey rsa:2048 -keyout example.key -out example.pem
|
||||
# openssl pkcs12 -export -out example.p12 -inkey example.key -in example.pem
|
||||
#openssl req -x509 -sha256 -nodes -subj "/CN=test" -days 1 -newkey rsa:2048 -keyout example.key -out example.pem
|
||||
#openssl pkcs12 -export -out example.p12 -inkey example.key -in example.pem
|
||||
signer = fe.DianXMLExtensionSigner('./tests/example.p12')
|
||||
|
||||
xml = fe.FeXML('Invoice',
|
||||
@ -116,17 +116,3 @@ def test_xml_sign_dian_using_bytes(monkeypatch):
|
||||
|
||||
xmlsigned = signer.sign_xml_string(xmlstring)
|
||||
assert "Signature" in xmlsigned
|
||||
|
||||
def test_xml_signature_timestamp(monkeypatch):
|
||||
xml = fe.FeXML(
|
||||
'Invoice',
|
||||
'http://www.dian.gov.co/contratos/facturaelectronica/v1')
|
||||
xml.find_or_create_element(
|
||||
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension/ext:ExtensionContent')
|
||||
ublextension = xml.fragment(
|
||||
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension', append=True)
|
||||
ublextension.find_or_create_element(
|
||||
'/ext:UBLExtension/ext:ExtensionContent')
|
||||
xmlstring = xml.tostring()
|
||||
signer = fe.DianXMLExtensionSigner('./tests/example.p12')
|
||||
xmlsigned = signer.sign_xml_string(xmlstring)
|
||||
|
@ -5,47 +5,24 @@
|
||||
|
||||
"""Tests for `facho` package."""
|
||||
|
||||
import pytest
|
||||
from datetime import datetime
|
||||
import io
|
||||
import zipfile
|
||||
|
||||
import facho.fe.form as form
|
||||
from facho import fe
|
||||
from facho.fe.form_xml import (
|
||||
DIANInvoiceXML, DIANCreditNoteXML, DIANDebitNoteXML)
|
||||
|
||||
from fixtures import (
|
||||
simple_invoice,
|
||||
simple_invoice_without_lines,
|
||||
simple_credit_note_without_lines,
|
||||
simple_debit_note_without_lines)
|
||||
|
||||
try:
|
||||
CUDE_ = open("./tests/cude.txt", 'r').read().strip()
|
||||
except FileNotFoundError:
|
||||
raise Exception("Archivo Cude No encontrado")
|
||||
|
||||
CUFE_ = (
|
||||
'8bb918b19ba22a694f1da'
|
||||
'11c643b5e9de39adf60311c'
|
||||
'f179179e9b33381030bcd4c3c'
|
||||
'3f156c506ed5908f9276f5bd9b4')
|
||||
|
||||
simple_invoice = simple_invoice
|
||||
simple_invoice_without_lines = simple_invoice_without_lines
|
||||
simple_credit_note_without_lines = simple_credit_note_without_lines
|
||||
simple_debit_note_without_lines = simple_debit_note_without_lines
|
||||
from facho.fe.form_xml import DIANInvoiceXML, DIANCreditNoteXML, DIANDebitNoteXML
|
||||
|
||||
from fixtures import *
|
||||
|
||||
def test_invoicesimple_build(simple_invoice):
|
||||
xml = DIANInvoiceXML(simple_invoice)
|
||||
|
||||
supplier_name = xml.get_element_text(
|
||||
'/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name')
|
||||
supplier_name = xml.get_element_text('/fe:Invoice/cac:AccountingSupplierParty/cac:Party/cac:PartyName/cbc:Name')
|
||||
assert supplier_name == simple_invoice.invoice_supplier.name
|
||||
|
||||
customer_name = xml.get_element_text(
|
||||
'/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyName/cbc:Name')
|
||||
customer_name = xml.get_element_text('/fe:Invoice/cac:AccountingCustomerParty/cac:Party/cac:PartyName/cbc:Name')
|
||||
assert customer_name == simple_invoice.invoice_customer.name
|
||||
|
||||
|
||||
@ -65,11 +42,9 @@ def test_invoicesimple_xml_signed(monkeypatch, simple_invoice):
|
||||
print(xml.tostring())
|
||||
xml.add_extension(signer)
|
||||
|
||||
elem = xml.get_element(
|
||||
'/fe:Invoice/ext:UBLExtensions/ext:UBLExtension[2]/ext:ExtensionContent/ds:Signature')
|
||||
elem = xml.get_element('/fe:Invoice/ext:UBLExtensions/ext:UBLExtension[2]/ext:ExtensionContent/ds:Signature')
|
||||
assert elem.text is not None
|
||||
|
||||
|
||||
def test_invoicesimple_zip(simple_invoice):
|
||||
xml_invoice = DIANInvoiceXML(simple_invoice)
|
||||
|
||||
@ -91,34 +66,26 @@ def test_invoicesimple_zip(simple_invoice):
|
||||
|
||||
def test_bug_cbcid_empty_on_invoice_line(simple_invoice):
|
||||
xml_invoice = DIANInvoiceXML(simple_invoice)
|
||||
cbc_id = xml_invoice.get_element_text(
|
||||
'/fe:Invoice/cac:InvoiceLine[1]/cbc:ID', format_=int)
|
||||
cbc_id = xml_invoice.get_element_text('/fe:Invoice/cac:InvoiceLine[1]/cbc:ID', format_=int)
|
||||
assert cbc_id == 1
|
||||
|
||||
|
||||
def test_invoice_line_count_numeric(simple_invoice):
|
||||
xml_invoice = DIANInvoiceXML(simple_invoice)
|
||||
count = xml_invoice.get_element_text(
|
||||
'/fe:Invoice/cbc:LineCountNumeric', format_=int)
|
||||
count = xml_invoice.get_element_text('/fe:Invoice/cbc:LineCountNumeric', format_=int)
|
||||
assert count == len(simple_invoice.invoice_lines)
|
||||
|
||||
|
||||
def test_invoice_profileexecutionid(simple_invoice):
|
||||
xml_invoice = DIANInvoiceXML(simple_invoice)
|
||||
cufe_extension = fe.DianXMLExtensionCUFE(simple_invoice)
|
||||
xml_invoice.add_extension(cufe_extension)
|
||||
id_ = xml_invoice.get_element_text(
|
||||
'/fe:Invoice/cbc:ProfileExecutionID', format_=int)
|
||||
id_ = xml_invoice.get_element_text('/fe:Invoice/cbc:ProfileExecutionID', format_=int)
|
||||
assert id_ == 2
|
||||
|
||||
|
||||
def test_invoice_invoice_type_code(simple_invoice):
|
||||
xml_invoice = DIANInvoiceXML(simple_invoice)
|
||||
id_ = xml_invoice.get_element_text(
|
||||
'/fe:Invoice/cbc:InvoiceTypeCode', format_=int)
|
||||
id_ = xml_invoice.get_element_text('/fe:Invoice/cbc:InvoiceTypeCode', format_=int)
|
||||
assert id_ == 1
|
||||
|
||||
|
||||
def test_invoice_totals(simple_invoice_without_lines):
|
||||
simple_invoice = simple_invoice_without_lines
|
||||
simple_invoice.invoice_ident = '323200000129'
|
||||
@ -126,50 +93,39 @@ def test_invoice_totals(simple_invoice_without_lines):
|
||||
simple_invoice.invoice_supplier.ident = '700085371'
|
||||
simple_invoice.invoice_customer.ident = '800199436'
|
||||
simple_invoice.add_invoice_line(form.InvoiceLine(
|
||||
quantity=form.Quantity(1, '94'),
|
||||
description='producto',
|
||||
item=form.StandardItem(9999),
|
||||
price=form.Price(form.Amount(1_500_000), '01', ''),
|
||||
tax=form.TaxTotal(
|
||||
subtotals=[
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto',
|
||||
item = form.StandardItem(9999),
|
||||
price = form.Price(form.Amount(1_500_000), '01', ''),
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
scheme=form.TaxScheme('01'),
|
||||
percent=19.0
|
||||
)]),
|
||||
withholding=form.WithholdingTaxTotal(
|
||||
subtotals=[])
|
||||
scheme = form.TaxScheme('01'),
|
||||
percent = 19.0
|
||||
)])
|
||||
))
|
||||
simple_invoice.calculate()
|
||||
assert 1 == len(simple_invoice.invoice_lines)
|
||||
assert form.Amount(1_500_000) == (
|
||||
simple_invoice.invoice_legal_monetary_total.line_extension_amount)
|
||||
assert form.Amount(1_785_000) == (
|
||||
simple_invoice.invoice_legal_monetary_total.payable_amount)
|
||||
|
||||
assert form.Amount(1_500_000) == simple_invoice.invoice_legal_monetary_total.line_extension_amount
|
||||
assert form.Amount(1_785_000) == simple_invoice.invoice_legal_monetary_total.payable_amount
|
||||
|
||||
def test_invoice_cufe(simple_invoice_without_lines):
|
||||
simple_invoice = simple_invoice_without_lines
|
||||
simple_invoice.invoice_ident = '323200000129'
|
||||
simple_invoice.invoice_issue = datetime.strptime(
|
||||
'2019-01-16 10:53:10-05:00', '%Y-%m-%d %H:%M:%S%z')
|
||||
simple_invoice.invoice_supplier.ident = form.PartyIdentification(
|
||||
'700085371', '5', '31')
|
||||
simple_invoice.invoice_customer.ident = form.PartyIdentification(
|
||||
'800199436', '5', '31')
|
||||
simple_invoice.invoice_issue = datetime.strptime('2019-01-16 10:53:10-05:00', '%Y-%m-%d %H:%M:%S%z')
|
||||
simple_invoice.invoice_supplier.ident = form.PartyIdentification('700085371', '5', '31')
|
||||
simple_invoice.invoice_customer.ident = form.PartyIdentification('800199436', '5', '31')
|
||||
simple_invoice.add_invoice_line(form.InvoiceLine(
|
||||
quantity=form.Quantity(
|
||||
1.00, '94'),
|
||||
description='producto',
|
||||
item=form.StandardItem(111),
|
||||
price=form.Price(form.Amount(1_500_000), '01', ''),
|
||||
tax=form.TaxTotal(
|
||||
subtotals=[
|
||||
quantity = form.Quantity(1.00, '94'),
|
||||
description = 'producto',
|
||||
item = form.StandardItem(111),
|
||||
price = form.Price(form.Amount(1_500_000), '01', ''),
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
scheme=form.TaxScheme('01'),
|
||||
percent=19.0
|
||||
)]),
|
||||
withholding=form.WithholdingTaxTotal(
|
||||
subtotals=[])
|
||||
scheme = form.TaxScheme('01'),
|
||||
percent = 19.0
|
||||
)])
|
||||
))
|
||||
|
||||
simple_invoice.calculate()
|
||||
@ -177,86 +133,65 @@ def test_invoice_cufe(simple_invoice_without_lines):
|
||||
|
||||
cufe_extension = fe.DianXMLExtensionCUFE(
|
||||
simple_invoice,
|
||||
tipo_ambiente=fe.AMBIENTE_PRODUCCION,
|
||||
clave_tecnica='693ff6f2a553c3646a063436fd4dd9ded0311471'
|
||||
tipo_ambiente = fe.AMBIENTE_PRODUCCION,
|
||||
clave_tecnica = '693ff6f2a553c3646a063436fd4dd9ded0311471'
|
||||
)
|
||||
formatVars = cufe_extension.formatVars()
|
||||
|
||||
# NumFac
|
||||
#NumFac
|
||||
assert formatVars[0] == '323200000129', "NumFac"
|
||||
|
||||
# FecFac
|
||||
#FecFac
|
||||
assert formatVars[1] == '2019-01-16', "FecFac"
|
||||
|
||||
# HoraFac
|
||||
#HoraFac
|
||||
assert formatVars[2] == '10:53:10-05:00', "HoraFac"
|
||||
|
||||
# ValorBruto
|
||||
#ValorBruto
|
||||
assert formatVars[3] == '1500000.00', "ValorBruto"
|
||||
|
||||
# CodImpuesto1
|
||||
#CodImpuesto1
|
||||
assert formatVars[4] == '01', "CodImpuesto1"
|
||||
|
||||
# ValorImpuesto1
|
||||
#ValorImpuesto1
|
||||
assert formatVars[5] == '285000.00', "ValorImpuesto1"
|
||||
|
||||
# CodImpuesto2
|
||||
#CodImpuesto2
|
||||
assert formatVars[6] == '04', "CodImpuesto2"
|
||||
|
||||
# ValorImpuesto2
|
||||
#ValorImpuesto2
|
||||
assert formatVars[7] == '0.00', "ValorImpuesto2"
|
||||
|
||||
# CodImpuesto3
|
||||
#CodImpuesto3
|
||||
assert formatVars[8] == '03', "CodImpuesto3"
|
||||
|
||||
# ValorImpuesto3
|
||||
#ValorImpuesto3
|
||||
assert formatVars[9] == '0.00', "ValorImpuesto3"
|
||||
|
||||
# ValTotFac
|
||||
#ValTotFac
|
||||
assert formatVars[10] == '1785000.00', "ValTotFac"
|
||||
|
||||
# NitOFE
|
||||
#NitOFE
|
||||
assert formatVars[11] == '700085371', "NitOFE"
|
||||
|
||||
# NumAdq
|
||||
#NumAdq
|
||||
assert formatVars[12] == '800199436', "NumAdq"
|
||||
|
||||
# ClTec
|
||||
#ClTec
|
||||
assert formatVars[13] == '693ff6f2a553c3646a063436fd4dd9ded0311471', "ClTec"
|
||||
|
||||
# TipoAmbiente
|
||||
#TipoAmbiente
|
||||
assert formatVars[14] == '1', "TipoAmbiente"
|
||||
|
||||
xml_invoice.add_extension(cufe_extension)
|
||||
cufe = xml_invoice.get_element_text('/fe:Invoice/cbc:UUID')
|
||||
# RESOLUCION 004: pagina 689
|
||||
assert cufe == CUFE_
|
||||
assert cufe == '8bb918b19ba22a694f1da11c643b5e9de39adf60311cf179179e9b33381030bcd4c3c3f156c506ed5908f9276f5bd9b4'
|
||||
|
||||
|
||||
|
||||
def test_credit_note_cude(simple_credit_note_without_lines):
|
||||
simple_invoice = simple_credit_note_without_lines
|
||||
simple_invoice.invoice_ident = '8110007871'
|
||||
simple_invoice.invoice_issue = datetime.strptime(
|
||||
'2019-01-12 07:00:00-05:00', '%Y-%m-%d %H:%M:%S%z')
|
||||
simple_invoice.invoice_supplier.ident = form.PartyIdentification(
|
||||
'900373076', '5', '31')
|
||||
simple_invoice.invoice_customer.ident = form.PartyIdentification(
|
||||
'8355990', '5', '31')
|
||||
simple_invoice.invoice_issue = datetime.strptime('2019-01-12 07:00:00-05:00', '%Y-%m-%d %H:%M:%S%z')
|
||||
simple_invoice.invoice_supplier.ident = form.PartyIdentification('900373076', '5', '31')
|
||||
simple_invoice.invoice_customer.ident = form.PartyIdentification('8355990', '5', '31')
|
||||
simple_invoice.add_invoice_line(form.InvoiceLine(
|
||||
quantity=form.Quantity(
|
||||
1, '94'),
|
||||
description='producto',
|
||||
item=form.StandardItem(111),
|
||||
price=form.Price(
|
||||
form.Amount(5_000), '01', ''),
|
||||
tax=form.TaxTotal(
|
||||
subtotals=[
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto',
|
||||
item = form.StandardItem(111),
|
||||
price = form.Price(form.Amount(5_000), '01', ''),
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
scheme=form.TaxScheme('01'),
|
||||
percent=19.0
|
||||
)]),
|
||||
withholding=form.WithholdingTaxTotal(
|
||||
subtotals=[])
|
||||
scheme = form.TaxScheme('01'),
|
||||
percent = 19.0
|
||||
)])
|
||||
))
|
||||
|
||||
simple_invoice.calculate()
|
||||
@ -265,39 +200,33 @@ def test_credit_note_cude(simple_credit_note_without_lines):
|
||||
cude_extension = fe.DianXMLExtensionCUDE(
|
||||
simple_invoice,
|
||||
'12301',
|
||||
tipo_ambiente=fe.AMBIENTE_PRODUCCION,
|
||||
tipo_ambiente = fe.AMBIENTE_PRODUCCION,
|
||||
)
|
||||
|
||||
xml_invoice.add_extension(cude_extension)
|
||||
cude = xml_invoice.get_element_text('/fe:CreditNote/cbc:UUID')
|
||||
# pag 612
|
||||
|
||||
assert cude == CUDE_
|
||||
assert cude == '907e4444decc9e59c160a2fb3b6659b33dc5b632a5008922b9a62f83f757b1c448e47f5867f2b50dbdb96f48c7681168'
|
||||
|
||||
|
||||
# pag 614
|
||||
def test_debit_note_cude(simple_debit_note_without_lines):
|
||||
simple_invoice = simple_debit_note_without_lines
|
||||
simple_invoice.invoice_ident = 'ND1001'
|
||||
simple_invoice.invoice_issue = datetime.strptime(
|
||||
'2019-01-18 10:58:00-05:00', '%Y-%m-%d %H:%M:%S%z')
|
||||
simple_invoice.invoice_supplier.ident = form.PartyIdentification(
|
||||
'900197264', '5', '31')
|
||||
simple_invoice.invoice_customer.ident = form.PartyIdentification(
|
||||
'10254102', '5', '31')
|
||||
simple_invoice.invoice_issue = datetime.strptime('2019-01-18 10:58:00-05:00', '%Y-%m-%d %H:%M:%S%z')
|
||||
simple_invoice.invoice_supplier.ident = form.PartyIdentification('900197264', '5', '31')
|
||||
simple_invoice.invoice_customer.ident = form.PartyIdentification('10254102', '5', '31')
|
||||
simple_invoice.add_invoice_line(form.InvoiceLine(
|
||||
quantity=form.Quantity(1, '94'),
|
||||
description='producto',
|
||||
item=form.StandardItem(111),
|
||||
price=form.Price(form.Amount(30_000), '01', ''),
|
||||
tax=form.TaxTotal(
|
||||
subtotals=[
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto',
|
||||
item = form.StandardItem(111),
|
||||
price = form.Price(form.Amount(30_000), '01', ''),
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
scheme=form.TaxScheme('04'),
|
||||
percent=8.0
|
||||
)]),
|
||||
withholding=form.WithholdingTaxTotal(
|
||||
subtotals=[])
|
||||
scheme = form.TaxScheme('04'),
|
||||
percent = 8.0
|
||||
)])
|
||||
))
|
||||
|
||||
simple_invoice.calculate()
|
||||
@ -306,7 +235,7 @@ def test_debit_note_cude(simple_debit_note_without_lines):
|
||||
cude_extension = fe.DianXMLExtensionCUDE(
|
||||
simple_invoice,
|
||||
'10201',
|
||||
tipo_ambiente=fe.AMBIENTE_PRUEBAS,
|
||||
tipo_ambiente = fe.AMBIENTE_PRUEBAS,
|
||||
)
|
||||
build_vars = cude_extension.buildVars()
|
||||
assert build_vars['NumFac'] == 'ND1001'
|
||||
@ -322,7 +251,8 @@ def test_debit_note_cude(simple_debit_note_without_lines):
|
||||
assert build_vars['Software-PIN'] == '10201'
|
||||
assert build_vars['TipoAmb'] == 2
|
||||
|
||||
cude_composicion = "".join(cude_extension.formatVars())
|
||||
|
||||
cude_composicion = "".join(cude_extension.formatVars())
|
||||
assert cude_composicion == 'ND10012019-01-1810:58:00-05:0030000.00010.00042400.00030.0032400.0090019726410254102102012'
|
||||
|
||||
xml_invoice.add_extension(cude_extension)
|
||||
|
@ -6,117 +6,91 @@
|
||||
"""Tests for `facho` package."""
|
||||
|
||||
import pytest
|
||||
# from datetime import datetime
|
||||
# import io
|
||||
# import zipfile
|
||||
from datetime import datetime
|
||||
import io
|
||||
import zipfile
|
||||
|
||||
import facho.fe.form as form
|
||||
# from facho import fe
|
||||
|
||||
from fixtures import (
|
||||
simple_invoice,
|
||||
simple_invoice_without_lines,
|
||||
simple_credit_note_without_lines,
|
||||
simple_debit_note_without_lines)
|
||||
|
||||
simple_invoice = simple_invoice
|
||||
simple_invoice_without_lines = simple_invoice_without_lines
|
||||
simple_credit_note_without_lines = simple_credit_note_without_lines
|
||||
simple_debit_note_without_lines = simple_debit_note_without_lines
|
||||
|
||||
from facho import fe
|
||||
|
||||
def test_invoice_legalmonetary():
|
||||
inv = form.NationalSalesInvoice()
|
||||
inv.add_invoice_line(form.InvoiceLine(
|
||||
quantity=form.Quantity(1, '94'),
|
||||
description='producto facho',
|
||||
item=form.StandardItem(9999),
|
||||
price=form.Price(
|
||||
amount=form.Amount(100.0),
|
||||
type_code='01',
|
||||
type='x'
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto facho',
|
||||
item = form.StandardItem(9999),
|
||||
price = form.Price(
|
||||
amount = form.Amount(100.0),
|
||||
type_code = '01',
|
||||
type = 'x'
|
||||
),
|
||||
tax=form.TaxTotal(
|
||||
subtotals=[
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
percent=19.0,
|
||||
)]),
|
||||
withholding=form.WithholdingTaxTotal(
|
||||
subtotals=[])
|
||||
percent = 19.0,
|
||||
)
|
||||
]
|
||||
)
|
||||
))
|
||||
|
||||
inv.calculate()
|
||||
assert inv.invoice_legal_monetary_total.line_extension_amount == (
|
||||
form.Amount(100.0))
|
||||
assert inv.invoice_legal_monetary_total.tax_exclusive_amount == (
|
||||
form.Amount(100.0))
|
||||
assert inv.invoice_legal_monetary_total.tax_inclusive_amount == (
|
||||
form.Amount(119.0))
|
||||
assert inv.invoice_legal_monetary_total.charge_total_amount == (
|
||||
form.Amount(0.0))
|
||||
|
||||
assert inv.invoice_legal_monetary_total.line_extension_amount == form.Amount(100.0)
|
||||
assert inv.invoice_legal_monetary_total.tax_exclusive_amount == form.Amount(100.0)
|
||||
assert inv.invoice_legal_monetary_total.tax_inclusive_amount == form.Amount(119.0)
|
||||
assert inv.invoice_legal_monetary_total.charge_total_amount == form.Amount(0.0)
|
||||
|
||||
def test_allowancecharge_as_discount():
|
||||
discount = form.AllowanceChargeAsDiscount(amount=form.Amount(1000.0))
|
||||
|
||||
assert discount.isDiscount()
|
||||
|
||||
|
||||
assert discount.isDiscount() == True
|
||||
|
||||
def test_FAU10():
|
||||
inv = form.NationalSalesInvoice()
|
||||
inv.add_invoice_line(form.InvoiceLine(
|
||||
quantity=form.Quantity(1, '94'),
|
||||
description='productofacho',
|
||||
item=form.StandardItem(9999),
|
||||
price=form.Price(
|
||||
amount=form.Amount(100.0),
|
||||
type_code='01',
|
||||
type='x'
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto facho',
|
||||
item = form.StandardItem(9999),
|
||||
price = form.Price(
|
||||
amount = form.Amount(100.0),
|
||||
type_code = '01',
|
||||
type = 'x'
|
||||
),
|
||||
tax=form.TaxTotal(
|
||||
subtotals=[
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
percent=19.0)]),
|
||||
withholding=form.WithholdingTaxTotal(
|
||||
subtotals=[])
|
||||
percent = 19.0,
|
||||
)
|
||||
]
|
||||
)
|
||||
))
|
||||
|
||||
inv.add_allowance_charge(form.AllowanceCharge(amount=form.Amount(19.0)))
|
||||
|
||||
inv.calculate()
|
||||
assert inv.invoice_legal_monetary_total.line_extension_amount == (
|
||||
form.Amount(100.0))
|
||||
assert inv.invoice_legal_monetary_total.tax_exclusive_amount == (
|
||||
form.Amount(100.0))
|
||||
assert inv.invoice_legal_monetary_total.tax_inclusive_amount == (
|
||||
form.Amount(119.0))
|
||||
assert inv.invoice_legal_monetary_total.charge_total_amount == (
|
||||
form.Amount(19.0))
|
||||
assert inv.invoice_legal_monetary_total.line_extension_amount == form.Amount(100.0)
|
||||
assert inv.invoice_legal_monetary_total.tax_exclusive_amount == form.Amount(100.0)
|
||||
assert inv.invoice_legal_monetary_total.tax_inclusive_amount == form.Amount(119.0)
|
||||
assert inv.invoice_legal_monetary_total.charge_total_amount == form.Amount(19.0)
|
||||
|
||||
|
||||
def test_FAU14():
|
||||
inv = form.NationalSalesInvoice()
|
||||
inv.add_invoice_line(form.InvoiceLine(
|
||||
quantity=form.Quantity(1, '94'),
|
||||
description='productofacho',
|
||||
item=form.StandardItem(9999),
|
||||
price=form.Price(
|
||||
amount=form.Amount(100.0),
|
||||
type_code='01',
|
||||
type='x'
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto facho',
|
||||
item = form.StandardItem(9999),
|
||||
price = form.Price(
|
||||
amount = form.Amount(100.0),
|
||||
type_code = '01',
|
||||
type = 'x'
|
||||
),
|
||||
tax=form.TaxTotal(
|
||||
subtotals=[
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
percent=19.0,
|
||||
)]),
|
||||
withholding=form.WithholdingTaxTotal(
|
||||
subtotals=[])
|
||||
percent = 19.0,
|
||||
)
|
||||
]
|
||||
)
|
||||
))
|
||||
inv.add_allowance_charge(form.AllowanceCharge(
|
||||
amount=form.Amount(19.0)))
|
||||
inv.add_prepaid_payment(form.PrePaidPayment(
|
||||
paid_amount=form.Amount(50.0)))
|
||||
inv.add_allowance_charge(form.AllowanceCharge(amount=form.Amount(19.0)))
|
||||
inv.add_prepaid_payment(form.PrePaidPayment(paid_amount = form.Amount(50.0)))
|
||||
inv.calculate()
|
||||
|
||||
wants = form.Amount(119.0 + 19.0 - 50.0)
|
||||
@ -126,42 +100,38 @@ def test_FAU14():
|
||||
|
||||
def test_invalid_tipo_operacion_nota_debito():
|
||||
reference = form.InvoiceDocumentReference(
|
||||
ident='11111',
|
||||
uuid='21312312',
|
||||
date='2020-05-05'
|
||||
ident = '11111',
|
||||
uuid = '21312312',
|
||||
date = '2020-05-05'
|
||||
)
|
||||
inv = form.DebitNote(reference)
|
||||
with pytest.raises(ValueError):
|
||||
inv.set_operation_type(22)
|
||||
|
||||
|
||||
def test_valid_tipo_operacion_nota_debito():
|
||||
reference = form.InvoiceDocumentReference(
|
||||
ident='11111',
|
||||
uuid='21312312',
|
||||
date='2020-05-05'
|
||||
ident = '11111',
|
||||
uuid = '21312312',
|
||||
date = '2020-05-05'
|
||||
)
|
||||
inv = form.DebitNote(reference)
|
||||
inv.set_operation_type('30')
|
||||
|
||||
|
||||
def test_invalid_tipo_operacion_nota_credito():
|
||||
reference = form.InvoiceDocumentReference(
|
||||
ident='11111',
|
||||
uuid='21312312',
|
||||
date='2020-05-05'
|
||||
ident = '11111',
|
||||
uuid = '21312312',
|
||||
date = '2020-05-05'
|
||||
)
|
||||
|
||||
inv = form.DebitNote(reference)
|
||||
with pytest.raises(ValueError):
|
||||
inv.set_operation_type('990')
|
||||
|
||||
|
||||
def test_valid_tipo_operacion_nota_credito():
|
||||
reference = form.InvoiceDocumentReference(
|
||||
ident='11111',
|
||||
uuid='21312312',
|
||||
date='2020-05-05'
|
||||
ident = '11111',
|
||||
uuid = '21312312',
|
||||
date = '2020-05-05'
|
||||
)
|
||||
inv = form.CreditNote(reference)
|
||||
inv.set_operation_type('20')
|
||||
@ -171,52 +141,41 @@ def test_quantity():
|
||||
quantity1 = form.Quantity(10, '94')
|
||||
assert quantity1 * form.Amount(3) == form.Amount(30)
|
||||
|
||||
|
||||
def test_invoice_line_quantity_without_taxes():
|
||||
line = form.InvoiceLine(
|
||||
quantity=form.Quantity(10, '94'),
|
||||
description='',
|
||||
item=form.StandardItem('test', 9999),
|
||||
price=form.Price(
|
||||
amount=form.Amount(30.00),
|
||||
type_code='01',
|
||||
type='x'),
|
||||
tax=form.TaxTotal(subtotals=[]),
|
||||
withholding=form.WithholdingTaxTotal(
|
||||
subtotals=[])
|
||||
)
|
||||
quantity = form.Quantity(10, '94'),
|
||||
description = '',
|
||||
item = form.StandardItem('test', 9999),
|
||||
price = form.Price(
|
||||
amount = form.Amount(30.00),
|
||||
type_code = '01',
|
||||
type = 'x'
|
||||
),
|
||||
tax = form.TaxTotal(subtotals=[]))
|
||||
line.calculate()
|
||||
assert line.total_amount == form.Amount(300)
|
||||
assert line.tax_amount == form.Amount(0)
|
||||
|
||||
|
||||
def test_invoice_legalmonetary_with_taxes():
|
||||
inv = form.NationalSalesInvoice()
|
||||
inv.add_invoice_line(form.InvoiceLine(
|
||||
quantity=form.Quantity(1, '94'),
|
||||
description='productofacho',
|
||||
item=form.StandardItem(9999),
|
||||
price=form.Price(
|
||||
amount=form.Amount(100.0),
|
||||
type_code='01',
|
||||
type='x'
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto facho',
|
||||
item = form.StandardItem(9999),
|
||||
price = form.Price(
|
||||
amount = form.Amount(100.0),
|
||||
type_code = '01',
|
||||
type = 'x'
|
||||
),
|
||||
tax=form.TaxTotal(subtotals=[]),
|
||||
withholding=form.WithholdingTaxTotal(
|
||||
subtotals=[])
|
||||
tax = form.TaxTotal(subtotals=[])
|
||||
))
|
||||
inv.calculate()
|
||||
|
||||
assert inv.invoice_legal_monetary_total.line_extension_amount == (
|
||||
form.Amount(100.0))
|
||||
assert inv.invoice_legal_monetary_total.tax_exclusive_amount == (
|
||||
form.Amount(100.0))
|
||||
assert inv.invoice_legal_monetary_total.tax_inclusive_amount == (
|
||||
form.Amount(100.0))
|
||||
assert inv.invoice_legal_monetary_total.charge_total_amount == (
|
||||
form.Amount(0.0))
|
||||
assert inv.invoice_legal_monetary_total.payable_amount == (
|
||||
form.Amount(100.0))
|
||||
assert inv.invoice_legal_monetary_total.line_extension_amount == form.Amount(100.0)
|
||||
assert inv.invoice_legal_monetary_total.tax_exclusive_amount == form.Amount(100.0)
|
||||
assert inv.invoice_legal_monetary_total.tax_inclusive_amount == form.Amount(100.0)
|
||||
assert inv.invoice_legal_monetary_total.charge_total_amount == form.Amount(0.0)
|
||||
assert inv.invoice_legal_monetary_total.payable_amount == form.Amount(100.0)
|
||||
|
||||
|
||||
def test_invoice_ident_prefix_automatic_invalid():
|
||||
@ -224,7 +183,6 @@ def test_invoice_ident_prefix_automatic_invalid():
|
||||
with pytest.raises(ValueError):
|
||||
inv.set_ident('SETPQJQJ1234567')
|
||||
|
||||
|
||||
def test_invoice_ident_prefix_automatic():
|
||||
inv = form.NationalSalesInvoice()
|
||||
inv.set_ident('SETP1234567')
|
||||
@ -242,15 +200,13 @@ def test_invoice_ident_prefix_automatic():
|
||||
inv.set_ident('1234567')
|
||||
assert inv.invoice_ident_prefix == ''
|
||||
|
||||
|
||||
def test_invoice_ident_prefix_manual():
|
||||
inv = form.NationalSalesInvoice()
|
||||
inv.set_ident('SETP1234567')
|
||||
inv.set_ident_prefix('SETA')
|
||||
assert inv.invoice_ident_prefix == 'SETA'
|
||||
|
||||
|
||||
def test_invoice_ident_prefix_automatic_debit():
|
||||
inv = form.DebitNote(form.BillingReference('', '', ''))
|
||||
inv = form.DebitNote(form.BillingReference('','',''))
|
||||
inv.set_ident('ABCDEF1234567')
|
||||
assert inv.invoice_ident_prefix == 'ABCDEF'
|
||||
|
@ -6,24 +6,13 @@
|
||||
"""Tests for `facho` package."""
|
||||
|
||||
import pytest
|
||||
# from datetime import datetime
|
||||
from datetime import datetime
|
||||
import copy
|
||||
|
||||
from facho.fe import form
|
||||
from facho.fe import form_xml
|
||||
# from fixtures import *
|
||||
|
||||
from fixtures import (
|
||||
simple_invoice,
|
||||
simple_invoice_without_lines,
|
||||
simple_credit_note_without_lines,
|
||||
simple_debit_note_without_lines)
|
||||
|
||||
simple_invoice = simple_invoice
|
||||
simple_invoice_without_lines = simple_invoice_without_lines
|
||||
simple_credit_note_without_lines = simple_credit_note_without_lines
|
||||
simple_debit_note_without_lines = simple_debit_note_without_lines
|
||||
|
||||
from fixtures import *
|
||||
|
||||
def test_import_DIANInvoiceXML():
|
||||
try:
|
||||
@ -38,82 +27,70 @@ def test_import_DIANDebitNoteXML():
|
||||
except AttributeError:
|
||||
pytest.fail("unexpected not found")
|
||||
|
||||
|
||||
def test_import_DIANCreditNoteXML():
|
||||
try:
|
||||
form_xml.DIANCreditNoteXML
|
||||
except AttributeError:
|
||||
pytest.fail("unexpected not found")
|
||||
|
||||
def test_allowance_charge_in_invoice(simple_invoice_without_lines):
|
||||
inv = copy.copy(simple_invoice_without_lines)
|
||||
inv.add_invoice_line(form.InvoiceLine(
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto facho',
|
||||
item = form.StandardItem(9999),
|
||||
price = form.Price(
|
||||
amount = form.Amount(100.0),
|
||||
type_code = '01',
|
||||
type = 'x'
|
||||
),
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
percent = 19.0,
|
||||
)
|
||||
]
|
||||
)
|
||||
))
|
||||
inv.add_allowance_charge(form.AllowanceCharge(amount=form.Amount(19.0)))
|
||||
inv.calculate()
|
||||
|
||||
xml = form_xml.DIANInvoiceXML(inv)
|
||||
assert xml.get_element_text('./cac:AllowanceCharge/cbc:ID') == '1'
|
||||
assert xml.get_element_text('./cac:AllowanceCharge/cbc:ChargeIndicator') == 'true'
|
||||
assert xml.get_element_text('./cac:AllowanceCharge/cbc:Amount') == '19.0'
|
||||
assert xml.get_element_text('./cac:AllowanceCharge/cbc:BaseAmount') == '100.0'
|
||||
|
||||
# def test_allowance_charge_in_invoice(simple_invoice_without_lines):
|
||||
# inv = copy.copy(simple_invoice_without_lines)
|
||||
# inv.add_invoice_line(form.InvoiceLine(
|
||||
# quantity=form.Quantity(1, '94'),
|
||||
# description='productofacho',
|
||||
# item=form.StandardItem(9999),
|
||||
# price=form.Price(
|
||||
# amount=form.Amount(100.0),
|
||||
# type_code='01',
|
||||
# type='x'
|
||||
# ),
|
||||
# tax=form.TaxTotal(
|
||||
# subtotals=[
|
||||
# form.TaxSubTotal(
|
||||
# percent=19.0,
|
||||
# )]),
|
||||
# withholding=form.WithholdingTaxTotal(
|
||||
# subtotals=[])
|
||||
# ))
|
||||
def test_allowance_charge_in_invoice_line(simple_invoice_without_lines):
|
||||
inv = copy.copy(simple_invoice_without_lines)
|
||||
inv.add_invoice_line(form.InvoiceLine(
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto facho',
|
||||
item = form.StandardItem(9999),
|
||||
price = form.Price(
|
||||
amount = form.Amount(100.0),
|
||||
type_code = '01',
|
||||
type = 'x'
|
||||
),
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
percent = 19.0,
|
||||
)
|
||||
]
|
||||
),
|
||||
allowance_charge = [
|
||||
form.AllowanceChargeAsDiscount(amount=form.Amount(10.0))
|
||||
]
|
||||
))
|
||||
inv.calculate()
|
||||
|
||||
# inv.add_allowance_charge(form.AllowanceCharge(amount=form.Amount(19.0)))
|
||||
# inv.calculate()
|
||||
# se aplico descuento
|
||||
assert inv.invoice_legal_monetary_total.line_extension_amount == form.Amount(90.0)
|
||||
|
||||
xml = form_xml.DIANInvoiceXML(inv)
|
||||
|
||||
# xml = form_xml.DIANInvoiceXML(inv)
|
||||
# assert xml.get_element_text('./cac:AllowanceCharge/cbc:ID') == '1'
|
||||
# assert xml.get_element_text(
|
||||
# './cac:AllowanceCharge/cbc:ChargeIndicator') == 'true'
|
||||
# assert xml.get_element_text(
|
||||
# './cac:AllowanceCharge/cbc:Amount') == '19.0'
|
||||
# assert xml.get_element_text(
|
||||
# './cac:AllowanceCharge/cbc:BaseAmount') == '100.0'
|
||||
|
||||
|
||||
# def test_allowance_charge_in_invoice_line(simple_invoice_without_lines):
|
||||
# inv = copy.copy(simple_invoice_without_lines)
|
||||
# inv.add_invoice_line(form.InvoiceLine(
|
||||
# quantity=form.Quantity(1, '94'),
|
||||
# description='producto facho',
|
||||
# item=form.StandardItem(9999),
|
||||
# price=form.Price(
|
||||
# amount=form.Amount(100.0),
|
||||
# type_code='01',
|
||||
# type='x'
|
||||
# ),
|
||||
# tax=form.TaxTotal(
|
||||
# subtotals=[
|
||||
# form.TaxSubTotal(
|
||||
# percent=19.0,
|
||||
# )]),
|
||||
# withholding=form.WithholdingTaxTotal(
|
||||
# subtotals=[]),
|
||||
# allowance_charge=[
|
||||
# form.AllowanceChargeAsDiscount(amount=form.Amount(10.0))
|
||||
# ]
|
||||
# ))
|
||||
# inv.calculate()
|
||||
|
||||
# # se aplico descuento
|
||||
# assert inv.invoice_legal_monetary_total.line_extension_amount == (
|
||||
# form.Amount(90.0))
|
||||
|
||||
# xml = form_xml.DIANInvoiceXML(inv)
|
||||
|
||||
# with pytest.raises(AttributeError):
|
||||
# assert xml.get_element_text(
|
||||
# '/fe:Invoice/cac:AllowanceCharge/cbc:ID') == '1'
|
||||
# xml.get_element_text(
|
||||
# '/fe:Invoice/cac:InvoiceLine/cac:AllowanceCharge/cbc:ID') == '1'
|
||||
# xml.get_element_text(
|
||||
# '/fe:Invoice/cac:InvoiceLine/cac:AllowanceCharge/cbc:BaseAmount'
|
||||
# ) == '100.0'
|
||||
with pytest.raises(AttributeError):
|
||||
assert xml.get_element_text('/fe:Invoice/cac:AllowanceCharge/cbc:ID') == '1'
|
||||
xml.get_element_text('/fe:Invoice/cac:InvoiceLine/cac:AllowanceCharge/cbc:ID') == '1'
|
||||
xml.get_element_text('/fe:Invoice/cac:InvoiceLine/cac:AllowanceCharge/cbc:BaseAmount') == '100.0'
|
||||
|
1026
tests/test_nomina.py
1026
tests/test_nomina.py
File diff suppressed because it is too large
Load Diff
@ -1,236 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# This file is part of facho. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
"""Tests for `facho` package."""
|
||||
# import re
|
||||
|
||||
# import pytest
|
||||
|
||||
# from facho import fe
|
||||
|
||||
# import helpers
|
||||
|
||||
# def atest_nomina_ajuste_reemplazar():
|
||||
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
|
||||
|
||||
# xml = nomina.toFachoXML()
|
||||
# print(xml)
|
||||
# assert False
|
||||
|
||||
# def test_nomina_ajuste_reemplazar_asignacion_tipo_xml():
|
||||
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
|
||||
# nomina.asignar_metadata(fe.nomina.Metadata(
|
||||
# novedad=fe.nomina.Novedad(
|
||||
# activa = True,
|
||||
# cune = "N0111"
|
||||
# ),
|
||||
# secuencia=fe.nomina.NumeroSecuencia(
|
||||
# prefijo = 'N',
|
||||
# consecutivo='00001'
|
||||
# ),
|
||||
# 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_pin='12',
|
||||
# razon_social='facho'
|
||||
# )
|
||||
# ))
|
||||
# nomina.asignar_empleador(fe.nomina.Empleador(
|
||||
# razon_social='facho',
|
||||
# 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.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',
|
||||
# tipo_xml = fe.nomina.InformacionGeneral.TIPO_XML_AJUSTES,
|
||||
# periodo_nomina = fe.nomina.PeriodoNomina(code='1'),
|
||||
# tipo_moneda = fe.nomina.TipoMoneda(code='COP')
|
||||
# ))
|
||||
|
||||
# xml = nomina.toFachoXML()
|
||||
|
||||
# assert xml.get_element_attribute('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/InformacionGeneral', 'TipoXML') == '103'
|
||||
|
||||
|
||||
# def test_adicionar_reemplazar_devengado_comprobante_total():
|
||||
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
|
||||
|
||||
# nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
|
||||
# dias_trabajados = 60,
|
||||
# sueldo_trabajado = fe.nomina.Amount(2_000_000)
|
||||
# ))
|
||||
|
||||
# nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||
# porcentaje = fe.nomina.Amount(19),
|
||||
# deduccion = fe.nomina.Amount(1_000_000)
|
||||
# ))
|
||||
|
||||
# xml = nomina.toFachoXML()
|
||||
|
||||
# assert xml.get_element_text('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ComprobanteTotal') == '1000000.00'
|
||||
|
||||
|
||||
# def test_adicionar_reemplazar_asignar_predecesor():
|
||||
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
|
||||
|
||||
# nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar.Predecesor(
|
||||
# numero = '123456',
|
||||
# cune = 'ABC123456',
|
||||
# fecha_generacion = '2021-11-16'
|
||||
# ))
|
||||
|
||||
# xml = nomina.toFachoXML()
|
||||
# print(xml.tostring())
|
||||
# assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor/@NumeroPred') == '123456'
|
||||
# assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor/@CUNEPred') == 'ABC123456'
|
||||
# assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor/@FechaGenPred') == '2021-11-16'
|
||||
|
||||
|
||||
# def test_adicionar_reemplazar_eliminar_predecesor_opcional():
|
||||
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar()
|
||||
|
||||
# nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Reemplazar.Predecesor(
|
||||
# numero = '123456',
|
||||
# cune = 'ABC123456',
|
||||
# fecha_generacion = '2021-11-16'
|
||||
# ))
|
||||
|
||||
# xml = nomina.toFachoXML()
|
||||
# print(xml.tostring())
|
||||
|
||||
# assert xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor') is not None
|
||||
# assert xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor') is None
|
||||
|
||||
# def test_adicionar_eliminar_reemplazar_predecesor_opcional():
|
||||
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Eliminar()
|
||||
|
||||
# nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Eliminar.Predecesor(
|
||||
# numero = '123456',
|
||||
# cune = 'ABC123456',
|
||||
# fecha_generacion = '2021-11-16'
|
||||
# ))
|
||||
|
||||
# xml = nomina.toFachoXML()
|
||||
# print(xml.tostring())
|
||||
# assert xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor') is not None
|
||||
# assert xml.get_element('/nominaajuste:NominaIndividualDeAjuste/Reemplazar/ReemplazandoPredecesor') is None
|
||||
|
||||
# def test_adicionar_eliminar_devengado_comprobante_total():
|
||||
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Eliminar()
|
||||
|
||||
# nomina.adicionar_devengado(fe.nomina.DevengadoBasico(
|
||||
# dias_trabajados = 60,
|
||||
# sueldo_trabajado = fe.nomina.Amount(2_000_000)
|
||||
# ))
|
||||
|
||||
# nomina.adicionar_deduccion(fe.nomina.DeduccionSalud(
|
||||
# porcentaje = fe.nomina.Amount(19),
|
||||
# deduccion = fe.nomina.Amount(1_000_000)
|
||||
# ))
|
||||
|
||||
# xml = nomina.toFachoXML()
|
||||
|
||||
# assert xml.get_element_text('/nominaajuste:NominaIndividualDeAjuste/Eliminar/ComprobanteTotal') == '1000000.00'
|
||||
|
||||
# def test_adicionar_eliminar_asignar_predecesor():
|
||||
# nomina = fe.nomina.DIANNominaIndividualDeAjuste.Eliminar()
|
||||
|
||||
# nomina.asignar_predecesor(fe.nomina.DIANNominaIndividualDeAjuste.Eliminar.Predecesor(
|
||||
# numero = '123456',
|
||||
# cune = 'ABC123456',
|
||||
# fecha_generacion = '2021-11-16'
|
||||
# ))
|
||||
|
||||
# xml = nomina.toFachoXML()
|
||||
# print(xml.tostring())
|
||||
# assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor/@NumeroPred') == '123456'
|
||||
# assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor/@CUNEPred') == 'ABC123456'
|
||||
# assert xml.get_element_text_or_attribute('/nominaajuste:NominaIndividualDeAjuste/Eliminar/EliminandoPredecesor/@FechaGenPred') == '2021-11-16'
|
||||
|
||||
# def test_nomina_devengado_horas_extras_diarias():
|
||||
# nomina = fe.nomina.DIANNominaIndividual()
|
||||
|
||||
# nomina.adicionar_devengado(fe.nomina.DevengadoHorasExtrasDiarias(
|
||||
# horas_extras=[
|
||||
# fe.nomina.DevengadoHoraExtra(
|
||||
# hora_inicio='2021-11-30T19:09:55',
|
||||
# hora_fin='2021-11-30T20:09:55',
|
||||
# cantidad=1,
|
||||
# porcentaje=fe.nomina.Amount(1),
|
||||
# pago=fe.nomina.Amount(100)
|
||||
# ),
|
||||
# fe.nomina.DevengadoHoraExtra(
|
||||
# hora_inicio='2021-11-30T18:09:55',
|
||||
# hora_fin='2021-11-30T19:09:55',
|
||||
# cantidad=2,
|
||||
# porcentaje=fe.nomina.Amount(2),
|
||||
# pago=fe.nomina.Amount(200)
|
||||
# )
|
||||
# ]
|
||||
# ))
|
||||
|
||||
# xml = nomina.toFachoXML()
|
||||
# extras = xml.get_element(
|
||||
# '/nomina:NominaIndividual/Devengados/HEDs/HED', multiple=True)
|
||||
# assert extras[0].get('HoraInicio') == '2021-11-30T19:09:55'
|
||||
# assert extras[0].get('HoraFin') == '2021-11-30T20:09:55'
|
||||
# assert extras[0].get('Cantidad') == '1'
|
||||
# assert extras[0].get('Porcentaje') == '1.00'
|
||||
# assert extras[0].get('Pago') == '100.00'
|
||||
# assert extras[1].get('HoraInicio') == '2021-11-30T18:09:55'
|
||||
# assert extras[1].get('HoraFin') == '2021-11-30T19:09:55'
|
||||
# assert extras[1].get('Cantidad') == '2'
|
||||
# assert extras[1].get('Porcentaje') == '2.00'
|
||||
# assert extras[1].get('Pago') == '200.00'
|
@ -3,28 +3,22 @@
|
||||
# This file is part of facho. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
# import pytest
|
||||
import pytest
|
||||
|
||||
import facho.fe.form as form
|
||||
from facho import fe
|
||||
from facho.fe.form_xml import DIANInvoiceXML, DIANCreditNoteXML, DIANDebitNoteXML
|
||||
|
||||
from facho.fe.form_xml import DIANInvoiceXML
|
||||
# from facho.fe.form_xml import (
|
||||
# DIANInvoiceXML, DIANCreditNoteXML, DIANDebitNoteXML)
|
||||
|
||||
from fixtures import simple_invoice
|
||||
from fixtures import *
|
||||
|
||||
from facho.fe.form import query
|
||||
|
||||
simple_invoice = simple_invoice
|
||||
|
||||
|
||||
def test_query_billing_reference(simple_invoice):
|
||||
xml = DIANInvoiceXML(simple_invoice)
|
||||
cufe_extension = fe.DianXMLExtensionCUFE(simple_invoice)
|
||||
xml.add_extension(cufe_extension)
|
||||
out = xml.tostring()
|
||||
|
||||
|
||||
reference = query.billing_reference(out, form.BillingReference)
|
||||
assert isinstance(reference, form.BillingReference)
|
||||
assert reference.ident != ''
|
||||
|
Loading…
Reference in New Issue
Block a user