8aa566cb7becbbee440e58d345337df75632f8ba
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

1) # -* coding: utf8 *-
2) 
Bernd Wurst Umbenannt aber wieder in ko...

Bernd Wurst authored 16 years ago

3) from Invoice import *
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) fontpath_vera = '/usr/share/fonts/ttf-bitstream-vera/'
18) 
19) 
20) def _formatPrice(price, symbol='€'):
21)   '''_formatPrice(price, symbol='€'):
22)   Gets a floating point value and returns a formatted price, suffixed by 'symbol'. '''
23)   s = ("%.2f" % price).replace('.', ',')
24)   pat = re.compile(r'([0-9])([0-9]{3}[.,])')
25)   while pat.search(s):
26)     s = pat.sub(r'\1.\2', s)
27)   return s+' '+symbol
28) 
29) def _niceCount(value):
30)   '''_niceCount(value):
31)   Returns a tuple (integer , decimals) where decimals can be None'''
32)   if type(value) == int:
33)     return ('%i' % value, None)
34)   if round(value, 2) == int(value):
35)     return ('%i' % int(value), None)
36)   s = '%.2f' % value
37)   (integer, decimals) = s.split('.', 1)
38)   if decimals[-1] == '0':
39)     decimals = decimals[:-1]
40)   return (integer, decimals)
41) 
42) 
43) def _registerFonts():
44)   pdfmetrics.registerFont(TTFont("Vera", fontpath_vera + "Vera.ttf"))
45)   pdfmetrics.registerFont(TTFont("Vera-Bold", fontpath_vera + "VeraBd.ttf"))
46)   pdfmetrics.registerFont(TTFont("Vera-Oblique", fontpath_vera + "VeraIt.ttf"))
47)   pdfmetrics.registerFont(TTFont("Vera-BoldOblique", fontpath_vera + "VeraBI.ttf"))
48) 
49) 
50) 
51) def _splitToWidth(canvas, text, width, font, size):
52)   '''_splitToWidth(canvas, text, width, font, size)
53)   Split a string to several lines of a given width.'''
54)   lines = []
55)   paras = text.split('\n')
56)   for para in paras:
57)     words = para.split(' ')
58)     while len(words) > 0:
59)       mywords = [words[0], ]
60)       del words[0]
61)       while len(words) > 0 and canvas.stringWidth(' '.join(mywords) + ' ' + words[0], font, size) <= width:
62)         mywords.append(words[0])
63)         del words[0]
64)       lines.append(' '.join(mywords))
65)   return lines
66) 
67) 
68) def _PageMarkers(canvas):
69)   """Setzt Falzmarken"""
70)   from reportlab.lib.units import cm
71)   canvas.setStrokeColorRGB(0,0,0)
72)   canvas.setLineWidth(0.01*cm)
73)   canvas.lines(
74)    [(0.3*cm,-10.5*cm,0.65*cm,-10.5*cm),
75)     (0.3*cm,-21.0*cm,0.65*cm,-21.0*cm),
76)     (0.3*cm,-14.85*cm,0.7*cm,-14.85*cm)]);
77) 
78) 
79) 
80) def _PageWrap(canvas):
81)   '''Seitenumbruch'''
82)   canvas.showPage()
83)   canvas.translate(0, A4[1])
84)   _PageMarkers(canvas)
85) 
86) 
87) 
88) def InvoiceToPDF(iv):
89)   _registerFonts()
90)   from StringIO import StringIO
91)   fd = StringIO()
92)   canvas = Canvas.Canvas(fd, pagesize=A4)
93)   (width, height) = A4
94)   font = 'Vera'
95)   canvas.setFont(font, 12)
96)   # Set marker to top.
97)   canvas.translate(0, A4[1])
98)   # Set default font size
99)   default_font_size = 9
100)   # set margins
101)   topmargin = 2*cm
102)   bottommargin = 2.5*cm
103)   leftmargin = 2*cm
104)   rightmargin = 2*cm
105) 
106)   num_pages = 1
107) 
108)   topcontent = -topmargin
109)   leftcontent = leftmargin
110)   rightcontent = A4[0] - rightmargin
111)   bottomcontent =  -(A4[1] - bottommargin)
112) 
113)   rightcolumn = 13*cm
114) 
115)   # Waehrungssysmbol
116)   symbol = '€'
117)   y = topcontent
118)   font_size = default_font_size
119)   font_height = 0.35*cm
120)   line_padding = 0.1*cm
121)   line_height = font_height+0.1*cm
122)   _PageMarkers(canvas)
123) 
124)   def _partHeight(part):
125)     height = 0
Bernd Wurst Umbenannt aber wieder in ko...

Bernd Wurst authored 16 years ago

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

Bernd Wurst authored 16 years ago

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

Bernd Wurst authored 16 years ago

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

Bernd Wurst authored 16 years ago

137)       ## FIXME: Das ist dreckig
138)       height = len(part.entries) * 1.1*cm
139)       height += 3*cm
140)     return height
141) 
142)   def _Footer():
143)     canvas.line(leftcontent, bottomcontent, rightcontent, bottomcontent)
144)     canvas.setFont(font, 8)
145)     canvas.drawCentredString(leftcontent+((rightcontent-leftcontent)/2), bottomcontent-10, 'schokokeks.org GbR · Bernd Wurst / Johannes Böck · http://www.schokokeks.org/')
146)     canvas.drawCentredString(leftcontent+((rightcontent-leftcontent)/2), bottomcontent-20, 'Steuernummer: 51072/01109 (FA Backnang) · USt-ID: DE255720588')
147)     canvas.drawCentredString(leftcontent+((rightcontent-leftcontent)/2), bottomcontent-30, 'Bankverbindung: Volksbank Backnang, BLZ 602 911 20, Konto Nr. 671279 017')
148)     canvas.drawCentredString(leftcontent+((rightcontent-leftcontent)/2), bottomcontent-40, 'IBAN: DE78602911200671279017, BIC: GENODES1VBK')
149)   
150)   
151)   addy_width = 8.5*cm
152)   addy_height = 5.0*cm
153) 
154)   font_size = 8
155)   x = 2.0 * cm
156)   y = -4.8 * cm - font_size - 1
157) 
158)   canvas.setFont(font, font_size)
159) 
160) 
161)   canvas.drawString(x, y+0.1*cm, ' schokokeks.org - Köchersberg 25 - 71540 Murrhardt')
162)   canvas.line(x, y, x + (8.5 * cm), y)
163)   y = y - font_size - 3
164) 
165)   font_size = 11
166)   x += 0.5*cm
167)   y -= 0.5*cm
168)   canvas.setFont(font, font_size)
169)   for line in iv.addresslines:
170)     canvas.drawString(x, y, line)
171)     y -= line_height
172) 
173) 
174)   font_size = default_font_size
175) 
176)   y = topcontent
177)   canvas.drawInlineImage("logo.png", rightcolumn, topcontent-(3*cm), width=4.08*cm, height=3*cm)
178)   y -= (3.5*cm)
179)   canvas.setFont(font+"-Bold", font_size)
180)   #canvas.drawString(rightcolumn, y, "schokokeks.org Webhosting")
181)   #y -= (font_size + 5 + 0.2*cm)
182)   canvas.drawString(rightcolumn, y, "schokokeks.org GbR")
183)   y -= (font_size + 5)
184)   canvas.setFont(font, font_size)
185)   canvas.drawString(rightcolumn, y, "Bernd Wurst / Johannes Böck")
186)   y -= (font_size + 5)
187)   canvas.drawString(rightcolumn, y, "Köchersberg 25")
188)   y -= (font_size + 5)
189)   canvas.drawString(rightcolumn, y, "71540 Murrhardt")
190)   y -= (font_size + 10)
191)   canvas.drawString(rightcolumn, y, "Tel: 07192-936432")
192)   y -= (font_size + 5)
193)   canvas.drawString(rightcolumn, y, "Fax: 07192-936431")
194)   y -= (font_size + 5)
195)   canvas.drawString(rightcolumn, y, "E-Mail: root@schokokeks.org")
196)   y -= (font_size + 10)
197)   y = -9.5*cm
198)   canvas.setFont(font+'-Bold', font_size+3)
199)   if iv.tender:
200)     canvas.drawString(leftcontent, y, 'Angebot')
201)   else:
202)     canvas.drawString(leftcontent, y, 'Rechnung')
203) 
204)   if iv.tender:
205)     canvas.setFont(font, font_size)
206)     canvas.drawString(rightcolumn, y, "Erstellungsdatum:")
207)     canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
208)     y -= (font_size + 0.1*cm)
209)     
210)   else:
211)     canvas.setFont(font+'-Bold', font_size)
212)     canvas.drawString(rightcolumn, y, "Bei Fragen bitte immer angeben:")
213)     y -= (font_size + 0.2*cm)
214)     canvas.setFont(font, font_size)
215)     canvas.drawString(rightcolumn, y, "Rechnungsdatum:")
216)     canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
217)     y -= (font_size + 0.1*cm)
218)     canvas.drawString(rightcolumn, y, "Rechnungsnummer:")
219)     canvas.drawRightString(rightcontent, y, "%i" % iv.id)
220)     y -= (font_size + 0.1*cm)
221)   if iv.customerno:
222)     canvas.drawString(rightcolumn, y, "Kundennummer:")
223)     canvas.drawRightString(rightcontent, y, "%s" % iv.customerno)
224)     y -= (font_size + 0.5*cm)
225)   canvas.setFont(font, font_size)
226) 
227)   canvas.drawString(leftcontent, y, iv.salutation)
228)   y -= font_size + 0.2*cm
229)   introText = 'hiermit stellen wir Ihnen die nachfolgend genannten Leistungen in Rechnung.'
230)   if iv.tender:
231)     introText = 'hiermit unterbreiten wir Ihnen folgendes Angebot.'
232)   intro = _splitToWidth(canvas, introText, rightcontent - leftcontent, font, font_size)
233)   for line in intro:
234)     canvas.drawString(leftcontent, y, line)
235)     y -= font_size + 0.1*cm
236)   y -= font_size + 0.1*cm
237) 
238)   
239)   font_size = default_font_size
240)   for part in iv.parts:
241)     if y - _partHeight(part) < (bottomcontent + (0.5*cm)):
242)       num_pages += 1
243)       y = bottomcontent + (0.5*cm)
244)       canvas.setFont(font, default_font_size-2)
245)       canvas.drawRightString(rightcontent, bottomcontent + line_padding, 'Fortsetzung auf Seite %i' % num_pages)
246)       _Footer()
247)       _PageWrap(canvas)
248)       y = topcontent - font_size
249)       canvas.setFillColor((0,0,0))
250)       canvas.setFont(font, font_size-2)
251)       canvas.drawCentredString(leftcontent + (rightcontent - leftcontent) / 2, y, '- Seite %i -' % num_pages)
252)       y -= line_padding*3
Bernd Wurst Umbenannt aber wieder in ko...

Bernd Wurst authored 16 years ago

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

Bernd Wurst authored 16 years ago

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

Bernd Wurst authored 16 years ago

380)     elif type(part) == Text: