Browse Source

Merge 63a9e8e253 into 6760152ed5

pull/107/merge
Fábio Luna 8 years ago
committed by GitHub
parent
commit
aa17698e47
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 78
      pytrustnfe/Servidores.py
  2. 9
      pytrustnfe/nfe/__init__.py
  3. 1
      pytrustnfe/nfe/comunicacao.py
  4. 456
      pytrustnfe/nfe/danfce.py
  5. 2
      pytrustnfe/nfe/templates/NfeAutorizacao.xml
  6. 12
      pytrustnfe/nfse/floripa/templates/processar_nota.xml
  7. 2
      setup.py

78
pytrustnfe/Servidores.py

@ -20,7 +20,6 @@ WS_NFCE_CADASTRO = 'NfeConsultaCadastro'
WS_NFCE_RECEPCAO_EVENTO = 'RecepcaoEventoCarta'
WS_NFCE_QR_CODE = 'NfeQRCode'
WS_NFCE_CONSULTA_DESTINADAS = 'NfeConsultaDest',
WS_NFCE_RET_AUTORIZACAO = 'NFeRetAutorizacao',
WS_NFE_CADASTRO = 'NfeConsultaCadastro'
@ -97,11 +96,8 @@ def localizar_url(servico, estado, mod='55', ambiente=2):
def localizar_qrcode(estado, ambiente=2):
sigla = SIGLA_ESTADO[estado]
dominio = ESTADO_WS[sigla]['65'][ambiente]['servidor']
complemento = ESTADO_WS[sigla]['65'][ambiente][WS_NFCE_QR_CODE]
if 'https://' in complemento:
return complemento
return "https://%s/%s" % (dominio, complemento)
ws_qrcode = ESTADO_WS[sigla][NFCE_MODELO][ambiente][WS_NFCE_QR_CODE]
return ws_qrcode
METODO_WS = {
@ -137,27 +133,53 @@ METODO_WS = {
}
SVRS = {
NFE_AMBIENTE_PRODUCAO: {
'servidor': 'nfe.svrs.rs.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_CANCELAMENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NfeAutorizacao.asmx',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NfeRetAutorizacao.asmx',
WS_NFE_CADASTRO: 'ws/CadConsultaCadastro/CadConsultaCadastro2.asmx',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao/nfeinutilizacao2.asmx',
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
NFE_MODELO: {
NFE_AMBIENTE_PRODUCAO: {
'servidor': 'nfe.svrs.rs.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_CANCELAMENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NfeAutorizacao.asmx',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NfeRetAutorizacao.asmx',
WS_NFE_CADASTRO: 'ws/CadConsultaCadastro/CadConsultaCadastro2.asmx',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao/nfeinutilizacao2.asmx',
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
},
NFE_AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfe-homologacao.svrs.rs.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_CANCELAMENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NfeAutorizacao.asmx',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NfeRetAutorizacao.asmx',
WS_NFE_CADASTRO: 'ws/CadConsultaCadastro/CadConsultaCadastro2.asmx',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao/nfeinutilizacao2.asmx',
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
}
},
NFE_AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfe-homologacao.svrs.rs.gov.br',
WS_NFE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_CANCELAMENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFE_AUTORIZACAO: 'ws/NfeAutorizacao/NfeAutorizacao.asmx',
WS_NFE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NfeRetAutorizacao.asmx',
WS_NFE_CADASTRO: 'ws/CadConsultaCadastro/CadConsultaCadastro2.asmx',
WS_NFE_INUTILIZACAO: 'ws/nfeinutilizacao/nfeinutilizacao2.asmx',
WS_NFE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
NFCE_MODELO: {
NFCE_AMBIENTE_PRODUCAO: {
'servidor': 'nfce.svrs.rs.gov.br',
WS_NFCE_INUTILIZACAO: 'ws/nfeinutilizacao/nfeinutilizacao2.asmx',
WS_NFCE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFCE_CANCELAMENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFCE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
WS_NFCE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao.asmx',
WS_NFCE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao.asmx',
WS_NFCE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFCE_QR_CODE: 'http://dec.fazenda.df.gov.br/ConsultarNFCe.aspx',
},
NFCE_AMBIENTE_HOMOLOGACAO: {
'servidor': 'nfce-homologacao.svrs.rs.gov.br',
WS_NFCE_INUTILIZACAO: 'ws/nfeinutilizacao/nfeinutilizacao2.asmx',
WS_NFCE_CONSULTA: 'ws/NfeConsulta/NfeConsulta2.asmx',
WS_NFCE_CANCELAMENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFCE_SITUACAO: 'ws/NfeStatusServico/NfeStatusServico2.asmx',
WS_NFCE_AUTORIZACAO: 'ws/NfeAutorizacao/NFeAutorizacao.asmx',
WS_NFCE_RET_AUTORIZACAO: 'ws/NfeRetAutorizacao/NFeRetAutorizacao.asmx',
WS_NFCE_RECEPCAO_EVENTO: 'ws/recepcaoevento/recepcaoevento.asmx',
WS_NFCE_QR_CODE: 'http://dec.fazenda.df.gov.br/ConsultarNFCe.aspx',
}
}
}
@ -317,7 +339,7 @@ UFAM = {
WS_NFE_INUTILIZACAO: 'nfce-services-nac/services/NfeInutilizacao2',
WS_NFE_CONSULTA: 'nfce-services-nac/services/NfeConsulta2',
WS_NFE_SITUACAO: 'nfce-services-nac/services/NfeStatusServico2',
WS_NFCE_QR_CODE: 'nfceweb/consultarNFCe.jsp',
WS_NFCE_QR_CODE: 'homnfce.sefaz.am.gov.br/nfceweb/consultarNFCe.jsp',
}
}
}
@ -626,7 +648,7 @@ UFSP = {
WS_NFCE_SITUACAO: 'ws/nfestatusservico2.asmx',
WS_NFCE_CADASTRO: 'ws/cadconsultacadastro2.asmx',
WS_NFCE_RECEPCAO_EVENTO: 'ws/recepcaoevento.asmx',
WS_NFCE_QR_CODE: 'NFCEConsultaPublica/Paginas/ConstultaQRCode.aspx',
WS_NFCE_QR_CODE: 'https://homologacao.nfce.fazenda.sp.gov.br/NFCEConsultaPublica/Paginas/ConstultaQRCode.aspx',
}
}
}

9
pytrustnfe/nfe/__init__.py

@ -87,9 +87,7 @@ def _add_qrCode(xml, **kwargs):
valor_total = inf_nfe['total']['vNF']
dest_cpf = 'Inexistente'
dest = nfe.find(".//{http://www.portalfiscal.inf.br/nfe}dest")
if dest:
dest_parent = dest.getparent()
dest_parent.remove(dest)
if inf_nfe.get('dest', False):
if inf_nfe['dest'].get('CPF', False):
dest_cpf = inf_nfe['dest']['CPF']
@ -97,7 +95,7 @@ def _add_qrCode(xml, **kwargs):
cpf = etree.Element('CPF')
cpf.text = dest_cpf
dest.append(cpf)
dest_parent.append(dest)
icms_total = inf_nfe['total']['vICMS']
dig_val = binascii.hexlify(xml.find(
".//{http://www.w3.org/2000/09/xmldsig#}DigestValue").text.encode()).decode()
@ -182,7 +180,7 @@ def _render(certificado, method, sign, **kwargs):
def _send(certificado, method, **kwargs):
xml_send = kwargs["xml"]
url = localizar_url(method, kwargs['estado'], '55',
url = localizar_url(method, kwargs['estado'], kwargs['modelo'],
kwargs['ambiente'])
cabecalho = _build_header(method, **kwargs)
@ -267,6 +265,7 @@ def xml_consulta_cadastro(certificado, **kwargs):
def consulta_cadastro(certificado, **kwargs):
if "xml" not in kwargs:
kwargs['xml'] = xml_consulta_cadastro(certificado, **kwargs)
kwargs['modelo'] = '55'
return _send(certificado, 'NfeConsultaCadastro', **kwargs)

1
pytrustnfe/nfe/comunicacao.py

@ -27,6 +27,7 @@ def executar_consulta(certificado, url, cabecalho, xmlEnviar, send_raw=False):
client = HttpClient(url, cert_path, key_path)
xml_enviar = _soap_xml(xmlEnviar, cabecalho)
xml_enviar = xml_enviar.encode('utf-8')
if send_raw:
xml = '<?xml version="1.0" encoding="utf-8"?>' + xmlEnviar.rstrip('\n')
xml_enviar = xml

456
pytrustnfe/nfe/danfce.py

@ -0,0 +1,456 @@
# -*- coding: utf-8 -*-
# © 2017 Johny Chen Jy, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from textwrap import wrap
from io import BytesIO
from reportlab.lib import utils
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm, mm
from reportlab.graphics.barcode import qr
from reportlab.graphics import renderPDF
from reportlab.graphics.shapes import Drawing
from reportlab.platypus import Table, TableStyle, Paragraph, Image
from reportlab.lib.enums import TA_CENTER
from reportlab.lib.styles import ParagraphStyle
def format_cnpj_cpf(value):
if len(value) < 12: # CPF
cValue = '%s.%s.%s-%s' % (value[:-8], value[-8:-5],
value[-5:-2], value[-2:])
else:
cValue = '%s.%s.%s/%s-%s' % (value[:-12], value[-12:-9],
value[-9:-6], value[-6:-2], value[-2:])
return cValue
def getdateUTC(cDateUTC):
cDt = cDateUTC[0:10].split('-')
cDt.reverse()
return '/'.join(cDt), cDateUTC[11:16]
def format_number(cNumber, precision=0, group_sep='.', decimal_sep=','):
if cNumber:
number = float(cNumber)
return ("{:,." + str(precision) + "f}").format(number).\
replace(",", "X").replace(".", ",").replace("X", ".")
return ""
def tagtext(oNode=None, cTag=None):
try:
xpath = ".//{http://www.portalfiscal.inf.br/nfe}%s" % (cTag)
cText = oNode.find(xpath).text
except:
cText = ''
return cText
def get_image(path, width=1 * cm):
img = utils.ImageReader(path)
iw, ih = img.getSize()
aspect = ih / float(iw)
return Image(path, width=width, height=(width * aspect))
def format_telefone(numero_telefone):
if len(numero_telefone) == 10:
telefone = '(%s) %s-%s' % (numero_telefone[0:2],
numero_telefone[2:6],
numero_telefone[6:])
else:
telefone = '(%s) %s-%s' % (numero_telefone[0:2],
numero_telefone[2:7],
numero_telefone[7:])
return telefone
class danfce(object):
def __init__(self, list_xml, logo=None):
self.current_font_size = 7
self.current_font_name = 'NimbusSanL-Regu'
self.max_height = 840
self.min_height = 1
self.min_width = 5
self.max_width = 200
self.current_height = 840
self.oPDF_IO = BytesIO()
self.canvas = canvas.Canvas(self.oPDF_IO, pagesize=(7.2 * cm, 30 * cm))
self.canvas.setTitle('DANFCE')
self.canvas.setLineWidth(.5)
self.canvas.setFont(self.current_font_name, self.current_font_size)
self.list_xml = list_xml
self.logo = logo
self.nfce_generate()
def ide_emit(self, oXML=None):
elem_emit = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}emit")
# Razão Social emitente
nomeEmpresa = tagtext(oNode=elem_emit, cTag='xFant')
self.drawTitle(nomeEmpresa, 10)
if self.logo:
img = get_image(self.logo, width=10 * mm)
img.drawOn(self.canvas, 5, 830)
cEnd = tagtext(oNode=elem_emit, cTag="xNome") + '<br />'
cEnd += "CNPJ: %s " % (format_cnpj_cpf(
tagtext(oNode=elem_emit, cTag='CNPJ')))
cEnd += "IE: %s" % (tagtext(oNode=elem_emit, cTag="IE")) + '<br />'
cEnd += tagtext(oNode=elem_emit, cTag='xLgr') + ', ' + tagtext(
oNode=elem_emit, cTag='nro') + ' - '
cEnd += tagtext(oNode=elem_emit, cTag='xBairro') + '<br />' + tagtext(
oNode=elem_emit, cTag='xMun') + ' - '
cEnd += tagtext(oNode=elem_emit, cTag='UF') + ' - ' + tagtext(
oNode=elem_emit, cTag='CEP') + '<br />'
cEnd += 'Fone: ' + format_telefone(tagtext(
oNode=elem_emit, cTag='fone'))
self._drawCenteredParagraph(cEnd)
self.drawLine()
def danfce_information(self):
self.drawTitle(
"DANFE NFC-e - Documento Auxiliar da Nota Fiscal de",
7, 'NimbusSanL-Bold')
self.drawTitle("Consumidor Eletrônica", 7, 'NimbusSanL-Bold')
self.drawString(
"NFC-e não permite aproveitamento de crédito de ICMS", True)
self.drawLine()
def produtos(self, oXML=None, el_det=None, oPaginator=None,
list_desc=None, list_cod_prod=None):
rows = [['Codigo', 'Descricao', 'Qtde', 'Un', 'Vl Unit', 'Vl Total']]
colWidths = (25, 90, 15, 15, 25, 25)
rowHeights = [7]
for id in range(oPaginator[0], oPaginator[1]):
item = el_det[id]
el_prod = item.find(".//{http://www.portalfiscal.inf.br/nfe}prod")
cod = tagtext(oNode=el_prod, cTag='cProd')
descricao = tagtext(oNode=el_prod, cTag='xProd')
Un = tagtext(oNode=el_prod, cTag='uCom')
qtde = format_number(tagtext(oNode=el_prod, cTag='qCom'),
precision=2)
vl_unit = format_number(tagtext(oNode=el_prod, cTag='vUnCom'),
precision=2)
vl_total = format_number(
tagtext(oNode=el_prod, cTag='vProd'), precision=2)
new_row = [cod, descricao, qtde, Un, vl_unit, vl_total]
rows.append(new_row)
rowHeights.append(self.current_font_size + 2)
self._draw_product_table(rows, colWidths, rowHeights)
def _draw_product_table(self, rows, colWidths, rowHeights):
table = Table(rows, colWidths, tuple(rowHeights))
table.setStyle(TableStyle([
('FONTSIZE', (0, 0), (-1, -1), 7),
('FONT', (0, 1), (-1, -1), 'NimbusSanL-Regu'),
('FONT', (0, 0), (-1, 0), 'NimbusSanL-Bold'),
('ALIGN', (0, 0), (-1, 0), "LEFT"),
('ALIGN', (1, 0), (-1, 0), "LEFT"),
('ALIGN', (2, 0), (-1, 0), "CENTER"),
('ALIGN', (3, 0), (-1, 0), "CENTER"),
('ALIGN', (0, 1), (-1, -1), "LEFT"),
('ALIGN', (1, 1), (-1, -1), "LEFT"),
('ALIGN', (2, 1), (-1, -1), "CENTER"),
('ALIGN', (3, 1), (-1, -1), "CENTER"),
]))
w, h = table.wrapOn(self.canvas, 200, 450)
table.drawOn(self.canvas, 0, self.current_height - (h * 1.2))
self.current_height -= (h * 1.1)
def totais(self, oXML=None):
# Impostos
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)
el_pag = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}pag")
troco = format_number(tagtext(oNode=el_pag, cTag="vTroco"))
payment_method_list = {'01': 'Dinheiro',
'02': 'Cheque',
'03': 'Cartão de Crédito',
'04': 'Cartão de Débito',
"05": "Crédito Loja",
'10': 'Vale Alimentação',
'11': 'Vale Refeição',
'12': 'Vale Presente',
'13': 'Vale Combustível',
'14': 'Duplicata Mercantil',
'15': 'Boleto Bancario',
'90': 'Sem Pagamento',
'99': 'Outros'}
quant_produtos = len(oXML.findall(
".//{http://www.portalfiscal.inf.br/nfe}det"))
payment_methods = []
for pagId, item in enumerate(el_pag):
if 'tPag' not in item.tag:
continue
payment = []
method = payment_method_list[item.text]
payment.append(method)
payment.append(format_number(item.getnext().text, precision=2))
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,
}
self.draw_totals_table(values)
self.drawLine()
def draw_totals_table(self, values):
rowHeights = [7, 7, 7, 7, 10]
data = [['QTD.TOTAL DE ITENS', values['quantidade_itens']],
['VALOR TOTAL R$', values['valor_total']],
['DESCONTO R$', values['desconto']],
['VALOR A PAGAR R$', values['valor_a_pagar']],
['FORMA DE PAGAMENTO', 'VALOR PAGO R$'],
]
for item in values['formas_de_pagamento']:
data.append([item[0], item[1]])
rowHeights.append(7)
data.append(['TROCO', format_number(values['troco'], precision=2)])
rowHeights.append(7)
table2 = Table(data, colWidths=(150, 50), rowHeights=tuple(rowHeights))
table2.setStyle(TableStyle([
('FONTSIZE', (0, 0), (-1, -1), 7),
('FONT', (0, 0), (1, -1), 'NimbusSanL-Regu'),
('FONT', (0, 4), (1, 4), 'NimbusSanL-Bold'),
('ALIGN', (1, 0), (1, -1), "RIGHT")
]))
w, h = table2.wrapOn(self.canvas, 200, 450)
table2.drawOn(self.canvas, 0, self.current_height - (h * 1.1))
self.current_height -= h
def inf_authentication(self, oXML=None):
el_infNFe = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}infNFe")
# n nfce, serie e data de solicitacao
el_ide = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}ide")
el_NFeSupl = oXML.find(
".//{http://www.portalfiscal.inf.br/nfe}infNFeSupl")
el_dest = el_infNFe.find(".//{http://www.portalfiscal.inf.br/nfe}dest")
# chave, n protocolo, data autorizacao
el_prot_nfe = oXML.find(
".//{http://www.portalfiscal.inf.br/nfe}protNFe")
el_infAdic = oXML.find(
".//{http://www.portalfiscal.inf.br/nfe}infAdic")
url_chave = tagtext(oNode=el_NFeSupl, cTag='urlChave')
access_key = tagtext(oNode=el_prot_nfe, cTag="chNFe")
frase_chave_acesso = 'Consulte pela Chave de Acesso em:<br />\
%s<br />%s' % (url_chave, access_key)
qrcode = tagtext(oNode=el_NFeSupl, cTag='qrCode')
cnpj = tagtext(oNode=el_dest, cTag='CNPJ')
cpf = tagtext(oNode=el_dest, cTag='CPF')
if cnpj:
cnpj_cpf = format_cnpj_cpf(cnpj)
cnpj_cpf = "CONSUMIDOR CNPJ: %s" % (cnpj)
elif cpf:
cnpj_cpf = format_cnpj_cpf(cpf)
cnpj_cpf = "CONSUMIDOR CPF: %s" % (cpf)
else:
cnpj_cpf = u"CONSUMIDOR NÃO IDENTIFICADO"
nNFC = tagtext(oNode=el_ide, cTag="nNF")
serie = tagtext(oNode=el_ide, cTag='serie')
dataSolicitacao = getdateUTC(tagtext(oNode=el_ide, cTag="dhEmi"))
dataSolicitacao = dataSolicitacao[0] + " " + dataSolicitacao[1]
numProtocolo = tagtext(oNode=el_prot_nfe, cTag="nProt")
dataAutorizacao = getdateUTC(tagtext(oNode=el_prot_nfe,
cTag='dhRecbto'))
dataAutorizacao = dataAutorizacao[0] + " " + dataAutorizacao[1]
text = u"%s <br />%s <br />NFC-e nº%s Série %s %s<br />\
Protocolo de autorização: %s<br />Data de autorização %s<br />\
" % (frase_chave_acesso, cnpj_cpf, nNFC, serie, dataSolicitacao,
numProtocolo, dataAutorizacao)
self._drawCenteredParagraph(text)
self.draw_qr_code(qrcode)
infAdFisco = tagtext(oNode=el_infAdic, cTag='infAdFisco')
self._drawCenteredParagraph(infAdFisco)
infCpl = tagtext(oNode=el_infAdic, cTag='infCpl')
self._drawCenteredParagraph(infCpl)
def _drawCenteredParagraph(self, text):
style = ParagraphStyle(
name='Normal',
fontName='NimbusSanL-Regu',
fontSize=7,
alignment=TA_CENTER,
leading=7,
)
paragraph = Paragraph(text, style=style)
w, h = paragraph.wrapOn(self.canvas, 180, 300)
paragraph.drawOn(self.canvas, 10, self.current_height - h)
self.current_height -= (h*1.1)
def drawString(self, string, centered=False):
if centered:
self.canvas.drawCentredString(
self.max_width / 2, self.current_height, string)
self.current_height -= self.current_font_size
else:
self.canvas.drawString(self.min_width, self.current_height, string)
self.current_height -= self.current_font_size
def drawTitle(self, string, size, font='NimbusSanL-Regu'):
self.canvas.setFont(font, size)
self.canvas.drawCentredString(
self.max_width / 2, self.current_height, string)
self.current_height -= self.current_font_size
self.canvas.setFont(self.current_font_name, self.current_font_size)
def drawLine(self):
self.canvas.line(self.min_width, self.current_height,
self.max_width, self.current_height)
self.current_height -= self.current_font_size
def draw_qr_code(self, string):
qr_code = qr.QrCodeWidget(string)
drawing = Drawing(23 * mm, 23 * mm)
drawing.add(qr_code)
renderPDF.draw(drawing, self.canvas, 20 * mm, self.current_height - 85)
self.current_height -= 85
def newpage(self):
self.current_height = self.max_height
self.Page += 1
self.canvas.showPage()
def nfce_generate(self):
for oXML in self.list_xml:
oXML_cobr = oXML.find(
".//{http://www.portalfiscal.inf.br/nfe}cobr")
self.NrPages = 1
self.Page = 1
# Calculando total linhas usadas para descrições dos itens
# Com bloco fatura, apenas 29 linhas para itens na primeira folha
nNr_Lin_Pg_1 = 34 if oXML_cobr is None else 30
# [ rec_ini , rec_fim , lines , limit_lines ]
oPaginator = [[0, 0, 0, nNr_Lin_Pg_1]]
el_det = oXML.findall(".//{http://www.portalfiscal.inf.br/nfe}det")
if el_det is not None:
list_desc = []
list_cod_prod = []
nPg = 0
for nId, item in enumerate(el_det):
el_prod = item.find(
".//{http://www.portalfiscal.inf.br/nfe}prod")
infAdProd = item.find(
".//{http://www.portalfiscal.inf.br/nfe}infAdProd")
list_ = wrap(tagtext(oNode=el_prod, cTag='xProd'), 56)
if infAdProd is not None:
list_.extend(wrap(infAdProd.text, 56))
list_desc.append(list_)
list_cProd = wrap(tagtext(oNode=el_prod, cTag='cProd'), 14)
list_cod_prod.append(list_cProd)
# Nr linhas necessárias p/ descrição item
nLin_Itens = len(list_)
if (oPaginator[nPg][2] + nLin_Itens) >= oPaginator[nPg][3]:
oPaginator.append([0, 0, 0, 77])
nPg += 1
oPaginator[nPg][0] = nId
oPaginator[nPg][1] = nId + 1
oPaginator[nPg][2] = nLin_Itens
else:
# adiciona-se 1 pelo funcionamento de xrange
oPaginator[nPg][1] = nId + 1
oPaginator[nPg][2] += nLin_Itens
self.NrPages = len(oPaginator) # Calculando nr. páginas
self.ide_emit(oXML=oXML)
# self.destinatario(oXML=oXML)
self.danfce_information()
self.produtos(oXML=oXML, el_det=el_det, oPaginator=oPaginator[0],
list_desc=list_desc, list_cod_prod=list_cod_prod)
self.drawLine()
self.totais(oXML=oXML)
self.inf_authentication(oXML=oXML)
# Gera o restante das páginas do XML
for oPag in oPaginator[1:]:
if oPag:
self.newpage()
self.ide_emit(oXML=oXML)
# self.destinatario(oXML=oXML)
self.produtos(oXML=oXML, el_det=el_det, oPaginator=oPag,
list_desc=list_desc,
list_cod_prod=list_cod_prod)
self.totais(oXML=oXML)
self.inf_authentication(oXML=oXML)
self.newpage()
self.canvas.save()
def writeto_pdf(self, fileObj):
pdf_out = self.oPDF_IO.getvalue()
self.oPDF_IO.close()
fileObj.write(pdf_out)

2
pytrustnfe/nfe/templates/NfeAutorizacao.xml

@ -491,7 +491,6 @@
</IPINT>
{% endif %}
</IPI>
{% endif %}
{% if imposto.II is defined %}
<II>
<vBC>{{ imposto.II.vBC }}</vBC>
@ -500,6 +499,7 @@
<vIOF>{{ imposto.II.vIOF }}</vIOF>
</II>
{% endif %}
{% endif %}
<PIS>
{% if imposto.PIS.CST in ('01', '02') %}
<PISAliq>

12
pytrustnfe/nfse/floripa/templates/processar_nota.xml

@ -1,13 +1,13 @@
<?xml version="1.0"?>
<xmlProcessamentoNfpse>
<bairroTomador>{{ rps.tomador.bairro|normalize|escape }}</bairroTomador>
<bairroTomador>{{ rps.tomador.bairro }}</bairroTomador>
<baseCalculo>{{ rps.base_calculo }}</baseCalculo>
<baseCalculoSubstituicao>0.0</baseCalculoSubstituicao>
<cfps>{{ rps.cfps }}</cfps>
<codigoMunicipioTomador>{{ rps.tomador.cidade }}</codigoMunicipioTomador>
<codigoPostalTomador>{{ rps.tomador.cep }}</codigoPostalTomador>
<complementoEnderecoTomador>{{ rps.tomador.complemento|normalize|escape }}</complementoEnderecoTomador>
<dadosAdicionais>{{ rps.observacoes|normalize|escape }}</dadosAdicionais>
<complementoEnderecoTomador>{{ rps.tomador.complemento }}</complementoEnderecoTomador>
<dadosAdicionais>{{ rps.observacoes }}</dadosAdicionais>
<dataEmissao>{{ rps.data_emissao }}</dataEmissao>
<emailTomador>{{ rps.tomador.email }}</emailTomador>
<identificacao>{{ rps.numero }}</identificacao>
@ -18,7 +18,7 @@
<itemServico>
<aliquota>{{ item.aliquota }}</aliquota>
<cst>{{ item.cst_servico }}</cst>
<descricaoServico>{{ item.descricao|normalize|escape }}</descricaoServico>
<descricaoServico>{{ item.descricao }}</descricaoServico>
<idCNAE>{{ item.cnae }}</idCNAE>
<quantidade>{{ item.quantidade }}</quantidade>
<valorTotal>{{ item.valor_total }}</valorTotal>
@ -26,12 +26,12 @@
</itemServico>
{% endfor %}
</itensServico>
<logradouroTomador>{{ rps.tomador.logradouro|normalize|escape }}</logradouroTomador>
<logradouroTomador>{{ rps.tomador.logradouro }}</logradouroTomador>
<nomeMunicipioTomador></nomeMunicipioTomador>
<numeroAEDF>{{ rps.aedf }}</numeroAEDF>
<numeroEnderecoTomador>{{ rps.tomador.numero }}</numeroEnderecoTomador>
<paisTomador>1058</paisTomador>
<razaoSocialTomador>{{ rps.tomador.razao_social|normalize|escape }}</razaoSocialTomador>
<razaoSocialTomador>{{ rps.tomador.razao_social }}</razaoSocialTomador>
<telefoneTomador>{{ rps.tomador.telefone }}</telefoneTomador>
<ufTomador>{{ rps.tomador.uf }}</ufTomador>
<valorISSQN>{{rps.valor_issqn }}</valorISSQN>

2
setup.py

@ -48,7 +48,7 @@ later (LGPLv2+)',
'signxml >= 2.4.0',
'lxml >= 3.5.0, < 5',
'suds-jurko >= 0.6',
'suds-jurko-requests >= 1.2',
'suds-jurko-requests >= 1.1',
'reportlab'
],
tests_require=[

Loading…
Cancel
Save