831fef3d3473e084ffae234b31455ce0ce3e174d
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

1) # -* coding: utf8 *-
2) 
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

3) import Invoice
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

4) import re
5) 
6) # reportlab imports
7) from reportlab.lib.units import cm
8) from reportlab.lib.pagesizes import A4
9) from reportlab.pdfbase.ttfonts import TTFont, TTFontFace, TTFontFile, TTFOpenFile, \
10)                                   TTFontParser, TTFontMaker, TTFError, \
11)                                   parse_utf8, makeToUnicodeCMap, \
12)                                   FF_SYMBOLIC, FF_NONSYMBOLIC, \
13)                                   calcChecksum
14) from reportlab.pdfbase import pdfmetrics
15) from reportlab.pdfgen import canvas as Canvas
16) 
17) 
18) def _formatPrice(price, symbol='€'):
19)   '''_formatPrice(price, symbol='€'):
20)   Gets a floating point value and returns a formatted price, suffixed by 'symbol'. '''
21)   s = ("%.2f" % price).replace('.', ',')
22)   pat = re.compile(r'([0-9])([0-9]{3}[.,])')
23)   while pat.search(s):
24)     s = pat.sub(r'\1.\2', s)
25)   return s+' '+symbol
26) 
27) def _niceCount(value):
28)   '''_niceCount(value):
29)   Returns a tuple (integer , decimals) where decimals can be None'''
30)   if type(value) == int:
31)     return ('%i' % value, None)
32)   if round(value, 2) == int(value):
33)     return ('%i' % int(value), None)
34)   s = '%.2f' % value
35)   (integer, decimals) = s.split('.', 1)
36)   if decimals[-1] == '0':
37)     decimals = decimals[:-1]
38)   return (integer, decimals)
39) 
40) 
41) def _registerFonts():
Bernd Wurst reportlab-2.1 erkennt den T...

Bernd Wurst authored 16 years ago

42)   pdfmetrics.registerFont(TTFont("Vera", "Vera.ttf"))
43)   pdfmetrics.registerFont(TTFont("Vera-Bold", "VeraBd.ttf"))
44)   pdfmetrics.registerFont(TTFont("Vera-Oblique", "VeraIt.ttf"))
45)   pdfmetrics.registerFont(TTFont("Vera-BoldOblique", "VeraBI.ttf"))
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

46) 
47) 
48) 
49) def _splitToWidth(canvas, text, width, font, size):
50)   '''_splitToWidth(canvas, text, width, font, size)
51)   Split a string to several lines of a given width.'''
52)   lines = []
53)   paras = text.split('\n')
54)   for para in paras:
55)     words = para.split(' ')
56)     while len(words) > 0:
57)       mywords = [words[0], ]
58)       del words[0]
59)       while len(words) > 0 and canvas.stringWidth(' '.join(mywords) + ' ' + words[0], font, size) <= width:
60)         mywords.append(words[0])
61)         del words[0]
62)       lines.append(' '.join(mywords))
63)   return lines
64) 
65) 
66) def _PageMarkers(canvas):
67)   """Setzt Falzmarken"""
68)   from reportlab.lib.units import cm
69)   canvas.setStrokeColorRGB(0,0,0)
70)   canvas.setLineWidth(0.01*cm)
71)   canvas.lines(
72)    [(0.3*cm,-10.5*cm,0.65*cm,-10.5*cm),
73)     (0.3*cm,-21.0*cm,0.65*cm,-21.0*cm),
74)     (0.3*cm,-14.85*cm,0.7*cm,-14.85*cm)]);
75) 
76) 
77) 
78) def _PageWrap(canvas):
79)   '''Seitenumbruch'''
80)   canvas.showPage()
81)   canvas.translate(0, A4[1])
82)   _PageMarkers(canvas)
83) 
84) 
85) 
86) def InvoiceToPDF(iv):
87)   _registerFonts()
88)   from StringIO import StringIO
89)   fd = StringIO()
90)   canvas = Canvas.Canvas(fd, pagesize=A4)
91)   (width, height) = A4
92)   font = 'Vera'
93)   canvas.setFont(font, 12)
94)   # Set marker to top.
95)   canvas.translate(0, A4[1])
96)   # Set default font size
97)   default_font_size = 9
98)   # set margins
99)   topmargin = 2*cm
100)   bottommargin = 2.5*cm
101)   leftmargin = 2*cm
102)   rightmargin = 2*cm
103) 
104)   num_pages = 1
105) 
106)   topcontent = -topmargin
107)   leftcontent = leftmargin
108)   rightcontent = A4[0] - rightmargin
109)   bottomcontent =  -(A4[1] - bottommargin)
110) 
111)   rightcolumn = 13*cm
112) 
113)   # Waehrungssysmbol
114)   symbol = '€'
115)   y = topcontent
116)   font_size = default_font_size
117)   font_height = 0.35*cm
118)   line_padding = 0.1*cm
119)   line_height = font_height+0.1*cm
120)   _PageMarkers(canvas)
121) 
122)   def _partHeight(part):
123)     height = 0
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

124)     if type(part) == Invoice.Text:
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

125)       left, right = leftcontent, rightcontent
126)       if part.urgent:
127)         left += 1.5*cm
128)         right -= 1.5*cm
129)         height += len(part.paragraphs) * 3 * line_padding
130)       if part.headline:
131)         height += (len(_splitToWidth(canvas, part.headline, right-left, font+'-Bold', default_font_size+1)) * line_height) + line_padding
132)       for para in part.paragraphs:  
133)         height += (len(_splitToWidth(canvas, para, right-left, font, default_font_size)) * line_height) + line_padding
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

134)     elif type(part) == Invoice.Table:
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

135)       ## FIXME: Das ist dreckig
136)       height = len(part.entries) * 1.1*cm
137)       height += 3*cm
138)     return height
139) 
Bernd Wurst Neuer Footer

Bernd Wurst authored 16 years ago

140)   def _Footer(canvas):
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

141)     canvas.line(leftcontent, bottomcontent, rightcontent, bottomcontent)
Bernd Wurst Neuer Footer

Bernd Wurst authored 16 years ago

142)     canvas.setFont(font, 7)
143)     canvas.drawString(leftcontent, bottomcontent-10, 'schokokeks.org GbR')
144)     canvas.drawString(leftcontent, bottomcontent-20, 'Bernd Wurst / Johannes Böck')
145)     canvas.drawString(leftcontent, bottomcontent-30, 'http://www.schokokeks.org')
146)     canvas.drawString(leftcontent, bottomcontent-40, 'root@schokokeks.org')
147)     
148)     canvas.drawString(leftcontent+((rightcontent-leftcontent)/3), bottomcontent-10, 'Steuernummer 51072/01109')
149)     canvas.drawString(leftcontent+((rightcontent-leftcontent)/3), bottomcontent-20, 'Finanzamt Backnang')
150)     canvas.drawString(leftcontent+((rightcontent-leftcontent)/3), bottomcontent-30, 'USt-ID: DE255720588')
151) 
152)     canvas.drawString(leftcontent+((rightcontent-leftcontent)/3)*2, bottomcontent-10, 'Volksbank Backnang (BLZ: 602 911 20)')
153)     canvas.drawString(leftcontent+((rightcontent-leftcontent)/3)*2, bottomcontent-20, 'Konto: 671279 017')
154)     canvas.drawString(leftcontent+((rightcontent-leftcontent)/3)*2, bottomcontent-30, 'IBAN: DE78602911200671279017')
155)     canvas.drawString(leftcontent+((rightcontent-leftcontent)/3)*2, bottomcontent-40, 'BIC: GENODES1VBK')
156) 
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

157)   
158)   addy_width = 8.5*cm
159)   addy_height = 5.0*cm
160) 
161)   font_size = 8
162)   x = 2.0 * cm
163)   y = -4.8 * cm - font_size - 1
164) 
165)   canvas.setFont(font, font_size)
166) 
167) 
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

168)   canvas.drawString(x, y+0.1*cm, ' schokokeks.org · Köchersberg 25 · 71540 Murrhardt')
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

169)   canvas.line(x, y, x + (8.5 * cm), y)
170)   y = y - font_size - 3
171) 
172)   font_size = 11
173)   x += 0.5*cm
174)   y -= 0.5*cm
175)   canvas.setFont(font, font_size)
176)   for line in iv.addresslines:
177)     canvas.drawString(x, y, line)
178)     y -= line_height
179) 
180) 
181)   font_size = default_font_size
182) 
183)   y = topcontent
184)   canvas.drawInlineImage("logo.png", rightcolumn, topcontent-(3*cm), width=4.08*cm, height=3*cm)
185)   y -= (3.5*cm)
186)   canvas.setFont(font+"-Bold", font_size)
187)   #canvas.drawString(rightcolumn, y, "schokokeks.org Webhosting")
188)   #y -= (font_size + 5 + 0.2*cm)
189)   canvas.drawString(rightcolumn, y, "schokokeks.org GbR")
190)   y -= (font_size + 5)
191)   canvas.setFont(font, font_size)
192)   canvas.drawString(rightcolumn, y, "Bernd Wurst / Johannes Böck")
193)   y -= (font_size + 5)
194)   canvas.drawString(rightcolumn, y, "Köchersberg 25")
195)   y -= (font_size + 5)
196)   canvas.drawString(rightcolumn, y, "71540 Murrhardt")
197)   y -= (font_size + 10)
198)   canvas.drawString(rightcolumn, y, "Tel: 07192-936432")
199)   y -= (font_size + 5)
200)   canvas.drawString(rightcolumn, y, "Fax: 07192-936431")
201)   y -= (font_size + 5)
202)   canvas.drawString(rightcolumn, y, "E-Mail: root@schokokeks.org")
203)   y -= (font_size + 10)
204)   y = -9.5*cm
205)   canvas.setFont(font+'-Bold', font_size+3)
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

206)   min_y = y
207)   if iv.caption:
208)     canvas.drawString(leftcontent, y, iv.caption)
209)     min_y -= (font_size + 3) + 0.5*cm
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

210) 
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

211)   if type(iv) == Invoice.Tender:
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

212)     canvas.setFont(font, font_size)
213)     canvas.drawString(rightcolumn, y, "Erstellungsdatum:")
214)     canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
215)     y -= (font_size + 0.1*cm)
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

216)   elif type(iv) == Invoice.Generic:
217)     canvas.setFont(font, font_size)
218)     canvas.drawString(rightcolumn, y, "Datum:")
219)     canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
220)     y -= (font_size + 0.1*cm)
221)   elif type(iv) == Invoice.Invoice:
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

222)     canvas.setFont(font+'-Bold', font_size)
223)     canvas.drawString(rightcolumn, y, "Bei Fragen bitte immer angeben:")
224)     y -= (font_size + 0.2*cm)
225)     canvas.setFont(font, font_size)
226)     canvas.drawString(rightcolumn, y, "Rechnungsdatum:")
227)     canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
228)     y -= (font_size + 0.1*cm)
229)     canvas.drawString(rightcolumn, y, "Rechnungsnummer:")
230)     canvas.drawRightString(rightcontent, y, "%i" % iv.id)
231)     y -= (font_size + 0.1*cm)
232)   if iv.customerno:
233)     canvas.drawString(rightcolumn, y, "Kundennummer:")
234)     canvas.drawRightString(rightcontent, y, "%s" % iv.customerno)
235)     y -= (font_size + 0.5*cm)
236)   canvas.setFont(font, font_size)
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

237)   y = min(min_y, y)
238) 
239)   if iv.salutation:
240)     canvas.drawString(leftcontent, y, iv.salutation)
241)     y -= font_size + 0.2*cm
242)     if type(iv) in [Invoice.Tender, Invoice.Invoice]:
243)       introText = 'hiermit stellen wir Ihnen die nachfolgend genannten Leistungen in Rechnung.'
244)       if type(iv) == Invoice.Tender:
245)         introText = 'hiermit unterbreiten wir Ihnen folgendes Angebot.'
246)       intro = _splitToWidth(canvas, introText, rightcontent - leftcontent, font, font_size)
247)       for line in intro:
248)         canvas.drawString(leftcontent, y, line)
249)         y -= font_size + 0.1*cm
250)       y -= font_size + 0.1*cm
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

251) 
252)   
253)   font_size = default_font_size
254)   for part in iv.parts:
255)     if y - _partHeight(part) < (bottomcontent + (0.5*cm)):
256)       num_pages += 1
257)       y = bottomcontent + (0.5*cm)
258)       canvas.setFont(font, default_font_size-2)
259)       canvas.drawRightString(rightcontent, bottomcontent + line_padding, 'Fortsetzung auf Seite %i' % num_pages)
Bernd Wurst Neuer Footer

Bernd Wurst authored 16 years ago

260)       _Footer(canvas)
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

261)       _PageWrap(canvas)
262)       y = topcontent - font_size
263)       canvas.setFillColor((0,0,0))
264)       canvas.setFont(font, font_size-2)
265)       canvas.drawCentredString(leftcontent + (rightcontent - leftcontent) / 2, y, '- Seite %i -' % num_pages)
266)       y -= line_padding*3
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

267)     if type(part) == Invoice.Table:
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

268)         
269)       left = leftcontent
270)       right = rightcontent
271)       top = topcontent
272)       bottom = bottomcontent
273)       canvas.setFont(font, font_size)
274)       canvas.drawString(left+(0.1*cm), y-line_height+line_padding, 'Anz.')
275)       canvas.drawString(left+(1.6*cm), y-line_height+line_padding, 'Beschreibung')
276)       if len(part.vat) == 1:
277)         canvas.drawRightString(left+(14.3*cm), y-line_height+line_padding, 'Einzelpreis')
278)       else:
279)         canvas.drawRightString(left+(13.7*cm), y-line_height+line_padding, 'Einzelpreis')
280)       canvas.drawRightString(left+(16.8*cm), y-line_height+line_padding, 'Gesamtpreis')
281)       canvas.setLineWidth(0.01*cm)
282)       canvas.line(left, y - line_height, right, y - line_height)
283)       y -= line_height + 0.02*cm
284)       odd=True
285)       for el in part.entries:
286)         subject = []
287)         if len(part.vat) == 1:
288)           subject = _splitToWidth(canvas, el['subject'], 10.3*cm, font, font_size)
289)         else:
290)           subject = _splitToWidth(canvas, el['subject'], 9.3*cm, font, font_size)
291)         desc = []
292)         if 'desc' in el and el['desc'] != '':
293)           desc = _splitToWidth(canvas, el['desc'], 14.5*cm, font, font_size)
294) 
295)         # draw the background
296)         if not odd:
297)           canvas.setFillColorRGB(0.9, 0.9, 0.9)
298)         else:
299)           canvas.setFillColorRGB(1, 1, 1)
300)         need_lines = len(subject) + len(desc)
301)         canvas.rect(left, y - (need_lines*line_height)-(2*line_padding), height = (need_lines*line_height)+(2*line_padding), width = right-left, fill=1, stroke=0)
302)         canvas.setFillColorRGB(0, 0, 0)
303)         y -= line_padding
304)         (integer, decimals) = _niceCount(el['count'])
305)         canvas.drawRightString(left+0.8*cm, y-font_height, integer)
306)         if decimals:
307)           canvas.drawString(left+0.8*cm, y-font_height, ',%s' % decimals)
308)         if len(part.vat) == 1:
309)           canvas.drawString(left+1.7*cm, y-font_height, subject[0])
310)           canvas.drawRightString(left+14.3*cm, y-font_height, _formatPrice(el['price']))
311)           if el['tender']:  
312)             canvas.drawRightString(left+16.8*cm, y-font_height, 'eventual')
313)           else:
314)             canvas.drawRightString(left+16.8*cm, y-font_height, _formatPrice(el['total']))
315)           subject = subject[1:]
316)           x = 1
317)           for line in subject:
318)             canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
319)             x += 1
320)           for line in desc:
321)             canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
322)             x += 1
323)         else:
324)           canvas.drawString(left+1.7*cm, y-font_height, subject[0])
325)           canvas.drawRightString(left+13.3*cm, y-font_height, _formatPrice(el['price']))
326)           canvas.drawString(left+13.7*cm, y-font_height, str(part.vat[el['vat']][1]))
327)           if el['tender']:  
328)             canvas.drawRightString(left+16.8*cm, y-font_height, 'eventual')
329)           else:
330)             canvas.drawRightString(left+16.8*cm, y-font_height, _formatPrice(el['total']))
331)           subject = subject[1:]
332)           x = 1
333)           for line in subject:
334)             canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
335)             x += 1
336)           for line in desc:
337)             canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
338)             x += 1
339)         odd = not odd
340)         y -= (need_lines * line_height) + line_padding
341)       if part.summary:
342)         y -= (0.3*cm)
343)         if part.vatType == 'gross':
344)           canvas.setFont(font+'-Bold', font_size)
345)           if iv.tender:
346)             canvas.drawRightString(left + 14.5*cm, y-font_height, 'Gesamtbetrag:')
347)           else:
348)             canvas.drawRightString(left + 14.5*cm, y-font_height, 'Rechnungsbetrag:')
349)           canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(part.sum))
350)           canvas.setFont(font, font_size)
351)           y -= line_height + line_padding
352)           summaries = []
353)           if len(part.vat) == 1:
354)             vat = part.vat.keys()[0]
355)             if iv.tender:
356)               summaries.append(('Im Gesamtbetrag sind %.1f%% MwSt enthalten:' % (vat*100), _formatPrice((part.sum/(vat+1))*vat)))
357)             else:
358)               summaries.append(('Im Rechnungsbetrag sind %.1f%% MwSt enthalten:' % (vat*100), _formatPrice((part.sum/(vat+1))*vat)))
359)           else:
360)             for vat, vatdata in part.vat.iteritems():
361)               summaries.append('%s: Im Teilbetrag von %s sind %.1f%% MwSt enthalten:' % (vatdata[1], _formatPrice(vatdata[0]), vat*100), _formatPrice((vatdata[0]/(vat+1))*vat))
362)           summaries.sort()
363)           for line in summaries:
364)             canvas.drawRightString(left + 14.5*cm, y-font_height, line[0])
365)             canvas.drawRightString(left + 16.8*cm, y-font_height, line[1])
366)             y -= line_height
367)         else:
368)           canvas.drawRightString(left + 14.5*cm, y-font_height, 'Nettobetrag:')
369)           canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(part.sum))
370)           y -= line_height
371)           summaries = []
372)           if len(part.vat) == 1:
373)             vat = part.vat.keys()[0]
374)             summaries.append(('zzgl. %.1f%% MwSt:' % (vat*100), _formatPrice(vat*part.sum)))
375)           else:
376)             for vat, vatdata in part.vat.iteritems():
377)               summaries.append(('zzgl. %.1f%% MwSt (%s):' % (vat*100, vatdata[1]), _formatPrice(vat*vatdata[0])))
378)           summaries.sort()
379)           for line in summaries:
380)             canvas.drawRightString(left + 14.5*cm, y-font_height, line[0])
381)             canvas.drawRightString(left + 16.8*cm, y-font_height, line[1])
382)             y -= line_height
383)           sum = 0
384)           for vat, vatdata in part.vat.iteritems():
385)             sum += (vat+1)*vatdata[0]
386)           canvas.setFont(font+'-Bold', font_size)
387)           if iv.tender:
388)             canvas.drawRightString(left + 14.5*cm, y-font_height, 'Gesamtbetrag:')
389)           else:
390)             canvas.drawRightString(left + 14.5*cm, y-font_height, 'Rechnungsbetrag:')
391)           canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(sum))
392)           canvas.setFont(font, font_size)
393)           y -= line_height + line_padding
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

394)     elif type(part) == Invoice.Text:
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

395)       my_font_size = font_size
396)       canvas.setFont(font, my_font_size)
397)       left, right = leftcontent, rightcontent
398)       firsttime = True
399)       headlines = []
400)       if part.urgent:
401)         left += 1.5*cm
402)         right -= 1.5*cm
403)       if part.headline:
404)         headlines = _splitToWidth(canvas, part.headline, right-left, font, my_font_size)
405)       for para in part.paragraphs:
406)         lines = _splitToWidth(canvas, para, right-left, font, my_font_size)
407)         if part.urgent:
408)           need_height = len(lines) * line_height
409)           if len(headlines) > 0:
410)             need_height += len(headlines) * (line_height + 1) + line_padding
411)           canvas.setFillColorRGB(0.95, 0.95, 0.95)
412)           canvas.rect(left-0.5*cm, y - (need_height+(6*line_padding)), height = need_height+(6*line_padding), width = right-left+1*cm, fill=1, stroke=1)
413)           canvas.setFillColorRGB(0, 0, 0)
414)           y -= line_padding*3
415)         if part.headline and firsttime:
416)           firsttime = False
417)           canvas.setFont(font+'-Bold', my_font_size+1)
418)           for line in headlines:
419)             canvas.drawString(left, y-(font_height+1), line)
420)             y -= line_height + 1
421)           y -= line_padding
422)           canvas.setFont(font, my_font_size)
423)         for line in lines:
424)           canvas.drawString(left, y-font_height, line)
425)           y -= line_height
426)         y -= line_padding*3
427)       left, right = leftcontent, rightcontent
428)     else:
429)       raise NotImplementedError("Cannot handle part of type %s" % type(part))
430)     y -= (0.5*cm)
431)     
Bernd Wurst Neuer Footer

Bernd Wurst authored 16 years ago

432)   _Footer(canvas)