se adiciona documentacion
FossilOrigin-Name: 20a903a2426d4454a9909c78411b3ad7bd7f7d34d576ed5618e73784f77c8d92
This commit is contained in:
parent
bcf5120d82
commit
48619106c5
18
README.rst
18
README.rst
@ -24,7 +24,7 @@ usando pip::
|
||||
CLI
|
||||
===
|
||||
|
||||
tambien se provee linea de comandos **facho** para firmado y envio de documentos::
|
||||
tambien se provee linea de comandos **facho** para generacion, firmado y envio de documentos::
|
||||
facho --help
|
||||
|
||||
CONTRIBUIR
|
||||
@ -32,17 +32,13 @@ CONTRIBUIR
|
||||
|
||||
ver **CONTRIBUTING.rst**
|
||||
|
||||
USO
|
||||
===
|
||||
|
||||
ver **USAGE.rst**
|
||||
|
||||
|
||||
DIAN HABILITACION
|
||||
=================
|
||||
|
||||
guia oficial actualizada al 2020-04-20: https://www.dian.gov.co/fizcalizacioncontrol/herramienconsulta/FacturaElectronica/Facturaci%C3%B3n_Gratuita_DIAN/Documents/Guia_usuario_08052019.pdf#search=numeracion
|
||||
|
||||
|
||||
ERROR X509SerialNumber
|
||||
======================
|
||||
|
||||
|
||||
lxml.etree.DocumentInvalid: Element '{http://www.w3.org/2000/09/xmldsig#}X509SerialNumber': '632837201711293159666920255411738137494572618415' is not a valid value of the atomic type 'xs:integer'
|
||||
|
||||
Actualmente el xmlschema usado por xmlsig para el campo X509SerialNumber es tipo
|
||||
integer ahi que parchar manualmente a tipo string, en el archivo site-packages/xmlsig/data/xmldsig-core-schema.xsd.
|
||||
|
24
USAGE.rst
Normal file
24
USAGE.rst
Normal file
@ -0,0 +1,24 @@
|
||||
uso de la libreria
|
||||
==================
|
||||
|
||||
**facho** es tanto una libreria para modelar y generar los documentos xml requeridos para la facturacion,
|
||||
asi como una herramienta de **consola** para facilitar algunas actividades como: generaciones de xml
|
||||
apartir de una especificacion en python, comprimir y enviar archivos según el SOAP vigente.
|
||||
|
||||
**facho** es diseñado para ser usado en conjunto con el documento **docs/DIAN/Anexo_Tecnico_Factura_Electronica_Vr1_7_2020.pdf**, ya que en gran medida sigue la terminologia presente en este.
|
||||
|
||||
|
||||
Para ejemplos ver **examples/** .
|
||||
|
||||
En terminos generales seria modelar la factura usando **facho/fe/form.py**, instanciar las extensiones requeridas ver **facho/fe/fe.py** y
|
||||
una vez generado el objeto invoice y las extensiones requeridas se procede a crear el XML, ejemplo:
|
||||
|
||||
~~~python
|
||||
....
|
||||
xml = form_xml.DIANInvoiceXML(invoice)
|
||||
extensions = module.extensions(invoice)
|
||||
for extension in extensions:
|
||||
xml.add_extension(extension)
|
||||
|
||||
form_xml.DIANWriteSigned(xml, "factura.xml", "llave privada", "frase")
|
||||
~~~
|
@ -1,39 +1,49 @@
|
||||
# este archivo es un ejemplo para le generacion
|
||||
# una factura de venta nacional usando el comando **facho**.
|
||||
#
|
||||
# ejemplo: facho generate-invoice generate-invoice-from-cli.py
|
||||
#
|
||||
# importar libreria de modelos
|
||||
import facho.fe.form as form
|
||||
import facho.fe.form_xml
|
||||
|
||||
# importar libreria extensiones xml para cumplir decreto
|
||||
from facho.fe import fe
|
||||
|
||||
# importar otras necesarias
|
||||
from datetime import datetime
|
||||
|
||||
def extensions(inv):
|
||||
nit = form.PartyIdentification('nit', '5', '31')
|
||||
security_code = fe.DianXMLExtensionSoftwareSecurityCode('id software', 'pin', inv.invoice_ident)
|
||||
authorization_provider = fe.DianXMLExtensionAuthorizationProvider()
|
||||
cufe = fe.DianXMLExtensionCUFE(inv, fe.DianXMLExtensionCUFE.AMBIENTE_PRUEBAS,
|
||||
'clave tecnica')
|
||||
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]
|
||||
|
||||
|
||||
# callback que retorna el modelado de documento electronico
|
||||
# a generar
|
||||
def invoice():
|
||||
inv = form.Invoice()
|
||||
# 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 = 'FACHO SOS',
|
||||
name = 'FACHO SOS',
|
||||
ident = form.PartyIdentification('900579212', '5', '31'),
|
||||
# obligaciones del contribuyente ver DIAN:FAK26
|
||||
responsability_code = form.Responsability(['O-07', 'O-09', 'O-14', 'O-48']),
|
||||
# ver DIAN:FAJ28
|
||||
responsability_regime_code = '48',
|
||||
# tipo de organizacion juridica ver DIAN:6.2.3
|
||||
organization_code = '1',
|
||||
email = "sdds@sd.com",
|
||||
address = form.Address(
|
||||
'', '', form.City('05001', 'Medellín'),
|
||||
form.Country('CO', 'Colombia'),
|
||||
form.CountrySubentity('05', 'Antioquia'))
|
||||
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',
|
||||
@ -44,22 +54,34 @@ def invoice():
|
||||
organization_code = '2',
|
||||
email = "sdds@sd.com",
|
||||
address = form.Address(
|
||||
'', '', form.City('05001', 'Medellín'),
|
||||
form.Country('CO', 'Colombia'),
|
||||
form.CountrySubentity('05', 'Antioquia'))
|
||||
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',
|
||||
# codigo correspondiente al medio de pago ver DIAN:3.4.2
|
||||
code = '10',
|
||||
# fecha de vencimiento de la factura
|
||||
due_at = datetime.now(),
|
||||
|
||||
# identificador numerico
|
||||
payment_id = '1'
|
||||
))
|
||||
# adicionar una linea al documento
|
||||
inv.add_invoice_line(form.InvoiceLine(
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto facho',
|
||||
# item general de codigo 999
|
||||
item = form.StandardItem('test', 9999),
|
||||
price = form.Price(
|
||||
# precio base del tiem
|
||||
amount = form.Amount(100.00),
|
||||
# ver DIAN:6.3.5.1
|
||||
type_code = '01',
|
||||
type = 'x'
|
||||
),
|
||||
@ -72,3 +94,26 @@ def invoice():
|
||||
)
|
||||
))
|
||||
return inv
|
||||
|
||||
# callback que retonar las extensiones XML necesarias
|
||||
# para que el documento final XML cumpla el decreto.
|
||||
#
|
||||
# muchos de los valores usados son obtenidos
|
||||
# del servicio web de la DIAN.
|
||||
def extensions(inv):
|
||||
security_code = fe.DianXMLExtensionSoftwareSecurityCode('id software', 'pin', inv.invoice_ident)
|
||||
authorization_provider = fe.DianXMLExtensionAuthorizationProvider()
|
||||
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]
|
||||
|
||||
|
||||
# callback con transformador a XML
|
||||
def document_xml():
|
||||
return form_xml.DIANInvoiceXML
|
114
examples/use-as-lib.py
Normal file
114
examples/use-as-lib.py
Normal file
@ -0,0 +1,114 @@
|
||||
# importar libreria de modelos
|
||||
import facho.fe.form as form
|
||||
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)
|
||||
authorization_provider = fe.DianXMLExtensionAuthorizationProvider()
|
||||
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]
|
||||
|
||||
# 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)
|
||||
|
||||
# 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 = 'FACHO SOS',
|
||||
name = 'FACHO SOS',
|
||||
ident = form.PartyIdentification('900579212', '5', '31'),
|
||||
# obligaciones del contribuyente ver DIAN:FAK26
|
||||
responsability_code = form.Responsability(['O-07', 'O-09', 'O-14', 'O-48']),
|
||||
# ver DIAN:FAJ28
|
||||
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'))
|
||||
))
|
||||
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'))
|
||||
))
|
||||
# asignar metodo de pago
|
||||
inv.set_payment_mean(form.PaymentMean(
|
||||
# metodo de pago ver DIAN:3.4.1
|
||||
id = '1',
|
||||
# codigo correspondiente al medio de pago ver DIAN:3.4.2
|
||||
code = '10',
|
||||
# fecha de vencimiento de la factura
|
||||
due_at = datetime.now(),
|
||||
|
||||
# identificador numerico
|
||||
payment_id = '1'
|
||||
))
|
||||
# adicionar una linea al documento
|
||||
inv.add_invoice_line(form.InvoiceLine(
|
||||
quantity = form.Quantity(1, '94'),
|
||||
description = 'producto facho',
|
||||
# item general de codigo 999
|
||||
item = form.StandardItem('test', 9999),
|
||||
price = form.Price(
|
||||
# precio base del tiem
|
||||
amount = form.Amount(100.00),
|
||||
# ver DIAN:6.3.5.1
|
||||
type_code = '01',
|
||||
type = 'x'
|
||||
),
|
||||
tax = form.TaxTotal(
|
||||
subtotals = [
|
||||
form.TaxSubTotal(
|
||||
percent = 19.00,
|
||||
)
|
||||
]
|
||||
)
|
||||
))
|
||||
|
||||
# refrescar valores de la factura
|
||||
inv.calculate()
|
||||
|
||||
# generar el documento xml en la ruta indicada
|
||||
generate_document(inv, 'ruta a donde guardar el .xml')
|
Loading…
Reference in New Issue
Block a user