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) 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
|
Generisch
Bernd Wurst authored 16 years ago
|
126) if type(part) == Invoice.Text:
|
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
|
Generisch
Bernd Wurst authored 16 years ago
|
136) elif type(part) == Invoice.Table:
|
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)
|
Generisch
Bernd Wurst authored 16 years ago
|
161) canvas.drawString(x, y+0.1*cm, ' schokokeks.org · Köchersberg 25 · 71540 Murrhardt')
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
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)
|
Generisch
Bernd Wurst authored 16 years ago
|
199) min_y = y
200) if iv.caption:
201) canvas.drawString(leftcontent, y, iv.caption)
202) min_y -= (font_size + 3) + 0.5*cm
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
203)
|
Generisch
Bernd Wurst authored 16 years ago
|
204) if type(iv) == Invoice.Tender:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
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)
|
Generisch
Bernd Wurst authored 16 years ago
|
209) elif type(iv) == Invoice.Generic:
210) canvas.setFont(font, font_size)
211) canvas.drawString(rightcolumn, y, "Datum:")
212) canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
213) y -= (font_size + 0.1*cm)
214) elif type(iv) == Invoice.Invoice:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
215) canvas.setFont(font+'-Bold', font_size)
216) canvas.drawString(rightcolumn, y, "Bei Fragen bitte immer angeben:")
217) y -= (font_size + 0.2*cm)
218) canvas.setFont(font, font_size)
219) canvas.drawString(rightcolumn, y, "Rechnungsdatum:")
220) canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
221) y -= (font_size + 0.1*cm)
222) canvas.drawString(rightcolumn, y, "Rechnungsnummer:")
223) canvas.drawRightString(rightcontent, y, "%i" % iv.id)
224) y -= (font_size + 0.1*cm)
225) if iv.customerno:
226) canvas.drawString(rightcolumn, y, "Kundennummer:")
227) canvas.drawRightString(rightcontent, y, "%s" % iv.customerno)
228) y -= (font_size + 0.5*cm)
229) canvas.setFont(font, font_size)
|
Generisch
Bernd Wurst authored 16 years ago
|
230) y = min(min_y, y)
231)
232) if iv.salutation:
233) canvas.drawString(leftcontent, y, iv.salutation)
234) y -= font_size + 0.2*cm
235) if type(iv) in [Invoice.Tender, Invoice.Invoice]:
236) introText = 'hiermit stellen wir Ihnen die nachfolgend genannten Leistungen in Rechnung.'
237) if type(iv) == Invoice.Tender:
238) introText = 'hiermit unterbreiten wir Ihnen folgendes Angebot.'
239) intro = _splitToWidth(canvas, introText, rightcontent - leftcontent, font, font_size)
240) for line in intro:
241) canvas.drawString(leftcontent, y, line)
242) y -= font_size + 0.1*cm
243) y -= font_size + 0.1*cm
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
244)
245)
246) font_size = default_font_size
247) for part in iv.parts:
248) if y - _partHeight(part) < (bottomcontent + (0.5*cm)):
249) num_pages += 1
250) y = bottomcontent + (0.5*cm)
251) canvas.setFont(font, default_font_size-2)
252) canvas.drawRightString(rightcontent, bottomcontent + line_padding, 'Fortsetzung auf Seite %i' % num_pages)
253) _Footer()
254) _PageWrap(canvas)
255) y = topcontent - font_size
256) canvas.setFillColor((0,0,0))
257) canvas.setFont(font, font_size-2)
258) canvas.drawCentredString(leftcontent + (rightcontent - leftcontent) / 2, y, '- Seite %i -' % num_pages)
259) y -= line_padding*3
|
Generisch
Bernd Wurst authored 16 years ago
|
260) if type(part) == Invoice.Table:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
261)
262) left = leftcontent
263) right = rightcontent
264) top = topcontent
265) bottom = bottomcontent
266) canvas.setFont(font, font_size)
267) canvas.drawString(left+(0.1*cm), y-line_height+line_padding, 'Anz.')
268) canvas.drawString(left+(1.6*cm), y-line_height+line_padding, 'Beschreibung')
269) if len(part.vat) == 1:
270) canvas.drawRightString(left+(14.3*cm), y-line_height+line_padding, 'Einzelpreis')
271) else:
272) canvas.drawRightString(left+(13.7*cm), y-line_height+line_padding, 'Einzelpreis')
273) canvas.drawRightString(left+(16.8*cm), y-line_height+line_padding, 'Gesamtpreis')
274) canvas.setLineWidth(0.01*cm)
275) canvas.line(left, y - line_height, right, y - line_height)
276) y -= line_height + 0.02*cm
277) odd=True
278) for el in part.entries:
279) subject = []
280) if len(part.vat) == 1:
281) subject = _splitToWidth(canvas, el['subject'], 10.3*cm, font, font_size)
282) else:
283) subject = _splitToWidth(canvas, el['subject'], 9.3*cm, font, font_size)
284) desc = []
285) if 'desc' in el and el['desc'] != '':
286) desc = _splitToWidth(canvas, el['desc'], 14.5*cm, font, font_size)
287)
288) # draw the background
289) if not odd:
290) canvas.setFillColorRGB(0.9, 0.9, 0.9)
291) else:
292) canvas.setFillColorRGB(1, 1, 1)
293) need_lines = len(subject) + len(desc)
294) 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)
295) canvas.setFillColorRGB(0, 0, 0)
296) y -= line_padding
297) (integer, decimals) = _niceCount(el['count'])
298) canvas.drawRightString(left+0.8*cm, y-font_height, integer)
299) if decimals:
300) canvas.drawString(left+0.8*cm, y-font_height, ',%s' % decimals)
301) if len(part.vat) == 1:
302) canvas.drawString(left+1.7*cm, y-font_height, subject[0])
303) canvas.drawRightString(left+14.3*cm, y-font_height, _formatPrice(el['price']))
304) if el['tender']:
305) canvas.drawRightString(left+16.8*cm, y-font_height, 'eventual')
306) else:
307) canvas.drawRightString(left+16.8*cm, y-font_height, _formatPrice(el['total']))
308) subject = subject[1:]
309) x = 1
310) for line in subject:
311) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
312) x += 1
313) for line in desc:
314) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
315) x += 1
316) else:
317) canvas.drawString(left+1.7*cm, y-font_height, subject[0])
318) canvas.drawRightString(left+13.3*cm, y-font_height, _formatPrice(el['price']))
319) canvas.drawString(left+13.7*cm, y-font_height, str(part.vat[el['vat']][1]))
320) if el['tender']:
321) canvas.drawRightString(left+16.8*cm, y-font_height, 'eventual')
322) else:
323) canvas.drawRightString(left+16.8*cm, y-font_height, _formatPrice(el['total']))
324) subject = subject[1:]
325) x = 1
326) for line in subject:
327) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
328) x += 1
329) for line in desc:
330) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
331) x += 1
332) odd = not odd
333) y -= (need_lines * line_height) + line_padding
334) if part.summary:
335) y -= (0.3*cm)
336) if part.vatType == 'gross':
337) canvas.setFont(font+'-Bold', font_size)
338) if iv.tender:
339) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Gesamtbetrag:')
340) else:
341) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Rechnungsbetrag:')
342) canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(part.sum))
343) canvas.setFont(font, font_size)
344) y -= line_height + line_padding
345) summaries = []
346) if len(part.vat) == 1:
347) vat = part.vat.keys()[0]
348) if iv.tender:
349) summaries.append(('Im Gesamtbetrag sind %.1f%% MwSt enthalten:' % (vat*100), _formatPrice((part.sum/(vat+1))*vat)))
350) else:
351) summaries.append(('Im Rechnungsbetrag sind %.1f%% MwSt enthalten:' % (vat*100), _formatPrice((part.sum/(vat+1))*vat)))
352) else:
353) for vat, vatdata in part.vat.iteritems():
354) summaries.append('%s: Im Teilbetrag von %s sind %.1f%% MwSt enthalten:' % (vatdata[1], _formatPrice(vatdata[0]), vat*100), _formatPrice((vatdata[0]/(vat+1))*vat))
355) summaries.sort()
356) for line in summaries:
357) canvas.drawRightString(left + 14.5*cm, y-font_height, line[0])
358) canvas.drawRightString(left + 16.8*cm, y-font_height, line[1])
359) y -= line_height
360) else:
361) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Nettobetrag:')
362) canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(part.sum))
363) y -= line_height
364) summaries = []
365) if len(part.vat) == 1:
366) vat = part.vat.keys()[0]
367) summaries.append(('zzgl. %.1f%% MwSt:' % (vat*100), _formatPrice(vat*part.sum)))
368) else:
369) for vat, vatdata in part.vat.iteritems():
370) summaries.append(('zzgl. %.1f%% MwSt (%s):' % (vat*100, vatdata[1]), _formatPrice(vat*vatdata[0])))
371) summaries.sort()
372) for line in summaries:
373) canvas.drawRightString(left + 14.5*cm, y-font_height, line[0])
374) canvas.drawRightString(left + 16.8*cm, y-font_height, line[1])
375) y -= line_height
376) sum = 0
377) for vat, vatdata in part.vat.iteritems():
378) sum += (vat+1)*vatdata[0]
379) canvas.setFont(font+'-Bold', font_size)
380) if iv.tender:
381) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Gesamtbetrag:')
382) else:
383) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Rechnungsbetrag:')
384) canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(sum))
385) canvas.setFont(font, font_size)
386) y -= line_height + line_padding
|
Generisch
Bernd Wurst authored 16 years ago
|
387) elif type(part) == Invoice.Text:
|