14 changed files with 496 additions and 274 deletions
-
4pytrustnfe/servicos/NfeStatusServico.py
-
1pytrustnfe/servicos/RecepcaoEvento.py
-
52pytrustnfe/servicos/assinatura.py
-
22pytrustnfe/servicos/comunicacao.py
-
23pytrustnfe/servicos/nfe_autorizacao.py
-
1pytrustnfe/utils.py
-
76pytrustnfe/xml/DynamicXml.py
-
22pytrustnfe/xml/__init__.py
-
58pytrustnfe/xml/filters.py
-
174pytrustnfe/xml/nfeEnv.xml
-
1setup.py
@ -1,76 +0,0 @@ |
|||
# coding=utf-8 |
|||
''' |
|||
Created on Jun 17, 2015 |
|||
|
|||
@author: danimar |
|||
''' |
|||
|
|||
import xml.etree.ElementTree as ET |
|||
from lxml.etree import Element, tostring |
|||
from __builtin__ import str |
|||
|
|||
|
|||
class DynamicXml(object): |
|||
|
|||
def __getattr__(self, name): |
|||
try: |
|||
return object.__getattribute__(self, name) |
|||
except: |
|||
self.__setattr__(name, None) |
|||
return object.__getattribute__(self, name) |
|||
|
|||
def __setattr__(self, obj, val): |
|||
if(obj == "value" or obj == "atributos" or obj == "_indice"): |
|||
object.__setattr__(self, obj, val) |
|||
else: |
|||
self._indice = self._indice + 1 |
|||
object.__setattr__(self, obj, DynamicXml(val, self._indice)) |
|||
|
|||
def __init__(self, value, indice=0): |
|||
self.value = unicode(value, 'utf-8') if isinstance(value, |
|||
str) else value |
|||
self.atributos = {} |
|||
self._indice = indice |
|||
|
|||
def __str__(self): |
|||
return unicode(self.value) |
|||
|
|||
def __call__(self, *args, **kw): |
|||
if(len(kw) > 0): |
|||
self.atributos = kw |
|||
if(len(args) > 0): |
|||
self.value = args[0] |
|||
else: |
|||
return self.value |
|||
|
|||
def __getitem__(self, i): |
|||
if not isinstance(self.value, list): |
|||
self.value = [] |
|||
if(i + 1 > len(self.value)): |
|||
self.value.append(DynamicXml(None)) |
|||
return self.value[i] |
|||
|
|||
def render(self, pretty_print=False): |
|||
root = Element(self.value) |
|||
self._gerar_xml(root, self) |
|||
return tostring(root, pretty_print=pretty_print) |
|||
|
|||
def _gerar_xml(self, xml, objeto): |
|||
items = sorted( |
|||
objeto.__dict__.items(), |
|||
key=lambda x: x[1]._indice if isinstance(x[1], DynamicXml) else 0 |
|||
) |
|||
for attr, value in items: |
|||
if(attr != "value" and attr != "atributos" and attr != "_indice"): |
|||
if isinstance(value(), list): |
|||
for item in value(): |
|||
sub = ET.SubElement(xml, attr) |
|||
self._gerar_xml(sub, item) |
|||
else: |
|||
sub = ET.SubElement(xml, attr) |
|||
if(unicode(value) != u"None"): |
|||
sub.text = unicode(value) |
|||
self._gerar_xml(sub, value) |
|||
elif(attr == "atributos"): |
|||
for atr, val in value.items(): |
|||
xml.set(atr.replace("__", ":"), str(val)) |
|||
@ -0,0 +1,22 @@ |
|||
import os.path |
|||
from lxml import etree |
|||
from jinja2 import Environment, FileSystemLoader |
|||
from . import filters |
|||
|
|||
|
|||
def render_xml(template_name, **nfe): |
|||
path = os.path.dirname(__file__) |
|||
env = Environment( |
|||
loader=FileSystemLoader(path), extensions=['jinja2.ext.with_']) |
|||
|
|||
env.filters["normalize"] = filters.normalize_str |
|||
env.filters["format_percent"] = filters.format_percent |
|||
env.filters["format_datetime"] = filters.format_datetime |
|||
env.filters["format_date"] = filters.format_date |
|||
|
|||
template = env.get_template(template_name) |
|||
|
|||
xml = template.render(**nfe) |
|||
xml = xml.replace('&', '&') |
|||
parser = etree.XMLParser(remove_blank_text=True, remove_comments=True) |
|||
return etree.fromstring(xml, parser=parser) |
|||
@ -0,0 +1,58 @@ |
|||
# coding=utf-8 |
|||
|
|||
from decimal import Decimal |
|||
from datetime import datetime |
|||
import dateutil.parser as parser_dateutil |
|||
|
|||
from unicodedata import normalize |
|||
|
|||
|
|||
def normalize_str(string): |
|||
""" |
|||
Remove special characters and return the ascii string |
|||
""" |
|||
if string: |
|||
if not isinstance(string, unicode): |
|||
string = unicode(string, 'utf-8', 'replace') |
|||
|
|||
string = string.encode('utf-8') |
|||
return normalize( |
|||
'NFKD', string.decode('utf-8')).encode('ASCII', 'ignore') |
|||
return '' |
|||
|
|||
|
|||
def format_percent(value): |
|||
if value: |
|||
return Decimal(value) / 100 |
|||
|
|||
|
|||
def format_datetime(value): |
|||
""" |
|||
Format datetime |
|||
""" |
|||
dt_format = '%Y-%m-%dT%H:%M:%I' |
|||
if isinstance(value, datetime): |
|||
return value.strftime(dt_format) |
|||
|
|||
try: |
|||
value = parser_dateutil.parse(value).strftime(dt_format) |
|||
except AttributeError: |
|||
pass |
|||
|
|||
return value |
|||
|
|||
|
|||
def format_date(value): |
|||
""" |
|||
Format date |
|||
""" |
|||
dt_format = '%Y-%m-%d' |
|||
if isinstance(value, datetime): |
|||
return value.strftime(dt_format) |
|||
|
|||
try: |
|||
value = parser_dateutil.parse(value).strftime(dt_format) |
|||
except AttributeError: |
|||
pass |
|||
|
|||
return value |
|||
@ -0,0 +1,174 @@ |
|||
<enviNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="3.10"> |
|||
<idLote>{{ idLote }}</idLote> |
|||
<indSinc>{{ indSinc }}</indSinc> |
|||
{% for NFe in NFes %} |
|||
<NFe xmlns="http://www.portalfiscal.inf.br/nfe"> |
|||
<infNFe versao="3.10" Id="{{ NFe.infNFe.Id }}"> |
|||
<ide> |
|||
{% with ide = NFe.infNFe.ide %} |
|||
<cUF>{{ ide.cUF }}</cUF> |
|||
<cNF>{{ ide.cNF }}</cNF> |
|||
<natOp>{{ ide.natOp }}</natOp> |
|||
<indPag>{{ ide.indPag }}</indPag> |
|||
<mod>{{ ide.mod }}</mod> |
|||
<serie>{{ ide.serie }}</serie> |
|||
<nNF>{{ ide.nNF }}</nNF> |
|||
<dhEmi>{{ ide.dhEmi }}</dhEmi> |
|||
<dhSaiEnt>{{ ide.dhSaiEnt }}</dhSaiEnt> |
|||
<tpNF>{{ ide.tpNF }}</tpNF> |
|||
<idDest>{{ ide.idDest }}</idDest> |
|||
<cMunFG>{{ ide.cMunFG }}</cMunFG> |
|||
<tpImp>{{ ide.tpImp }}</tpImp> |
|||
<tpEmis>{{ ide.tpEmis }}</tpEmis> |
|||
<cDV>{{ ide.cDV }}</cDV> |
|||
<tpAmb>{{ ide.tpAmb }}</tpAmb> |
|||
<finNFe>{{ ide.finNFe }}</finNFe> |
|||
<indFinal>{{ ide.indFinal }}</indFinal> |
|||
<indPres>{{ ide.indPres }}</indPres> |
|||
<procEmi>{{ ide.procEmi }}</procEmi> |
|||
<verProc>Odoo Brasil 9.0</verProc> |
|||
{% endwith %} |
|||
</ide> |
|||
<emit> |
|||
{% with emit = NFe.infNFe.emit %} |
|||
<CNPJ>{{ emit.CNPJ }}</CNPJ> |
|||
<xNome>{{ emit.xNome }}</xNome> |
|||
<xFant>{{ emit.xFant }}</xFant> |
|||
<enderEmit> |
|||
<xLgr>{{ emit.enderEmit.xLgr }}</xLgr> |
|||
<nro>{{ emit.enderEmit.nro }}</nro> |
|||
<xBairro>{{ emit.enderEmit.xBairro }}</xBairro> |
|||
<cMun>{{ emit.enderEmit.cMun }}</cMun> |
|||
<xMun>{{ emit.enderEmit.xMun }}</xMun> |
|||
<UF>{{ emit.enderEmit.UF }}</UF> |
|||
<CEP>{{ emit.enderEmit.CEP }}</CEP> |
|||
<cPais>{{ emit.enderEmit.cPais }}</cPais> |
|||
<xPais>{{ emit.enderEmit.xPais }}</xPais> |
|||
<fone>{{ emit.enderEmit.fone }}</fone> |
|||
</enderEmit> |
|||
<IE>{{ emit.IE }}</IE> |
|||
<CRT>{{ emit.CRT }}</CRT> |
|||
{% endwith %} |
|||
</emit> |
|||
<dest> |
|||
{% with dest = NFe.infNFe.dest %} |
|||
<CNPJ>{{ dest.CNPJ }}</CNPJ> |
|||
<CPF>{{ dest.CPF }}</CPF> |
|||
<xNome>{{ dest.xNome }}</xNome> |
|||
<enderDest> |
|||
<xLgr>{{ dest.enderDest.xLgr }}</xLgr> |
|||
<nro>{{ dest.enderDest.nro }}</nro> |
|||
<xBairro>{{ dest.enderDest.xBairro }}</xBairro> |
|||
<cMun>{{ dest.enderDest.cMun }}</cMun> |
|||
<xMun>{{ dest.enderDest.xMun }}</xMun> |
|||
<UF>{{ dest.enderDest.UF }}</UF> |
|||
<CEP>{{ dest.enderDest.CEP }}</CEP> |
|||
<cPais>{{ dest.enderDest.cPais }}</cPais> |
|||
<xPais>{{ dest.enderDest.xPais }}</xPais> |
|||
<fone>{{ dest.enderDest.fone }}</fone> |
|||
</enderDest> |
|||
<indIEDest>{{ dest.indIEDest }}</indIEDest> |
|||
<IE>{{ dest.IE }}</IE> |
|||
{% endwith %} |
|||
</dest> |
|||
{% for det in NFe.infNFe.detalhes %} |
|||
<det nItem="1"> |
|||
<prod> |
|||
{% with prod = det.prod %} |
|||
<cProd>{{ prod.cProd }}</cProd> |
|||
<cEAN>{{ prod.cEAN }}</cEAN> |
|||
<xProd>{{ prod.xProd }}</xProd> |
|||
<NCM>{{ prod.NCM }}</NCM> |
|||
<CFOP>{{ prod.CFOP }}</CFOP> |
|||
<uCom>{{ prod.uCom }}</uCom> |
|||
<qCom>{{ prod.qCom }}</qCom> |
|||
<vUnCom>{{ prod.vUnCom }}</vUnCom> |
|||
<vProd>{{ prod.vProd }}</vProd> |
|||
<cEANTrib>{{ prod.cEANTrib }}</cEANTrib> |
|||
<uTrib>{{ prod.uTrib }}</uTrib> |
|||
<qTrib>{{ prod.qTrib }}</qTrib> |
|||
<vUnTrib>{{ prod.vUnTrib }}</vUnTrib> |
|||
<indTot>{{ prod.indTot }}</indTot> |
|||
{% endwith %} |
|||
</prod> |
|||
<imposto> |
|||
{% with imposto = det.imposto %} |
|||
<vTotTrib>{{ imposto.vTotTrib }}</vTotTrib> |
|||
<ICMS> |
|||
<ICMS00> |
|||
<orig>{{ imposto.ICMS.ICMS00.orig }}</orig> |
|||
<CST>{{ imposto.ICMS.ICMS00.CST }}</CST> |
|||
<modBC>{{ imposto.ICMS.ICMS00.modBC }}</modBC> |
|||
<vBC>{{ imposto.ICMS.ICMS00.vBC }}</vBC> |
|||
<pICMS>{{ imposto.ICMS.ICMS00.pICMS }}</pICMS> |
|||
<vICMS>{{ imposto.ICMS.ICMS00.vICMS }}</vICMS> |
|||
</ICMS00> |
|||
</ICMS> |
|||
<IPI> |
|||
<cEnq>{{ imposto.IPI.cEnq }}</cEnq> |
|||
<IPITrib> |
|||
<CST>{{ imposto.IPI.IPITrib.CST }}</CST> |
|||
<vBC>{{ imposto.IPI.IPITrib.vBC }}</vBC> |
|||
<pIPI>{{ imposto.IPI.IPITrib.pIPI }}</pIPI> |
|||
<vIPI>{{ imposto.IPI.IPITrib.vIPI }}</vIPI> |
|||
</IPITrib> |
|||
</IPI> |
|||
<PIS> |
|||
<PISAliq> |
|||
<CST>{{ imposto.PIS.PISAliq.CST }}</CST> |
|||
<vBC>{{ imposto.PIS.PISAliq.vBC }}</vBC> |
|||
<pPIS>{{ imposto.PIS.PISAliq.pPIS }}</pPIS> |
|||
<vPIS>{{ imposto.PIS.PISAliq.vPIS }}</vPIS> |
|||
</PISAliq> |
|||
</PIS> |
|||
<COFINS> |
|||
<COFINSAliq> |
|||
<CST>{{ imposto.COFINS.COFINSAliq.CST }}</CST> |
|||
<vBC>{{ imposto.COFINS.COFINSAliq.vBC }}</vBC> |
|||
<pCOFINS>{{ imposto.COFINS.COFINSAliq.pCOFINS }}</pCOFINS> |
|||
<vCOFINS>{{ imposto.COFINS.COFINSAliq.vCOFINS }}</vCOFINS> |
|||
</COFINSAliq> |
|||
</COFINS> |
|||
{% endwith %} |
|||
</imposto> |
|||
</det> |
|||
{% endfor %} |
|||
<total> |
|||
{% with total = NFe.infNFe.total %} |
|||
<ICMSTot> |
|||
<vBC>{{ total.vBC }}</vBC> |
|||
<vICMS>{{ total.vICMS }}</vICMS> |
|||
<vICMSDeson>{{ total.vICMSDeson }}</vICMSDeson> |
|||
<vBCST>{{ total.vBCST }}</vBCST> |
|||
<vST>{{ total.vST }}</vST> |
|||
<vProd>{{ total.vProd }}</vProd> |
|||
<vFrete>{{ total.vFrete }}</vFrete> |
|||
<vSeg>{{ total.vSeg }}</vSeg> |
|||
<vDesc>{{ total.vDesc }}</vDesc> |
|||
<vII>{{ total.vII }}</vII> |
|||
<vIPI>{{ total.vIPI }}</vIPI> |
|||
<vPIS>{{ total.vPIS }}</vPIS> |
|||
<vCOFINS>{{ total.vCOFINS }}</vCOFINS> |
|||
<vOutro>{{ total.vOutro }}</vOutro> |
|||
<vNF>{{ total.vNF }}</vNF> |
|||
<vTotTrib>{{ total.vTotTrib }}</vTotTrib> |
|||
</ICMSTot> |
|||
{% endwith %} |
|||
</total> |
|||
<transp> |
|||
<modFrete>{{ NFe.infNFe.transp.modFrete }}</modFrete> |
|||
</transp> |
|||
<cobr> |
|||
<dup> |
|||
<nDup>339/1</nDup> |
|||
<dVenc>2016-06-02</dVenc> |
|||
<vDup>8611.76</vDup> |
|||
</dup> |
|||
</cobr> |
|||
<infAdic> |
|||
<infCpl>{{ NFe.infNFe.infAdic.infCpl }}</infCpl> |
|||
</infAdic> |
|||
</infNFe> |
|||
</NFe> |
|||
{% endfor %} |
|||
</enviNFe> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue