pdfinvoice
This commit is contained in:
@@ -1 +1 @@
|
||||
Version 2.6.0-development+timestamp.2013.08.21.04.38.11
|
||||
Version 2.6.0-development+timestamp.2013.08.21.05.07.02
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
"""
|
||||
BSD license - created by Massimo Di Pierro
|
||||
"""
|
||||
from reportlab.pdfgen.canvas import Canvas
|
||||
from reportlab.platypus import Table
|
||||
from reportlab.lib.pagesizes import A4
|
||||
from reportlab.lib.units import cm
|
||||
from decimal import Decimal
|
||||
import cStringIO
|
||||
import datetime
|
||||
|
||||
def listify(item):
|
||||
if isinstance(item,basestring):
|
||||
item = item.split('\n')
|
||||
return item
|
||||
|
||||
class PDF(object):
|
||||
def __init__(self, page_size=A4, font_face='Helvetica'):
|
||||
self.page_size = page_size
|
||||
self.font_face = font_face
|
||||
self.logo = None
|
||||
def format_currency(self,value):
|
||||
a = list(str(int(value)))
|
||||
for k in range(len(a)-3,0,-3):
|
||||
a.insert(k,',')
|
||||
a = ''.join(a)
|
||||
b = ("%.2f" % (value-int(value)))[2:]
|
||||
return "%s.%s" % (a,b)
|
||||
def draw(self, invoice, items_page=10):
|
||||
""" Draws the invoice """
|
||||
buffer = cStringIO.StringIO()
|
||||
invoice_items = invoice['items']
|
||||
pages = max((len(invoice_items)-2)/items_page+1,1)
|
||||
canvas = Canvas(buffer, pagesize=self.page_size)
|
||||
for page in range(pages):
|
||||
canvas.translate(0, 29.7 * cm)
|
||||
canvas.setFont(self.font_face, 10)
|
||||
|
||||
canvas.saveState()
|
||||
canvas.setStrokeColorRGB(0.9, 0.5, 0.2)
|
||||
canvas.setFillColorRGB(0.2, 0.2, 0.2)
|
||||
canvas.setFont(self.font_face, 16)
|
||||
canvas.drawString(1 * cm, -1 * cm, invoice.get('title',''))
|
||||
if self.logo:
|
||||
canvas.drawInlineImage(self.logo, 1 * cm, -1 * cm, 250, 16)
|
||||
canvas.setLineWidth(4)
|
||||
canvas.line(0, -1.25 * cm, 21.7 * cm, -1.25 * cm)
|
||||
canvas.restoreState()
|
||||
|
||||
canvas.saveState()
|
||||
notes = listify(invoice.get('notes',''))
|
||||
textobject = canvas.beginText(1 * cm, -25 * cm)
|
||||
for line in notes:
|
||||
textobject.textLine(line)
|
||||
canvas.drawText(textobject)
|
||||
textobject = canvas.beginText(18 * cm, -28 * cm)
|
||||
textobject.textLine('Pag.%s/%s' % (page+1,pages))
|
||||
canvas.drawText(textobject)
|
||||
canvas.restoreState()
|
||||
|
||||
canvas.saveState()
|
||||
business_details = listify(invoice.get('from','FROM:'))
|
||||
canvas.setFont(self.font_face, 9)
|
||||
textobject = canvas.beginText(13 * cm, -2.5 * cm)
|
||||
for line in business_details:
|
||||
textobject.textLine(line)
|
||||
canvas.drawText(textobject)
|
||||
canvas.restoreState()
|
||||
|
||||
canvas.saveState()
|
||||
client_info = listify(invoice.get('to','TO:'))
|
||||
textobject = canvas.beginText(1.5 * cm, -2.5 * cm)
|
||||
for line in client_info:
|
||||
textobject.textLine(line)
|
||||
canvas.drawText(textobject)
|
||||
canvas.restoreState()
|
||||
|
||||
textobject = canvas.beginText(1.5 * cm, -6.75 * cm)
|
||||
textobject.textLine(u'Invoice ID: %s' % invoice.get('id','<invoice id>'))
|
||||
textobject.textLine(u'Invoice Date: %s' % invoice.get('date',datetime.date.today()))
|
||||
textobject.textLine(u'Client: %s' % invoice.get('client_name','<invoice client>'))
|
||||
canvas.drawText(textobject)
|
||||
|
||||
items = invoice_items[1:][page*items_page:(page+1)*items_page]
|
||||
if items:
|
||||
data = [invoice_items[0]]
|
||||
for item in items:
|
||||
data.append([
|
||||
self.format_currency(x)
|
||||
if isinstance(x,float) else x
|
||||
for x in item])
|
||||
righta = [k for k,v in enumerate(items[0])
|
||||
if isinstance(v,(int,float,Decimal))]
|
||||
if page == pages-1:
|
||||
total = self.format_currency(invoice['total'])
|
||||
else:
|
||||
total = ''
|
||||
data.append(['']*(len(items[0])-1)+[total])
|
||||
colWidths = [2.5*cm]*len(items[0])
|
||||
colWidths[1] = (21.5-2.5*len(items[0]))*cm
|
||||
table = Table(data, colWidths=colWidths)
|
||||
table.setStyle([
|
||||
('FONT', (0, 0), (-1, -1), self.font_face),
|
||||
('FONTSIZE', (0, 0), (-1, -1), 8),
|
||||
('TEXTCOLOR', (0, 0), (-1, -1), (0.2, 0.2, 0.2)),
|
||||
('GRID', (0, 0), (-1, -2), 1, (0.7, 0.7, 0.7)),
|
||||
('GRID', (-1, -1), (-1, -1), 1, (0.7, 0.7, 0.7)),
|
||||
('BACKGROUND', (0, 0), (-1, 0), (0.8, 0.8, 0.8)),
|
||||
]+[('ALIGN',(k,0),(k,-1),'RIGHT') for k in righta])
|
||||
tw, th, = table.wrapOn(canvas, 15 * cm, 19 * cm)
|
||||
table.drawOn(canvas, 1 * cm, -8 * cm - th)
|
||||
|
||||
if page == pages-1:
|
||||
items = invoice['totals'][1:]
|
||||
if items:
|
||||
data = [invoice['totals'][0]]
|
||||
for item in items:
|
||||
data.append([
|
||||
self.format_currency(x)
|
||||
if isinstance(x,float) else x
|
||||
for x in item])
|
||||
righta = [k for k,v in enumerate(items[0])
|
||||
if isinstance(v,(int,float,Decimal))]
|
||||
total = self.format_currency(invoice['total'])
|
||||
data.append(['']*(len(items[0])-1)+[total])
|
||||
colWidths = [2.5*cm]*len(items[0])
|
||||
colWidths[1] = (21.5-2.5*len(items[0]))*cm
|
||||
table = Table(data, colWidths=colWidths)
|
||||
table.setStyle([
|
||||
('FONT', (0, 0), (-1, -1), self.font_face),
|
||||
('FONTSIZE', (0, 0), (-1, -1), 8),
|
||||
('TEXTCOLOR', (0, 0), (-1, -1), (0.2, 0.2, 0.2)),
|
||||
('GRID', (0, 0), (-1, -2), 1, (0.7, 0.7, 0.7)),
|
||||
('GRID', (-1, -1), (-1, -1), 1, (0.7, 0.7, 0.7)),
|
||||
('BACKGROUND', (0, 0), (-1, 0), (0.8, 0.8, 0.8)),
|
||||
]+[('ALIGN',(k,0),(k,-1),'RIGHT') for k in righta])
|
||||
tw, th, = table.wrapOn(canvas, 15 * cm, 19 * cm)
|
||||
table.drawOn(canvas, 1 * cm, -18 * cm - th)
|
||||
canvas.showPage()
|
||||
canvas.save()
|
||||
return buffer.getvalue()
|
||||
|
||||
if __name__=='__main__':
|
||||
invoice = {
|
||||
'title': 'Invoice - web2py.com',
|
||||
'id': '00001',
|
||||
'date': '10/10/2013',
|
||||
'client_name': 'Nobody',
|
||||
'from': 'FROM:\nweb2py.com\nWabash ave\nChicago',
|
||||
'to': 'TO:\nNobody\nHis address',
|
||||
'notes': 'no comment!',
|
||||
'total': 650.00,
|
||||
'items': [
|
||||
['Codice','Desc','Quantity','Unit price','Total']]+[
|
||||
['000001','Chair',2,10.0,20.0] for k in range(30)],
|
||||
'totals': [
|
||||
['Codice','Desc','Total']]+[
|
||||
['000001','Chairs',600.0],
|
||||
['','Tax',50.0]],
|
||||
}
|
||||
print PDF().draw(invoice,items_page=20)
|
||||
Reference in New Issue
Block a user