source: OpenRLabs-Git/deploy/rlabs-docker/web2py-rlabs/gluon/contrib/pdfinvoice.py

main
Last change on this file was 42bd667, checked in by David Fuertes <dfuertes@…>, 4 years ago

Historial Limpio

  • Property mode set to 100755
File size: 6.9 KB
Line 
1"""
2BSD license -  created by Massimo Di Pierro
3"""
4from __future__ import print_function
5from reportlab.pdfgen.canvas import Canvas
6from reportlab.platypus import Table
7from reportlab.lib.pagesizes import A4
8from reportlab.lib.units import cm
9from decimal import Decimal
10import cStringIO
11import datetime
12
13def listify(item):
14    if isinstance(item,basestring):
15        item = item.split('\n')
16    return item
17
18class PDF(object):
19    def __init__(self, page_size=A4, font_face='Helvetica'):
20        self.page_size = page_size
21        self.font_face = font_face
22        self.logo = None
23    def format_currency(self,value):
24        a = list(str(int(value)))
25        for k in range(len(a)-3,0,-3):
26            a.insert(k,',')
27        a = ''.join(a)
28        b = ("%.2f" % (value-int(value)))[2:]
29        return "%s.%s" % (a,b)
30    def draw(self, invoice, items_page=10):
31        """ Draws the invoice """
32        buffer = cStringIO.StringIO()
33        invoice_items = invoice['items']
34        pages = max((len(invoice_items)-2)/items_page+1,1)
35        canvas = Canvas(buffer, pagesize=self.page_size)
36        for page in range(pages):
37            canvas.translate(0, 29.7 * cm)
38            canvas.setFont(self.font_face, 10)
39
40            canvas.saveState()
41            canvas.setStrokeColorRGB(0.9, 0.5, 0.2)
42            canvas.setFillColorRGB(0.2, 0.2, 0.2)
43            canvas.setFont(self.font_face, 16)
44            canvas.drawString(1 * cm, -1 * cm, invoice.get('title',''))
45            if self.logo:
46                canvas.drawInlineImage(self.logo, 1 * cm, -1 * cm, 250, 16)
47            canvas.setLineWidth(4)
48            canvas.line(0, -1.25 * cm, 21.7 * cm, -1.25 * cm)
49            canvas.restoreState()
50
51            canvas.saveState()
52            notes = listify(invoice.get('notes',''))
53            textobject = canvas.beginText(1 * cm, -25 * cm)
54            for line in notes:
55                textobject.textLine(line)
56            canvas.drawText(textobject)
57            textobject = canvas.beginText(18 * cm, -28 * cm)
58            textobject.textLine('Pag.%s/%s' % (page+1,pages))
59            canvas.drawText(textobject)
60            canvas.restoreState()
61
62            canvas.saveState()
63            business_details = listify(invoice.get('from','FROM:'))
64            canvas.setFont(self.font_face, 9)
65            textobject = canvas.beginText(13 * cm, -2.5 * cm)
66            for line in business_details:
67                textobject.textLine(line)
68            canvas.drawText(textobject)
69            canvas.restoreState()
70
71            canvas.saveState()
72            client_info = listify(invoice.get('to','TO:'))
73            textobject = canvas.beginText(1.5 * cm, -2.5 * cm)
74            for line in client_info:
75                textobject.textLine(line)
76            canvas.drawText(textobject)
77            canvas.restoreState()
78
79            textobject = canvas.beginText(1.5 * cm, -6.75 * cm)
80            textobject.textLine(u'Invoice ID: %s' % invoice.get('id','<invoice id>'))
81            textobject.textLine(u'Invoice Date: %s' % invoice.get('date',datetime.date.today()))
82            textobject.textLine(u'Client: %s' % invoice.get('client_name','<invoice client>'))
83            canvas.drawText(textobject)
84
85            items = invoice_items[1:][page*items_page:(page+1)*items_page]
86            if items:
87                data = [invoice_items[0]]
88                for item in items:
89                    data.append([
90                            self.format_currency(x)
91                            if isinstance(x,float) else x
92                            for x in item])
93                righta = [k for k,v in enumerate(items[0])
94                          if isinstance(v,(int,float,Decimal))]
95                if page == pages-1:
96                    total = self.format_currency(invoice['total'])
97                else:
98                    total = ''
99                data.append(['']*(len(items[0])-1)+[total])
100                colWidths = [2.5*cm]*len(items[0])
101                colWidths[1] = (21.5-2.5*len(items[0]))*cm
102                table = Table(data, colWidths=colWidths)
103                table.setStyle([
104                        ('FONT', (0, 0), (-1, -1), self.font_face),
105                        ('FONTSIZE', (0, 0), (-1, -1), 8),
106                        ('TEXTCOLOR', (0, 0), (-1, -1), (0.2, 0.2, 0.2)),
107                        ('GRID', (0, 0), (-1, -2), 1, (0.7, 0.7, 0.7)),
108                        ('GRID', (-1, -1), (-1, -1), 1, (0.7, 0.7, 0.7)),
109                        ('BACKGROUND', (0, 0), (-1, 0), (0.8, 0.8, 0.8)),
110                        ]+[('ALIGN',(k,0),(k,-1),'RIGHT') for k in righta])
111                tw, th, = table.wrapOn(canvas, 15 * cm, 19 * cm)
112                table.drawOn(canvas, 1 * cm, -8 * cm - th)
113
114            if page == pages-1:
115                items = invoice['totals'][1:]
116                if items:
117                    data = [invoice['totals'][0]]
118                    for item in items:
119                        data.append([
120                                self.format_currency(x)
121                                if isinstance(x,float) else x
122                                for x in item])
123                    righta = [k for k,v in enumerate(items[0])
124                              if isinstance(v,(int,float,Decimal))]
125                    total = self.format_currency(invoice['total'])
126                    data.append(['']*(len(items[0])-1)+[total])
127                    colWidths = [2.5*cm]*len(items[0])
128                    colWidths[1] = (21.5-2.5*len(items[0]))*cm
129                    table = Table(data, colWidths=colWidths)
130                    table.setStyle([
131                            ('FONT', (0, 0), (-1, -1), self.font_face),
132                            ('FONTSIZE', (0, 0), (-1, -1), 8),
133                            ('TEXTCOLOR', (0, 0), (-1, -1), (0.2, 0.2, 0.2)),
134                            ('GRID', (0, 0), (-1, -2), 1, (0.7, 0.7, 0.7)),
135                            ('GRID', (-1, -1), (-1, -1), 1, (0.7, 0.7, 0.7)),
136                            ('BACKGROUND', (0, 0), (-1, 0), (0.8, 0.8, 0.8)),
137                            ]+[('ALIGN',(k,0),(k,-1),'RIGHT') for k in righta])
138                    tw, th, = table.wrapOn(canvas, 15 * cm, 19 * cm)
139                    table.drawOn(canvas, 1 * cm, -18 * cm - th)
140            canvas.showPage()
141            canvas.save()
142        return buffer.getvalue()
143
144if __name__=='__main__':
145    invoice = {
146        'title':          'Invoice - web2py.com',
147        'id':             '00001',
148        'date':           '10/10/2013',
149        'client_name':    'Nobody',
150        'from':           'FROM:\nweb2py.com\nWabash ave\nChicago',
151        'to':             'TO:\nNobody\nHis address',
152        'notes':          'no comment!',
153        'total':          650.00,
154        'items': [
155            ['Codice','Desc','Quantity','Unit price','Total']]+[
156            ['000001','Chair',2,10.0,20.0] for k in range(30)],
157        'totals': [
158            ['Codice','Desc','Total']]+[
159            ['000001','Chairs',600.0],
160            ['','Tax',50.0]],
161        }
162    print(PDF().draw(invoice,items_page=20))
Note: See TracBrowser for help on using the repository browser.