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)
|
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
9) from custom_elements import basicPage, firstPage, address
10)
|
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)
|
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) from pprint import pprint
75) pprint( (width, words_width))
76)
77) my_x = x
78) for idx in range(len(words)):
79) word = words[idx]
80) canvas.drawString(my_x, y, word)
81) my_x += canvas.stringWidth(word, font, size) + available_each
82) return
83)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
84)
85) def _PageWrap(canvas):
86) '''Seitenumbruch'''
87) canvas.showPage()
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
88) basicPage(canvas)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
89)
90)
91)
92) def InvoiceToPDF(iv):
93) from StringIO import StringIO
94) fd = StringIO()
95) canvas = Canvas.Canvas(fd, pagesize=A4)
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
96)
97)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
98) canvas.setFont(font, 12)
99)
100) num_pages = 1
101)
102) # Waehrungssysmbol
103) symbol = '€'
104) y = topcontent
105) font_size = default_font_size
106) font_height = 0.35*cm
107) line_padding = 0.1*cm
108) line_height = font_height+0.1*cm
109)
110) def _partHeight(part):
111) height = 0
|
Generisch
Bernd Wurst authored 16 years ago
|
112) if type(part) == Invoice.Text:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
113) left, right = leftcontent, rightcontent
114) if part.urgent:
115) left += 1.5*cm
116) right -= 1.5*cm
117) height += len(part.paragraphs) * 3 * line_padding
118) if part.headline:
119) height += (len(_splitToWidth(canvas, part.headline, right-left, font+'-Bold', default_font_size+1)) * line_height) + line_padding
120) for para in part.paragraphs:
121) height += (len(_splitToWidth(canvas, para, right-left, font, default_font_size)) * line_height) + line_padding
|
Generisch
Bernd Wurst authored 16 years ago
|
122) elif type(part) == Invoice.Table:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
123) ## FIXME: Das ist dreckig
124) height = len(part.entries) * 1.1*cm
125) height += 3*cm
126) return height
127)
128)
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
129)
130) address(canvas, iv.addresslines)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
131)
132) font_size = default_font_size
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
133) y = firstPage(canvas)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
134)
135) canvas.setFont(font+'-Bold', font_size+3)
|
Generisch
Bernd Wurst authored 16 years ago
|
136) min_y = y
137) if iv.caption:
138) canvas.drawString(leftcontent, y, iv.caption)
139) min_y -= (font_size + 3) + 0.5*cm
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
140)
|
Generisch
Bernd Wurst authored 16 years ago
|
141) if type(iv) == Invoice.Tender:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
142) canvas.setFont(font, font_size)
143) canvas.drawString(rightcolumn, y, "Erstellungsdatum:")
144) canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
145) y -= (font_size + 0.1*cm)
|
Generisch
Bernd Wurst authored 16 years ago
|
146) elif type(iv) == Invoice.Generic:
147) canvas.setFont(font, font_size)
148) canvas.drawString(rightcolumn, y, "Datum:")
149) canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
150) y -= (font_size + 0.1*cm)
151) elif type(iv) == Invoice.Invoice:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
152) canvas.setFont(font+'-Bold', font_size)
153) canvas.drawString(rightcolumn, y, "Bei Fragen bitte immer angeben:")
154) y -= (font_size + 0.2*cm)
155) canvas.setFont(font, font_size)
156) canvas.drawString(rightcolumn, y, "Rechnungsdatum:")
157) canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
158) y -= (font_size + 0.1*cm)
159) canvas.drawString(rightcolumn, y, "Rechnungsnummer:")
160) canvas.drawRightString(rightcontent, y, "%i" % iv.id)
161) y -= (font_size + 0.1*cm)
162) if iv.customerno:
163) canvas.drawString(rightcolumn, y, "Kundennummer:")
164) canvas.drawRightString(rightcontent, y, "%s" % iv.customerno)
165) y -= (font_size + 0.5*cm)
166) canvas.setFont(font, font_size)
|
Generisch
Bernd Wurst authored 16 years ago
|
167) y = min(min_y, y)
168)
169) if iv.salutation:
170) canvas.drawString(leftcontent, y, iv.salutation)
171) y -= font_size + 0.2*cm
172) if type(iv) in [Invoice.Tender, Invoice.Invoice]:
173) introText = 'hiermit stellen wir Ihnen die nachfolgend genannten Leistungen in Rechnung.'
174) if type(iv) == Invoice.Tender:
175) introText = 'hiermit unterbreiten wir Ihnen folgendes Angebot.'
176) intro = _splitToWidth(canvas, introText, rightcontent - leftcontent, font, font_size)
177) for line in intro:
178) canvas.drawString(leftcontent, y, line)
179) y -= font_size + 0.1*cm
180) y -= font_size + 0.1*cm
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
181)
182)
183) font_size = default_font_size
184) for part in iv.parts:
185) if y - _partHeight(part) < (bottomcontent + (0.5*cm)):
186) num_pages += 1
187) y = bottomcontent + (0.5*cm)
188) canvas.setFont(font, default_font_size-2)
189) canvas.drawRightString(rightcontent, bottomcontent + line_padding, 'Fortsetzung auf Seite %i' % num_pages)
190) _PageWrap(canvas)
191) y = topcontent - font_size
192) canvas.setFillColor((0,0,0))
193) canvas.setFont(font, font_size-2)
194) canvas.drawCentredString(leftcontent + (rightcontent - leftcontent) / 2, y, '- Seite %i -' % num_pages)
195) y -= line_padding*3
|
Generisch
Bernd Wurst authored 16 years ago
|
196) if type(part) == Invoice.Table:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
197)
198) left = leftcontent
199) right = rightcontent
200) top = topcontent
201) bottom = bottomcontent
202) canvas.setFont(font, font_size)
203) canvas.drawString(left+(0.1*cm), y-line_height+line_padding, 'Anz.')
204) canvas.drawString(left+(1.6*cm), y-line_height+line_padding, 'Beschreibung')
205) if len(part.vat) == 1:
206) canvas.drawRightString(left+(14.3*cm), y-line_height+line_padding, 'Einzelpreis')
207) else:
208) canvas.drawRightString(left+(13.7*cm), y-line_height+line_padding, 'Einzelpreis')
209) canvas.drawRightString(left+(16.8*cm), y-line_height+line_padding, 'Gesamtpreis')
210) canvas.setLineWidth(0.01*cm)
211) canvas.line(left, y - line_height, right, y - line_height)
212) y -= line_height + 0.02*cm
213) odd=True
214) for el in part.entries:
215) subject = []
216) if len(part.vat) == 1:
217) subject = _splitToWidth(canvas, el['subject'], 10.3*cm, font, font_size)
218) else:
219) subject = _splitToWidth(canvas, el['subject'], 9.3*cm, font, font_size)
220) desc = []
221) if 'desc' in el and el['desc'] != '':
222) desc = _splitToWidth(canvas, el['desc'], 14.5*cm, font, font_size)
223)
224) # draw the background
225) if not odd:
226) canvas.setFillColorRGB(0.9, 0.9, 0.9)
227) else:
228) canvas.setFillColorRGB(1, 1, 1)
229) need_lines = len(subject) + len(desc)
230) 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)
231) canvas.setFillColorRGB(0, 0, 0)
232) y -= line_padding
233) (integer, decimals) = _niceCount(el['count'])
234) canvas.drawRightString(left+0.8*cm, y-font_height, integer)
235) if decimals:
236) canvas.drawString(left+0.8*cm, y-font_height, ',%s' % decimals)
237) if len(part.vat) == 1:
238) canvas.drawString(left+1.7*cm, y-font_height, subject[0])
239) canvas.drawRightString(left+14.3*cm, y-font_height, _formatPrice(el['price']))
240) if el['tender']:
241) canvas.drawRightString(left+16.8*cm, y-font_height, 'eventual')
242) else:
243) canvas.drawRightString(left+16.8*cm, y-font_height, _formatPrice(el['total']))
244) subject = subject[1:]
245) x = 1
246) for line in subject:
247) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
248) x += 1
249) for line in desc:
250) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
251) x += 1
252) else:
253) canvas.drawString(left+1.7*cm, y-font_height, subject[0])
254) canvas.drawRightString(left+13.3*cm, y-font_height, _formatPrice(el['price']))
255) canvas.drawString(left+13.7*cm, y-font_height, str(part.vat[el['vat']][1]))
256) if el['tender']:
257) canvas.drawRightString(left+16.8*cm, y-font_height, 'eventual')
258) else:
259) canvas.drawRightString(left+16.8*cm, y-font_height, _formatPrice(el['total']))
260) subject = subject[1:]
261) x = 1
262) for line in subject:
263) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
264) x += 1
265) for line in desc:
266) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, line)
267) x += 1
268) odd = not odd
269) y -= (need_lines * line_height) + line_padding
270) if part.summary:
271) y -= (0.3*cm)
272) if part.vatType == 'gross':
273) canvas.setFont(font+'-Bold', font_size)
274) if iv.tender:
275) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Gesamtbetrag:')
276) else:
277) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Rechnungsbetrag:')
278) canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(part.sum))
279) canvas.setFont(font, font_size)
280) y -= line_height + line_padding
281) summaries = []
282) if len(part.vat) == 1:
283) vat = part.vat.keys()[0]
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
284) (integer, decimals) = _niceCount( (vat * 100) )
285) vatstr = '%s' % integer
286) if decimals:
287) vatstr += ',%s' % decimals
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
288) if iv.tender:
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
289) summaries.append(('Im Gesamtbetrag sind %s%% MwSt enthalten:' % vatstr, _formatPrice((part.sum/(vat+1))*vat)))
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
290) else:
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
291) summaries.append(('Im Rechnungsbetrag sind %s%% MwSt enthalten:' % vatstr, _formatPrice((part.sum/(vat+1))*vat)))
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
292) else:
293) for vat, vatdata in part.vat.iteritems():
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
294) (integer, decimals) = _niceCount( (vat * 100) )
295) vatstr = '%s' % integer
296) if decimals:
297) vatstr += ',%s' % decimals
298) summaries.append(('%s: Im Teilbetrag von %s sind %s%% MwSt enthalten:' % (vatdata[1], _formatPrice(vatdata[0]), vatstr), _formatPrice((vatdata[0]/(vat+1))*vat)))
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
299) summaries.sort()
300) for line in summaries:
301) canvas.drawRightString(left + 14.5*cm, y-font_height, line[0])
302) canvas.drawRightString(left + 16.8*cm, y-font_height, line[1])
303) y -= line_height
304) else:
305) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Nettobetrag:')
306) canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(part.sum))
307) y -= line_height
308) summaries = []
309) if len(part.vat) == 1:
310) vat = part.vat.keys()[0]
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
311) (integer, decimals) = _niceCount( (vat * 100) )
312) vatstr = '%s' % integer
313) if decimals:
314) vatstr += ',%s' % decimals
315) summaries.append(('zzgl. %s%% MwSt:' % vatstr, _formatPrice(vat*part.sum)))
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
316) else:
317) for vat, vatdata in part.vat.iteritems():
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
318) (integer, decimals) = _niceCount( (vat * 100) )
319) vatstr = '%s' % integer
320) if decimals:
321) vatstr += ',%s' % decimals
322) summaries.append(('zzgl. %s%% MwSt (%s):' % (vatstr, vatdata[1]), _formatPrice(vat*vatdata[0])))
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
323) summaries.sort()
324) for line in summaries:
325) canvas.drawRightString(left + 14.5*cm, y-font_height, line[0])
326) canvas.drawRightString(left + 16.8*cm, y-font_height, line[1])
327) y -= line_height
328) sum = 0
329) for vat, vatdata in part.vat.iteritems():
330) sum += (vat+1)*vatdata[0]
331) canvas.setFont(font+'-Bold', font_size)
332) if iv.tender:
333) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Gesamtbetrag:')
334) else:
335) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Rechnungsbetrag:')
336) canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(sum))
337) canvas.setFont(font, font_size)
338) y -= line_height + line_padding
|
Generisch
Bernd Wurst authored 16 years ago
|
339) elif type(part) == Invoice.Text:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
340) my_font_size = font_size
341) canvas.setFont(font, my_font_size)
342) left, right = leftcontent, rightcontent
343) firsttime = True
344) headlines = []
345) if part.urgent:
346) left += 1.5*cm
347) right -= 1.5*cm
348) if part.headline:
349) headlines = _splitToWidth(canvas, part.headline, right-left, font, my_font_size)
350) for para in part.paragraphs:
351) lines = _splitToWidth(canvas, para, right-left, font, my_font_size)
352) if part.urgent:
353) need_height = len(lines) * line_height
354) if len(headlines) > 0:
355) need_height += len(headlines) * (line_height + 1) + line_padding
356) canvas.setFillColorRGB(0.95, 0.95, 0.95)
357) 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)
358) canvas.setFillColorRGB(0, 0, 0)
359) y -= line_padding*3
360) if part.headline and firsttime:
361) firsttime = False
362) canvas.setFont(font+'-Bold', my_font_size+1)
363) for line in headlines:
364) canvas.drawString(left, y-(font_height+1), line)
365) y -= line_height + 1
366) y -= line_padding
367) canvas.setFont(font, my_font_size)
|
InvoiceText als Blocksatz d...
Bernd Wurst authored 16 years ago
|
368) for line in lines[:-1]:
369) _drawJustifiedString(left, y-font_height, line, canvas, right-left, font, my_font_size)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
370) y -= line_height
|
InvoiceText als Blocksatz d...
Bernd Wurst authored 16 years ago
|
371) canvas.drawString(left, y-font_height, lines[-1])
372) y -= line_height
373)
|