Browse Source

Teste para gerar a danfe - Ajuste na logo e dados da empresa

pull/40/head
Danimar Ribeiro 9 years ago
parent
commit
374e0ec283
  1. 63
      pytrustnfe/nfe/danfe.py
  2. 46
      pytrustnfe/test/XMLs/NFe00000857.xml
  3. 22
      pytrustnfe/test/test_danfe.py
  4. 1
      requirements.txt
  5. 1
      setup.py

63
pytrustnfe/nfe/danfe.py

@ -3,12 +3,8 @@
# 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).
# Classe para geração de PDF da DANFE a partir de xml etree.fromstring # Classe para geração de PDF da DANFE a partir de xml etree.fromstring
# TO DO
# Layout Paisagem
# Logo imagem da empresa
from cStringIO import StringIO as IO from cStringIO import StringIO as IO
from lxml import etree
from textwrap import wrap from textwrap import wrap
from reportlab.lib import utils from reportlab.lib import utils
@ -18,6 +14,7 @@ from reportlab.lib.pagesizes import A4
from reportlab.lib.colors import black, gray from reportlab.lib.colors import black, gray
from reportlab.graphics.barcode import code128 from reportlab.graphics.barcode import code128
from reportlab.lib.styles import getSampleStyleSheet from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.enums import TA_CENTER
from reportlab.platypus import Paragraph, Image from reportlab.platypus import Paragraph, Image
@ -58,6 +55,12 @@ def tagtext(oNode=None, cTag=None):
cText = '' cText = ''
return 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): def get_image(path, width=1*cm):
img = utils.ImageReader(path) img = utils.ImageReader(path)
@ -68,7 +71,7 @@ def get_image(path, width=1*cm):
class danfe(object): class danfe(object):
def __init__(self, sizepage=A4, list_xml=None, recibo=True, def __init__(self, sizepage=A4, list_xml=None, recibo=True,
orientation='portrait'):
orientation='portrait', logo=None):
self.width = 210 # 21 x 29,7cm self.width = 210 # 21 x 29,7cm
self.height = 297 self.height = 297
self.nLeft = 10 self.nLeft = 10
@ -76,6 +79,7 @@ class danfe(object):
self.nTop = 7 self.nTop = 7
self.nBottom = 15 self.nBottom = 15
self.nlin = self.nTop self.nlin = self.nTop
self.logo = logo
self.oFrete = {'0': '0 - Emitente', self.oFrete = {'0': '0 - Emitente',
'1': '1 - Dest/Remet', '1': '1 - Dest/Remet',
'2': '2 - Terceiros', '2': '2 - Terceiros',
@ -248,31 +252,39 @@ class danfe(object):
styles = getSampleStyleSheet() styles = getSampleStyleSheet()
styleN = styles['Normal'] styleN = styles['Normal']
styleN.fontSize = 11
styleN.fontName = 'NimbusSanL-Regu'
styleN.fontSize = 10
styleN.fontName = 'NimbusSanL-Bold'
styleN.alignment = TA_CENTER
# Razão Social emitente # Razão Social emitente
P = Paragraph(tagtext(oNode=elem_emit, cTag='xNome'), styleN) P = Paragraph(tagtext(oNode=elem_emit, cTag='xNome'), styleN)
w, h = P.wrap(55*mm, 50*mm) w, h = P.wrap(55*mm, 50*mm)
P.drawOn(self.canvas, (self.nLeft+30)*mm, P.drawOn(self.canvas, (self.nLeft+30)*mm,
(self.height-self.nlin-10)*mm)
(self.height-self.nlin-12)*mm)
logo = '/home/danimar/Downloads/innova.png'
img = get_image(logo, width=2*cm)
img.drawOn(self.canvas, (self.nLeft+5)*mm, (self.height-self.nlin-22)*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( cEnd = tagtext(oNode=elem_emit, cTag='xLgr') + ', ' + tagtext(
oNode=elem_emit, cTag='nro') + ' - ' oNode=elem_emit, cTag='nro') + ' - '
cEnd += tagtext(oNode=elem_emit, cTag='xBairro') + ' - ' + tagtext(
cEnd += tagtext(oNode=elem_emit, cTag='xBairro') + '<br />' + tagtext(
oNode=elem_emit, cTag='xMun') + ' - ' oNode=elem_emit, cTag='xMun') + ' - '
cEnd += 'Fone: ' + tagtext(oNode=elem_emit, cTag='fone') + '<br />'
cEnd += tagtext(oNode=elem_emit, cTag='UF') + ' - ' + tagtext( cEnd += tagtext(oNode=elem_emit, cTag='UF') + ' - ' + tagtext(
oNode=elem_emit, cTag='CEP') oNode=elem_emit, cTag='CEP')
cEnd += ' - Fone: ' + tagtext(oNode=elem_emit, cTag='fone')
styleN.fontSize = 8
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 styleN.leading = 10
P = Paragraph(cEnd, styleN) P = Paragraph(cEnd, styleN)
w, h = P.wrap(80*mm, 30*mm)
P.drawOn(self.canvas, (self.nLeft+5)*mm, (self.height-self.nlin-30)*mm)
w, h = P.wrap(55*mm, 30*mm)
P.drawOn(self.canvas, (self.nLeft+30)*mm,
(self.height-self.nlin-31)*mm)
# Homologação # Homologação
if tagtext(oNode=elem_ide, cTag='tpAmb') == '2': if tagtext(oNode=elem_ide, cTag='tpAmb') == '2':
@ -695,7 +707,7 @@ obsCont[@xCampo='NomeVendedor']")
P = Paragraph(tagtext(oNode=el_infAdic, P = Paragraph(tagtext(oNode=el_infAdic,
cTag='infCpl'), styles['Normal']) cTag='infCpl'), styles['Normal'])
w, h = P.wrap(92*mm, 32*mm) w, h = P.wrap(92*mm, 32*mm)
P.drawOn(self.canvas, (self.nLeft+1)*mm, (self.height-self.nlin-12)*mm)
P.drawOn(self.canvas, (self.nLeft+1)*mm, (self.height-self.nlin-17)*mm)
self.nlin += 36 self.nlin += 36
@ -792,20 +804,7 @@ obsCont[@xCampo='NomeVendedor']")
y = self.height - y y = self.height - y
self.canvas.drawCentredString(x*mm, y*mm, value) self.canvas.drawCentredString(x*mm, y*mm, value)
def get_buffer(self):
def writeto_pdf(self, fileObj):
pdf_out = self.oPDF_IO.getvalue() pdf_out = self.oPDF_IO.getvalue()
self.oPDF_IO.close() self.oPDF_IO.close()
return pdf_out
# Exemplo de uso
if __name__ == "__main__":
xml_string = open(
"/home/danimar/Downloads/nfe-envio-2017-02-13-10-10.xml", "r").read()
xml_element = etree.fromstring(xml_string)
oDanfe = danfe(list_xml=[xml_element])
oFile = open('/home/danimar/DANFE.pdf', 'w')
oFile.write(oDanfe.get_buffer())
oFile.close()
fileObj.write(pdf_out)

46
pytrustnfe/test/XMLs/NFe00000857.xml

@ -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&#227;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&#201;DITO DE ICMS NO VALOR CORRESPONDENTE &#192; AL&#205;QUOTA DE 1,25%, NOS TERMOS DO ART. 23 DA LC 123/2006 &gt;&gt;IMPORTANTE&lt;&lt; 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&#231;amento SO176) **VENCIMENTO: 15/04/2017 ==&gt; .</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>

22
pytrustnfe/test/test_danfe.py

@ -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)

1
requirements.txt

@ -13,3 +13,4 @@ eight >= 0.3.0, < 0.4
cryptography >= 1.4, < 1.8 cryptography >= 1.4, < 1.8
pyOpenSSL >= 16.0.0, < 17 pyOpenSSL >= 16.0.0, < 17
certifi >= 2015.11.20.1 certifi >= 2015.11.20.1
reportlab

1
setup.py

@ -35,6 +35,7 @@ later (LGPLv2+)',
'lxml >= 3.6.0, < 3.7', 'lxml >= 3.6.0, < 3.7',
'suds >= 0.4', 'suds >= 0.4',
'suds_requests >= 0.3', 'suds_requests >= 0.3',
'reportlab'
], ],
test_suite='nose.collector', test_suite='nose.collector',
tests_require=[ tests_require=[

Loading…
Cancel
Save