from reportlab.pdfgen.canvas import Canvas
from reportlab.platypus import Table
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm
import cStringIO
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()
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(18 * cm, -1 * cm, invoice['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 = invoice.get('notes',[])
textobject = canvas.beginText(1 * cm, -23 * 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 = invoice['business']
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()
textobject = canvas.beginText(1.5 * cm, -2.5 * cm)
for line in invoice['client_address']:
textobject.textLine(line)
canvas.drawText(textobject)
textobject = canvas.beginText(1.5 * cm, -6.75 * cm)
textobject.textLine(u'Invoice ID: %s' % invoice['id'])
textobject.textLine(u'Invoice Date: %s' % invoice['date'])
textobject.textLine(u'Client: %s' % invoice['client_name'])
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))]
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))]
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, -16 * cm - th)
canvas.showPage()
canvas.save()
return buffer.getvalue()
if __name__=='__main__':
invoice = {
'title': 'Invoice',
'id': '00001',
'date': '10/10/2013',
'business': ['FROM:', 'Mr Accountant','1st Street'],
'client_name': 'Mr Blue',
'client_address': ['TO:','Blue','2nd Street'],
'notes': ['no comment!'],
'total': 2000.00,
'items': [
['Code','Descr','Quantity','Unit price','Total']]+[
['000001','Chair',k,20.0,80.0] for k in range(30)],
'totals': [
['Code','Descr','Totale']]+[
['000001','Test',80.0] for k in range(5)],
}
print PDF().draw(invoice)