2960b23c6cfe403fc8f45fec613083c757b311bf
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) 
Bernd Wurst Trennung von Firmen-spezifi...

Bernd Wurst authored 16 years ago

6) # our page size and margins
7) from metrics import *
8) # our custom page style
Bernd Wurst Break long address-lines

Bernd Wurst authored 15 years ago

9) from custom_elements import basicPage, firstPage, address_header
Bernd Wurst Trennung von Firmen-spezifi...

Bernd Wurst authored 16 years ago

10) 
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

11) # reportlab imports
12) from reportlab.lib.units import cm
13) from reportlab.pdfgen import canvas as Canvas
14) 
15) 
16) def _formatPrice(price, symbol='€'):
17)   '''_formatPrice(price, symbol='€'):
18)   Gets a floating point value and returns a formatted price, suffixed by 'symbol'. '''
19)   s = ("%.2f" % price).replace('.', ',')
20)   pat = re.compile(r'([0-9])([0-9]{3}[.,])')
21)   while pat.search(s):
22)     s = pat.sub(r'\1.\2', s)
23)   return s+' '+symbol
24) 
25) def _niceCount(value):
26)   '''_niceCount(value):
27)   Returns a tuple (integer , decimals) where decimals can be None'''
28)   if type(value) == int:
29)     return ('%i' % value, None)
30)   if round(value, 2) == int(value):
31)     return ('%i' % int(value), None)
32)   s = '%.2f' % value
33)   (integer, decimals) = s.split('.', 1)
34)   if decimals[-1] == '0':
35)     decimals = decimals[:-1]
36)   return (integer, decimals)
37) 
38) 
39) def _splitToWidth(canvas, text, width, font, size):
40)   '''_splitToWidth(canvas, text, width, font, size)
41)   Split a string to several lines of a given width.'''
42)   lines = []
43)   paras = text.split('\n')
44)   for para in paras:
45)     words = para.split(' ')
46)     while len(words) > 0:
47)       mywords = [words[0], ]
48)       del words[0]
49)       while len(words) > 0 and canvas.stringWidth(' '.join(mywords) + ' ' + words[0], font, size) <= width:
50)         mywords.append(words[0])
51)         del words[0]
52)       lines.append(' '.join(mywords))
53)   return lines
54) 
55) 
Bernd Wurst InvoiceText als Blocksatz d...

Bernd Wurst authored 16 years ago

56) def _drawJustifiedString(x, y, text, canvas, width, font, size):
57)   text = text.strip()
58)   if canvas.stringWidth(text, font, size) > width:
59)     canvas.drawString(x, y, text)
60)     # too long line, I cannot handle this
61)     return
62)   if not ' ' in text:
63)     canvas.drawString(x, y, text)
64)     # no space in there, nothing to justify
65)     return
66)   
67)   words = [ '%s' % w for w in text.split(' ')]
68)   words_width = 0.0
69)   for word in words:
70)     words_width += canvas.stringWidth(word, font, size)
71)   
72)   available_space = width - words_width
73)   available_each = available_space / float((len(words) - 1))
74)  
75)   my_x = x
76)   for idx in range(len(words)):
77)     word = words[idx]
78)     canvas.drawString(my_x, y, word)
79)     my_x += canvas.stringWidth(word, font, size) + available_each
80)   return
81) 
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

82) 
83) def _PageWrap(canvas):
84)   '''Seitenumbruch'''
85)   canvas.showPage()
Bernd Wurst Trennung von Firmen-spezifi...

Bernd Wurst authored 16 years ago

86)   basicPage(canvas)
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

87) 
88) 
Bernd Wurst Break long address-lines

Bernd Wurst authored 15 years ago

89) def address(canvas, lines):
90)   x = 2.0 * cm
91)   y = page_height - 5.0*cm
92)   canvas.setFont(font, 8)
93)   canvas.drawString(x+0.5*cm, y+0.1*cm, 'schokokeks.org · Köchersberg 25 · 71540 Murrhardt')
94)   canvas.setLineWidth(1)
95)   canvas.line(x+0.4*cm, y, x + address_width, y)
96)   y = y - 0.2*cm
97) 
98)   line_height = 11 + 0.1*cm
99)   y -= line_height
100)   canvas.setFont(font, 11)
101)   for line in lines:
102)     fontsize = 11
103)     if canvas.stringWidth(line, font, fontsize) > address_width:
104)       # Wenn es in zwei Zeilen passt, dann ist alles okay, ansonsten verkleinern
105)       if canvas.stringWidth(line, font, fontsize) > 2*address_width:
106)         for fontsize in [10.5, 10, 9.5, 9, 8.5]:
107)           if canvas.stringWidth(line, font, fontsize) <= 2*address_width:
108)             break
109)       mylines = _splitToWidth(canvas, line, address_width, font, fontsize)
110)       for l in mylines:
111)         canvas.drawString(x+0.5*cm, y, l)
112)         y -= line_height
113)     else:
114)       canvas.drawString(x+0.5*cm, y, line)
115)       y -= line_height
116) 
117) 
118) 
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

119) 
120) def InvoiceToPDF(iv):
121)   from StringIO import StringIO
122)   fd = StringIO()
123)   canvas = Canvas.Canvas(fd, pagesize=A4)
Bernd Wurst Trennung von Firmen-spezifi...

Bernd Wurst authored 16 years ago

124)   
125)   
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

126)   canvas.setFont(font, 12)
127) 
128)   num_pages = 1
129) 
130)   # Waehrungssysmbol
131)   symbol = '€'
132)   y = topcontent
133)   font_size = default_font_size
134)   font_height = 0.35*cm
135)   line_padding = 0.1*cm
136)   line_height = font_height+0.1*cm
137) 
138)   def _partHeight(part):
139)     height = 0
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

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

Bernd Wurst authored 16 years ago

141)       left, right = leftcontent, rightcontent
142)       if part.urgent:
143)         left += 1.5*cm
144)         right -= 1.5*cm
145)         height += len(part.paragraphs) * 3 * line_padding
146)       if part.headline:
147)         height += (len(_splitToWidth(canvas, part.headline, right-left, font+'-Bold', default_font_size+1)) * line_height) + line_padding
148)       for para in part.paragraphs:  
149)         height += (len(_splitToWidth(canvas, para, right-left, font, default_font_size)) * line_height) + line_padding
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

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

Bernd Wurst authored 16 years ago

151)       ## FIXME: Das ist dreckig
Bernd Wurst Bessere Höhen-Approximation

Bernd Wurst authored 15 years ago

152)       height = len(part.entries) * 2*cm
153)       height += 3.5*cm
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

154)     return height
155) 
156) 
Bernd Wurst Trennung von Firmen-spezifi...

Bernd Wurst authored 16 years ago

157)    
158)   address(canvas, iv.addresslines)
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

159) 
160)   font_size = default_font_size
Bernd Wurst Trennung von Firmen-spezifi...

Bernd Wurst authored 16 years ago

161)   y = firstPage(canvas)
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

162) 
163)   canvas.setFont(font+'-Bold', font_size+3)
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

164)   min_y = y
165)   if iv.caption:
166)     canvas.drawString(leftcontent, y, iv.caption)
167)     min_y -= (font_size + 3) + 0.5*cm
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

168) 
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

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

Bernd Wurst authored 16 years ago

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

Bernd Wurst authored 16 years ago

174)   elif type(iv) == Invoice.Generic:
175)     canvas.setFont(font, font_size)
176)     canvas.drawString(rightcolumn, y, "Datum:")
177)     canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
178)     y -= (font_size + 0.1*cm)
179)   elif type(iv) == Invoice.Invoice:
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

180)     canvas.setFont(font+'-Bold', font_size)
181)     canvas.drawString(rightcolumn, y, "Bei Fragen bitte immer angeben:")
182)     y -= (font_size + 0.2*cm)
183)     canvas.setFont(font, font_size)
184)     canvas.drawString(rightcolumn, y, "Rechnungsdatum:")
185)     canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
186)     y -= (font_size + 0.1*cm)
187)     canvas.drawString(rightcolumn, y, "Rechnungsnummer:")
188)     canvas.drawRightString(rightcontent, y, "%i" % iv.id)
189)     y -= (font_size + 0.1*cm)
190)   if iv.customerno:
191)     canvas.drawString(rightcolumn, y, "Kundennummer:")
192)     canvas.drawRightString(rightcontent, y, "%s" % iv.customerno)
193)     y -= (font_size + 0.5*cm)
194)   canvas.setFont(font, font_size)
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

195)   y = min(min_y, y)
196) 
197)   if iv.salutation:
198)     canvas.drawString(leftcontent, y, iv.salutation)
199)     y -= font_size + 0.2*cm
200)     if type(iv) in [Invoice.Tender, Invoice.Invoice]:
201)       introText = 'hiermit stellen wir Ihnen die nachfolgend genannten Leistungen in Rechnung.'
202)       if type(iv) == Invoice.Tender:
203)         introText = 'hiermit unterbreiten wir Ihnen folgendes Angebot.'
204)       intro = _splitToWidth(canvas, introText, rightcontent - leftcontent, font, font_size)
205)       for line in intro:
206)         canvas.drawString(leftcontent, y, line)
207)         y -= font_size + 0.1*cm
208)       y -= font_size + 0.1*cm
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

209) 
210)   
211)   font_size = default_font_size
212)   for part in iv.parts:
213)     if y - _partHeight(part) < (bottomcontent + (0.5*cm)):
214)       num_pages += 1
215)       y = bottomcontent + (0.5*cm)
216)       canvas.setFont(font, default_font_size-2)
217)       canvas.drawRightString(rightcontent, bottomcontent + line_padding, 'Fortsetzung auf Seite %i' % num_pages)
218)       _PageWrap(canvas)
219)       y = topcontent - font_size
220)       canvas.setFillColor((0,0,0))
221)       canvas.setFont(font, font_size-2)
222)       canvas.drawCentredString(leftcontent + (rightcontent - leftcontent) / 2, y, '- Seite %i -' % num_pages)
223)       y -= line_padding*3
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

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

Bernd Wurst authored 16 years ago

225)         
226)       left = leftcontent
227)       right = rightcontent
228)       top = topcontent
229)       bottom = bottomcontent
230)       canvas.setFont(font, font_size)
231)       canvas.drawString(left+(0.1*cm), y-line_height+line_padding, 'Anz.')
232)       canvas.drawString(left+(1.6*cm), y-line_height+line_padding, 'Beschreibung')
233)       if len(part.vat) == 1:
234)         canvas.drawRightString(left+(14.3*cm), y-line_height+line_padding, 'Einzelpreis')
235)       else:
236)         canvas.drawRightString(left+(13.7*cm), y-line_height+line_padding, 'Einzelpreis')
237)       canvas.drawRightString(left+(16.8*cm), y-line_height+line_padding, 'Gesamtpreis')
238)       canvas.setLineWidth(0.01*cm)
239)       canvas.line(left, y - line_height, right, y - line_height)
240)       y -= line_height + 0.02*cm
241)       odd=True
242)       for el in part.entries:
243)         subject = []
244)         if len(part.vat) == 1:
245)           subject = _splitToWidth(canvas, el['subject'], 10.3*cm, font, font_size)
246)         else:
247)           subject = _splitToWidth(canvas, el['subject'], 9.3*cm, font, font_size)
248)         desc = []
249)         if 'desc' in el and el['desc'] != '':
Bernd Wurst Blocksatz auch für Beschrei...

Bernd Wurst authored 16 years ago

250)           desc = _splitToWidth(canvas, el['desc'], 11*cm, font, font_size)
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

251) 
252)         # draw the background
253)         if not odd:
254)           canvas.setFillColorRGB(0.9, 0.9, 0.9)
255)         else:
256)           canvas.setFillColorRGB(1, 1, 1)
257)         need_lines = len(subject) + len(desc)
258)         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)
259)         canvas.setFillColorRGB(0, 0, 0)
260)         y -= line_padding
261)         (integer, decimals) = _niceCount(el['count'])
262)         canvas.drawRightString(left+0.8*cm, y-font_height, integer)
263)         if decimals:
264)           canvas.drawString(left+0.8*cm, y-font_height, ',%s' % decimals)
265)         if len(part.vat) == 1:
266)           canvas.drawString(left+1.7*cm, y-font_height, subject[0])
267)           canvas.drawRightString(left+14.3*cm, y-font_height, _formatPrice(el['price']))
268)           if el['tender']:  
269)             canvas.drawRightString(left+16.8*cm, y-font_height, 'eventual')
270)           else:
271)             canvas.drawRightString(left+16.8*cm, y-font_height, _formatPrice(el['total']))
272)           subject = subject[1:]
273)           x = 1
274)           for line in subject:
275)             canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
276)             x += 1
Bernd Wurst Blocksatz auch für Beschrei...

Bernd Wurst authored 16 years ago

277)           for line in desc[:-1]:
278)             _drawJustifiedString(left+1.7*cm, y-(x * line_height)-font_height, line, canvas, 11*cm, font, font_size)
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

279)             x += 1
Bernd Wurst Blocksatz auch für Beschrei...

Bernd Wurst authored 16 years ago

280)           canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, desc[-1])
281)           x += 1
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

282)         else:
283)           canvas.drawString(left+1.7*cm, y-font_height, subject[0])
284)           canvas.drawRightString(left+13.3*cm, y-font_height, _formatPrice(el['price']))
285)           canvas.drawString(left+13.7*cm, y-font_height, str(part.vat[el['vat']][1]))
286)           if el['tender']:  
287)             canvas.drawRightString(left+16.8*cm, y-font_height, 'eventual')
288)           else:
289)             canvas.drawRightString(left+16.8*cm, y-font_height, _formatPrice(el['total']))
290)           subject = subject[1:]
291)           x = 1
292)           for line in subject:
293)             canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
294)             x += 1
295)           for line in desc:
296)             canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
297)             x += 1
298)         odd = not odd
299)         y -= (need_lines * line_height) + line_padding
300)       if part.summary:
301)         y -= (0.3*cm)
302)         if part.vatType == 'gross':
303)           canvas.setFont(font+'-Bold', font_size)
304)           if iv.tender:
305)             canvas.drawRightString(left + 14.5*cm, y-font_height, 'Gesamtbetrag:')
306)           else:
307)             canvas.drawRightString(left + 14.5*cm, y-font_height, 'Rechnungsbetrag:')
308)           canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(part.sum))
309)           canvas.setFont(font, font_size)
310)           y -= line_height + line_padding
311)           summaries = []
312)           if len(part.vat) == 1:
313)             vat = part.vat.keys()[0]
Bernd Wurst Trennung von Firmen-spezifi...

Bernd Wurst authored 16 years ago

314)             (integer, decimals) = _niceCount( (vat * 100) )
315)             vatstr = '%s' % integer
316)             if decimals:
317)               vatstr += ',%s' % decimals
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

318)             if iv.tender:
Bernd Wurst Trennung von Firmen-spezifi...

Bernd Wurst authored 16 years ago

319)               summaries.append(('Im Gesamtbetrag sind %s%% MwSt enthalten:' % vatstr, _formatPrice((part.sum/(vat+1))*vat)))
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

320)             else:
Bernd Wurst Trennung von Firmen-spezifi...

Bernd Wurst authored 16 years ago

321)               summaries.append(('Im Rechnungsbetrag sind %s%% MwSt enthalten:' % vatstr, _formatPrice((part.sum/(vat+1))*vat)))
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

322)           else:
323)             for vat, vatdata in part.vat.iteritems():
Bernd Wurst Trennung von Firmen-spezifi...

Bernd Wurst authored 16 years ago

324)               (integer, decimals) = _niceCount( (vat * 100) )
325)               vatstr = '%s' % integer
326)               if decimals:
327)                 vatstr += ',%s' % decimals
328)               summaries.append(('%s: Im Teilbetrag von %s sind %s%% MwSt enthalten:' % (vatdata[1], _formatPrice(vatdata[0]), vatstr), _formatPrice((vatdata[0]/(vat+1))*vat)))
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

329)           summaries.sort()
330)           for line in summaries:
331)             canvas.drawRightString(left + 14.5*cm, y-font_height, line[0])
332)             canvas.drawRightString(left + 16.8*cm, y-font_height, line[1])
333)             y -= line_height
334)         else:
335)           canvas.drawRightString(left + 14.5*cm, y-font_height, 'Nettobetrag:')
336)           canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(part.sum))
337)           y -= line_height
338)           summaries = []
339)           if len(part.vat) == 1:
340)             vat = part.vat.keys()[0]
Bernd Wurst Trennung von Firmen-spezifi...

Bernd Wurst authored 16 years ago

341)             (integer, decimals) = _niceCount( (vat * 100) )
342)             vatstr = '%s' % integer
343)             if decimals:
344)               vatstr += ',%s' % decimals
345)             summaries.append(('zzgl. %s%% MwSt:' % vatstr, _formatPrice(vat*part.sum)))
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

346)           else:
347)             for vat, vatdata in part.vat.iteritems():
Bernd Wurst Trennung von Firmen-spezifi...

Bernd Wurst authored 16 years ago

348)               (integer, decimals) = _niceCount( (vat * 100) )
349)               vatstr = '%s' % integer
350)               if decimals:
351)                 vatstr += ',%s' % decimals
352)               summaries.append(('zzgl. %s%% MwSt (%s):' % (vatstr, vatdata[1]), _formatPrice(vat*vatdata[0])))
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

353)           summaries.sort()
354)           for line in summaries:
355)             canvas.drawRightString(left + 14.5*cm, y-font_height, line[0])
356)             canvas.drawRightString(left + 16.8*cm, y-font_height, line[1])
357)             y -= line_height
358)           sum = 0
359)           for vat, vatdata in part.vat.iteritems():
360)             sum += (vat+1)*vatdata[0]
361)           canvas.setFont(font+'-Bold', font_size)
362)           if iv.tender:
363)             canvas.drawRightString(left + 14.5*cm, y-font_height, 'Gesamtbetrag:')
364)           else:
365)             canvas.drawRightString(left + 14.5*cm, y-font_height, 'Rechnungsbetrag:')
366)           canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(sum))
367)           canvas.setFont(font, font_size)
368)           y -= line_height + line_padding
Bernd Wurst Generisch

Bernd Wurst authored 16 years ago

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

Bernd Wurst authored 16 years ago

370)       my_font_size = font_size
371)       canvas.setFont(font, my_font_size)
372)       left, right = leftcontent, rightcontent
373)       firsttime = True
374)       headlines = []
375)       if part.urgent:
376)         left += 1.5*cm
377)         right -= 1.5*cm
378)       if part.headline:
379)         headlines = _splitToWidth(canvas, part.headline, right-left, font, my_font_size)
380)       for para in part.paragraphs:
381)         lines = _splitToWidth(canvas, para, right-left, font, my_font_size)
382)         if part.urgent:
383)           need_height = len(lines) * line_height
384)           if len(headlines) > 0:
385)             need_height += len(headlines) * (line_height + 1) + line_padding
386)           canvas.setFillColorRGB(0.95, 0.95, 0.95)
387)           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)
388)           canvas.setFillColorRGB(0, 0, 0)
389)           y -= line_padding*3
390)         if part.headline and firsttime:
391)           firsttime = False
392)           canvas.setFont(font+'-Bold', my_font_size+1)
393)           for line in headlines:
394)             canvas.drawString(left, y-(font_height+1), line)
395)             y -= line_height + 1
396)           y -= line_padding
397)           canvas.setFont(font, my_font_size)
Bernd Wurst InvoiceText als Blocksatz d...

Bernd Wurst authored 16 years ago

398)         for line in lines[:-1]:
399)           _drawJustifiedString(left, y-font_height, line, canvas, right-left, font, my_font_size)
Bernd Wurst Struktur verändern (broken!)

Bernd Wurst authored 16 years ago

400)           y -= line_height
Bernd Wurst InvoiceText als Blocksatz d...

Bernd Wurst authored 16 years ago

401)         canvas.drawString(left, y-font_height, lines[-1])
402)         y -= line_height
403)