Fix: Facho para habilitacion de nomina python 3.9
This commit is contained in:
parent
c49e67b8a6
commit
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
|
||||
|
@ -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,8 +153,7 @@ 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:
|
||||
@ -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)
|
||||
@ -255,8 +242,8 @@ class FachoXML:
|
||||
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,8 +265,7 @@ 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
|
||||
@ -300,8 +286,7 @@ 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
|
||||
self.builder.append_next(last_slibing, 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
|
||||
|
||||
@ -329,8 +313,7 @@ class FachoXML:
|
||||
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)
|
||||
@ -494,11 +472,9 @@ class FachoXML:
|
||||
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,
|
||||
|
@ -46,16 +46,5 @@
|
||||
<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>
|
||||
|
@ -1,479 +0,0 @@
|
||||
<?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>TarifaImpuestoReteFuente</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>2.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Compras generales (declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>3.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Compras generales (no declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>1.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Compras con tarjeta débito o crédito</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>1.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Compras de bienes o productos agrícolas o pecuarios sin procesamiento industrial</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>2.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Compras de bienes o productos agrícolas o pecuarios con procesamiento industrial (declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>3.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Compras de bienes o productos agrícolas o pecuarios con procesamiento industrial declarantes (no declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>0.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Compras de café pergamino o cereza</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>0.10</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Compras de combustibles derivados del petróleo</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>1.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Enajenación de activos fijos de personas naturales (notarías y tránsito son agentes retenedores)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>1.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Compras de vehículos</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>1.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Compras de bienes raíces cuya destinación y uso sea vivienda de habitación (por las primeras 20.000 UVT, es decir hasta $637.780.000)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>2.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Compras de bienes raíces cuya destinación y uso sea vivienda de habitación (exceso de las primeras 20.000 UVT, es decir superior a $637.780.000)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>2.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Compras de bienes raíces cuya destinación y uso sea distinto a vivienda de habitación</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>4.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Servicios generales (declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>6.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Servicios generales (no declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>4.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Por emolumentos eclesiásticos (declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>3.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Por emolumentos eclesiásticos (no declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>1.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Servicios de transporte de carga</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>3.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Servicios de transporte nacional de pasajeros por vía terrestre (declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>3.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Servicios de transporte nacional de pasajeros por vía terrestre (no declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>1.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Servicios de transporte nacional de pasajeros por vía aérea o marítima</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>1.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Servicios prestados por empresas de servicios temporales (sobre AIU)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>2.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Servicios prestados por empresas de vigilancia y aseo (sobre AIU)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>2.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Servicios integrales de salud prestados por IPS</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>3.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Servicios de hoteles y restaurantes (declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>3.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Servicios de hoteles y restaurantes (no declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>4.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Arrendamiento de bienes muebles</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>3.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Arrendamiento de bienes inmuebles (declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>3.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Arrendamiento de bienes inmuebles (no declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>2.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Otros ingresos tributarios (declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>3.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Otros ingresos tributarios (no declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>11.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Honorarios y comisiones (personas jurídicas)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>11.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Honorarios y comisiones personas naturales que suscriban contrato o cuya sumatoria de los pagos o abonos en cuenta superen las 3.300 UVT ($105.135.000)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>10.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Honorarios y comisiones (no declarantes)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>3.50</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Servicios de licenciamiento o derecho de uso de software</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>7.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Intereses o rendimientos financieros</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>4.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Rendimientos financieros provenientes de títulos de renta fija</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>20.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Loterías, rifas, apuestas y similares</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>3.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Retención en colocación independiente de juegos de suerte y azar</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
<Value ColumnRef="code">
|
||||
<SimpleValue>2.00</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Contratos de construcción y urbanización</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
</SimpleCodeList>
|
||||
</gc:CodeList>
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- DIAN Genericode listas de valores: Ultima modificación 03-04-2022 - wcbr-->
|
||||
<!-- 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>
|
||||
@ -35,10 +35,7 @@
|
||||
<SimpleValue>01</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Factura electrónica de Venta</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Tipos de factura</SimpleValue>
|
||||
<SimpleValue>Factura de Venta Nacional</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
@ -46,10 +43,7 @@
|
||||
<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>
|
||||
<SimpleValue>Factura de Exportación </SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
@ -57,21 +51,7 @@
|
||||
<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>
|
||||
<SimpleValue>Factura de Contingencia</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
@ -81,9 +61,6 @@
|
||||
<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">
|
||||
@ -92,9 +69,6 @@
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>Nota Débito</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="description">
|
||||
<SimpleValue>Exclusivo en referencias a documentos (elementos DocumentReference)</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
</SimpleCodeList>
|
||||
</gc:CodeList>
|
||||
|
@ -75,7 +75,7 @@
|
||||
<SimpleValue>06</SimpleValue>
|
||||
</Value>
|
||||
<Value ColumnRef="name">
|
||||
<SimpleValue>ReteRenta</SimpleValue>
|
||||
<SimpleValue>ReteFuente</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
<Row>
|
||||
@ -150,15 +150,6 @@
|
||||
<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>
|
||||
@ -167,5 +158,5 @@
|
||||
<SimpleValue>Nombre de la figura tributaria</SimpleValue>
|
||||
</Value>
|
||||
</Row>
|
||||
</SimpleCodeList>
|
||||
</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'))
|
||||
|
200
facho/fe/fe.py
200
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',
|
||||
'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
|
||||
@ -98,7 +77,7 @@ def mock_xades_policy():
|
||||
class FeXML(FachoXML):
|
||||
|
||||
def __init__(self, root, namespace):
|
||||
# raise Exception(namespace)
|
||||
|
||||
super().__init__("{%s}%s" % (namespace, root),
|
||||
nsmap=NAMESPACES)
|
||||
|
||||
@ -108,25 +87,15 @@ class FeXML(FachoXML):
|
||||
|
||||
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,6 +294,7 @@ 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
|
||||
@ -385,9 +304,7 @@ class DianXMLExtensionSigner:
|
||||
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
|
||||
|
||||
@ -476,21 +386,22 @@ class DianXMLExtensionAuthorizationProvider(FachoXMLExtension):
|
||||
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,11 +67,9 @@ 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):
|
||||
@ -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]:
|
||||
@ -134,7 +124,7 @@ 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))
|
||||
@ -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='')
|
||||
|
||||
@ -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):
|
||||
@ -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):
|
||||
"""
|
||||
@ -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,13 +679,11 @@ 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:
|
||||
@ -806,7 +691,6 @@ class Invoice:
|
||||
self._calculate_legal_monetary_total()
|
||||
self._refresh_charges_base_amount()
|
||||
|
||||
|
||||
class NationalSalesInvoice(Invoice):
|
||||
def __init__(self):
|
||||
super().__init__(NationalSalesInvoiceDocumentType())
|
||||
@ -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
|
||||
@ -237,34 +231,11 @@ class InformacionGeneral:
|
||||
def __str__(self):
|
||||
self.valor
|
||||
|
||||
# TABLA 5.5.7
|
||||
@dataclass
|
||||
class TIPO_XML:
|
||||
valor: str
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.valor == str(other)
|
||||
|
||||
@dataclass
|
||||
class TIPO_XML_NORMAL(TIPO_XML):
|
||||
valor: str = '102'
|
||||
|
||||
def __str__(self):
|
||||
self.valor
|
||||
|
||||
@dataclass
|
||||
class TIPO_XML_AJUSTES(TIPO_XML):
|
||||
valor: str = '103'
|
||||
|
||||
def __str__(self):
|
||||
self.valor
|
||||
|
||||
fecha_generacion: typing.Union[str, Fecha]
|
||||
hora_generacion: str
|
||||
periodo_nomina: PeriodoNomina
|
||||
tipo_moneda: TipoMoneda
|
||||
tipo_ambiente: TIPO_AMBIENTE
|
||||
tipo_xml: TIPO_XML
|
||||
software_pin: str
|
||||
|
||||
def __post_init__(self):
|
||||
@ -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
|
@ -22,4 +22,4 @@ exclude = docs
|
||||
test = pytest
|
||||
|
||||
[tool:pytest]
|
||||
addopts = --ignore=setup.py
|
||||
collect_ignore = ['setup.py']
|
||||
|
27
setup.py
27
setup.py
@ -25,24 +25,7 @@ requirements = ['Click>=8.1.7',
|
||||
# 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']
|
||||
|
||||
"""
|
||||
'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()
|
||||
assert xml.get_element_text('/atd:AttachedDocument/cbc:ID') == '123'
|
||||
|
||||
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)
|
||||
|
@ -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()
|
||||
|
||||
# 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=[])
|
||||
# ))
|
||||
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'
|
||||
|
||||
# inv.add_allowance_charge(form.AllowanceCharge(amount=form.Amount(19.0)))
|
||||
# inv.calculate()
|
||||
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()
|
||||
|
||||
# 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'
|
||||
# se aplico descuento
|
||||
assert inv.invoice_legal_monetary_total.line_extension_amount == form.Amount(90.0)
|
||||
|
||||
xml = form_xml.DIANInvoiceXML(inv)
|
||||
|
||||
# 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,22 +3,16 @@
|
||||
# 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)
|
||||
|
Loading…
Reference in New Issue
Block a user