Browse Source

Merge branch 'master3' into issue-overwriting

pull/188/head
Danimar Ribeiro 7 years ago
committed by GitHub
parent
commit
16c60d45cb
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      pytrustnfe/Servidores.py
  2. 71
      pytrustnfe/nfe/__init__.py
  3. 46
      pytrustnfe/nfe/danfce.py
  4. 58
      pytrustnfe/nfe/danfe.py
  5. 110
      pytrustnfe/nfe/templates/NfeAutorizacao.xml
  6. 2
      pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml
  7. 2
      pytrustnfe/nfse/paulistana/templates/EnvioRPS.xml
  8. 9
      pytrustnfe/xml/__init__.py
  9. 2
      setup.py
  10. 10
      tests/XMLs/paulistana_signature.xml
  11. 34
      tests/test_add_qr_code.py
  12. 189
      tests/xml_com_qrcode.xml
  13. 190
      tests/xml_sem_qrcode.xml

6
pytrustnfe/Servidores.py

@ -79,6 +79,8 @@ def localizar_url(servico, estado, mod='55', ambiente=2):
if sigla in ('AC', 'RN', 'PB', 'SC', 'RJ') and \ if sigla in ('AC', 'RN', 'PB', 'SC', 'RJ') and \
servico == WS_NFE_CADASTRO: servico == WS_NFE_CADASTRO:
dominio = 'cad.svrs.rs.gov.br' dominio = 'cad.svrs.rs.gov.br'
if sigla == 'AN' and servico == WS_NFE_RECEPCAO_EVENTO:
dominio = 'www.nfe.fazenda.gov.br'
return "https://%s/%s" % (dominio, complemento) return "https://%s/%s" % (dominio, complemento)
@ -152,7 +154,7 @@ SVRS = {
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento4.asmx?wsdl', WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento4.asmx?wsdl',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao4.asmx?wsdl', WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao4.asmx?wsdl',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao4.asmx?wsdl', # noqa WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao4.asmx?wsdl', # noqa
WS_NFCE_QR_CODE: 'http://dec.fazenda.df.gov.br/ConsultarNFCe.aspx',
WS_NFCE_QR_CODE: 'http://dec.fazenda.df.gov.br/ConsultarNFCe.aspx?',
}, },
AMBIENTE_HOMOLOGACAO: { AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfce-homologacao.svrs.rs.gov.br', 'servidor': 'nfce-homologacao.svrs.rs.gov.br',
@ -162,7 +164,7 @@ SVRS = {
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento4.asmx?wsdl', WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento4.asmx?wsdl',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao4.asmx?wsdl', WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao4.asmx?wsdl',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao4.asmx?wsdl', # noqa WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao4.asmx?wsdl', # noqa
WS_NFCE_QR_CODE: 'http://dec.fazenda.df.gov.br/ConsultarNFCe.aspx',
WS_NFCE_QR_CODE: 'http://dec.fazenda.df.gov.br/ConsultarNFCe.aspx?',
} }
} }
} }

71
pytrustnfe/nfe/__init__.py

@ -4,13 +4,11 @@
import os import os
import hashlib
import binascii
from lxml import etree from lxml import etree
from .assinatura import Assinatura from .assinatura import Assinatura
from pytrustnfe.xml import render_xml, sanitize_response from pytrustnfe.xml import render_xml, sanitize_response
from pytrustnfe.utils import gerar_chave, ChaveNFe from pytrustnfe.utils import gerar_chave, ChaveNFe
from pytrustnfe.Servidores import localizar_url, localizar_qrcode
from pytrustnfe.Servidores import localizar_url
from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key from pytrustnfe.certificado import extract_cert_and_key_from_pfx, save_cert_key
# Zeep # Zeep
@ -38,54 +36,6 @@ def _generate_nfe_id(**kwargs):
item['infNFe']['ide']['cDV'] = chave_nfe[len(chave_nfe) - 1:] item['infNFe']['ide']['cDV'] = chave_nfe[len(chave_nfe) - 1:]
def _add_qrCode(xml, **kwargs):
xml = etree.fromstring(xml)
inf_nfe = kwargs['NFes'][0]['infNFe']
nfe = xml.find(".//{http://www.portalfiscal.inf.br/nfe}NFe")
infnfesupl = etree.Element('infNFeSupl')
qrcode = etree.Element('qrCode')
chave_nfe = inf_nfe['Id'][3:]
dh_emissao = binascii.hexlify(inf_nfe['ide']['dhEmi'].encode()).decode()
versao = '100'
ambiente = kwargs['ambiente']
valor_total = inf_nfe['total']['vNF']
dest_cpf = 'Inexistente'
dest = nfe.find(".//{http://www.portalfiscal.inf.br/nfe}dest")
if inf_nfe.get('dest', False):
if inf_nfe['dest'].get('CPF', False):
dest_cpf = inf_nfe['dest']['CPF']
dest = etree.Element('dest')
cpf = etree.Element('CPF')
cpf.text = dest_cpf
dest.append(cpf)
icms_total = inf_nfe['total']['vICMS']
dig_val = binascii.hexlify(xml.find(
".//{http://www.w3.org/2000/09/xmldsig#}DigestValue").text.encode()).decode()
cid_token = kwargs['NFes'][0]['infNFe']['codigo_seguranca']['cid_token']
csc = kwargs['NFes'][0]['infNFe']['codigo_seguranca']['csc']
c_hash_QR_code = "chNFe={0}&nVersao={1}&tpAmb={2}&cDest={3}&dhEmi={4}&vNF\
={5}&vICMS={6}&digVal={7}&cIdToken={8}{9}".\
format(chave_nfe, versao, ambiente, dest_cpf, dh_emissao,
valor_total, icms_total, dig_val, cid_token, csc)
c_hash_QR_code = hashlib.sha1(c_hash_QR_code.encode()).hexdigest()
QR_code_url = "?chNFe={0}&nVersao={1}&tpAmb={2}&{3}dhEmi={4}&vNF={5}&vICMS\
={6}&digVal={7}&cIdToken={8}&cHashQRCode={9}".\
format(chave_nfe, versao, ambiente,
'cDest={}&'.format(dest_cpf) if dest_cpf != 'Inexistente'
else '', dh_emissao, valor_total, icms_total, dig_val,
cid_token, c_hash_QR_code)
qr_code_server = localizar_qrcode(kwargs['estado'], ambiente)
qrcode_text = qr_code_server + QR_code_url
qrcode.text = etree.CDATA(qrcode_text)
infnfesupl.append(qrcode)
nfe.insert(1, infnfesupl)
return etree.tostring(xml, encoding=str)
def _render(certificado, method, sign, **kwargs): def _render(certificado, method, sign, **kwargs):
path = os.path.join(os.path.dirname(__file__), 'templates') path = os.path.join(os.path.dirname(__file__), 'templates')
xmlElem_send = render_xml(path, '%s.xml' % method, True, **kwargs) xmlElem_send = render_xml(path, '%s.xml' % method, True, **kwargs)
@ -107,9 +57,6 @@ def _render(certificado, method, sign, **kwargs):
xml_send = signer.assina_xml( xml_send = signer.assina_xml(
xmlElem_send, kwargs['manifesto']['identificador']) xmlElem_send, kwargs['manifesto']['identificador'])
if modelo == '65':
xml_send = _add_qrCode(xml_send, **kwargs)
else: else:
xml_send = etree.tostring(xmlElem_send, encoding=str) xml_send = etree.tostring(xmlElem_send, encoding=str)
return xml_send return xml_send
@ -129,7 +76,9 @@ def _send(certificado, method, **kwargs):
session.verify = False session.verify = False
transport = Transport(session=session) transport = Transport(session=session)
xml = etree.fromstring(xml_send)
parser = etree.XMLParser(strip_cdata=False)
xml = etree.fromstring(xml_send, parser=parser)
client = Client(base_url, transport=transport) client = Client(base_url, transport=transport)
port = next(iter(client.wsdl.port_types)) port = next(iter(client.wsdl.port_types))
@ -247,9 +196,7 @@ def xml_consulta_distribuicao_nfe(certificado, **kwargs): # Assinar
return _render(certificado, 'NFeDistribuicaoDFe', False, **kwargs) return _render(certificado, 'NFeDistribuicaoDFe', False, **kwargs)
def consulta_distribuicao_nfe(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_consulta_distribuicao_nfe(certificado, **kwargs)
def _send_v310(certificado, **kwargs):
xml_send = kwargs["xml"] xml_send = kwargs["xml"]
base_url = localizar_url( base_url = localizar_url(
'NFeDistribuicaoDFe', kwargs['estado'], kwargs['modelo'], 'NFeDistribuicaoDFe', kwargs['estado'], kwargs['modelo'],
@ -280,6 +227,12 @@ def consulta_distribuicao_nfe(certificado, **kwargs):
} }
def consulta_distribuicao_nfe(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_consulta_distribuicao_nfe(certificado, **kwargs)
return _send_v310(certificado, **kwargs)
def xml_download_nfe(certificado, **kwargs): # Assinar def xml_download_nfe(certificado, **kwargs): # Assinar
return _render(certificado, 'NFeDistribuicaoDFe', False, **kwargs) return _render(certificado, 'NFeDistribuicaoDFe', False, **kwargs)
@ -287,4 +240,4 @@ def xml_download_nfe(certificado, **kwargs): # Assinar
def download_nfe(certificado, **kwargs): def download_nfe(certificado, **kwargs):
if "xml" not in kwargs: if "xml" not in kwargs:
kwargs['xml'] = xml_download_nfe(certificado, **kwargs) kwargs['xml'] = xml_download_nfe(certificado, **kwargs)
return _send(certificado, 'NFeDistribuicaoDFe', **kwargs)
return _send_v310(certificado, **kwargs)

46
pytrustnfe/nfe/danfce.py

@ -72,7 +72,7 @@ def format_telefone(telefone):
class danfce(object): class danfce(object):
def __init__(self, list_xml, logo=None):
def __init__(self, list_xml, logo=None, timezone=None):
self.current_font_size = 7 self.current_font_size = 7
self.current_font_name = 'NimbusSanL-Regu' self.current_font_name = 'NimbusSanL-Regu'
@ -188,14 +188,14 @@ class danfce(object):
# Impostos # Impostos
el_total = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}total") el_total = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}total")
total_tributo = format_number(tagtext(oNode=el_total, cTag='vTotTrib'),
precision=2)
valor_total = format_number(tagtext(oNode=el_total, cTag='vProd'),
precision=2)
desconto = format_number(tagtext(oNode=el_total, cTag='vDesc'),
precision=2)
valor_a_pagar = format_number(tagtext(oNode=el_total, cTag='vNF'),
precision=2)
total_tributo = format_number(
tagtext(oNode=el_total, cTag='vTotTrib'), precision=2)
valor_total = format_number(
tagtext(oNode=el_total, cTag='vProd'), precision=2)
desconto = format_number(
tagtext(oNode=el_total, cTag='vDesc'), precision=2)
valor_a_pagar = format_number(
tagtext(oNode=el_total, cTag='vNF'), precision=2)
el_pag = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}pag") el_pag = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}pag")
troco = format_number(tagtext(oNode=el_pag, cTag="vTroco")) troco = format_number(tagtext(oNode=el_pag, cTag="vTroco"))
@ -216,26 +216,26 @@ class danfce(object):
".//{http://www.portalfiscal.inf.br/nfe}det")) ".//{http://www.portalfiscal.inf.br/nfe}det"))
payment_methods = [] payment_methods = []
for pagId, item in enumerate(el_pag): for pagId, item in enumerate(el_pag):
if 'tPag' not in item.tag:
continue
payment = [] payment = []
method = payment_method_list[item.text]
tipo_pagamento = tagtext(oNode=item, cTag="tPag")
val = format_number(tagtext(oNode=item, cTag="vPag"), precision=2)
method = payment_method_list[tipo_pagamento]
payment.append(method) payment.append(method)
payment.append(format_number(item.getnext().text, precision=2))
payment.append(val)
payment_methods.append(payment) payment_methods.append(payment)
values = {'quantidade_itens': quant_produtos,
'total_tributo': total_tributo,
'valor_total': valor_total,
'desconto': desconto,
'valor_a_pagar': valor_a_pagar,
'formas_de_pagamento': payment_methods,
'troco': troco,
}
values = {
'quantidade_itens': quant_produtos,
'total_tributo': total_tributo,
'valor_total': valor_total,
'desconto': desconto,
'valor_a_pagar': valor_a_pagar,
'formas_de_pagamento': payment_methods,
'troco': troco,
}
self.draw_totals_table(values) self.draw_totals_table(values)

58
pytrustnfe/nfe/danfe.py

@ -80,6 +80,8 @@ def getdateByTimezone(cDateUTC, timezone=None):
def format_number(cNumber): def format_number(cNumber):
if cNumber: if cNumber:
# Vírgula para a separação de milhar e 2f para 2 casas decimais
cNumber = "{:,.2f}".format(float(cNumber))
return cNumber.replace(",", "X").replace(".", ",").replace("X", ".") return cNumber.replace(",", "X").replace(".", ",").replace("X", ".")
return "" return ""
@ -195,7 +197,8 @@ class danfe(object):
oXML=oXML, el_det=el_det, max_index=nId, oXML=oXML, el_det=el_det, max_index=nId,
list_desc=list_desc, list_cod_prod=list_cod_prod) list_desc=list_desc, list_cod_prod=list_cod_prod)
self.adicionais(oXML=oXML)
tamanho_ocupado = self.calculo_issqn(oXML=oXML)
self.adicionais(oXML=oXML, tamanho_diminuir=tamanho_ocupado)
# Gera o restante das páginas do XML # Gera o restante das páginas do XML
while index < nId: while index < nId:
@ -746,8 +749,8 @@ obsCont[@xCampo='NomeVendedor']")
tagtext(oNode=el_prod, cTag='qCom'))) tagtext(oNode=el_prod, cTag='qCom')))
self.stringRight(nMr - 64.5, nLin, format_number( self.stringRight(nMr - 64.5, nLin, format_number(
tagtext(oNode=el_prod, cTag='vUnCom'))) tagtext(oNode=el_prod, cTag='vUnCom')))
self.stringRight(nMr - 50.5, nLin,
tagtext(oNode=el_prod, cTag='vProd'))
self.stringRight(nMr - 50.5, nLin, format_number(
tagtext(oNode=el_prod, cTag='vProd')))
self.stringRight(nMr - 38.5, nLin, format_number(vBC)) self.stringRight(nMr - 38.5, nLin, format_number(vBC))
self.stringRight(nMr - 26.5, nLin, format_number(vICMS)) self.stringRight(nMr - 26.5, nLin, format_number(vICMS))
self.stringRight(nMr - 7.5, nLin, format_number(pICMS)) self.stringRight(nMr - 7.5, nLin, format_number(pICMS))
@ -777,7 +780,49 @@ obsCont[@xCampo='NomeVendedor']")
self.nlin += nH + 3 self.nlin += nH + 3
return id return id
def adicionais(self, oXML=None):
def calculo_issqn(self, oXML=None):
elem_emit = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}emit")
el_total = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}total")
issqn_total = el_total.find(
".//{http://www.portalfiscal.inf.br/nfe}ISSQNtot")
if not issqn_total:
return 0
self.nlin += 1
nMr = self.width - self.nRight
self.canvas.setFont('NimbusSanL-Bold', 7)
self.string(self.nLeft + 1, self.nlin + 1, 'CÁLCULO DO ISSQN')
self.rect(self.nLeft, self.nlin + 2,
self.width - self.nLeft - self.nRight, 5.5)
self.vline(nMr - 47.5, self.nlin + 2, 5.5)
self.vline(nMr - 95, self.nlin + 2, 5.5)
self.vline(nMr - 142.5, self.nlin + 2, 5.5)
self.vline(nMr - 190, self.nlin + 2, 5.5)
# Labels
self.canvas.setFont('NimbusSanL-Regu', 5)
self.string(self.nLeft + 1, self.nlin + 3.8, 'INSCRIÇÃO MUNICIPAL')
self.string(nMr - 141.5, self.nlin + 3.8, 'VALOR TOTAL DOS SERVIÇOS')
self.string(nMr - 94, self.nlin + 3.8, 'BASE DE CÁLCULO DO ISSQN')
self.string(nMr - 46.5, self.nlin + 3.8, 'VALOR DO ISSQN')
# Conteúdo campos
self.canvas.setFont('NimbusSanL-Regu', 8)
self.string(
self.nLeft + 1, self.nlin + 6.7,
tagtext(oNode=elem_emit, cTag='IM'))
self.stringRight(
self.nLeft + 94, self.nlin + 6.7,
format_number(tagtext(oNode=issqn_total, cTag='vServ')))
self.stringRight(
self.nLeft + 141.5, self.nlin + 6.7,
format_number(tagtext(oNode=issqn_total, cTag='vBC')))
self.stringRight(
self.nLeft + 189, self.nlin + 6.7,
format_number(tagtext(oNode=issqn_total, cTag='vISS')))
self.nlin += 8 # Nr linhas ocupadas pelo bloco
return 8
def adicionais(self, oXML=None, tamanho_diminuir=0):
el_infAdic = oXML.find( el_infAdic = oXML.find(
".//{http://www.portalfiscal.inf.br/nfe}infAdic") ".//{http://www.portalfiscal.inf.br/nfe}infAdic")
@ -789,8 +834,8 @@ obsCont[@xCampo='NomeVendedor']")
'INFORMAÇÕES COMPLEMENTARES') 'INFORMAÇÕES COMPLEMENTARES')
self.string((self.width / 2) + 1, self.nlin + 4, 'RESERVADO AO FISCO') self.string((self.width / 2) + 1, self.nlin + 4, 'RESERVADO AO FISCO')
self.rect(self.nLeft, self.nlin + 2, self.rect(self.nLeft, self.nlin + 2,
self.width - self.nLeft - self.nRight, 42)
self.vline(self.width / 2, self.nlin + 2, 42)
self.width - self.nLeft - self.nRight, 42 - tamanho_diminuir)
self.vline(self.width / 2, self.nlin + 2, 42 - tamanho_diminuir)
# Conteúdo campos # Conteúdo campos
styles = getSampleStyleSheet() styles = getSampleStyleSheet()
styleN = styles['Normal'] styleN = styles['Normal']
@ -984,4 +1029,3 @@ obsCont[@xCampo='NomeVendedor']")
paragraph = Paragraph(ptext, style=style) paragraph = Paragraph(ptext, style=style)
w, h = paragraph.wrapOn(self.canvas, x, y) w, h = paragraph.wrapOn(self.canvas, x, y)
return w, h, paragraph return w, h, paragraph

110
pytrustnfe/nfe/templates/NfeAutorizacao.xml

@ -266,6 +266,7 @@
<imposto> <imposto>
{% with imposto = det.imposto %} {% with imposto = det.imposto %}
<vTotTrib>{{ imposto.vTotTrib }}</vTotTrib> <vTotTrib>{{ imposto.vTotTrib }}</vTotTrib>
{% if imposto.ICMS is defined %}
<ICMS> <ICMS>
{% if imposto.ICMS.CST == '00' -%} {% if imposto.ICMS.CST == '00' -%}
<ICMS00> <ICMS00>
@ -529,37 +530,58 @@
</ICMSSN900> </ICMSSN900>
{% endif %} {% endif %}
</ICMS> </ICMS>
{% if NFe.infNFe.ide.mod != '65' %}
<IPI>
<clEnq>{{ imposto.IPI.clEnq }}</clEnq>
<CNPJProd>{{ imposto.IPI.CNPJProd }}</CNPJProd>
<cSelo>{{ imposto.IPI.cSelo }}</cSelo>
<qSelo>{{ imposto.IPI.qSelo }}</qSelo>
<cEnq>{{ imposto.IPI.cEnq }}</cEnq>
{% if imposto.IPI.CST in ('00', '49', '50', '99') %}
<IPITrib>
<CST>{{ imposto.IPI.CST }}</CST>
<vBC>{{ imposto.IPI.vBC }}</vBC>
<pIPI>{{ imposto.IPI.pIPI }}</pIPI>
<qUnid>{{ imposto.IPI.qUnid }}</qUnid>
<vUnid>{{ imposto.IPI.vUnid }}</vUnid>
<vIPI>{{ imposto.IPI.vIPI }}</vIPI>
</IPITrib>
{% endif %}
{% if imposto.IPI.CST in ('01', '02', '03', '04', '51', '52', '53', '54', '55') %}
<IPINT>
<CST>{{ imposto.IPI.CST }}</CST>
</IPINT>
{% endif %}
</IPI>
{% if imposto.II is defined %}
<II>
<vBC>{{ imposto.II.vBC }}</vBC>
<vDespAdu>{{ imposto.II.vDespAdu }}</vDespAdu>
<vII>{{ imposto.II.vII }}</vII>
<vIOF>{{ imposto.II.vIOF }}</vIOF>
</II>
{% endif %} {% endif %}
{% if NFe.infNFe.ide.mod != '65' and imposto.IPI is defined %}
<IPI>
<clEnq>{{ imposto.IPI.clEnq }}</clEnq>
<CNPJProd>{{ imposto.IPI.CNPJProd }}</CNPJProd>
<cSelo>{{ imposto.IPI.cSelo }}</cSelo>
<qSelo>{{ imposto.IPI.qSelo }}</qSelo>
<cEnq>{{ imposto.IPI.cEnq }}</cEnq>
{% if imposto.IPI.CST in ('00', '49', '50', '99') %}
<IPITrib>
<CST>{{ imposto.IPI.CST }}</CST>
<vBC>{{ imposto.IPI.vBC }}</vBC>
<pIPI>{{ imposto.IPI.pIPI }}</pIPI>
<qUnid>{{ imposto.IPI.qUnid }}</qUnid>
<vUnid>{{ imposto.IPI.vUnid }}</vUnid>
<vIPI>{{ imposto.IPI.vIPI }}</vIPI>
</IPITrib>
{% endif %}
{% if imposto.IPI.CST in ('01', '02', '03', '04', '51', '52', '53', '54', '55') %}
<IPINT>
<CST>{{ imposto.IPI.CST }}</CST>
</IPINT>
{% endif %}
</IPI>
{% if imposto.II is defined %}
<II>
<vBC>{{ imposto.II.vBC }}</vBC>
<vDespAdu>{{ imposto.II.vDespAdu }}</vDespAdu>
<vII>{{ imposto.II.vII }}</vII>
<vIOF>{{ imposto.II.vIOF }}</vIOF>
</II>
{% endif %}
{% endif %}
{% if imposto.ISSQN is defined %}
<ISSQN>
<vBC>{{ imposto.ISSQN.vBC }}</vBC>
<vAliq>{{ imposto.ISSQN.vAliq }}</vAliq>
<vISSQN>{{ imposto.ISSQN.vISSQN }}</vISSQN>
<cMunFG>{{ imposto.ISSQN.cMunFG }}</cMunFG>
<cListServ>{{ imposto.ISSQN.cListServ }}</cListServ>
<vDeducao>{{ imposto.ISSQN.vDeducao }}</vDeducao>
<vOutro>{{ imposto.ISSQN.vOutro }}</vOutro>
<vDescIncond>{{ imposto.ISSQN.vDescIncond }}</vDescIncond>
<vDescCond>{{ imposto.ISSQN.vDescCond }}</vDescCond>
<vISSRet>{{ imposto.ISSQN.vDeducao }}</vISSRet>
<indISS>{{ imposto.ISSQN.indISS }}</indISS>
<cServico>{{ imposto.ISSQN.cServico }}</cServico>
<cMun>{{ imposto.ISSQN.cMun }}</cMun>
<cPais>{{ imposto.ISSQN.cPais }}</cPais>
<nProcesso>{{ imposto.ISSQN.nProcesso }}</nProcesso>
<indIncentivo>{{ imposto.ISSQN.indIncentivo }}</indIncentivo>
</ISSQN>
{% endif %} {% endif %}
<PIS> <PIS>
{% if imposto.PIS.CST in ('01', '02') %} {% if imposto.PIS.CST in ('01', '02') %}
@ -637,33 +659,13 @@
{% endif %} {% endif %}
</COFINS> </COFINS>
{% if imposto.COFINSST is defined %} {% if imposto.COFINSST is defined %}
<PISST>
<COFINSST>
<vBC>{{ imposto.COFINSST.vBC }}</vBC> <vBC>{{ imposto.COFINSST.vBC }}</vBC>
<pCOFINS>{{ imposto.COFINSST.pCOFINS }}</pCOFINS> <pCOFINS>{{ imposto.COFINSST.pCOFINS }}</pCOFINS>
<qBCProd>{{ imposto.COFINSST.qBCProd }}</qBCProd> <qBCProd>{{ imposto.COFINSST.qBCProd }}</qBCProd>
<vAliqProd>{{ imposto.COFINSST.vAliqProd }}</vAliqProd> <vAliqProd>{{ imposto.COFINSST.vAliqProd }}</vAliqProd>
<vCOFINS>{{ imposto.COFINSST.vCOFINS }}</vCOFINS> <vCOFINS>{{ imposto.COFINSST.vCOFINS }}</vCOFINS>
</PISST>
{% endif %}
{% if imposto.ISSQN is defined %}
<ISSQN>
<vBC>{{ imposto.ISSQN.vBC }}</vBC>
<vAliq>{{ imposto.ISSQN.vAliq }}</vAliq>
<vISSQN>{{ imposto.ISSQN.vISSQN }}</vISSQN>
<cMunFG>{{ imposto.ISSQN.cMunFG }}</cMunFG>
<cListServ>{{ imposto.ISSQN.cListServ }}</cListServ>
<vDeducao>{{ imposto.ISSQN.vDeducao }}</vDeducao>
<vOutro>{{ imposto.ISSQN.vOutro }}</vOutro>
<vDescIncond>{{ imposto.ISSQN.vDescIncond }}</vDescIncond>
<vDescCond>{{ imposto.ISSQN.vDescCond }}</vDescCond>
<vISSRet>{{ imposto.ISSQN.vDeducao }}</vISSRet>
<indISS>{{ imposto.ISSQN.indISS }}</indISS>
<cServico>{{ imposto.ISSQN.cServico }}</cServico>
<cMun>{{ imposto.ISSQN.cMun }}</cMun>
<cPais>{{ imposto.ISSQN.cPais }}</cPais>
<nProcesso>{{ imposto.ISSQN.nProcesso }}</nProcesso>
<indIncentivo>{{ imposto.ISSQN.vDeducao }}</indIncentivo>
</ISSQN>
</COFINSST>
{% endif %} {% endif %}
{% if imposto.ICMSUFDest is defined %} {% if imposto.ICMSUFDest is defined %}
<ICMSUFDest> <ICMSUFDest>
@ -870,6 +872,10 @@
</compra> </compra>
{% endif %} {% endif %}
</infNFe> </infNFe>
<infNFeSupl>
<qrCode>{{ NFe.infNFe.qrCode }}</qrCode>
<urlChave>{{ NFe.infNFe.urlChave }}</urlChave>
</infNFeSupl>
</NFe> </NFe>
{% endfor %} {% endfor %}
</enviNFe> </enviNFe>

2
pytrustnfe/nfse/paulistana/templates/EnvioLoteRPS.xml

@ -55,6 +55,8 @@
<CEP>{{ rps.tomador.cep }}</CEP> <CEP>{{ rps.tomador.cep }}</CEP>
</EnderecoTomador> </EnderecoTomador>
<Discriminacao>{{ rps.descricao|normalize|escape }}</Discriminacao> <Discriminacao>{{ rps.descricao|normalize|escape }}</Discriminacao>
<ValorCargaTributaria>{{ rps.valor_carga_tributaria }}</ValorCargaTributaria>
<FonteCargaTributaria>{{ rps.fonte_carga_tributaria }}</FonteCargaTributaria>
</RPS> </RPS>
{% endfor %} {% endfor %}
</PedidoEnvioLoteRPS> </PedidoEnvioLoteRPS>

2
pytrustnfe/nfse/paulistana/templates/EnvioRPS.xml

@ -46,6 +46,8 @@
<CEP>{{ rps.tomador.cep }}</CEP> <CEP>{{ rps.tomador.cep }}</CEP>
</EnderecoTomador> </EnderecoTomador>
<Discriminacao>{{ rps.descricao }}</Discriminacao> <Discriminacao>{{ rps.descricao }}</Discriminacao>
<ValorCargaTributaria>{{ rps.valor_carga_tributaria }}</ValorCargaTributaria>
<FonteCargaTributaria>{{ rps.fonte_carga_tributaria }}</FonteCargaTributaria>
{% endfor %} {% endfor %}
</RPS> </RPS>
</PedidoEnvioRPS> </PedidoEnvioRPS>

9
pytrustnfe/xml/__init__.py

@ -19,7 +19,6 @@ def render_xml(path, template_name, remove_empty, **nfe):
nfe = recursively_normalize(nfe) nfe = recursively_normalize(nfe)
env = Environment( env = Environment(
loader=FileSystemLoader(path), extensions=['jinja2.ext.with_']) loader=FileSystemLoader(path), extensions=['jinja2.ext.with_'])
env.filters["normalize"] = filters.strip_line_feed env.filters["normalize"] = filters.strip_line_feed
env.filters["normalize_str"] = filters.normalize_str env.filters["normalize_str"] = filters.normalize_str
env.filters["format_percent"] = filters.format_percent env.filters["format_percent"] = filters.format_percent
@ -28,10 +27,13 @@ def render_xml(path, template_name, remove_empty, **nfe):
env.filters["comma"] = filters.format_with_comma env.filters["comma"] = filters.format_with_comma
template = env.get_template(template_name) template = env.get_template(template_name)
xml = template.render(**nfe)
xml = template.render(**nfe).replace('\n', '')
parser = etree.XMLParser(remove_blank_text=True, remove_comments=True, parser = etree.XMLParser(remove_blank_text=True, remove_comments=True,
strip_cdata=False) strip_cdata=False)
root = etree.fromstring(xml, parser=parser) root = etree.fromstring(xml, parser=parser)
for element in root.iter("*"): # remove espaços em branco
if element.text is not None and not element.text.strip():
element.text = None
if remove_empty: if remove_empty:
context = etree.iterwalk(root) context = etree.iterwalk(root)
for dummy, elem in context: for dummy, elem in context:
@ -39,9 +41,6 @@ def render_xml(path, template_name, remove_empty, **nfe):
if recursively_empty(elem): if recursively_empty(elem):
parent.remove(elem) parent.remove(elem)
return root return root
for element in root.iter("*"): # remove espaços em branco
if element.text is not None and not element.text.strip():
element.text = None
return etree.tostring(root, encoding=str) return etree.tostring(root, encoding=str)

2
setup.py

@ -2,7 +2,7 @@
from setuptools import setup, find_packages from setuptools import setup, find_packages
VERSION = "1.0.6"
VERSION = "1.0.16"
setup( setup(

10
tests/XMLs/paulistana_signature.xml

@ -1,4 +1,4 @@
<PedidoEnvioLoteRPS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.prefeitura.sp.gov.br/nfe"><Cabecalho xmlns="" Versao="1"><CPFCNPJRemetente><CNPJ>12345678901234</CNPJ></CPFCNPJRemetente><transacao>false</transacao><dtInicio>2016-08-29</dtInicio><dtFim>2016-08-29</dtFim><QtdRPS>1</QtdRPS><ValorTotalServicos/><ValorTotalDeducoes/></Cabecalho><RPS xmlns=""><Assinatura>E4fpHYkQa7Naxn6IKGb7NwwZu5tPk/KXJ9hCwtZgq0xvKS450aQqqBL+7Iv46lTgqrSMu7+gLrl+LC1qs/8aT2mbHE8uaVFSbzwZ+sF/BkcT6nsFHLMswEiTAEs95Jb7hN1cC91xqQGRH4buw0TzxHKmhuLJ22WwtG/scxyKtjM=</Assinatura><ChaveRPS><InscricaoPrestador>123456</InscricaoPrestador><SerieRPS>1</SerieRPS><NumeroRPS>1</NumeroRPS></ChaveRPS><TipoRPS>RPS</TipoRPS><DataEmissao>2016-08-29</DataEmissao><StatusRPS>N</StatusRPS><TributacaoRPS>T</TributacaoRPS><ValorServicos/><ValorDeducoes/><ValorPIS>0.00</ValorPIS><ValorCOFINS>0.00</ValorCOFINS><ValorINSS>0.00</ValorINSS><ValorIR>0.00</ValorIR><ValorCSLL>0.00</ValorCSLL><CodigoServico>07498</CodigoServico><AliquotaServicos>5.00</AliquotaServicos><ISSRetido>false</ISSRetido><CPFCNPJTomador/><InscricaoMunicipalTomador>123456</InscricaoMunicipalTomador><RazaoSocialTomador>Trustcode</RazaoSocialTomador><EnderecoTomador><TipoLogradouro>1</TipoLogradouro><Logradouro>Vinicius de Moraes, 42</Logradouro><NumeroEndereco>42</NumeroEndereco><ComplementoEndereco/><Bairro>Corrego</Bairro><Cidade>Floripa</Cidade><UF>SC</UF><CEP>88037240</CEP></EnderecoTomador><Discriminacao>Venda de servico</Discriminacao></RPS><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<PedidoEnvioLoteRPS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.prefeitura.sp.gov.br/nfe"><Cabecalho xmlns="" Versao="1"><CPFCNPJRemetente><CNPJ>12345678901234</CNPJ></CPFCNPJRemetente><transacao>false</transacao><dtInicio>2016-08-29</dtInicio><dtFim>2016-08-29</dtFim><QtdRPS>1</QtdRPS><ValorTotalServicos/><ValorTotalDeducoes/></Cabecalho><RPS xmlns=""><Assinatura>E4fpHYkQa7Naxn6IKGb7NwwZu5tPk/KXJ9hCwtZgq0xvKS450aQqqBL+7Iv46lTgqrSMu7+gLrl+LC1qs/8aT2mbHE8uaVFSbzwZ+sF/BkcT6nsFHLMswEiTAEs95Jb7hN1cC91xqQGRH4buw0TzxHKmhuLJ22WwtG/scxyKtjM=</Assinatura><ChaveRPS><InscricaoPrestador>123456</InscricaoPrestador><SerieRPS>1</SerieRPS><NumeroRPS>1</NumeroRPS></ChaveRPS><TipoRPS>RPS</TipoRPS><DataEmissao>2016-08-29</DataEmissao><StatusRPS>N</StatusRPS><TributacaoRPS>T</TributacaoRPS><ValorServicos/><ValorDeducoes/><ValorPIS>0.00</ValorPIS><ValorCOFINS>0.00</ValorCOFINS><ValorINSS>0.00</ValorINSS><ValorIR>0.00</ValorIR><ValorCSLL>0.00</ValorCSLL><CodigoServico>07498</CodigoServico><AliquotaServicos>5.00</AliquotaServicos><ISSRetido>false</ISSRetido><CPFCNPJTomador/><InscricaoMunicipalTomador>123456</InscricaoMunicipalTomador><RazaoSocialTomador>Trustcode</RazaoSocialTomador><EnderecoTomador><TipoLogradouro>1</TipoLogradouro><Logradouro>Vinicius de Moraes, 42</Logradouro><NumeroEndereco>42</NumeroEndereco><ComplementoEndereco/><Bairro>Corrego</Bairro><Cidade>Floripa</Cidade><UF>SC</UF><CEP>88037240</CEP></EnderecoTomador><Discriminacao>Venda de servico</Discriminacao><ValorCargaTributaria/><FonteCargaTributaria/></RPS><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo> <SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
@ -8,12 +8,12 @@
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms> </Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>ePJnD6hyDvlJo08PFX8h2TXk0ZM=</DigestValue>
<DigestValue>IAh8GGlbp/Tnqma+2RZ7UrGZhTc=</DigestValue>
</Reference> </Reference>
</SignedInfo> </SignedInfo>
<SignatureValue>GbaQaTEtxuKdRRaadginWPFH5K65ywqEikkwChWO3xX5Kglq8RPm4+LjnpJmuTcE
9I2BVon3GJFh+c/6RKzJPose6FXog2xnCpTOgwA/rks/gKsUAaRlXCPsLcKMKaOj
3eH21RHEyrxBAbdpEUdlEgQWaWzmGq009EiQ544sD6c=</SignatureValue>
<SignatureValue>gjkMTCq0uuaX8tkRBlLjgybn8a2O4Axl6HHq1MN8nnEMliERcziU3pa3r1jbghlE
EUyIO8bTZ0V7c05pQvHQgVUHcSo6vHld4ZQNk7JfMfmpez4uxrUeuSrSqSLCwT9W
NmTY9EJ16GyrQNELw+SkYuEFOvqZTU3qjDZkLddQ8bc=</SignatureValue>
<KeyInfo> <KeyInfo>
<X509Data> <X509Data>
<X509Certificate>MIICMTCCAZqgAwIBAgIQfYOsIEVuAJ1FwwcTrY0t1DANBgkqhkiG9w0BAQUFADBX <X509Certificate>MIICMTCCAZqgAwIBAgIQfYOsIEVuAJ1FwwcTrY0t1DANBgkqhkiG9w0BAQUFADBX

34
tests/test_add_qr_code.py

@ -1,34 +0,0 @@
# -*- coding: utf-8-*-
# © 2016 Alessandro Fernandes Martini
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import unittest
# from lxml import etree
from pytrustnfe.nfe import _add_qrCode
class TestAddQRCode(unittest.TestCase):
def setUp(self):
self.xml_sem_qrcode = open('tests/xml_sem_qrcode.xml', 'r')
self.xml_com_qrcode = open('tests/xml_com_qrcode.xml', 'r')
dhEmi = '2016-11-09T16:03:25-00:00'
chave_nfe = 'NFe35161121332917000163650010000000011448875034'
ambiente = 2
valor_total = '324.00'
icms_total = '61.56'
cid_token = '000001'
csc = '123456789'
estado = '35'
total = {'vNF': valor_total, 'vICMS': icms_total}
infnfe = {'ide': {'dhEmi': dhEmi}, 'Id': chave_nfe, 'total': total,
'codigo_seguranca': {'cid_token': cid_token, 'csc': csc}}
infnfe = {'infNFe': infnfe}
self.kwargs = {}
self.kwargs['ambiente'] = ambiente
self.kwargs['estado'] = estado
self.kwargs['NFes'] = [infnfe]
def test_add_qrCode(self):
xml_init = self.xml_sem_qrcode.read()
xml_end = _add_qrCode(xml_init, **self.kwargs)
self.assertEqual(xml_end, self.xml_com_qrcode.read())

189
tests/xml_com_qrcode.xml

@ -1,189 +0,0 @@
<enviNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="3.10">
<idLote>103</idLote>
<indSinc>1</indSinc>
<NFe xmlns="http://www.portalfiscal.inf.br/nfe">
<infNFe versao="3.10" Id="NFe35161121332917000163650010000000011448875034">
<ide>
<cUF>35</cUF>
<cNF>44887503</cNF>
<natOp>Venda POS</natOp>
<indPag>0</indPag>
<mod>65</mod>
<serie>1</serie>
<nNF>1</nNF>
<dhEmi>2016-11-09T16:03:58-00:00</dhEmi>
<tpNF>1</tpNF>
<idDest>1</idDest>
<cMunFG>3550308</cMunFG>
<tpImp>4</tpImp>
<tpEmis>1</tpEmis>
<cDV>4</cDV>
<tpAmb>2</tpAmb>
<finNFe>1</finNFe>
<indFinal>1</indFinal>
<indPres>1</indPres>
<procEmi>0</procEmi>
<verProc>Odoo Brasil 10</verProc>
</ide>
<emit>
<CNPJ>21332917000163</CNPJ>
<xNome>LEL AMBIENTAL LTDA - EPP</xNome>
<xFant>Zell Ambiental</xFant>
<enderEmit>
<xLgr>Rua Padre João</xLgr>
<nro>444</nro>
<xBairro>Penha de França</xBairro>
<cMun>3550308</cMun>
<xMun>São Paulo</xMun>
<UF>SP</UF>
<CEP>03637000</CEP>
<cPais>1058</cPais>
<xPais>Brasil</xPais>
<fone>3425323750</fone>
</enderEmit>
<IE>244694180116</IE>
<CRT>3</CRT>
</emit>
<det nItem="1">
<prod>
<cProd>MISC</cProd>
<cEAN/>
<xProd>NOTA FISCAL EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL</xProd>
<NCM>28431000</NCM>
<CEST>2806300</CEST>
<CFOP>5101</CFOP>
<uCom>Unit(s</uCom>
<qCom>18.0</qCom>
<vUnCom>18.00</vUnCom>
<vProd>324.00</vProd>
<cEANTrib/>
<uTrib>Unit(s</uTrib>
<qTrib>18.0</qTrib>
<vUnTrib>18.00</vUnTrib>
<indTot>1</indTot>
</prod>
<imposto>
<vTotTrib>0.00</vTotTrib>
<ICMS>
<ICMS00>
<orig>0</orig>
<CST>00</CST>
<modBC>3</modBC>
<vBC>324.00</vBC>
<pICMS>19.00</pICMS>
<vICMS>61.56</vICMS>
</ICMS00>
</ICMS>
<PIS>
<PISAliq>
<CST>01</CST>
<vBC>324.00</vBC>
<pPIS>0.00</pPIS>
<vPIS>2.11</vPIS>
</PISAliq>
</PIS>
<COFINS>
<COFINSAliq>
<CST>01</CST>
<vBC>324.00</vBC>
<pCOFINS>0.00</pCOFINS>
<vCOFINS>9.72</vCOFINS>
</COFINSAliq>
</COFINS>
</imposto>
</det>
<total>
<ICMSTot>
<vBC>324.00</vBC>
<vICMS>61.56</vICMS>
<vICMSDeson>0.00</vICMSDeson>
<vBCST>0.00</vBCST>
<vST>0.00</vST>
<vProd>324.00</vProd>
<vFrete>0.00</vFrete>
<vSeg>0.00</vSeg>
<vDesc>0.00</vDesc>
<vII>0.00</vII>
<vIPI>0.00</vIPI>
<vPIS>2.11</vPIS>
<vCOFINS>9.72</vCOFINS>
<vOutro>0.00</vOutro>
<vNF>324.00</vNF>
<vTotTrib>0.00</vTotTrib>
</ICMSTot>
</total>
<transp>
<modFrete>9</modFrete>
</transp>
<pag>
<tPag>01</tPag>
<vPag>324.00</vPag>
</pag>
</infNFe>
<infNFeSupl><qrCode><![CDATA[https://homologacao.nfce.fazenda.sp.gov.br/NFCEConsultaPublica/Paginas/ConstultaQRCode.aspx?chNFe=35161121332917000163650010000000011448875034&nVersao=100&tpAmb=2&dhEmi=323031362d31312d30395431363a30333a32352d30303a3030&vNF=324.00&vICMS=61.56&digVal=66664a5a2b30346a6d484e33754c7830386875796b7942733272343d&cIdToken=000001&cHashQRCode=6d674f77ece8067d1255c5ca33fc2acaab3a0e8e]]></qrCode></infNFeSupl><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#NFe35161121332917000163650010000000011448875034">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>ffJZ+04jmHN3uLx08huykyBs2r4=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>u42y8bBqNM336yc7r0+5YWiePmCerKu3cFcp2J+lmQzIK6snba7txyeBtwVos8jQxrYLsnfWtKb5P6FxmhDeqAB41o2aoSIcnxc0yxdFn2ZDTquwU+AurH6E4hGclz8D/5qapv2+g3y+VpXMZFNNCqZSm2vJpvXBmPEY/7oO2cPB13N7WDhDRmI9H4kRDsPuxeeJetr2Bf1ThGJ0EUA4DXC7My0kl/Bw0rYwoPDhoqhxinr9Wocw1UyQ1vprLF0JVHXOtSq39Uqfqmj5QUDwUvvh4YL9bFZ8lvZZ0CZDmILaFGvr1XH3CwJ2Ws3RLlb12Arj5OT4vS8ZKhJtr/dpfA==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIIPzCCBiegAwIBAgIQYdesnYUNG8VPne0qhTeKOzANBgkqhkiG9w0BAQsFADB4
MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE2MDQGA1UECxMtU2Vj
cmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwgZG8gQnJhc2lsIC0gUkZCMRwwGgYD
VQQDExNBQyBDZXJ0aXNpZ24gUkZCIEc0MB4XDTE2MDUxMDAwMDAwMFoXDTE3MDUw
OTIzNTk1OVowgekxCzAJBgNVBAYTAkJSMRMwEQYDVQQKFApJQ1AtQnJhc2lsMQsw
CQYDVQQIEwJTUDESMBAGA1UEBxQJU2FvIFBhdWxvMTYwNAYDVQQLFC1TZWNyZXRh
cmlhIGRhIFJlY2VpdGEgRmVkZXJhbCBkbyBCcmFzaWwgLSBSRkIxFjAUBgNVBAsU
DVJGQiBlLUNOUEogQTExJDAiBgNVBAsUG0F1dGVudGljYWRvIHBvciBBUiBTdW5z
aGluZTEuMCwGA1UEAxMlTEVaIEFNQklFTlRBTCBMVERBIEVQUDoyMTMzMjkxNzAw
MDE2MzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANEG6j0uXIvvHlMz
0IGzuY/vuFQncIoSE+cBUk0uq6J3dtmGAg4oaVWCHUfHbX9s2Ag1jIG+PFAo2dlt
sbLSEji74XhD+IpM/9aHm3ke8kb05ay+bYRuUjTNSwUbslT1+amAmIu7m1yPBi6u
v3+/Lj2I0g7VeBBAjv/TiBG0VRCURXvKrwWrv2Lpybo/yDnENGtRqQHihqeYFKin
nDzBsMbv4ripbi3XiAgcy/bF6NFgVMqxrNnGvSiSUhDRkmceVFIysRXUMke02Qo1
Q5Ik1j1goUIHP44QOruXCMiT0yOK8u0qNAXR0yzSaWcBR2aJCeWgFg7sNbB50Qcx
c+2GKUECAwEAAaOCA1EwggNNMIG2BgNVHREEga4wgaugPQYFYEwBAwSgNAQyMTYw
NjE5ODYzNDEzNzgyODg2NTAwMDAwMDAwMDAwMDAwMDAwMDQwMDAwMzczU1NQU1Cg
IgYFYEwBAwKgGQQXTEVPTkFSRE8gREUgTElNQSBTQU5UT1OgGQYFYEwBAwOgEAQO
MjEzMzI5MTcwMDAxNjOgFwYFYEwBAwegDgQMMDAwMDAwMDAwMDAwgRJ3YWduZXJA
emVsbC5jb20uYnIwCQYDVR0TBAIwADAfBgNVHSMEGDAWgBQukerWbeWyWYLcOIUp
djQWVjzQPjAOBgNVHQ8BAf8EBAMCBeAwfwYDVR0gBHgwdjB0BgZgTAECAQwwajBo
BggrBgEFBQcCARZcaHR0cDovL2ljcC1icmFzaWwuY2VydGlzaWduLmNvbS5ici9y
ZXBvc2l0b3Jpby9kcGMvQUNfQ2VydGlzaWduX1JGQi9EUENfQUNfQ2VydGlzaWdu
X1JGQi5wZGYwggEWBgNVHR8EggENMIIBCTBXoFWgU4ZRaHR0cDovL2ljcC1icmFz
aWwuY2VydGlzaWduLmNvbS5ici9yZXBvc2l0b3Jpby9sY3IvQUNDZXJ0aXNpZ25S
RkJHNC9MYXRlc3RDUkwuY3JsMFagVKBShlBodHRwOi8vaWNwLWJyYXNpbC5vdXRy
YWxjci5jb20uYnIvcmVwb3NpdG9yaW8vbGNyL0FDQ2VydGlzaWduUkZCRzQvTGF0
ZXN0Q1JMLmNybDBWoFSgUoZQaHR0cDovL3JlcG9zaXRvcmlvLmljcGJyYXNpbC5n
b3YuYnIvbGNyL0NlcnRpc2lnbi9BQ0NlcnRpc2lnblJGQkc0L0xhdGVzdENSTC5j
cmwwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMIGbBggrBgEFBQcBAQSB
jjCBizBfBggrBgEFBQcwAoZTaHR0cDovL2ljcC1icmFzaWwuY2VydGlzaWduLmNv
bS5ici9yZXBvc2l0b3Jpby9jZXJ0aWZpY2Fkb3MvQUNfQ2VydGlzaWduX1JGQl9H
NC5wN2MwKAYIKwYBBQUHMAGGHGh0dHA6Ly9vY3NwLmNlcnRpc2lnbi5jb20uYnIw
DQYJKoZIhvcNAQELBQADggIBAFIUBrNIyC4kBap/7hCW63tQhA/WNnWDNYpKM5wN
zwApVV2bqFMJURzO/7AUrHu7uZS1p/Ubo+w2dFjmnmj5DniQkY85Sd6HNa1fukJY
PK13wcUMVHMjeevIAcxnYraNdN4BIz1Svl6A8leGFgIEuDUll7Td+R7+aA8N5JYQ
dFFIe2VxvJNbWP/WA49oI8U2wkoPTfOZtfrgKf2msHm3FnTfnmyOPhIf8L31iFt6
MbKuFjOGIaWu+Z/gRDqj/EbFcEMUrDbeIYqz2724ZGBOJrkjHO7DBqXXoN9pzCTO
RB5+gILMEnMS7zFsCuLOtLVohxgYUzg8p4Fy3nsHEzb/7IDVOnKLfjh/c5GSTvOa
JT6qznYV2yav7NyuUSNUv+5bCIBNk45+qrQ8DwpsLBsFa+RLfCwvYVK95ad/xVgJ
QosPJuzW3t0fU/FWbc00sZWV6lgBPyWhdF8EodaRIWC+EOC2wJbODyw+vdX8pUxT
TUJKV2iAP8206gR2h07o2CZgXckJGJQ5MnBUbS78AaITXZ5JlPaS7ZdU9zWY3kD+
j5YERs0+UweijKi5eHZioGRZRDZ2uksh1wrgeLFLWuiSNaPFYVVrQ/ZGo+E5uVNl
8FuoR6P9TZjx1/A4XjqLQ9yPoPWgIWe14Vh/76dVcgz3ElWMbmPCDoc/wX+FoHX1
Fbux
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</NFe>
</enviNFe>

190
tests/xml_sem_qrcode.xml

@ -1,190 +0,0 @@
<?xml version="1.0"?>
<enviNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="3.10">
<idLote>103</idLote>
<indSinc>1</indSinc>
<NFe xmlns="http://www.portalfiscal.inf.br/nfe">
<infNFe versao="3.10" Id="NFe35161121332917000163650010000000011448875034">
<ide>
<cUF>35</cUF>
<cNF>44887503</cNF>
<natOp>Venda POS</natOp>
<indPag>0</indPag>
<mod>65</mod>
<serie>1</serie>
<nNF>1</nNF>
<dhEmi>2016-11-09T16:03:58-00:00</dhEmi>
<tpNF>1</tpNF>
<idDest>1</idDest>
<cMunFG>3550308</cMunFG>
<tpImp>4</tpImp>
<tpEmis>1</tpEmis>
<cDV>4</cDV>
<tpAmb>2</tpAmb>
<finNFe>1</finNFe>
<indFinal>1</indFinal>
<indPres>1</indPres>
<procEmi>0</procEmi>
<verProc>Odoo Brasil 10</verProc>
</ide>
<emit>
<CNPJ>21332917000163</CNPJ>
<xNome>LEL AMBIENTAL LTDA - EPP</xNome>
<xFant>Zell Ambiental</xFant>
<enderEmit>
<xLgr>Rua Padre João</xLgr>
<nro>444</nro>
<xBairro>Penha de França</xBairro>
<cMun>3550308</cMun>
<xMun>São Paulo</xMun>
<UF>SP</UF>
<CEP>03637000</CEP>
<cPais>1058</cPais>
<xPais>Brasil</xPais>
<fone>3425323750</fone>
</enderEmit>
<IE>244694180116</IE>
<CRT>3</CRT>
</emit>
<det nItem="1">
<prod>
<cProd>MISC</cProd>
<cEAN/>
<xProd>NOTA FISCAL EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL</xProd>
<NCM>28431000</NCM>
<CEST>2806300</CEST>
<CFOP>5101</CFOP>
<uCom>Unit(s</uCom>
<qCom>18.0</qCom>
<vUnCom>18.00</vUnCom>
<vProd>324.00</vProd>
<cEANTrib/>
<uTrib>Unit(s</uTrib>
<qTrib>18.0</qTrib>
<vUnTrib>18.00</vUnTrib>
<indTot>1</indTot>
</prod>
<imposto>
<vTotTrib>0.00</vTotTrib>
<ICMS>
<ICMS00>
<orig>0</orig>
<CST>00</CST>
<modBC>3</modBC>
<vBC>324.00</vBC>
<pICMS>19.00</pICMS>
<vICMS>61.56</vICMS>
</ICMS00>
</ICMS>
<PIS>
<PISAliq>
<CST>01</CST>
<vBC>324.00</vBC>
<pPIS>0.00</pPIS>
<vPIS>2.11</vPIS>
</PISAliq>
</PIS>
<COFINS>
<COFINSAliq>
<CST>01</CST>
<vBC>324.00</vBC>
<pCOFINS>0.00</pCOFINS>
<vCOFINS>9.72</vCOFINS>
</COFINSAliq>
</COFINS>
</imposto>
</det>
<total>
<ICMSTot>
<vBC>324.00</vBC>
<vICMS>61.56</vICMS>
<vICMSDeson>0.00</vICMSDeson>
<vBCST>0.00</vBCST>
<vST>0.00</vST>
<vProd>324.00</vProd>
<vFrete>0.00</vFrete>
<vSeg>0.00</vSeg>
<vDesc>0.00</vDesc>
<vII>0.00</vII>
<vIPI>0.00</vIPI>
<vPIS>2.11</vPIS>
<vCOFINS>9.72</vCOFINS>
<vOutro>0.00</vOutro>
<vNF>324.00</vNF>
<vTotTrib>0.00</vTotTrib>
</ICMSTot>
</total>
<transp>
<modFrete>9</modFrete>
</transp>
<pag>
<tPag>01</tPag>
<vPag>324.00</vPag>
</pag>
</infNFe>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#NFe35161121332917000163650010000000011448875034">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>ffJZ+04jmHN3uLx08huykyBs2r4=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>u42y8bBqNM336yc7r0+5YWiePmCerKu3cFcp2J+lmQzIK6snba7txyeBtwVos8jQxrYLsnfWtKb5P6FxmhDeqAB41o2aoSIcnxc0yxdFn2ZDTquwU+AurH6E4hGclz8D/5qapv2+g3y+VpXMZFNNCqZSm2vJpvXBmPEY/7oO2cPB13N7WDhDRmI9H4kRDsPuxeeJetr2Bf1ThGJ0EUA4DXC7My0kl/Bw0rYwoPDhoqhxinr9Wocw1UyQ1vprLF0JVHXOtSq39Uqfqmj5QUDwUvvh4YL9bFZ8lvZZ0CZDmILaFGvr1XH3CwJ2Ws3RLlb12Arj5OT4vS8ZKhJtr/dpfA==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIIPzCCBiegAwIBAgIQYdesnYUNG8VPne0qhTeKOzANBgkqhkiG9w0BAQsFADB4
MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE2MDQGA1UECxMtU2Vj
cmV0YXJpYSBkYSBSZWNlaXRhIEZlZGVyYWwgZG8gQnJhc2lsIC0gUkZCMRwwGgYD
VQQDExNBQyBDZXJ0aXNpZ24gUkZCIEc0MB4XDTE2MDUxMDAwMDAwMFoXDTE3MDUw
OTIzNTk1OVowgekxCzAJBgNVBAYTAkJSMRMwEQYDVQQKFApJQ1AtQnJhc2lsMQsw
CQYDVQQIEwJTUDESMBAGA1UEBxQJU2FvIFBhdWxvMTYwNAYDVQQLFC1TZWNyZXRh
cmlhIGRhIFJlY2VpdGEgRmVkZXJhbCBkbyBCcmFzaWwgLSBSRkIxFjAUBgNVBAsU
DVJGQiBlLUNOUEogQTExJDAiBgNVBAsUG0F1dGVudGljYWRvIHBvciBBUiBTdW5z
aGluZTEuMCwGA1UEAxMlTEVaIEFNQklFTlRBTCBMVERBIEVQUDoyMTMzMjkxNzAw
MDE2MzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANEG6j0uXIvvHlMz
0IGzuY/vuFQncIoSE+cBUk0uq6J3dtmGAg4oaVWCHUfHbX9s2Ag1jIG+PFAo2dlt
sbLSEji74XhD+IpM/9aHm3ke8kb05ay+bYRuUjTNSwUbslT1+amAmIu7m1yPBi6u
v3+/Lj2I0g7VeBBAjv/TiBG0VRCURXvKrwWrv2Lpybo/yDnENGtRqQHihqeYFKin
nDzBsMbv4ripbi3XiAgcy/bF6NFgVMqxrNnGvSiSUhDRkmceVFIysRXUMke02Qo1
Q5Ik1j1goUIHP44QOruXCMiT0yOK8u0qNAXR0yzSaWcBR2aJCeWgFg7sNbB50Qcx
c+2GKUECAwEAAaOCA1EwggNNMIG2BgNVHREEga4wgaugPQYFYEwBAwSgNAQyMTYw
NjE5ODYzNDEzNzgyODg2NTAwMDAwMDAwMDAwMDAwMDAwMDQwMDAwMzczU1NQU1Cg
IgYFYEwBAwKgGQQXTEVPTkFSRE8gREUgTElNQSBTQU5UT1OgGQYFYEwBAwOgEAQO
MjEzMzI5MTcwMDAxNjOgFwYFYEwBAwegDgQMMDAwMDAwMDAwMDAwgRJ3YWduZXJA
emVsbC5jb20uYnIwCQYDVR0TBAIwADAfBgNVHSMEGDAWgBQukerWbeWyWYLcOIUp
djQWVjzQPjAOBgNVHQ8BAf8EBAMCBeAwfwYDVR0gBHgwdjB0BgZgTAECAQwwajBo
BggrBgEFBQcCARZcaHR0cDovL2ljcC1icmFzaWwuY2VydGlzaWduLmNvbS5ici9y
ZXBvc2l0b3Jpby9kcGMvQUNfQ2VydGlzaWduX1JGQi9EUENfQUNfQ2VydGlzaWdu
X1JGQi5wZGYwggEWBgNVHR8EggENMIIBCTBXoFWgU4ZRaHR0cDovL2ljcC1icmFz
aWwuY2VydGlzaWduLmNvbS5ici9yZXBvc2l0b3Jpby9sY3IvQUNDZXJ0aXNpZ25S
RkJHNC9MYXRlc3RDUkwuY3JsMFagVKBShlBodHRwOi8vaWNwLWJyYXNpbC5vdXRy
YWxjci5jb20uYnIvcmVwb3NpdG9yaW8vbGNyL0FDQ2VydGlzaWduUkZCRzQvTGF0
ZXN0Q1JMLmNybDBWoFSgUoZQaHR0cDovL3JlcG9zaXRvcmlvLmljcGJyYXNpbC5n
b3YuYnIvbGNyL0NlcnRpc2lnbi9BQ0NlcnRpc2lnblJGQkc0L0xhdGVzdENSTC5j
cmwwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMIGbBggrBgEFBQcBAQSB
jjCBizBfBggrBgEFBQcwAoZTaHR0cDovL2ljcC1icmFzaWwuY2VydGlzaWduLmNv
bS5ici9yZXBvc2l0b3Jpby9jZXJ0aWZpY2Fkb3MvQUNfQ2VydGlzaWduX1JGQl9H
NC5wN2MwKAYIKwYBBQUHMAGGHGh0dHA6Ly9vY3NwLmNlcnRpc2lnbi5jb20uYnIw
DQYJKoZIhvcNAQELBQADggIBAFIUBrNIyC4kBap/7hCW63tQhA/WNnWDNYpKM5wN
zwApVV2bqFMJURzO/7AUrHu7uZS1p/Ubo+w2dFjmnmj5DniQkY85Sd6HNa1fukJY
PK13wcUMVHMjeevIAcxnYraNdN4BIz1Svl6A8leGFgIEuDUll7Td+R7+aA8N5JYQ
dFFIe2VxvJNbWP/WA49oI8U2wkoPTfOZtfrgKf2msHm3FnTfnmyOPhIf8L31iFt6
MbKuFjOGIaWu+Z/gRDqj/EbFcEMUrDbeIYqz2724ZGBOJrkjHO7DBqXXoN9pzCTO
RB5+gILMEnMS7zFsCuLOtLVohxgYUzg8p4Fy3nsHEzb/7IDVOnKLfjh/c5GSTvOa
JT6qznYV2yav7NyuUSNUv+5bCIBNk45+qrQ8DwpsLBsFa+RLfCwvYVK95ad/xVgJ
QosPJuzW3t0fU/FWbc00sZWV6lgBPyWhdF8EodaRIWC+EOC2wJbODyw+vdX8pUxT
TUJKV2iAP8206gR2h07o2CZgXckJGJQ5MnBUbS78AaITXZ5JlPaS7ZdU9zWY3kD+
j5YERs0+UweijKi5eHZioGRZRDZ2uksh1wrgeLFLWuiSNaPFYVVrQ/ZGo+E5uVNl
8FuoR6P9TZjx1/A4XjqLQ9yPoPWgIWe14Vh/76dVcgz3ElWMbmPCDoc/wX+FoHX1
Fbux
</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</NFe>
</enviNFe>
Loading…
Cancel
Save