Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
1) # -* coding: utf8 *-
2)
|
Generisch
Bernd Wurst authored 16 years ago
|
3) import Invoice
|
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():
|
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"))
|
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
|
Generisch
Bernd Wurst authored 16 years ago
|
124) if type(part) == Invoice.Text:
|
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
|
Generisch
Bernd Wurst authored 16 years ago
|
134) elif type(part) == Invoice.Table:
|
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)
|
Neuer Footer
Bernd Wurst authored 16 years ago
|
140) def _Footer(canvas):
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
141) canvas.line(leftcontent, bottomcontent, rightcontent, bottomcontent)
|
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)
|
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)
|
Generisch
Bernd Wurst authored 16 years ago
|
168) canvas.drawString(x, y+0.1*cm, ' schokokeks.org · Köchersberg 25 · 71540 Murrhardt')
|
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)
|
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
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
210)
|
Generisch
Bernd Wurst authored 16 years ago
|
211) if type(iv) == Invoice.Tender:
|
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)
|
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:
|
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)
|
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
|
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)
|
Neuer Footer
Bernd Wurst authored 16 years ago
|
260) _Footer(canvas)
|
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
|
Generisch
Bernd Wurst authored 16 years ago
|
267) if type(part) == Invoice.Table:
|
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
|
Generisch
Bernd Wurst authored 16 years ago
|
394) elif type(part) == Invoice.Text:
|
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)
|
Neuer Footer
Bernd Wurst authored 16 years ago
|
432) _Footer(canvas)
|