diff --git a/pytrustnfe/nfe/danfe.py b/pytrustnfe/nfe/danfe.py
index 295cc64..bbaddf0 100644
--- a/pytrustnfe/nfe/danfe.py
+++ b/pytrustnfe/nfe/danfe.py
@@ -3,12 +3,8 @@
# 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
-# TO DO
-# Layout Paisagem
-# Logo imagem da empresa
from cStringIO import StringIO as IO
-from lxml import etree
from textwrap import wrap
from reportlab.lib import utils
@@ -18,6 +14,7 @@ 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
@@ -58,6 +55,12 @@ def tagtext(oNode=None, cTag=None):
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)
@@ -68,7 +71,7 @@ def get_image(path, width=1*cm):
class danfe(object):
def __init__(self, sizepage=A4, list_xml=None, recibo=True,
- orientation='portrait'):
+ orientation='portrait', logo=None):
self.width = 210 # 21 x 29,7cm
self.height = 297
self.nLeft = 10
@@ -76,6 +79,7 @@ class danfe(object):
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',
@@ -248,31 +252,39 @@ class danfe(object):
styles = getSampleStyleSheet()
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
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-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(
oNode=elem_emit, cTag='nro') + ' - '
- cEnd += tagtext(oNode=elem_emit, cTag='xBairro') + ' - ' + tagtext(
+ cEnd += tagtext(oNode=elem_emit, cTag='xBairro') + '
' + tagtext(
oNode=elem_emit, cTag='xMun') + ' - '
+ cEnd += 'Fone: ' + tagtext(oNode=elem_emit, cTag='fone') + '
'
cEnd += tagtext(oNode=elem_emit, cTag='UF') + ' - ' + tagtext(
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'
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(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
if tagtext(oNode=elem_ide, cTag='tpAmb') == '2':
@@ -695,7 +707,7 @@ obsCont[@xCampo='NomeVendedor']")
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-12)*mm)
+ P.drawOn(self.canvas, (self.nLeft+1)*mm, (self.height-self.nlin-17)*mm)
self.nlin += 36
@@ -792,20 +804,7 @@ obsCont[@xCampo='NomeVendedor']")
y = self.height - y
self.canvas.drawCentredString(x*mm, y*mm, value)
- def get_buffer(self):
+ def writeto_pdf(self, fileObj):
pdf_out = self.oPDF_IO.getvalue()
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)
diff --git a/pytrustnfe/test/XMLs/NFe00000857.xml b/pytrustnfe/test/XMLs/NFe00000857.xml
new file mode 100644
index 0000000..cb47a9c
--- /dev/null
+++ b/pytrustnfe/test/XMLs/NFe00000857.xml
@@ -0,0 +1,46 @@
+3513416577Venda Não Contribuintes15518572017-02-24T11:39:30-00:002017-02-24T11:39:30-00:0012355030811721100Odoo Brasil 1021332917000163TRUSTCODE TECNOLOGIA DA INFORMAÇÃO LTDATrustcodeRua Vinicius de Moraes42Córrego Grande3550308FlorianópolisSC880372401058Brasil1135302850144013873114111370685000184NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCALAV AMAZONAS1193Centro4314902Porto AlegreRS902405421058Brasil9VTS-L1231100907VENTIS PRETO- O2 CO H2S DIFUSAO902710006108UN1.0100.00100.00UN1.03562.2695.0010.000102999493657.260.000.0007070.000.000.000.000.003562.2695.000.000.000.000.000.000.000.003657.260.001SEDEXFalse - False, FalseINV/2017/01263562.263657.26012017-03-161828.63022017-04-151828.63PERMITE 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 ==> .OC 0045-05/2017 N/S 16122WZ-021bNLOBxpMk5J6rrz37coB8/pvTBE=Y++vItLsZAbwzM/YDsgGqSn2+u035OSigoskd1x7DDJuAFuM0imbOuC20TAJPODcZCFxfqO1VTFCVgMmJUtHGzwvVdr3DSlbxIevfTF0nNwBYN2LzQVY2R/495ro2Vw2waKfOU+O2IZrKlFxBfu91Vv/JRpbECElwZaDK1BEp2ekGkB0tHfisGbQu1WFR8HBqwcyn8khhScO8nE7S+MR8uyEqf5057AiZZr1/vG/vyNhN1yzP8FFT3kHOG3w2aNe0H85s9spUrSC5hOAIy0yD6/NUUfH9AOOlER+cCLgLT52W7I5nnxC7dgEzG6YQffy1XGd/TQ4RC7ppKwmkVFaoQ==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
+2SP_NFE_PL_008i2351702213329170001635500100000085711341657772017-02-24T08:39:31-03:00135170000807903bNLOBxpMk5J6rrz37coB8/pvTBE=100Autorizado o uso da NF-e
diff --git a/pytrustnfe/test/test_danfe.py b/pytrustnfe/test/test_danfe.py
new file mode 100644
index 0000000..c73bfd9
--- /dev/null
+++ b/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)
diff --git a/requirements.txt b/requirements.txt
index a8fbe02..e343fde 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -13,3 +13,4 @@ eight >= 0.3.0, < 0.4
cryptography >= 1.4, < 1.8
pyOpenSSL >= 16.0.0, < 17
certifi >= 2015.11.20.1
+reportlab
diff --git a/setup.py b/setup.py
index 223c55c..9d396e9 100644
--- a/setup.py
+++ b/setup.py
@@ -35,6 +35,7 @@ later (LGPLv2+)',
'lxml >= 3.6.0, < 3.7',
'suds >= 0.4',
'suds_requests >= 0.3',
+ 'reportlab'
],
test_suite='nose.collector',
tests_require=[