Browse Source
Merge pull request #40 from danimaribeiro/feature/danfe
Merge pull request #40 from danimaribeiro/feature/danfe
Impressão de danfe através do reportlabpull/45/head
committed by
GitHub
5 changed files with 881 additions and 1 deletions
-
810pytrustnfe/nfe/danfe.py
-
46pytrustnfe/test/XMLs/NFe00000857.xml
-
22pytrustnfe/test/test_danfe.py
-
1requirements.txt
-
3setup.py
@ -0,0 +1,810 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2017 Edson Bernardino, ITK Soft |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
# Classe para geração de PDF da DANFE a partir de xml etree.fromstring |
||||
|
|
||||
|
|
||||
|
from cStringIO import StringIO as IO |
||||
|
from textwrap import wrap |
||||
|
|
||||
|
from reportlab.lib import utils |
||||
|
from reportlab.pdfgen import canvas |
||||
|
from reportlab.lib.units import mm, cm |
||||
|
from reportlab.lib.pagesizes import A4 |
||||
|
from reportlab.lib.colors import black, gray |
||||
|
from reportlab.graphics.barcode import code128 |
||||
|
from reportlab.lib.styles import getSampleStyleSheet |
||||
|
from reportlab.lib.enums import TA_CENTER |
||||
|
from reportlab.platypus import Paragraph, Image |
||||
|
|
||||
|
|
||||
|
def chunks(cString, nLen): |
||||
|
for start in range(0, len(cString), nLen): |
||||
|
yield cString[start:start+nLen] |
||||
|
|
||||
|
|
||||
|
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 |
||||
|
|
||||
|
REGIME_TRIBUTACAO = { |
||||
|
'1': 'Simples Nacional', |
||||
|
'2': 'Simples Nacional, excesso sublimite de receita bruta', |
||||
|
'3': 'Regime Normal' |
||||
|
} |
||||
|
|
||||
|
|
||||
|
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)) |
||||
|
|
||||
|
|
||||
|
class danfe(object): |
||||
|
def __init__(self, sizepage=A4, list_xml=None, recibo=True, |
||||
|
orientation='portrait', logo=None): |
||||
|
self.width = 210 # 21 x 29,7cm |
||||
|
self.height = 297 |
||||
|
self.nLeft = 10 |
||||
|
self.nRight = 10 |
||||
|
self.nTop = 7 |
||||
|
self.nBottom = 15 |
||||
|
self.nlin = self.nTop |
||||
|
self.logo = logo |
||||
|
self.oFrete = {'0': '0 - Emitente', |
||||
|
'1': '1 - Dest/Remet', |
||||
|
'2': '2 - Terceiros', |
||||
|
'9': '9 - Sem Frete'} |
||||
|
|
||||
|
self.oPDF_IO = IO() |
||||
|
if orientation == 'landscape': |
||||
|
raise NameError('Rotina não implementada') |
||||
|
else: |
||||
|
size = sizepage |
||||
|
|
||||
|
self.canvas = canvas.Canvas(self.oPDF_IO, pagesize=size) |
||||
|
self.canvas.setTitle('DANFE') |
||||
|
self.canvas.setStrokeColor(black) |
||||
|
|
||||
|
for oXML in 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 29 |
||||
|
# [ 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 = [] |
||||
|
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'), 51) |
||||
|
if infAdProd is not None: |
||||
|
list_.extend(wrap(infAdProd.text, 51)) |
||||
|
list_desc.append(list_) |
||||
|
|
||||
|
# 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 |
||||
|
|
||||
|
if recibo: |
||||
|
self.recibo_entrega(oXML=oXML) |
||||
|
|
||||
|
self.ide_emit(oXML=oXML) |
||||
|
self.destinatario(oXML=oXML) |
||||
|
|
||||
|
if oXML_cobr is not None: |
||||
|
self.faturas(oXML=oXML_cobr) |
||||
|
|
||||
|
self.impostos(oXML=oXML) |
||||
|
self.transportes(oXML=oXML) |
||||
|
self.produtos(oXML=oXML, el_det=el_det, oPaginator=oPaginator[0], |
||||
|
list_desc=list_desc) |
||||
|
|
||||
|
self.adicionais(oXML=oXML) |
||||
|
|
||||
|
# Gera o restante das páginas do XML |
||||
|
for oPag in oPaginator[1:]: |
||||
|
self.newpage() |
||||
|
self.ide_emit(oXML=oXML) |
||||
|
self.produtos(oXML=oXML, el_det=el_det, oPaginator=oPag, |
||||
|
list_desc=list_desc, nHeight=77) |
||||
|
|
||||
|
self.newpage() |
||||
|
|
||||
|
self.canvas.save() |
||||
|
|
||||
|
def ide_emit(self, oXML=None): |
||||
|
elem_infNFe = oXML.find( |
||||
|
".//{http://www.portalfiscal.inf.br/nfe}infNFe") |
||||
|
elem_protNFe = oXML.find( |
||||
|
".//{http://www.portalfiscal.inf.br/nfe}protNFe") |
||||
|
elem_emit = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}emit") |
||||
|
elem_ide = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}ide") |
||||
|
|
||||
|
cChave = elem_infNFe.attrib.get('Id')[3:] |
||||
|
barcode128 = code128.Code128(cChave, barHeight=10*mm, barWidth=0.25*mm) |
||||
|
|
||||
|
self.canvas.setLineWidth(.5) |
||||
|
self.rect(self.nLeft, self.nlin+1, self.nLeft+75, 32) |
||||
|
self.rect(self.nLeft+115, self.nlin+1, |
||||
|
self.width-self.nLeft-self.nRight-115, 39) |
||||
|
|
||||
|
self.rect(self.nLeft+116, self.nlin+15, |
||||
|
self.width-self.nLeft-self.nRight-117, 6) |
||||
|
|
||||
|
self.rect(self.nLeft, self.nlin+33, |
||||
|
self.width-self.nLeft-self.nRight, 14) |
||||
|
self.hline(self.nLeft, self.nlin+40, self.width-self.nRight) |
||||
|
self.vline(self.nLeft+60, self.nlin+40, 7) |
||||
|
self.vline(self.nLeft+100, self.nlin+40, 7) |
||||
|
|
||||
|
# Labels |
||||
|
self.canvas.setFont('NimbusSanL-Bold', 12) |
||||
|
self.stringcenter(self.nLeft+98, self.nlin+4, 'DANFE') |
||||
|
self.stringcenter(self.nLeft+109, self.nlin+19.5, |
||||
|
tagtext(oNode=elem_ide, cTag='tpNF')) |
||||
|
self.canvas.setFont('NimbusSanL-Bold', 8) |
||||
|
cNF = tagtext(oNode=elem_ide, cTag='nNF') |
||||
|
cNF = '{0:011,}'.format(int(cNF)).replace(",", ".") |
||||
|
self.stringcenter(self.nLeft+100, self.nlin+25, "Nº %s" % (cNF)) |
||||
|
|
||||
|
self.stringcenter(self.nLeft+100, self.nlin+29, u"SÉRIE %s" % ( |
||||
|
tagtext(oNode=elem_ide, cTag='serie'))) |
||||
|
cPag = "Página %s de %s" % (str(self.Page), str(self.NrPages)) |
||||
|
self.stringcenter(self.nLeft+100, self.nlin+32, cPag) |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 6) |
||||
|
self.string(self.nLeft+86, self.nlin+8, 'Documento Auxiliar da') |
||||
|
self.string(self.nLeft+86, self.nlin+10.5, 'Nota Fiscal Eletrônica') |
||||
|
self.string(self.nLeft+86, self.nlin+16, '0 - Entrada') |
||||
|
self.string(self.nLeft+86, self.nlin+19, '1 - Saída') |
||||
|
self.rect(self.nLeft+105, self.nlin+15, 8, 6) |
||||
|
|
||||
|
self.stringcenter( |
||||
|
self.nLeft+152, self.nlin+25, |
||||
|
'Consulta de autenticidade no portal nacional da NF-e') |
||||
|
self.stringcenter( |
||||
|
self.nLeft+152, self.nlin+28, |
||||
|
'www.nfe.fazenda.gov.br/portal ou no site da SEFAZ Autorizadora') |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 5) |
||||
|
self.string(self.nLeft+117, self.nlin+16.7, 'CHAVE DE ACESSO') |
||||
|
self.string(self.nLeft+116, self.nlin+2.7, 'CONTROLE DO FISCO') |
||||
|
|
||||
|
self.string(self.nLeft+1, self.nlin+34.7, 'NATUREZA DA OPERAÇÃO') |
||||
|
self.string(self.nLeft+116, self.nlin+34.7, |
||||
|
'PROTOCOLO DE AUTORIZAÇÃO DE USO') |
||||
|
self.string(self.nLeft+1, self.nlin+41.7, 'INSCRIÇÃO ESTADUAL') |
||||
|
self.string(self.nLeft+61, self.nlin+41.7, |
||||
|
'INSCRIÇÃO ESTADUAL DO SUBST. TRIB.') |
||||
|
self.string(self.nLeft+101, self.nlin+41.7, 'CNPJ') |
||||
|
|
||||
|
# Conteúdo campos |
||||
|
barcode128.drawOn(self.canvas, (self.nLeft+111.5)*mm, |
||||
|
(self.height-self.nlin-14)*mm) |
||||
|
self.canvas.setFont('NimbusSanL-Bold', 6) |
||||
|
nW_Rect = (self.width-self.nLeft-self.nRight-117) / 2 |
||||
|
self.stringcenter(self.nLeft+116.5+nW_Rect, self.nlin+19.5, |
||||
|
' '.join(chunks(cChave, 4))) # Chave |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 8) |
||||
|
cDt, cHr = getdateUTC(tagtext(oNode=elem_protNFe, cTag='dhRecbto')) |
||||
|
cProtocolo = tagtext(oNode=elem_protNFe, cTag='nProt') |
||||
|
cDt = cProtocolo + ' - ' + cDt + ' ' + cHr |
||||
|
nW_Rect = (self.width-self.nLeft-self.nRight-110) / 2 |
||||
|
self.stringcenter(self.nLeft+115+nW_Rect, self.nlin+38.7, cDt) |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 8) |
||||
|
self.string(self.nLeft+1, self.nlin+38.7, |
||||
|
tagtext(oNode=elem_ide, cTag='natOp')) |
||||
|
self.string(self.nLeft+1, self.nlin+46, |
||||
|
tagtext(oNode=elem_emit, cTag='IE')) |
||||
|
self.string(self.nLeft+101, self.nlin+46, |
||||
|
format_cnpj_cpf(tagtext(oNode=elem_emit, cTag='CNPJ'))) |
||||
|
|
||||
|
styles = getSampleStyleSheet() |
||||
|
styleN = styles['Normal'] |
||||
|
styleN.fontSize = 10 |
||||
|
styleN.fontName = 'NimbusSanL-Bold' |
||||
|
styleN.alignment = TA_CENTER |
||||
|
|
||||
|
# Razão Social emitente |
||||
|
P = Paragraph(tagtext(oNode=elem_emit, cTag='xNome'), styleN) |
||||
|
w, h = P.wrap(55*mm, 50*mm) |
||||
|
P.drawOn(self.canvas, (self.nLeft+30)*mm, |
||||
|
(self.height-self.nlin-12)*mm) |
||||
|
|
||||
|
if self.logo: |
||||
|
img = get_image(self.logo, width=2*cm) |
||||
|
img.drawOn(self.canvas, (self.nLeft+5)*mm, |
||||
|
(self.height-self.nlin-22)*mm) |
||||
|
|
||||
|
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 += 'Fone: ' + tagtext(oNode=elem_emit, cTag='fone') + '<br />' |
||||
|
cEnd += tagtext(oNode=elem_emit, cTag='UF') + ' - ' + tagtext( |
||||
|
oNode=elem_emit, cTag='CEP') |
||||
|
|
||||
|
regime = tagtext(oNode=elem_emit, cTag='CRT') |
||||
|
cEnd += u'<br />Regime Tributário: %s' % (REGIME_TRIBUTACAO[regime]) |
||||
|
|
||||
|
styleN.fontName = 'NimbusSanL-Regu' |
||||
|
styleN.fontSize = 7 |
||||
|
styleN.leading = 10 |
||||
|
P = Paragraph(cEnd, styleN) |
||||
|
w, h = P.wrap(55*mm, 30*mm) |
||||
|
P.drawOn(self.canvas, (self.nLeft+30)*mm, |
||||
|
(self.height-self.nlin-31)*mm) |
||||
|
|
||||
|
# Homologação |
||||
|
if tagtext(oNode=elem_ide, cTag='tpAmb') == '2': |
||||
|
self.canvas.saveState() |
||||
|
self.canvas.rotate(90) |
||||
|
self.canvas.setFont('Times-Bold', 40) |
||||
|
self.canvas.setFillColorRGB(0.57, 0.57, 0.57) |
||||
|
self.string(self.nLeft+65, 449, 'SEM VALOR FISCAL') |
||||
|
self.canvas.restoreState() |
||||
|
|
||||
|
self.nlin += 48 |
||||
|
|
||||
|
def destinatario(self, oXML=None): |
||||
|
elem_ide = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}ide") |
||||
|
elem_dest = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}dest") |
||||
|
nMr = self.width-self.nRight |
||||
|
|
||||
|
self.nlin += 1 |
||||
|
|
||||
|
self.canvas.setFont('NimbusSanL-Bold', 7) |
||||
|
self.string(self.nLeft+1, self.nlin+1, 'DESTINATÁRIO/REMETENTE') |
||||
|
self.rect(self.nLeft, self.nlin+2, |
||||
|
self.width-self.nLeft-self.nRight, 20) |
||||
|
self.vline(nMr-25, self.nlin+2, 20) |
||||
|
self.hline(self.nLeft, self.nlin+8.66, self.width-self.nLeft) |
||||
|
self.hline(self.nLeft, self.nlin+15.32, self.width-self.nLeft) |
||||
|
self.vline(nMr-70, self.nlin+2, 6.66) |
||||
|
self.vline(nMr-53, self.nlin+8.66, 6.66) |
||||
|
self.vline(nMr-99, self.nlin+8.66, 6.66) |
||||
|
self.vline(nMr-90, self.nlin+15.32, 6.66) |
||||
|
self.vline(nMr-102, self.nlin+15.32, 6.66) |
||||
|
self.vline(nMr-136, self.nlin+15.32, 6.66) |
||||
|
# Labels/Fields |
||||
|
self.canvas.setFont('NimbusSanL-Bold', 5) |
||||
|
self.string(self.nLeft+1, self.nlin+3.7, 'NOME/RAZÃO SOCIAL') |
||||
|
self.string(nMr-69, self.nlin+3.7, 'CNPJ/CPF') |
||||
|
self.string(nMr-24, self.nlin+3.7, 'DATA DA EMISSÃO') |
||||
|
self.string(self.nLeft+1, self.nlin+10.3, 'ENDEREÇO') |
||||
|
self.string(nMr-98, self.nlin+10.3, 'BAIRRO/DISTRITO') |
||||
|
self.string(nMr-52, self.nlin+10.3, 'CEP') |
||||
|
self.string(nMr-24, self.nlin+10.3, 'DATA DE ENTRADA/SAÍDA') |
||||
|
self.string(self.nLeft+1, self.nlin+17.1, 'MUNICÍPIO') |
||||
|
self.string(nMr-135, self.nlin+17.1, 'FONE/FAX') |
||||
|
self.string(nMr-101, self.nlin+17.1, 'UF') |
||||
|
self.string(nMr-89, self.nlin+17.1, 'INSCRIÇÃO ESTADUAL') |
||||
|
self.string(nMr-24, self.nlin+17.1, 'HORA DE ENTRADA/SAÍDA') |
||||
|
# Conteúdo campos |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 8) |
||||
|
self.string(self.nLeft+1, self.nlin+7.5, |
||||
|
tagtext(oNode=elem_dest, cTag='xNome')) |
||||
|
self.string(nMr-69, self.nlin+7.5, |
||||
|
format_cnpj_cpf(tagtext(oNode=elem_dest, cTag='CNPJ'))) |
||||
|
cDt, cHr = getdateUTC(tagtext(oNode=elem_ide, cTag='dhEmi')) |
||||
|
self.string(nMr-24, self.nlin+7.7, cDt) |
||||
|
cDt, cHr = getdateUTC(tagtext(oNode=elem_ide, cTag='dhSaiEnt')) |
||||
|
self.string(nMr-24, self.nlin+14.3, cDt) # Dt saída |
||||
|
cEnd = tagtext(oNode=elem_dest, cTag='xLgr') + ', ' + tagtext( |
||||
|
oNode=elem_dest, cTag='nro') |
||||
|
self.string(self.nLeft+1, self.nlin+14.3, cEnd) |
||||
|
self.string(nMr-98, self.nlin+14.3, |
||||
|
tagtext(oNode=elem_dest, cTag='xBairro')) |
||||
|
self.string(nMr-52, self.nlin+14.3, |
||||
|
tagtext(oNode=elem_dest, cTag='CEP')) |
||||
|
self.string(self.nLeft+1, self.nlin+21.1, |
||||
|
tagtext(oNode=elem_dest, cTag='xMun')) |
||||
|
self.string(nMr-135, self.nlin+21.1, |
||||
|
tagtext(oNode=elem_dest, cTag='fone')) |
||||
|
self.string(nMr-101, self.nlin+21.1, |
||||
|
tagtext(oNode=elem_dest, cTag='UF')) |
||||
|
self.string(nMr-89, self.nlin+21.1, |
||||
|
tagtext(oNode=elem_dest, cTag='IE')) |
||||
|
|
||||
|
self.nlin += 24 # Nr linhas ocupadas pelo bloco |
||||
|
|
||||
|
def faturas(self, oXML=None): |
||||
|
|
||||
|
nMr = self.width-self.nRight |
||||
|
|
||||
|
self.canvas.setFont('NimbusSanL-Bold', 7) |
||||
|
self.string(self.nLeft+1, self.nlin+1, 'FATURA') |
||||
|
self.rect(self.nLeft, self.nlin+2, |
||||
|
self.width-self.nLeft-self.nRight, 13) |
||||
|
self.vline(nMr-47.5, self.nlin+2, 13) |
||||
|
self.vline(nMr-95, self.nlin+2, 13) |
||||
|
self.vline(nMr-142.5, self.nlin+2, 13) |
||||
|
self.hline(nMr-47.5, self.nlin+8.5, self.width-self.nLeft) |
||||
|
# Labels |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 5) |
||||
|
self.string(nMr-46.5, self.nlin+3.8, 'CÓDIGO VENDEDOR') |
||||
|
self.string(nMr-46.5, self.nlin+10.2, 'NOME VENDEDOR') |
||||
|
self.string(nMr-93.5, self.nlin+3.8, |
||||
|
'FATURA VENCIMENTO VALOR') |
||||
|
self.string(nMr-140.5, self.nlin+3.8, |
||||
|
'FATURA VENCIMENTO VALOR') |
||||
|
self.string(self.nLeft+2, self.nlin+3.8, |
||||
|
'FATURA VENCIMENTO VALOR') |
||||
|
|
||||
|
# Conteúdo campos |
||||
|
self.canvas.setFont('NimbusSanL-Bold', 6) |
||||
|
nLin = 7 |
||||
|
nPar = 1 |
||||
|
nCol = 0 |
||||
|
nAju = 0 |
||||
|
|
||||
|
line_iter = iter(oXML[1:10]) # Salta elemt 1 e considera os próximos 9 |
||||
|
for oXML_dup in line_iter: |
||||
|
|
||||
|
cDt, cHr = getdateUTC(tagtext(oNode=oXML_dup, cTag='dVenc')) |
||||
|
self.string(self.nLeft+nCol+1, self.nlin+nLin, |
||||
|
tagtext(oNode=oXML_dup, cTag='nDup')) |
||||
|
self.string(self.nLeft+nCol+17, self.nlin+nLin, cDt) |
||||
|
self.stringRight( |
||||
|
self.nLeft+nCol+47, self.nlin+nLin, |
||||
|
format_number(tagtext(oNode=oXML_dup, cTag='vDup'), |
||||
|
precision=2)) |
||||
|
|
||||
|
if nPar == 3: |
||||
|
nLin = 7 |
||||
|
nPar = 1 |
||||
|
nCol += 47 |
||||
|
nAju += 1 |
||||
|
nCol += nAju * (0.3) |
||||
|
else: |
||||
|
nLin += 3.3 |
||||
|
nPar += 1 |
||||
|
|
||||
|
# Campos adicionais XML - Condicionados a existencia de financeiro |
||||
|
elem_infAdic = oXML.getparent().find( |
||||
|
".//{http://www.portalfiscal.inf.br/nfe}infAdic") |
||||
|
if elem_infAdic is not None: |
||||
|
codvend = elem_infAdic.find( |
||||
|
".//{http://www.portalfiscal.inf.br/nfe}obsCont\ |
||||
|
[@xCampo='CodVendedor']") |
||||
|
self.string(nMr-46.5, self.nlin+7.7, |
||||
|
tagtext(oNode=codvend, cTag='xTexto')) |
||||
|
vend = elem_infAdic.find(".//{http://www.portalfiscal.inf.br/nfe}\ |
||||
|
obsCont[@xCampo='NomeVendedor']") |
||||
|
self.string(nMr-46.5, self.nlin+14.3, |
||||
|
tagtext(oNode=vend, cTag='xTexto')[:36]) |
||||
|
|
||||
|
self.nlin += 16 # Nr linhas ocupadas pelo bloco |
||||
|
|
||||
|
def impostos(self, oXML=None): |
||||
|
# Impostos |
||||
|
el_total = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}total") |
||||
|
nMr = self.width-self.nRight |
||||
|
self.nlin += 1 |
||||
|
self.canvas.setFont('NimbusSanL-Bold', 7) |
||||
|
self.string(self.nLeft+1, self.nlin+1, 'CÁLCULO DO IMPOSTO') |
||||
|
self.rect(self.nLeft, self.nlin+2, |
||||
|
self.width-self.nLeft-self.nRight, 13) |
||||
|
self.hline(self.nLeft, self.nlin+8.5, self.width-self.nLeft) |
||||
|
self.vline(nMr-35, self.nlin+2, 6.5) |
||||
|
self.vline(nMr-72, self.nlin+2, 6.5) |
||||
|
self.vline(nMr-110, self.nlin+2, 6.5) |
||||
|
self.vline(nMr-148, self.nlin+2, 6.5) |
||||
|
self.vline(nMr-35, self.nlin+8.5, 6.5) |
||||
|
self.vline(nMr-66, self.nlin+8.5, 6.5) |
||||
|
self.vline(nMr-90, self.nlin+8.5, 6.5) |
||||
|
self.vline(nMr-119, self.nlin+8.5, 6.5) |
||||
|
self.vline(nMr-140, self.nlin+8.5, 6.5) |
||||
|
self.vline(nMr-163, self.nlin+8.5, 6.5) |
||||
|
# Labels |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 5) |
||||
|
self.string(nMr-34, self.nlin+3.8, 'VALOR TOTAL DOS PRODUTOS') |
||||
|
self.string(nMr-71, self.nlin+3.8, 'VALOR DO ICMS ST') |
||||
|
self.string(nMr-109, self.nlin+3.8, 'BASE DE CÁLCULO DO ICMS ST') |
||||
|
self.string(nMr-147, self.nlin+3.8, 'VALOR DO ICMS') |
||||
|
self.string(self.nLeft+1, self.nlin+3.8, 'BASE DE CÁLCULO DO ICMS') |
||||
|
self.string(nMr-34, self.nlin+10.2, 'VALOR TOTAL DA NOTA') |
||||
|
self.string(nMr-65, self.nlin+10.2, 'VALOR APROX TRIBUTOS') |
||||
|
self.string(nMr-89, self.nlin+10.2, 'VALOR DO IPI') |
||||
|
self.string(nMr-118, self.nlin+10.2, 'OUTRAS DESP. ACESSÓRIAS') |
||||
|
self.string(nMr-139, self.nlin+10.2, 'DESCONTO') |
||||
|
self.string(nMr-162, self.nlin+10.2, 'VALOR DO SEGURO') |
||||
|
self.string(self.nLeft+1, self.nlin+10.2, 'VALOR DO FRETE') |
||||
|
# Conteúdo campos |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 8) |
||||
|
self.stringRight( |
||||
|
self.nLeft+41, self.nlin+7.7, |
||||
|
format_number(tagtext(oNode=el_total, cTag='vBC'), precision=2)) |
||||
|
self.stringRight( |
||||
|
self.nLeft+79, self.nlin+7.7, |
||||
|
format_number(tagtext(oNode=el_total, cTag='vICMS'), precision=2)) |
||||
|
self.stringRight( |
||||
|
self.nLeft+117, self.nlin+7.7, |
||||
|
format_number(tagtext(oNode=el_total, cTag='vBCST'), precision=2)) |
||||
|
self.stringRight( |
||||
|
nMr-36, self.nlin+7.7, |
||||
|
format_number(tagtext(oNode=el_total, cTag='vST'), precision=2)) |
||||
|
self.stringRight( |
||||
|
nMr-1, self.nlin+7.7, |
||||
|
format_number(tagtext(oNode=el_total, cTag='vProd'), precision=2)) |
||||
|
self.stringRight( |
||||
|
self.nLeft+26, self.nlin+14.1, |
||||
|
format_number(tagtext(oNode=el_total, cTag='vFrete'), precision=2)) |
||||
|
self.stringRight( |
||||
|
self.nLeft+49, self.nlin+14.1, |
||||
|
format_number(tagtext(oNode=el_total, cTag='vSeg'), precision=2)) |
||||
|
self.stringRight( |
||||
|
self.nLeft+70, self.nlin+14.1, |
||||
|
format_number(tagtext(oNode=el_total, cTag='vDesc'), precision=2)) |
||||
|
self.stringRight( |
||||
|
self.nLeft+99, self.nlin+14.1, |
||||
|
format_number(tagtext(oNode=el_total, cTag='vOutro'), precision=2)) |
||||
|
self.stringRight( |
||||
|
self.nLeft+123, self.nlin+14.1, |
||||
|
format_number(tagtext(oNode=el_total, cTag='vIPI'), precision=2)) |
||||
|
self.stringRight( |
||||
|
self.nLeft+154, self.nlin+14.1, |
||||
|
format_number(tagtext(oNode=el_total, cTag='vTotTrib'), |
||||
|
precision=2)) |
||||
|
self.stringRight( |
||||
|
nMr-1, self.nlin+14.1, |
||||
|
format_number(tagtext(oNode=el_total, cTag='vNF'), precision=2)) |
||||
|
|
||||
|
self.nlin += 17 # Nr linhas ocupadas pelo bloco |
||||
|
|
||||
|
def transportes(self, oXML=None): |
||||
|
el_transp = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}transp") |
||||
|
nMr = self.width-self.nRight |
||||
|
|
||||
|
self.canvas.setFont('NimbusSanL-Bold', 7) |
||||
|
self.string(self.nLeft+1, self.nlin+1, |
||||
|
'TRANSPORTADOR/VOLUMES TRANSPORTADOS') |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 5) |
||||
|
self.rect(self.nLeft, self.nlin+2, |
||||
|
self.width-self.nLeft-self.nRight, 20) |
||||
|
self.hline(self.nLeft, self.nlin+8.6, self.width-self.nLeft) |
||||
|
self.hline(self.nLeft, self.nlin+15.2, self.width-self.nLeft) |
||||
|
self.vline(nMr-40, self.nlin+2, 13.2) |
||||
|
self.vline(nMr-49, self.nlin+2, 20) |
||||
|
self.vline(nMr-92, self.nlin+2, 6.6) |
||||
|
self.vline(nMr-120, self.nlin+2, 6.6) |
||||
|
self.vline(nMr-75, self.nlin+2, 6.6) |
||||
|
self.vline(nMr-26, self.nlin+15.2, 6.6) |
||||
|
self.vline(nMr-102, self.nlin+8.6, 6.6) |
||||
|
self.vline(nMr-85, self.nlin+15.2, 6.6) |
||||
|
self.vline(nMr-121, self.nlin+15.2, 6.6) |
||||
|
self.vline(nMr-160, self.nlin+15.2, 6.6) |
||||
|
# Labels/Fields |
||||
|
self.string(nMr-39, self.nlin+3.8, 'CNPJ/CPF') |
||||
|
self.string(nMr-74, self.nlin+3.8, 'PLACA DO VEÍCULO') |
||||
|
self.string(nMr-91, self.nlin+3.8, 'CÓDIGO ANTT') |
||||
|
self.string(nMr-119, self.nlin+3.8, 'FRETE POR CONTA') |
||||
|
self.string(self.nLeft+1, self.nlin+3.8, 'RAZÃO SOCIAL') |
||||
|
self.string(nMr-48, self.nlin+3.8, 'UF') |
||||
|
self.string(nMr-39, self.nlin+10.3, 'INSCRIÇÃO ESTADUAL') |
||||
|
self.string(nMr-48, self.nlin+10.3, 'UF') |
||||
|
self.string(nMr-101, self.nlin+10.3, 'MUNICÍPIO') |
||||
|
self.string(self.nLeft+1, self.nlin+10.3, 'ENDEREÇO') |
||||
|
self.string(nMr-48, self.nlin+17, 'PESO BRUTO') |
||||
|
self.string(nMr-25, self.nlin+17, 'PESO LÍQUIDO') |
||||
|
self.string(nMr-84, self.nlin+17, 'NUMERAÇÃO') |
||||
|
self.string(nMr-120, self.nlin+17, 'MARCA') |
||||
|
self.string(nMr-159, self.nlin+17, 'ESPÉCIE') |
||||
|
self.string(self.nLeft+1, self.nlin+17, 'QUANTIDADE') |
||||
|
# Conteúdo campos |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 8) |
||||
|
self.string(self.nLeft+1, self.nlin+7.7, |
||||
|
tagtext(oNode=el_transp, cTag='xNome')[:40]) |
||||
|
self.string(self.nLeft+71, self.nlin+7.7, |
||||
|
self.oFrete[tagtext(oNode=el_transp, cTag='modFrete')]) |
||||
|
self.string(nMr-39, self.nlin+7.7, |
||||
|
format_cnpj_cpf(tagtext(oNode=el_transp, cTag='CNPJ'))) |
||||
|
self.string(self.nLeft+1, self.nlin+14.2, |
||||
|
tagtext(oNode=el_transp, cTag='xEnder')[:45]) |
||||
|
self.string(self.nLeft+89, self.nlin+14.2, |
||||
|
tagtext(oNode=el_transp, cTag='xMun')) |
||||
|
self.string(nMr-48, self.nlin+14.2, |
||||
|
tagtext(oNode=el_transp, cTag='UF')) |
||||
|
self.string(nMr-39, self.nlin+14.2, |
||||
|
tagtext(oNode=el_transp, cTag='IE')) |
||||
|
self.string(self.nLeft+1, self.nlin+21.2, |
||||
|
tagtext(oNode=el_transp, cTag='qVol')) |
||||
|
self.string(self.nLeft+31, self.nlin+21.2, |
||||
|
tagtext(oNode=el_transp, cTag='esp')) |
||||
|
self.string(self.nLeft+70, self.nlin+21.2, |
||||
|
tagtext(oNode=el_transp, cTag='marca')) |
||||
|
self.string(self.nLeft+106, self.nlin+21.2, |
||||
|
tagtext(oNode=el_transp, cTag='nVol')) |
||||
|
self.stringRight( |
||||
|
nMr-27, self.nlin+21.2, |
||||
|
format_number(tagtext(oNode=el_transp, cTag='pesoB'), precision=3)) |
||||
|
self.stringRight( |
||||
|
nMr-1, self.nlin+21.2, |
||||
|
format_number(tagtext(oNode=el_transp, cTag='pesoL'), precision=3)) |
||||
|
|
||||
|
self.nlin += 23 |
||||
|
|
||||
|
def produtos(self, oXML=None, el_det=None, oPaginator=None, |
||||
|
list_desc=None, nHeight=29): |
||||
|
|
||||
|
nMr = self.width-self.nRight |
||||
|
nStep = 2.5 # Passo entre linhas |
||||
|
nH = 7.5 + (nHeight * nStep) # cabeçalho 7.5 |
||||
|
self.nlin += 1 |
||||
|
|
||||
|
self.canvas.setFont('NimbusSanL-Bold', 7) |
||||
|
self.string(self.nLeft+1, self.nlin+1, 'DADOS DO PRODUTO/SERVIÇO') |
||||
|
self.rect(self.nLeft, self.nlin+2, |
||||
|
self.width-self.nLeft-self.nRight, nH) |
||||
|
self.hline(self.nLeft, self.nlin+8, self.width-self.nLeft) |
||||
|
|
||||
|
self.canvas.setFont('NimbusSanL-Regu', 5.5) |
||||
|
# Colunas |
||||
|
self.vline(self.nLeft+11, self.nlin+2, nH) |
||||
|
self.stringcenter(self.nLeft+5.5, self.nlin+5.5, 'CÓDIGO') |
||||
|
self.vline(nMr-7, self.nlin+2, nH) |
||||
|
self.stringcenter(nMr-3.5, self.nlin+4.5, 'ALÍQ') |
||||
|
self.stringcenter(nMr-3.5, self.nlin+6.5, 'IPI') |
||||
|
self.vline(nMr-14, self.nlin+2, nH) |
||||
|
self.stringcenter(nMr-10.5, self.nlin+4.5, 'ALÍQ') |
||||
|
self.stringcenter(nMr-10.5, self.nlin+6.5, 'ICMS') |
||||
|
self.vline(nMr-26, self.nlin+2, nH) |
||||
|
self.stringcenter(nMr-20, self.nlin+5.5, 'VLR. IPI') |
||||
|
self.vline(nMr-38, self.nlin+2, nH) |
||||
|
self.stringcenter(nMr-32, self.nlin+5.5, 'VLR. ICMS') |
||||
|
self.vline(nMr-50, self.nlin+2, nH) |
||||
|
self.stringcenter(nMr-44, self.nlin+5.5, 'BC ICMS') |
||||
|
self.vline(nMr-64, self.nlin+2, nH) |
||||
|
self.stringcenter(nMr-57, self.nlin+5.5, 'VLR TOTAL') |
||||
|
self.vline(nMr-77, self.nlin+2, nH) |
||||
|
self.stringcenter(nMr-70.5, self.nlin+5.5, 'VLR UNIT') |
||||
|
self.vline(nMr-90, self.nlin+2, nH) |
||||
|
self.stringcenter(nMr-83.5, self.nlin+5.5, 'QTD') |
||||
|
self.vline(nMr-98, self.nlin+2, nH) |
||||
|
self.stringcenter(nMr-94, self.nlin+5.5, 'UNID') |
||||
|
self.vline(nMr-104, self.nlin+2, nH) |
||||
|
self.stringcenter(nMr-101, self.nlin+5.5, 'CFOP') |
||||
|
self.vline(nMr-110, self.nlin+2, nH) |
||||
|
self.stringcenter(nMr-107, self.nlin+5.5, 'CST') |
||||
|
self.vline(nMr-123, self.nlin+2, nH) |
||||
|
self.stringcenter(nMr-116.5, self.nlin+5.5, 'NCM/SH') |
||||
|
|
||||
|
nWidth_Prod = nMr-135-self.nLeft-11 |
||||
|
nCol_ = self.nLeft+11 + (nWidth_Prod / 2) |
||||
|
self.stringcenter(nCol_, self.nlin+5.5, 'DESCRIÇÃO DO PRODUTO/SERVIÇO') |
||||
|
|
||||
|
# Conteúdo campos |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 5) |
||||
|
nLin = self.nlin+10.5 |
||||
|
|
||||
|
for id in xrange(oPaginator[0], oPaginator[1]): |
||||
|
item = el_det[id] |
||||
|
el_prod = item.find(".//{http://www.portalfiscal.inf.br/nfe}prod") |
||||
|
el_imp = item.find( |
||||
|
".//{http://www.portalfiscal.inf.br/nfe}imposto") |
||||
|
|
||||
|
el_imp_ICMS = el_imp.find( |
||||
|
".//{http://www.portalfiscal.inf.br/nfe}ICMS") |
||||
|
el_imp_IPI = el_imp.find( |
||||
|
".//{http://www.portalfiscal.inf.br/nfe}IPI") |
||||
|
|
||||
|
cCST = tagtext(oNode=el_imp_ICMS, cTag='orig') + \ |
||||
|
tagtext(oNode=el_imp_ICMS, cTag='CST') |
||||
|
vBC = tagtext(oNode=el_imp_ICMS, cTag='vBC') |
||||
|
vICMS = tagtext(oNode=el_imp_ICMS, cTag='vICMS') |
||||
|
pICMS = tagtext(oNode=el_imp_ICMS, cTag='pICMS') |
||||
|
|
||||
|
vIPI = tagtext(oNode=el_imp_IPI, cTag='vIPI') |
||||
|
pIPI = tagtext(oNode=el_imp_IPI, cTag='pIPI') |
||||
|
|
||||
|
self.string(self.nLeft+1, nLin, |
||||
|
tagtext(oNode=el_prod, cTag='cProd')) |
||||
|
self.stringcenter(nMr-116.5, nLin, |
||||
|
tagtext(oNode=el_prod, cTag='NCM')) |
||||
|
self.stringcenter(nMr-107, nLin, cCST) |
||||
|
self.stringcenter(nMr-101, nLin, |
||||
|
tagtext(oNode=el_prod, cTag='CFOP')) |
||||
|
self.stringcenter(nMr-94, nLin, |
||||
|
tagtext(oNode=el_prod, cTag='uCom')) |
||||
|
self.stringRight(nMr-77.5, nLin, format_number( |
||||
|
tagtext(oNode=el_prod, cTag='qCom'), precision=4)) |
||||
|
self.stringRight(nMr-64.5, nLin, format_number( |
||||
|
tagtext(oNode=el_prod, cTag='vUnCom'), precision=2)) |
||||
|
self.stringRight(nMr-50.5, nLin, format_number( |
||||
|
tagtext(oNode=el_prod, cTag='vProd'), precision=2)) |
||||
|
self.stringRight(nMr-38.5, nLin, format_number(vBC, precision=2)) |
||||
|
self.stringRight(nMr-26.5, nLin, format_number(vICMS, precision=2)) |
||||
|
self.stringRight(nMr-7.5, nLin, format_number(pICMS, precision=2)) |
||||
|
|
||||
|
if vIPI: |
||||
|
self.stringRight(nMr-14.5, nLin, |
||||
|
format_number(vIPI, precision=2)) |
||||
|
if pIPI: |
||||
|
self.stringRight(nMr-0.5, nLin, |
||||
|
format_number(pIPI, precision=2)) |
||||
|
|
||||
|
self.canvas.setStrokeColor(gray) |
||||
|
self.hline(self.nLeft, nLin+0.5, self.width-self.nLeft) |
||||
|
self.canvas.setStrokeColor(black) |
||||
|
# Descrição Item |
||||
|
for des in list_desc[id]: |
||||
|
self.string(self.nLeft+12, nLin, des) |
||||
|
nLin += nStep |
||||
|
|
||||
|
self.nlin += nH + 3 |
||||
|
|
||||
|
def adicionais(self, oXML=None): |
||||
|
el_infAdic = oXML.find( |
||||
|
".//{http://www.portalfiscal.inf.br/nfe}infAdic") |
||||
|
|
||||
|
self.nlin += 2 |
||||
|
self.canvas.setFont('NimbusSanL-Bold', 6) |
||||
|
self.string(self.nLeft+1, self.nlin+1, 'DADOS ADICIONAIS') |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 5) |
||||
|
self.string(self.nLeft+1, self.nlin+4, 'INFORMAÇÕES COMPLEMENTARES') |
||||
|
self.string((self.width/2)+1, self.nlin+4, 'RESERVADO AO FISCO') |
||||
|
self.rect(self.nLeft, self.nlin+2, |
||||
|
self.width-self.nLeft-self.nRight, 34) |
||||
|
self.vline(self.width/2, self.nlin+2, 34) |
||||
|
# Conteúdo campos |
||||
|
styles = getSampleStyleSheet() |
||||
|
styleN = styles['Normal'] |
||||
|
styleN.fontSize = 6 |
||||
|
styleN.fontName = 'NimbusSanL-Regu' |
||||
|
styleN.leading = 7 |
||||
|
|
||||
|
P = Paragraph(tagtext(oNode=el_infAdic, |
||||
|
cTag='infCpl'), styles['Normal']) |
||||
|
w, h = P.wrap(92*mm, 32*mm) |
||||
|
P.drawOn(self.canvas, (self.nLeft+1)*mm, (self.height-self.nlin-17)*mm) |
||||
|
|
||||
|
self.nlin += 36 |
||||
|
|
||||
|
def recibo_entrega(self, oXML=None): |
||||
|
el_ide = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}ide") |
||||
|
el_dest = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}dest") |
||||
|
el_total = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}total") |
||||
|
el_emit = oXML.find(".//{http://www.portalfiscal.inf.br/nfe}emit") |
||||
|
|
||||
|
# self.nlin = self.height-self.nBottom-18 # 17 altura recibo |
||||
|
nW = 40 |
||||
|
nH = 17 |
||||
|
self.canvas.setLineWidth(.5) |
||||
|
self.rect(self.nLeft, self.nlin, |
||||
|
self.width-(self.nLeft+self.nRight), nH) |
||||
|
self.hline(self.nLeft, self.nlin+8.5, self.width-self.nRight-nW) |
||||
|
self.vline(self.width-self.nRight-nW, self.nlin, nH) |
||||
|
self.vline(self.nLeft+nW, self.nlin+8.5, 8.5) |
||||
|
|
||||
|
# Labels |
||||
|
self.canvas.setFont('NimbusSanL-Regu', 5) |
||||
|
self.string(self.nLeft+1, self.nlin+10.2, 'DATA DE RECEBIMENTO') |
||||
|
self.string(self.nLeft+41, self.nlin+10.2, |
||||
|
'IDENTIFICAÇÃO E ASSINATURA DO RECEBEDOR') |
||||
|
self.stringcenter(self.width-self.nRight-(nW/2), self.nlin+2, 'NF-e') |
||||
|
# Conteúdo campos |
||||
|
self.canvas.setFont('NimbusSanL-Bold', 8) |
||||
|
cNF = tagtext(oNode=el_ide, cTag='nNF') |
||||
|
cNF = '{0:011,}'.format(int(cNF)).replace(",", ".") |
||||
|
self.string(self.width-self.nRight-nW+2, self.nlin+8, "Nº %s" % (cNF)) |
||||
|
self.string(self.width-self.nRight-nW+2, self.nlin+14, |
||||
|
u"SÉRIE %s" % (tagtext(oNode=el_ide, cTag='serie'))) |
||||
|
|
||||
|
cDt, cHr = getdateUTC(tagtext(oNode=el_ide, cTag='dhEmi')) |
||||
|
cTotal = format_number(tagtext(oNode=el_total, cTag='vNF'), |
||||
|
precision=2) |
||||
|
|
||||
|
cEnd = tagtext(oNode=el_dest, cTag='xNome') + ' - ' |
||||
|
cEnd += tagtext(oNode=el_dest, cTag='xLgr') + ', ' + tagtext( |
||||
|
oNode=el_dest, cTag='nro') + ', ' |
||||
|
cEnd += tagtext(oNode=el_dest, cTag='xBairro') + ', ' + tagtext( |
||||
|
oNode=el_dest, cTag='xMun') + ' - ' |
||||
|
cEnd += tagtext(oNode=el_dest, cTag='UF') |
||||
|
|
||||
|
cString = u""" |
||||
|
RECEBEMOS DE %s OS PRODUTOS/SERVIÇOS CONSTANTES DA NOTA FISCAL INDICADA |
||||
|
ABAIXO. EMISSÃO: %s VALOR TOTAL: %s |
||||
|
DESTINATARIO: %s""" % (tagtext(oNode=el_emit, cTag='xNome'), |
||||
|
cDt, cTotal, cEnd) |
||||
|
|
||||
|
styles = getSampleStyleSheet() |
||||
|
styleN = styles['Normal'] |
||||
|
styleN.fontName = 'NimbusSanL-Regu' |
||||
|
styleN.fontSize = 6 |
||||
|
styleN.leading = 7 |
||||
|
|
||||
|
P = Paragraph(cString, styleN) |
||||
|
w, h = P.wrap(149*mm, 7*mm) |
||||
|
P.drawOn(self.canvas, (self.nLeft+1)*mm, |
||||
|
(self.height-self.nlin-7.5)*mm) |
||||
|
|
||||
|
self.nlin += 20 |
||||
|
self.hline(self.nLeft, self.nlin, self.width-self.nRight) |
||||
|
self.nlin += 2 |
||||
|
|
||||
|
def newpage(self): |
||||
|
self.nlin = self.nTop |
||||
|
self.Page += 1 |
||||
|
self.canvas.showPage() |
||||
|
|
||||
|
def hline(self, x, y, width): |
||||
|
y = self.height - y |
||||
|
self.canvas.line(x*mm, y*mm, width*mm, y*mm) |
||||
|
|
||||
|
def vline(self, x, y, width): |
||||
|
width = self.height - y - width |
||||
|
y = self.height - y |
||||
|
self.canvas.line(x*mm, y*mm, x*mm, width*mm) |
||||
|
|
||||
|
def rect(self, col, lin, nWidth, nHeight, fill=False): |
||||
|
lin = self.height - nHeight - lin |
||||
|
self.canvas.rect(col*mm, lin*mm, nWidth*mm, nHeight*mm, |
||||
|
stroke=True, fill=fill) |
||||
|
|
||||
|
def string(self, x, y, value): |
||||
|
y = self.height - y |
||||
|
self.canvas.drawString(x*mm, y*mm, value) |
||||
|
|
||||
|
def stringRight(self, x, y, value): |
||||
|
y = self.height - y |
||||
|
self.canvas.drawRightString(x*mm, y*mm, value) |
||||
|
|
||||
|
def stringcenter(self, x, y, value): |
||||
|
y = self.height - y |
||||
|
self.canvas.drawCentredString(x*mm, y*mm, value) |
||||
|
|
||||
|
def writeto_pdf(self, fileObj): |
||||
|
pdf_out = self.oPDF_IO.getvalue() |
||||
|
self.oPDF_IO.close() |
||||
|
fileObj.write(pdf_out) |
||||
@ -0,0 +1,46 @@ |
|||||
|
<nfeProc xmlns="http://www.portalfiscal.inf.br/nfe" versao="3.10"><NFe><infNFe versao="3.10" Id="NFe35170221332917000163550010000008571134165777"><ide><cUF>35</cUF><cNF>13416577</cNF><natOp>Venda Não Contribuintes</natOp><indPag>1</indPag><mod>55</mod><serie>1</serie><nNF>857</nNF><dhEmi>2017-02-24T11:39:30-00:00</dhEmi><dhSaiEnt>2017-02-24T11:39:30-00:00</dhSaiEnt><tpNF>1</tpNF><idDest>2</idDest><cMunFG>3550308</cMunFG><tpImp>1</tpImp><tpEmis>1</tpEmis><cDV>7</cDV><tpAmb>2</tpAmb><finNFe>1</finNFe><indFinal>1</indFinal><indPres>0</indPres><procEmi>0</procEmi><verProc>Odoo Brasil 10</verProc></ide><emit><CNPJ>21332917000163</CNPJ><xNome>TRUSTCODE TECNOLOGIA DA INFORMAÇÃO LTDA</xNome><xFant>Trustcode</xFant><enderEmit><xLgr>Rua Vinicius de Moraes</xLgr><nro>42</nro><xBairro>Córrego Grande</xBairro><cMun>3550308</cMun><xMun>Florianópolis</xMun><UF>SC</UF><CEP>88037240</CEP><cPais>1058</cPais><xPais>Brasil</xPais><fone>1135302850</fone></enderEmit><IE>144013873114</IE><CRT>1</CRT></emit><dest><CNPJ>11370685000184</CNPJ><xNome>NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL</xNome><enderDest><xLgr>AV AMAZONAS</xLgr><nro>1193</nro><xBairro>Centro</xBairro><cMun>4314902</cMun><xMun>Porto Alegre</xMun><UF>RS</UF><CEP>90240542</CEP><cPais>1058</cPais><xPais>Brasil</xPais></enderDest><indIEDest>9</indIEDest></dest><det nItem="1"><prod><cProd>VTS-L1231100907</cProd><cEAN/><xProd>VENTIS PRETO- O2 CO H2S DIFUSAO</xProd><NCM>90271000</NCM><CFOP>6108</CFOP><uCom>UN</uCom><qCom>1.0</qCom><vUnCom>100.00</vUnCom><vProd>100.00</vProd><cEANTrib/><uTrib>UN</uTrib><qTrib>1.0</qTrib><vUnTrib>3562.26</vUnTrib><vFrete>95.00</vFrete><indTot>1</indTot></prod><imposto><vTotTrib>0.00</vTotTrib><ICMS><ICMSSN102><orig>0</orig><CSOSN>102</CSOSN></ICMSSN102></ICMS><IPI><cEnq>999</cEnq><IPITrib><CST>49</CST><vBC>3657.26</vBC><pIPI>0.00</pIPI><vIPI>0.00</vIPI></IPITrib></IPI><PIS><PISNT><CST>07</CST></PISNT></PIS><COFINS><COFINSNT><CST>07</CST></COFINSNT></COFINS></imposto></det><total><ICMSTot><vBC>0.00</vBC><vICMS>0.00</vICMS><vICMSDeson>0.00</vICMSDeson><vBCST>0.00</vBCST><vST>0.00</vST><vProd>3562.26</vProd><vFrete>95.00</vFrete><vSeg>0.00</vSeg><vDesc>0.00</vDesc><vII>0.00</vII><vIPI>0.00</vIPI><vPIS>0.00</vPIS><vCOFINS>0.00</vCOFINS><vOutro>0.00</vOutro><vNF>3657.26</vNF><vTotTrib>0.00</vTotTrib></ICMSTot></total><transp><modFrete>1</modFrete><transporta><xNome>SEDEX</xNome><xEnder>False - False, False</xEnder></transporta></transp><cobr><fat><nFat>INV/2017/0126</nFat><vOrig>3562.26</vOrig><vLiq>3657.26</vLiq></fat><dup><nDup>01</nDup><dVenc>2017-03-16</dVenc><vDup>1828.63</vDup></dup><dup><nDup>02</nDup><dVenc>2017-04-15</dVenc><vDup>1828.63</vDup></dup></cobr><infAdic><infCpl>PERMITE O APROVEITAMENTO DO CRÉDITO DE ICMS NO VALOR CORRESPONDENTE À ALÍQUOTA DE 1,25%, NOS TERMOS DO ART. 23 DA LC 123/2006 >>IMPORTANTE<< P/ LIQUIDACAO DESTA NF, EFETUE DEPOSITO IDENTIFICADO NO BANCO BRADESCO AG: 1992-5, C/c: 4897-6 PEDIDO DE COMPRAS: OC 0045-05/2017 N/S 16122WZ-021 (Orçamento SO176) **VENCIMENTO: 15/04/2017 ==> .</infCpl></infAdic><compra><xPed>OC 0045-05/2017 N/S 16122WZ-021</xPed></compra></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="#NFe35170221332917000163550010000008571134165777"><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>bNLOBxpMk5J6rrz37coB8/pvTBE=</DigestValue></Reference></SignedInfo><SignatureValue>Y++vItLsZAbwzM/YDsgGqSn2+u035OSigoskd1x7DDJuAFuM0imbOuC20TAJPODcZCFxfqO1VTFCVgMmJUtHGzwvVdr3DSlbxIevfTF0nNwBYN2LzQVY2R/495ro2Vw2waKfOU+O2IZrKlFxBfu91Vv/JRpbECElwZaDK1BEp2ekGkB0tHfisGbQu1WFR8HBqwcyn8khhScO8nE7S+MR8uyEqf5057AiZZr1/vG/vyNhN1yzP8FFT3kHOG3w2aNe0H85s9spUrSC5hOAIy0yD6/NUUfH9AOOlER+cCLgLT52W7I5nnxC7dgEzG6YQffy1XGd/TQ4RC7ppKwmkVFaoQ==</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><protNFe versao="3.10"><infProt><tpAmb>2</tpAmb><verAplic>SP_NFE_PL_008i2</verAplic><chNFe>35170221332917000163550010000008571134165777</chNFe><dhRecbto>2017-02-24T08:39:31-03:00</dhRecbto><nProt>135170000807903</nProt><digVal>bNLOBxpMk5J6rrz37coB8/pvTBE=</digVal><cStat>100</cStat><xMotivo>Autorizado o uso da NF-e</xMotivo></infProt></protNFe></nfeProc> |
||||
@ -0,0 +1,22 @@ |
|||||
|
# coding=utf-8 |
||||
|
|
||||
|
import tempfile |
||||
|
import os.path |
||||
|
import unittest |
||||
|
from lxml import etree |
||||
|
from pytrustnfe.nfe.danfe import danfe |
||||
|
|
||||
|
|
||||
|
class test_danfe(unittest.TestCase): |
||||
|
|
||||
|
caminho = os.path.dirname(__file__) |
||||
|
|
||||
|
def test_can_generate_danfe(self): |
||||
|
path = os.path.join(os.path.dirname(__file__), 'XMLs') |
||||
|
xml_string = open(os.path.join(path, 'NFe00000857.xml'), "r").read() |
||||
|
xml_element = etree.fromstring(xml_string) |
||||
|
|
||||
|
oDanfe = danfe(list_xml=[xml_element]) |
||||
|
|
||||
|
with tempfile.TemporaryFile(mode='w') as oFile: |
||||
|
oDanfe.writeto_pdf(oFile) |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue