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)
140) def _Footer():
141) canvas.line(leftcontent, bottomcontent, rightcontent, bottomcontent)
142) canvas.setFont(font, 8)
143) canvas.drawCentredString(leftcontent+((rightcontent-leftcontent)/2), bottomcontent-10, 'schokokeks.org GbR · Bernd Wurst / Johannes Böck · http://www.schokokeks.org/')
144) canvas.drawCentredString(leftcontent+((rightcontent-leftcontent)/2), bottomcontent-20, 'Steuernummer: 51072/01109 (FA Backnang) · USt-ID: DE255720588')
145) canvas.drawCentredString(leftcontent+((rightcontent-leftcontent)/2), bottomcontent-30, 'Bankverbindung: Volksbank Backnang, BLZ 602 911 20, Konto Nr. 671279 017')
146) canvas.drawCentredString(leftcontent+((rightcontent-leftcontent)/2), bottomcontent-40, 'IBAN: DE78602911200671279017, BIC: GENODES1VBK')
147)
148)
149) addy_width = 8.5*cm
150) addy_height = 5.0*cm
151)
152) font_size = 8
153) x = 2.0 * cm
154) y = -4.8 * cm - font_size - 1
155)
156) canvas.setFont(font, font_size)
157)
158)
|
Generisch
Bernd Wurst authored 16 years ago
|
159) canvas.drawString(x, y+0.1*cm, ' schokokeks.org · Köchersberg 25 · 71540 Murrhardt')
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
160) canvas.line(x, y, x + (8.5 * cm), y)
161) y = y - font_size - 3
162)
163) font_size = 11
164) x += 0.5*cm
165) y -= 0.5*cm
166) canvas.setFont(font, font_size)
167) for line in iv.addresslines:
168) canvas.drawString(x, y, line)
169) y -= line_height
170)
171)
172) font_size = default_font_size
173)
174) y = topcontent
175) canvas.drawInlineImage("logo.png", rightcolumn, topcontent-(3*cm), width=4.08*cm, height=3*cm)
176) y -= (3.5*cm)
177) canvas.setFont(font+"-Bold", font_size)
178) #canvas.drawString(rightcolumn, y, "schokokeks.org Webhosting")
179) #y -= (font_size + 5 + 0.2*cm)
180) canvas.drawString(rightcolumn, y, "schokokeks.org GbR")
181) y -= (font_size + 5)
182) canvas.setFont(font, font_size)
183) canvas.drawString(rightcolumn, y, "Bernd Wurst / Johannes Böck")
184) y -= (font_size + 5)
185) canvas.drawString(rightcolumn, y, "Köchersberg 25")
186) y -= (font_size + 5)
187) canvas.drawString(rightcolumn, y, "71540 Murrhardt")
188) y -= (font_size + 10)
189) canvas.drawString(rightcolumn, y, "Tel: 07192-936432")
190) y -= (font_size + 5)
191) canvas.drawString(rightcolumn, y, "Fax: 07192-936431")
192) y -= (font_size + 5)
193) canvas.drawString(rightcolumn, y, "E-Mail: root@schokokeks.org")
194) y -= (font_size + 10)
195) y = -9.5*cm
196) canvas.setFont(font+'-Bold', font_size+3)
|
Generisch
Bernd Wurst authored 16 years ago
|
197) min_y = y
198) if iv.caption:
199) canvas.drawString(leftcontent, y, iv.caption)
200) min_y -= (font_size + 3) + 0.5*cm
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
201)
|
Generisch
Bernd Wurst authored 16 years ago
|
202) if type(iv) == Invoice.Tender:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
203) canvas.setFont(font, font_size)
204) canvas.drawString(rightcolumn, y, "Erstellungsdatum:")
205) canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
206) y -= (font_size + 0.1*cm)
|
Generisch
Bernd Wurst authored 16 years ago
|
207) elif type(iv) == Invoice.Generic:
208) canvas.setFont(font, font_size)
209) canvas.drawString(rightcolumn, y, "Datum:")
210) canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
211) y -= (font_size + 0.1*cm)
212) elif type(iv) == Invoice.Invoice:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
213) canvas.setFont(font+'-Bold', font_size)
214) canvas.drawString(rightcolumn, y, "Bei Fragen bitte immer angeben:")
215) y -= (font_size + 0.2*cm)
216) canvas.setFont(font, font_size)
217) canvas.drawString(rightcolumn, y, "Rechnungsdatum:")
218) canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
219) y -= (font_size + 0.1*cm)
220) canvas.drawString(rightcolumn, y, "Rechnungsnummer:")
221) canvas.drawRightString(rightcontent, y, "%i" % iv.id)
222) y -= (font_size + 0.1*cm)
223) if iv.customerno:
224) canvas.drawString(rightcolumn, y, "Kundennummer:")
225) canvas.drawRightString(rightcontent, y, "%s" % iv.customerno)
226) y -= (font_size + 0.5*cm)
227) canvas.setFont(font, font_size)
|
Generisch
Bernd Wurst authored 16 years ago
|
228) y = min(min_y, y)
229)
230) if iv.salutation:
231) canvas.drawString(leftcontent, y, iv.salutation)
232) y -= font_size + 0.2*cm
233) if type(iv) in [Invoice.Tender, Invoice.Invoice]:
234) introText = 'hiermit stellen wir Ihnen die nachfolgend genannten Leistungen in Rechnung.'
235) if type(iv) == Invoice.Tender:
236) introText = 'hiermit unterbreiten wir Ihnen folgendes Angebot.'
237) intro = _splitToWidth(canvas, introText, rightcontent - leftcontent, font, font_size)
238) for line in intro:
239) canvas.drawString(leftcontent, y, line)
240) y -= font_size + 0.1*cm
241) y -= font_size + 0.1*cm
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
242)
243)
244) font_size = default_font_size
245) for part in iv.parts:
246) if y - _partHeight(part) < (bottomcontent + (0.5*cm)):
247) num_pages += 1
248) y = bottomcontent + (0.5*cm)
249) canvas.setFont(font, default_font_size-2)
250) canvas.drawRightString(rightcontent, bottomcontent + line_padding, 'Fortsetzung auf Seite %i' % num_pages)
251) _Footer()
252) _PageWrap(canvas)
253) y = topcontent - font_size
254) canvas.setFillColor((0,0,0))
255) canvas.setFont(font, font_size-2)
256) canvas.drawCentredString(leftcontent + (rightcontent - leftcontent) / 2, y, '- Seite %i -' % num_pages)
257) y -= line_padding*3
|
Generisch
Bernd Wurst authored 16 years ago
|
258) if type(part) == Invoice.Table:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
259)
260) left = leftcontent
261) right = rightcontent
262) top = topcontent
263) bottom = bottomcontent
264) canvas.setFont(font, font_size)
265) canvas.drawString(left+(0.1*cm), y-line_height+line_padding, 'Anz.')
266) canvas.drawString(left+(1.6*cm), y-line_height+line_padding, 'Beschreibung')
267) if len(part.vat) == 1:
268) canvas.drawRightString(left+(14.3*cm), y-line_height+line_padding, 'Einzelpreis')
269) else:
270) canvas.drawRightString(left+(13.7*cm), y-line_height+line_padding, 'Einzelpreis')
271) canvas.drawRightString(left+(16.8*cm), y-line_height+line_padding, 'Gesamtpreis')
272) canvas.setLineWidth(0.01*cm)
273) canvas.line(left, y - line_height, right, y - line_height)
274) y -= line_height + 0.02*cm
275) odd=True
276) for el in part.entries:
277) subject = []
278) if len(part.vat) == 1:
279) subject = _splitToWidth(canvas, el['subject'], 10.3*cm, font, font_size)
280) else:
281) subject = _splitToWidth(canvas, el['subject'], 9.3*cm, font, font_size)
282) desc = []
283) if 'desc' in el and el['desc'] != '':
284) desc = _splitToWidth(canvas, el['desc'], 14.5*cm, font, font_size)
285)
286) # draw the background
287) if not odd:
288) canvas.setFillColorRGB(0.9, 0.9, 0.9)
289) else:
290) canvas.setFillColorRGB(1, 1, 1)
291) need_lines = len(subject) + len(desc)
292) 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)
293) canvas.setFillColorRGB(0, 0, 0)
294) y -= line_padding
295) (integer, decimals) = _niceCount(el['count'])
296) canvas.drawRightString(left+0.8*cm, y-font_height, integer)
297) if decimals:
298) canvas.drawString(left+0.8*cm, y-font_height, ',%s' % decimals)
299) if len(part.vat) == 1:
300) canvas.drawString(left+1.7*cm, y-font_height, subject[0])
301) canvas.drawRightString(left+14.3*cm, y-font_height, _formatPrice(el['price']))
302) if el['tender']:
303) canvas.drawRightString(left+16.8*cm, y-font_height, 'eventual')
304) else:
305) canvas.drawRightString(left+16.8*cm, y-font_height, _formatPrice(el['total']))
306) subject = subject[1:]
307) x = 1
308) for line in subject:
309) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
310) x += 1
311) for line in desc:
312) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
313) x += 1
314) else:
315) canvas.drawString(left+1.7*cm, y-font_height, subject[0])
316) canvas.drawRightString(left+13.3*cm, y-font_height, _formatPrice(el['price']))
317) canvas.drawString(left+13.7*cm, y-font_height, str(part.vat[el['vat']][1]))
318) if el['tender']:
319) canvas.drawRightString(left+16.8*cm, y-font_height, 'eventual')
320) else:
321) canvas.drawRightString(left+16.8*cm, y-font_height, _formatPrice(el['total']))
322) subject = subject[1:]
323) x = 1
324) for line in subject:
325) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
326) x += 1
327) for line in desc:
328) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
329) x += 1
330) odd = not odd
331) y -= (need_lines * line_height) + line_padding
332) if part.summary:
333) y -= (0.3*cm)
334) if part.vatType == 'gross':
335) canvas.setFont(font+'-Bold', font_size)
336) if iv.tender:
337) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Gesamtbetrag:')
338) else:
339) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Rechnungsbetrag:')
340) canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(part.sum))
341) canvas.setFont(font, font_size)
342) y -= line_height + line_padding
343) summaries = []
344) if len(part.vat) == 1:
345) vat = part.vat.keys()[0]
346) if iv.tender:
347) summaries.append(('Im Gesamtbetrag sind %.1f%% MwSt enthalten:' % (vat*100), _formatPrice((part.sum/(vat+1))*vat)))
348) else:
349) summaries.append(('Im Rechnungsbetrag sind %.1f%% MwSt enthalten:' % (vat*100), _formatPrice((part.sum/(vat+1))*vat)))
350) else:
351) for vat, vatdata in part.vat.iteritems():
352) summaries.append('%s: Im Teilbetrag von %s sind %.1f%% MwSt enthalten:' % (vatdata[1], _formatPrice(vatdata[0]), vat*100), _formatPrice((vatdata[0]/(vat+1))*vat))
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) else:
359) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Nettobetrag:')
360) canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(part.sum))
361) y -= line_height
362) summaries = []
363) if len(part.vat) == 1:
364) vat = part.vat.keys()[0]
365) summaries.append(('zzgl. %.1f%% MwSt:' % (vat*100), _formatPrice(vat*part.sum)))
366) else:
367) for vat, vatdata in part.vat.iteritems():
368) summaries.append(('zzgl. %.1f%% MwSt (%s):' % (vat*100, vatdata[1]), _formatPrice(vat*vatdata[0])))
369) summaries.sort()
370) for line in summaries:
371) canvas.drawRightString(left + 14.5*cm, y-font_height, line[0])
372) canvas.drawRightString(left + 16.8*cm, y-font_height, line[1])
373) y -= line_height
374) sum = 0
375) for vat, vatdata in part.vat.iteritems():
376) sum += (vat+1)*vatdata[0]
377) canvas.setFont(font+'-Bold', font_size)
378) if iv.tender:
379) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Gesamtbetrag:')
380) else:
381) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Rechnungsbetrag:')
382) canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(sum))
383) canvas.setFont(font, font_size)
384) y -= line_height + line_padding
|
Generisch
Bernd Wurst authored 16 years ago
|
385) elif type(part) == Invoice.Text:
|