|
|
@ -2,10 +2,12 @@ |
|
|
# © 2017 Johny Chen Jy, Trustcode |
|
|
# © 2017 Johny Chen Jy, Trustcode |
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|
|
|
|
|
|
|
|
|
|
|
import os |
|
|
import re |
|
|
import re |
|
|
from textwrap import wrap |
|
|
from textwrap import wrap |
|
|
from io import BytesIO |
|
|
from io import BytesIO |
|
|
|
|
|
|
|
|
|
|
|
from reportlab.pdfbase import pdfmetrics |
|
|
|
|
|
from reportlab.pdfbase.ttfonts import TTFont |
|
|
from reportlab.lib import utils |
|
|
from reportlab.lib import utils |
|
|
from reportlab.pdfgen import canvas |
|
|
from reportlab.pdfgen import canvas |
|
|
from reportlab.lib.units import cm, mm |
|
|
from reportlab.lib.units import cm, mm |
|
|
@ -19,25 +21,34 @@ from reportlab.lib.styles import ParagraphStyle |
|
|
|
|
|
|
|
|
def format_cnpj_cpf(value): |
|
|
def format_cnpj_cpf(value): |
|
|
if len(value) < 12: # CPF |
|
|
if len(value) < 12: # CPF |
|
|
cValue = '%s.%s.%s-%s' % (value[:-8], value[-8:-5], |
|
|
|
|
|
value[-5:-2], value[-2:]) |
|
|
|
|
|
|
|
|
cValue = "%s.%s.%s-%s" % (value[:-8], value[-8:-5], value[-5:-2], value[-2:]) |
|
|
else: |
|
|
else: |
|
|
cValue = '%s.%s.%s/%s-%s' % (value[:-12], value[-12:-9], |
|
|
|
|
|
value[-9:-6], value[-6:-2], value[-2:]) |
|
|
|
|
|
|
|
|
cValue = "%s.%s.%s/%s-%s" % ( |
|
|
|
|
|
value[:-12], |
|
|
|
|
|
value[-12:-9], |
|
|
|
|
|
value[-9:-6], |
|
|
|
|
|
value[-6:-2], |
|
|
|
|
|
value[-2:], |
|
|
|
|
|
) |
|
|
return cValue |
|
|
return cValue |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def getdateUTC(cDateUTC): |
|
|
def getdateUTC(cDateUTC): |
|
|
cDt = cDateUTC[0:10].split('-') |
|
|
|
|
|
|
|
|
cDt = cDateUTC[0:10].split("-") |
|
|
cDt.reverse() |
|
|
cDt.reverse() |
|
|
return '/'.join(cDt), cDateUTC[11:16] |
|
|
|
|
|
|
|
|
return "/".join(cDt), cDateUTC[11:16] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def format_number(cNumber, precision=0, group_sep='.', decimal_sep=','): |
|
|
|
|
|
|
|
|
def format_number(cNumber, precision=0, group_sep=".", decimal_sep=","): |
|
|
if cNumber: |
|
|
if cNumber: |
|
|
number = float(cNumber) |
|
|
number = float(cNumber) |
|
|
return ("{:,." + str(precision) + "f}").format(number).\ |
|
|
|
|
|
replace(",", "X").replace(".", ",").replace("X", ".") |
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
("{:,." + str(precision) + "f}") |
|
|
|
|
|
.format(number) |
|
|
|
|
|
.replace(",", "X") |
|
|
|
|
|
.replace(".", ",") |
|
|
|
|
|
.replace("X", ".") |
|
|
|
|
|
) |
|
|
return "" |
|
|
return "" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -46,7 +57,7 @@ def tagtext(oNode=None, cTag=None): |
|
|
xpath = ".//{http://www.portalfiscal.inf.br/nfe}%s" % (cTag) |
|
|
xpath = ".//{http://www.portalfiscal.inf.br/nfe}%s" % (cTag) |
|
|
cText = oNode.find(xpath).text |
|
|
cText = oNode.find(xpath).text |
|
|
except: |
|
|
except: |
|
|
cText = '' |
|
|
|
|
|
|
|
|
cText = "" |
|
|
return cText |
|
|
return cText |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -58,24 +69,27 @@ def get_image(path, width=1 * cm): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def format_telefone(telefone): |
|
|
def format_telefone(telefone): |
|
|
telefone = re.sub('[^0-9]', '', telefone) |
|
|
|
|
|
|
|
|
telefone = re.sub("[^0-9]", "", telefone) |
|
|
if len(telefone) == 10: |
|
|
if len(telefone) == 10: |
|
|
telefone = '(%s) %s-%s' % (telefone[0:2], |
|
|
|
|
|
telefone[2:6], |
|
|
|
|
|
telefone[6:]) |
|
|
|
|
|
|
|
|
telefone = "(%s) %s-%s" % (telefone[0:2], telefone[2:6], telefone[6:]) |
|
|
elif len(telefone) == 11: |
|
|
elif len(telefone) == 11: |
|
|
telefone = '(%s) %s-%s' % (telefone[0:2], |
|
|
|
|
|
telefone[2:7], |
|
|
|
|
|
telefone[7:]) |
|
|
|
|
|
|
|
|
telefone = "(%s) %s-%s" % (telefone[0:2], telefone[2:7], telefone[7:]) |
|
|
return telefone |
|
|
return telefone |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class danfce(object): |
|
|
class danfce(object): |
|
|
|
|
|
|
|
|
def __init__(self, list_xml, logo=None, timezone=None): |
|
|
def __init__(self, list_xml, logo=None, timezone=None): |
|
|
|
|
|
|
|
|
|
|
|
dir_fonts = os.path.dirname(os.path.realpath(__file__)) |
|
|
|
|
|
pdfmetrics.registerFont( |
|
|
|
|
|
TTFont( |
|
|
|
|
|
'NimbusSanL-Bold', |
|
|
|
|
|
os.path.join(dir_fonts,'fonts/NimbusSanL Bold.ttf'))) |
|
|
|
|
|
pdfmetrics.registerFont( |
|
|
|
|
|
TTFont( |
|
|
|
|
|
'NimbusSanL-Regu', |
|
|
|
|
|
os.path.join(dir_fonts, 'fonts/NimbusSanL Regular.ttf'))) |
|
|
self.current_font_size = 7 |
|
|
self.current_font_size = 7 |
|
|
self.current_font_name = 'NimbusSanL-Regu' |
|
|
|
|
|
|
|
|
self.current_font_name = "NimbusSanL-Regu" |
|
|
|
|
|
|
|
|
self.max_height = 840 |
|
|
self.max_height = 840 |
|
|
self.min_height = 1 |
|
|
self.min_height = 1 |
|
|
@ -85,8 +99,8 @@ class danfce(object): |
|
|
|
|
|
|
|
|
self.oPDF_IO = BytesIO() |
|
|
self.oPDF_IO = BytesIO() |
|
|
self.canvas = canvas.Canvas(self.oPDF_IO, pagesize=(7.2 * cm, 30 * cm)) |
|
|
self.canvas = canvas.Canvas(self.oPDF_IO, pagesize=(7.2 * cm, 30 * cm)) |
|
|
self.canvas.setTitle('DANFCE') |
|
|
|
|
|
self.canvas.setLineWidth(.5) |
|
|
|
|
|
|
|
|
self.canvas.setTitle("DANFCE") |
|
|
|
|
|
self.canvas.setLineWidth(0.5) |
|
|
self.canvas.setFont(self.current_font_name, self.current_font_size) |
|
|
self.canvas.setFont(self.current_font_name, self.current_font_size) |
|
|
|
|
|
|
|
|
self.list_xml = list_xml |
|
|
self.list_xml = list_xml |
|
|
@ -99,52 +113,69 @@ class danfce(object): |
|
|
elem_emit = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}emit") |
|
|
elem_emit = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}emit") |
|
|
|
|
|
|
|
|
# Razão Social emitente |
|
|
# Razão Social emitente |
|
|
nomeEmpresa = tagtext(oNode=elem_emit, cTag='xFant') |
|
|
|
|
|
|
|
|
nomeEmpresa = tagtext(oNode=elem_emit, cTag="xFant") |
|
|
self.drawTitle(nomeEmpresa, 10) |
|
|
self.drawTitle(nomeEmpresa, 10) |
|
|
|
|
|
|
|
|
if self.logo: |
|
|
if self.logo: |
|
|
img = get_image(self.logo, width=10 * mm) |
|
|
img = get_image(self.logo, width=10 * mm) |
|
|
img.drawOn(self.canvas, 5, 830) |
|
|
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')) |
|
|
|
|
|
|
|
|
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._drawCenteredParagraph(cEnd) |
|
|
self.drawLine() |
|
|
self.drawLine() |
|
|
|
|
|
|
|
|
def danfce_information(self, oXML=None): |
|
|
def danfce_information(self, oXML=None): |
|
|
el_ide = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}ide") |
|
|
el_ide = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}ide") |
|
|
tipo_emissao = tagtext(oNode=el_ide, cTag='tpEmis') |
|
|
|
|
|
if tipo_emissao in ('5', '9'): |
|
|
|
|
|
|
|
|
tipo_emissao = tagtext(oNode=el_ide, cTag="tpEmis") |
|
|
|
|
|
if tipo_emissao in ("5", "9"): |
|
|
self.current_height -= 5 |
|
|
self.current_height -= 5 |
|
|
self.drawTitle("EMITIDA EM CONTINGÊNCIA",9, 'NimbusSanL-Bold') |
|
|
|
|
|
self.drawTitle("Pendente de autorização", 7, 'NimbusSanL-Bold') |
|
|
|
|
|
|
|
|
self.drawTitle("EMITIDA EM CONTINGÊNCIA", 9, "NimbusSanL-Bold") |
|
|
|
|
|
self.drawTitle("Pendente de autorização", 7, "NimbusSanL-Bold") |
|
|
self.drawLine() |
|
|
self.drawLine() |
|
|
else: |
|
|
else: |
|
|
self.drawTitle( |
|
|
self.drawTitle( |
|
|
"DANFE NFC-e - Documento Auxiliar da Nota Fiscal de", |
|
|
"DANFE NFC-e - Documento Auxiliar da Nota Fiscal de", |
|
|
7, 'NimbusSanL-Bold') |
|
|
|
|
|
|
|
|
7, |
|
|
|
|
|
"NimbusSanL-Bold", |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
self.drawTitle("Consumidor Eletrônica", 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.drawString("NFC-e não permite aproveitamento de crédito de ICMS", True) |
|
|
self.drawLine() |
|
|
self.drawLine() |
|
|
|
|
|
|
|
|
def produtos(self, oXML=None, el_det=None, oPaginator=None, |
|
|
|
|
|
list_desc=None, list_cod_prod=None): |
|
|
|
|
|
|
|
|
def produtos( |
|
|
|
|
|
self, |
|
|
|
|
|
oXML=None, |
|
|
|
|
|
el_det=None, |
|
|
|
|
|
oPaginator=None, |
|
|
|
|
|
list_desc=None, |
|
|
|
|
|
list_cod_prod=None, |
|
|
|
|
|
): |
|
|
|
|
|
|
|
|
rows = [['Cód', 'Descrição', 'Qtde', 'Un', 'Unit.', 'Total']] |
|
|
|
|
|
|
|
|
rows = [["Cód", "Descrição", "Qtde", "Un", "Unit.", "Total"]] |
|
|
colWidths = (25, 90, 15, 15, 25, 25) |
|
|
colWidths = (25, 90, 15, 15, 25, 25) |
|
|
rowHeights = [7] |
|
|
rowHeights = [7] |
|
|
|
|
|
|
|
|
@ -153,17 +184,14 @@ class danfce(object): |
|
|
item = el_det[id] |
|
|
item = el_det[id] |
|
|
el_prod = item.find(".//{http://www.portalfiscal.inf.br/nfe}prod") |
|
|
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') |
|
|
|
|
|
descricao = (descricao[:20] + '..') if len(descricao) > 20 else descricao |
|
|
|
|
|
Un = tagtext(oNode=el_prod, cTag='uCom') |
|
|
|
|
|
|
|
|
cod = tagtext(oNode=el_prod, cTag="cProd") |
|
|
|
|
|
descricao = tagtext(oNode=el_prod, cTag="xProd") |
|
|
|
|
|
descricao = (descricao[:20] + "..") if len(descricao) > 20 else descricao |
|
|
|
|
|
Un = tagtext(oNode=el_prod, cTag="uCom") |
|
|
Un = (Un[:2]) if len(Un) > 2 else Un |
|
|
Un = (Un[:2]) if len(Un) > 2 else Un |
|
|
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) |
|
|
|
|
|
|
|
|
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] |
|
|
new_row = [cod, descricao, qtde, Un, vl_unit, vl_total] |
|
|
|
|
|
|
|
|
@ -174,54 +202,57 @@ class danfce(object): |
|
|
|
|
|
|
|
|
def _draw_product_table(self, rows, colWidths, rowHeights): |
|
|
def _draw_product_table(self, rows, colWidths, rowHeights): |
|
|
table = Table(rows, colWidths, tuple(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"), |
|
|
|
|
|
])) |
|
|
|
|
|
|
|
|
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) |
|
|
w, h = table.wrapOn(self.canvas, 200, 450) |
|
|
table.drawOn(self.canvas, 0, self.current_height - (h * 1.2)) |
|
|
table.drawOn(self.canvas, 0, self.current_height - (h * 1.2)) |
|
|
self.current_height -= (h * 1.1) |
|
|
|
|
|
|
|
|
self.current_height -= h * 1.1 |
|
|
|
|
|
|
|
|
def totais(self, oXML=None): |
|
|
def totais(self, oXML=None): |
|
|
# 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( |
|
|
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) |
|
|
|
|
|
|
|
|
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 = tagtext(oNode=el_pag, cTag="vTroco") |
|
|
troco = 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_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 = [] |
|
|
payment_methods = [] |
|
|
for pagId, item in enumerate(el_pag): |
|
|
for pagId, item in enumerate(el_pag): |
|
|
@ -236,13 +267,13 @@ class danfce(object): |
|
|
payment_methods.append(payment) |
|
|
payment_methods.append(payment) |
|
|
|
|
|
|
|
|
values = { |
|
|
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, |
|
|
|
|
|
|
|
|
"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) |
|
|
@ -252,26 +283,30 @@ class danfce(object): |
|
|
def draw_totals_table(self, values): |
|
|
def draw_totals_table(self, values): |
|
|
rowHeights = [7, 7, 7, 7, 7] |
|
|
rowHeights = [7, 7, 7, 7, 7] |
|
|
data = [ |
|
|
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']: |
|
|
|
|
|
|
|
|
["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]]) |
|
|
data.append([item[0], item[1]]) |
|
|
rowHeights.append(7) |
|
|
rowHeights.append(7) |
|
|
data.append(['TROCO', format_number(values['troco'], precision=2)]) |
|
|
|
|
|
|
|
|
data.append(["TROCO", format_number(values["troco"], precision=2)]) |
|
|
rowHeights.append(7) |
|
|
rowHeights.append(7) |
|
|
|
|
|
|
|
|
table2 = Table(data, colWidths=(150, 50), rowHeights=tuple(rowHeights)) |
|
|
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") |
|
|
|
|
|
])) |
|
|
|
|
|
|
|
|
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) |
|
|
w, h = table2.wrapOn(self.canvas, 200, 450) |
|
|
table2.drawOn(self.canvas, 0, self.current_height - (h * 1.1)) |
|
|
table2.drawOn(self.canvas, 0, self.current_height - (h * 1.1)) |
|
|
self.current_height -= h |
|
|
self.current_height -= h |
|
|
@ -281,27 +316,27 @@ class danfce(object): |
|
|
# n nfce, serie e data de solicitacao |
|
|
# n nfce, serie e data de solicitacao |
|
|
el_ide = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}ide") |
|
|
el_ide = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}ide") |
|
|
|
|
|
|
|
|
el_NFeSupl = oXML.find( |
|
|
|
|
|
".//{http://www.portalfiscal.inf.br/nfe}infNFeSupl") |
|
|
|
|
|
|
|
|
el_NFeSupl = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}infNFeSupl") |
|
|
|
|
|
|
|
|
el_dest = el_infNFe.find(".//{http://www.portalfiscal.inf.br/nfe}dest") |
|
|
el_dest = el_infNFe.find(".//{http://www.portalfiscal.inf.br/nfe}dest") |
|
|
# chave, n protocolo, data autorizacao |
|
|
# chave, n protocolo, data autorizacao |
|
|
el_prot_nfe = oXML.find( |
|
|
|
|
|
".//{http://www.portalfiscal.inf.br/nfe}protNFe") |
|
|
|
|
|
|
|
|
el_prot_nfe = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}protNFe") |
|
|
|
|
|
|
|
|
el_infAdic = oXML.find( |
|
|
|
|
|
".//{http://www.portalfiscal.inf.br/nfe}infAdic") |
|
|
|
|
|
|
|
|
el_infAdic = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}infAdic") |
|
|
|
|
|
|
|
|
url_chave = tagtext(oNode=el_NFeSupl, cTag='urlChave') |
|
|
|
|
|
|
|
|
url_chave = tagtext(oNode=el_NFeSupl, cTag="urlChave") |
|
|
access_key = tagtext(oNode=el_prot_nfe, cTag="chNFe") |
|
|
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) |
|
|
|
|
|
|
|
|
frase_chave_acesso = ( |
|
|
|
|
|
"Consulte pela Chave de Acesso em:<br />\ |
|
|
|
|
|
%s<br />%s" |
|
|
|
|
|
% (url_chave, access_key) |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
qrcode = tagtext(oNode=el_NFeSupl, cTag='qrCode') |
|
|
|
|
|
|
|
|
qrcode = tagtext(oNode=el_NFeSupl, cTag="qrCode") |
|
|
|
|
|
|
|
|
cnpj = tagtext(oNode=el_dest, cTag='CNPJ') |
|
|
|
|
|
cpf = tagtext(oNode=el_dest, cTag='CPF') |
|
|
|
|
|
|
|
|
cnpj = tagtext(oNode=el_dest, cTag="CNPJ") |
|
|
|
|
|
cpf = tagtext(oNode=el_dest, cTag="CPF") |
|
|
if cnpj: |
|
|
if cnpj: |
|
|
cnpj_cpf = format_cnpj_cpf(cnpj) |
|
|
cnpj_cpf = format_cnpj_cpf(cnpj) |
|
|
cnpj_cpf = "CONSUMIDOR CNPJ: %s" % (cnpj) |
|
|
cnpj_cpf = "CONSUMIDOR CNPJ: %s" % (cnpj) |
|
|
@ -312,45 +347,53 @@ class danfce(object): |
|
|
cnpj_cpf = u"CONSUMIDOR NÃO IDENTIFICADO" |
|
|
cnpj_cpf = u"CONSUMIDOR NÃO IDENTIFICADO" |
|
|
|
|
|
|
|
|
nNFC = tagtext(oNode=el_ide, cTag="nNF") |
|
|
nNFC = tagtext(oNode=el_ide, cTag="nNF") |
|
|
serie = tagtext(oNode=el_ide, cTag='serie') |
|
|
|
|
|
|
|
|
serie = tagtext(oNode=el_ide, cTag="serie") |
|
|
|
|
|
|
|
|
dataSolicitacao = getdateUTC(tagtext(oNode=el_ide, cTag="dhEmi")) |
|
|
dataSolicitacao = getdateUTC(tagtext(oNode=el_ide, cTag="dhEmi")) |
|
|
dataSolicitacao = dataSolicitacao[0] + " " + dataSolicitacao[1] |
|
|
dataSolicitacao = dataSolicitacao[0] + " " + dataSolicitacao[1] |
|
|
|
|
|
|
|
|
text = u"%s <br />%s <br />NFC-e nº%s Série %s %s<br />" % ( |
|
|
text = u"%s <br />%s <br />NFC-e nº%s Série %s %s<br />" % ( |
|
|
frase_chave_acesso, cnpj_cpf, nNFC, serie, dataSolicitacao) |
|
|
|
|
|
|
|
|
frase_chave_acesso, |
|
|
|
|
|
cnpj_cpf, |
|
|
|
|
|
nNFC, |
|
|
|
|
|
serie, |
|
|
|
|
|
dataSolicitacao, |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
self._drawCenteredParagraph(text) |
|
|
self._drawCenteredParagraph(text) |
|
|
|
|
|
|
|
|
tipo_emissao = tagtext(oNode=el_ide, cTag='tpEmis') |
|
|
|
|
|
if tipo_emissao in ('5', '9'): |
|
|
|
|
|
|
|
|
tipo_emissao = tagtext(oNode=el_ide, cTag="tpEmis") |
|
|
|
|
|
if tipo_emissao in ("5", "9"): |
|
|
self.current_height -= 8 |
|
|
self.current_height -= 8 |
|
|
self.drawTitle("EMITIDA EM CONTINGÊNCIA",9, 'NimbusSanL-Bold') |
|
|
|
|
|
self.drawTitle("Pendente de autorização - Via Consumidor", 7, 'NimbusSanL-Bold') |
|
|
|
|
|
|
|
|
self.drawTitle("EMITIDA EM CONTINGÊNCIA", 9, "NimbusSanL-Bold") |
|
|
|
|
|
self.drawTitle( |
|
|
|
|
|
"Pendente de autorização - Via Consumidor", 7, "NimbusSanL-Bold" |
|
|
|
|
|
) |
|
|
else: |
|
|
else: |
|
|
numProtocolo = tagtext(oNode=el_prot_nfe, cTag="nProt") |
|
|
numProtocolo = tagtext(oNode=el_prot_nfe, cTag="nProt") |
|
|
|
|
|
|
|
|
dataAutorizacao = getdateUTC(tagtext(oNode=el_prot_nfe, |
|
|
|
|
|
cTag='dhRecbto')) |
|
|
|
|
|
|
|
|
dataAutorizacao = getdateUTC(tagtext(oNode=el_prot_nfe, cTag="dhRecbto")) |
|
|
dataAutorizacao = dataAutorizacao[0] + " " + dataAutorizacao[1] |
|
|
dataAutorizacao = dataAutorizacao[0] + " " + dataAutorizacao[1] |
|
|
|
|
|
|
|
|
text = "Protocolo de autorização: %s<br />Data de autorização %s<br />" % ( |
|
|
text = "Protocolo de autorização: %s<br />Data de autorização %s<br />" % ( |
|
|
numProtocolo, dataAutorizacao) |
|
|
|
|
|
|
|
|
numProtocolo, |
|
|
|
|
|
dataAutorizacao, |
|
|
|
|
|
) |
|
|
self._drawCenteredParagraph(text) |
|
|
self._drawCenteredParagraph(text) |
|
|
|
|
|
|
|
|
self.draw_qr_code(qrcode) |
|
|
self.draw_qr_code(qrcode) |
|
|
|
|
|
|
|
|
infAdFisco = tagtext(oNode=el_infAdic, cTag='infAdFisco') |
|
|
|
|
|
|
|
|
infAdFisco = tagtext(oNode=el_infAdic, cTag="infAdFisco") |
|
|
self._drawCenteredParagraph(infAdFisco) |
|
|
self._drawCenteredParagraph(infAdFisco) |
|
|
|
|
|
|
|
|
infCpl = tagtext(oNode=el_infAdic, cTag='infCpl') |
|
|
|
|
|
|
|
|
infCpl = tagtext(oNode=el_infAdic, cTag="infCpl") |
|
|
self._drawCenteredParagraph(infCpl) |
|
|
self._drawCenteredParagraph(infCpl) |
|
|
|
|
|
|
|
|
def _drawCenteredParagraph(self, text): |
|
|
def _drawCenteredParagraph(self, text): |
|
|
|
|
|
|
|
|
style = ParagraphStyle( |
|
|
style = ParagraphStyle( |
|
|
name='Normal', |
|
|
|
|
|
fontName='NimbusSanL-Regu', |
|
|
|
|
|
|
|
|
name="Normal", |
|
|
|
|
|
fontName="NimbusSanL-Regu", |
|
|
fontSize=7, |
|
|
fontSize=7, |
|
|
alignment=TA_CENTER, |
|
|
alignment=TA_CENTER, |
|
|
leading=7, |
|
|
leading=7, |
|
|
@ -359,27 +402,28 @@ class danfce(object): |
|
|
paragraph = Paragraph(text, style=style) |
|
|
paragraph = Paragraph(text, style=style) |
|
|
w, h = paragraph.wrapOn(self.canvas, 180, 300) |
|
|
w, h = paragraph.wrapOn(self.canvas, 180, 300) |
|
|
paragraph.drawOn(self.canvas, 10, self.current_height - h) |
|
|
paragraph.drawOn(self.canvas, 10, self.current_height - h) |
|
|
self.current_height -= (h*1.1) |
|
|
|
|
|
|
|
|
self.current_height -= h * 1.1 |
|
|
|
|
|
|
|
|
def drawString(self, string, centered=False): |
|
|
def drawString(self, string, centered=False): |
|
|
if centered: |
|
|
if centered: |
|
|
self.canvas.drawCentredString( |
|
|
self.canvas.drawCentredString( |
|
|
self.max_width / 2, self.current_height, string) |
|
|
|
|
|
|
|
|
self.max_width / 2, self.current_height, string |
|
|
|
|
|
) |
|
|
self.current_height -= self.current_font_size |
|
|
self.current_height -= self.current_font_size |
|
|
else: |
|
|
else: |
|
|
self.canvas.drawString(self.min_width, self.current_height, string) |
|
|
self.canvas.drawString(self.min_width, self.current_height, string) |
|
|
self.current_height -= self.current_font_size |
|
|
self.current_height -= self.current_font_size |
|
|
|
|
|
|
|
|
def drawTitle(self, string, size, font='NimbusSanL-Regu'): |
|
|
|
|
|
|
|
|
def drawTitle(self, string, size, font="NimbusSanL-Regu"): |
|
|
self.canvas.setFont(font, size) |
|
|
self.canvas.setFont(font, size) |
|
|
self.canvas.drawCentredString( |
|
|
|
|
|
self.max_width / 2, self.current_height, string) |
|
|
|
|
|
|
|
|
self.canvas.drawCentredString(self.max_width / 2, self.current_height, string) |
|
|
self.current_height -= self.current_font_size |
|
|
self.current_height -= self.current_font_size |
|
|
self.canvas.setFont(self.current_font_name, self.current_font_size) |
|
|
self.canvas.setFont(self.current_font_name, self.current_font_size) |
|
|
|
|
|
|
|
|
def drawLine(self): |
|
|
def drawLine(self): |
|
|
self.canvas.line(self.min_width, self.current_height, |
|
|
|
|
|
self.max_width, self.current_height) |
|
|
|
|
|
|
|
|
self.canvas.line( |
|
|
|
|
|
self.min_width, self.current_height, self.max_width, self.current_height |
|
|
|
|
|
) |
|
|
self.current_height -= self.current_font_size |
|
|
self.current_height -= self.current_font_size |
|
|
|
|
|
|
|
|
def draw_qr_code(self, string): |
|
|
def draw_qr_code(self, string): |
|
|
@ -396,8 +440,7 @@ class danfce(object): |
|
|
|
|
|
|
|
|
def nfce_generate(self): |
|
|
def nfce_generate(self): |
|
|
for oXML in self.list_xml: |
|
|
for oXML in self.list_xml: |
|
|
oXML_cobr = oXML.find( |
|
|
|
|
|
".//{http://www.portalfiscal.inf.br/nfe}cobr") |
|
|
|
|
|
|
|
|
oXML_cobr = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}cobr") |
|
|
|
|
|
|
|
|
self.NrPages = 1 |
|
|
self.NrPages = 1 |
|
|
self.Page = 1 |
|
|
self.Page = 1 |
|
|
@ -413,17 +456,17 @@ class danfce(object): |
|
|
list_cod_prod = [] |
|
|
list_cod_prod = [] |
|
|
nPg = 0 |
|
|
nPg = 0 |
|
|
for nId, item in enumerate(el_det): |
|
|
for nId, item in enumerate(el_det): |
|
|
el_prod = item.find( |
|
|
|
|
|
".//{http://www.portalfiscal.inf.br/nfe}prod") |
|
|
|
|
|
|
|
|
el_prod = item.find(".//{http://www.portalfiscal.inf.br/nfe}prod") |
|
|
infAdProd = item.find( |
|
|
infAdProd = item.find( |
|
|
".//{http://www.portalfiscal.inf.br/nfe}infAdProd") |
|
|
|
|
|
|
|
|
".//{http://www.portalfiscal.inf.br/nfe}infAdProd" |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
list_ = wrap(tagtext(oNode=el_prod, cTag='xProd'), 56) |
|
|
|
|
|
|
|
|
list_ = wrap(tagtext(oNode=el_prod, cTag="xProd"), 56) |
|
|
if infAdProd is not None: |
|
|
if infAdProd is not None: |
|
|
list_.extend(wrap(infAdProd.text, 56)) |
|
|
list_.extend(wrap(infAdProd.text, 56)) |
|
|
list_desc.append(list_) |
|
|
list_desc.append(list_) |
|
|
|
|
|
|
|
|
list_cProd = wrap(tagtext(oNode=el_prod, cTag='cProd'), 14) |
|
|
|
|
|
|
|
|
list_cProd = wrap(tagtext(oNode=el_prod, cTag="cProd"), 14) |
|
|
list_cod_prod.append(list_cProd) |
|
|
list_cod_prod.append(list_cProd) |
|
|
|
|
|
|
|
|
# Nr linhas necessárias p/ descrição item |
|
|
# Nr linhas necessárias p/ descrição item |
|
|
@ -440,14 +483,19 @@ class danfce(object): |
|
|
oPaginator[nPg][1] = nId + 1 |
|
|
oPaginator[nPg][1] = nId + 1 |
|
|
oPaginator[nPg][2] += nLin_Itens |
|
|
oPaginator[nPg][2] += nLin_Itens |
|
|
|
|
|
|
|
|
self.NrPages = len(oPaginator) # Calculando nr. páginas |
|
|
|
|
|
|
|
|
self.NrPages = len(oPaginator) # Calculando nr. páginas |
|
|
|
|
|
|
|
|
self.ide_emit(oXML=oXML) |
|
|
self.ide_emit(oXML=oXML) |
|
|
# self.destinatario(oXML=oXML) |
|
|
# self.destinatario(oXML=oXML) |
|
|
self.danfce_information(oXML=oXML) |
|
|
self.danfce_information(oXML=oXML) |
|
|
|
|
|
|
|
|
self.produtos(oXML=oXML, el_det=el_det, oPaginator=oPaginator[0], |
|
|
|
|
|
list_desc=list_desc, list_cod_prod=list_cod_prod) |
|
|
|
|
|
|
|
|
self.produtos( |
|
|
|
|
|
oXML=oXML, |
|
|
|
|
|
el_det=el_det, |
|
|
|
|
|
oPaginator=oPaginator[0], |
|
|
|
|
|
list_desc=list_desc, |
|
|
|
|
|
list_cod_prod=list_cod_prod, |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
self.drawLine() |
|
|
self.drawLine() |
|
|
|
|
|
|
|
|
@ -461,9 +509,13 @@ class danfce(object): |
|
|
self.newpage() |
|
|
self.newpage() |
|
|
self.ide_emit(oXML=oXML) |
|
|
self.ide_emit(oXML=oXML) |
|
|
# self.destinatario(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.produtos( |
|
|
|
|
|
oXML=oXML, |
|
|
|
|
|
el_det=el_det, |
|
|
|
|
|
oPaginator=oPag, |
|
|
|
|
|
list_desc=list_desc, |
|
|
|
|
|
list_cod_prod=list_cod_prod, |
|
|
|
|
|
) |
|
|
self.totais(oXML=oXML) |
|
|
self.totais(oXML=oXML) |
|
|
self.inf_authentication(oXML=oXML) |
|
|
self.inf_authentication(oXML=oXML) |
|
|
|
|
|
|
|
|
|