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
|
Break long address-lines
Bernd Wurst authored 15 years ago
|
9) from custom_elements import basicPage, firstPage, address_header
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
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)
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)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
82)
83) def _PageWrap(canvas):
84) '''Seitenumbruch'''
85) canvas.showPage()
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
86) basicPage(canvas)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
87)
88)
|
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)
|
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)
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
124)
125)
|
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
|
Generisch
Bernd Wurst authored 16 years ago
|
140) if type(part) == Invoice.Text:
|
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
|
Höhen noch genauer approxim...
Bernd Wurst authored 15 years ago
|
146) # Rechne eine Zeile mehr für den Rahmen
147) height += line_height
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
148) if part.headline:
149) height += (len(_splitToWidth(canvas, part.headline, right-left, font+'-Bold', default_font_size+1)) * line_height) + line_padding
150) for para in part.paragraphs:
151) height += (len(_splitToWidth(canvas, para, right-left, font, default_font_size)) * line_height) + line_padding
|
Generisch
Bernd Wurst authored 16 years ago
|
152) elif type(part) == Invoice.Table:
|
Höhen noch genauer approxim...
Bernd Wurst authored 15 years ago
|
153) # Eine Zeile plus 2 mal line_padding für Tabellenkopf
154) height = line_height + 2 * line_padding
|
Höhe der Tabelle besser app...
Bernd Wurst authored 15 years ago
|
155) for el in part.entries:
|
Höhen noch genauer approxim...
Bernd Wurst authored 15 years ago
|
156) # Die Abstände oben und unten
157) height += 2 * line_padding
|
Höhe der Tabelle besser app...
Bernd Wurst authored 15 years ago
|
158) # Die Breite ist konservativ
159) height += line_height*len(_splitToWidth(canvas, el['subject'], 9.3*cm, font, font_size))
160) if 'desc' in el and el['desc'] != '':
161) height += line_height * len(_splitToWidth(canvas, el['desc'], 11*cm, font, font_size))
|
Höhen noch genauer approxim...
Bernd Wurst authored 15 years ago
|
162) if part.vatType == 'net':
163) # Eine Zeile mehr
164) height += line_height + line_padding
165) # Für die MwSt-Summen
166) height += (line_height + line_padding) * len(part.vat)
167) # Für den Rechnungsbetrag
168) height += line_height + line_padding
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
169) return height
170)
171)
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
172)
173) address(canvas, iv.addresslines)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
174)
175) font_size = default_font_size
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
176) y = firstPage(canvas)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
177)
178) canvas.setFont(font+'-Bold', font_size+3)
|
Generisch
Bernd Wurst authored 16 years ago
|
179) min_y = y
180) if iv.caption:
181) canvas.drawString(leftcontent, y, iv.caption)
182) min_y -= (font_size + 3) + 0.5*cm
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
183)
|
Generisch
Bernd Wurst authored 16 years ago
|
184) if type(iv) == Invoice.Tender:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
185) canvas.setFont(font, font_size)
186) canvas.drawString(rightcolumn, y, "Erstellungsdatum:")
187) canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
188) y -= (font_size + 0.1*cm)
|
Generisch
Bernd Wurst authored 16 years ago
|
189) elif type(iv) == Invoice.Generic:
190) canvas.setFont(font, font_size)
191) canvas.drawString(rightcolumn, y, "Datum:")
192) canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
193) y -= (font_size + 0.1*cm)
194) elif type(iv) == Invoice.Invoice:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
195) canvas.setFont(font+'-Bold', font_size)
196) canvas.drawString(rightcolumn, y, "Bei Fragen bitte immer angeben:")
197) y -= (font_size + 0.2*cm)
198) canvas.setFont(font, font_size)
199) canvas.drawString(rightcolumn, y, "Rechnungsdatum:")
200) canvas.drawRightString(rightcontent, y, "%s" % iv.date.strftime('%d. %m. %Y'))
201) y -= (font_size + 0.1*cm)
202) canvas.drawString(rightcolumn, y, "Rechnungsnummer:")
203) canvas.drawRightString(rightcontent, y, "%i" % iv.id)
204) y -= (font_size + 0.1*cm)
205) if iv.customerno:
206) canvas.drawString(rightcolumn, y, "Kundennummer:")
207) canvas.drawRightString(rightcontent, y, "%s" % iv.customerno)
208) y -= (font_size + 0.5*cm)
209) canvas.setFont(font, font_size)
|
Generisch
Bernd Wurst authored 16 years ago
|
210) y = min(min_y, y)
211)
212) if iv.salutation:
213) canvas.drawString(leftcontent, y, iv.salutation)
214) y -= font_size + 0.2*cm
215) if type(iv) in [Invoice.Tender, Invoice.Invoice]:
216) introText = 'hiermit stellen wir Ihnen die nachfolgend genannten Leistungen in Rechnung.'
217) if type(iv) == Invoice.Tender:
218) introText = 'hiermit unterbreiten wir Ihnen folgendes Angebot.'
219) intro = _splitToWidth(canvas, introText, rightcontent - leftcontent, font, font_size)
220) for line in intro:
221) canvas.drawString(leftcontent, y, line)
222) y -= font_size + 0.1*cm
223) y -= font_size + 0.1*cm
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
224)
225)
226) font_size = default_font_size
227) for part in iv.parts:
228) if y - _partHeight(part) < (bottomcontent + (0.5*cm)):
229) num_pages += 1
230) y = bottomcontent + (0.5*cm)
231) canvas.setFont(font, default_font_size-2)
232) canvas.drawRightString(rightcontent, bottomcontent + line_padding, 'Fortsetzung auf Seite %i' % num_pages)
233) _PageWrap(canvas)
234) y = topcontent - font_size
235) canvas.setFillColor((0,0,0))
236) canvas.setFont(font, font_size-2)
237) canvas.drawCentredString(leftcontent + (rightcontent - leftcontent) / 2, y, '- Seite %i -' % num_pages)
238) y -= line_padding*3
|
Höhen noch genauer approxim...
Bernd Wurst authored 15 years ago
|
239) # Debug: Was hat die Höhenbestimmung für diesen Teil als Höhe herausgefunden?
240) #canvas.line(leftcontent, y-_partHeight(part), rightcontent, y-_partHeight(part))
241)
|
Generisch
Bernd Wurst authored 16 years ago
|
242) if type(part) == Invoice.Table:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
243)
244) left = leftcontent
245) right = rightcontent
246) top = topcontent
247) bottom = bottomcontent
248) canvas.setFont(font, font_size)
249) canvas.drawString(left+(0.1*cm), y-line_height+line_padding, 'Anz.')
250) canvas.drawString(left+(1.6*cm), y-line_height+line_padding, 'Beschreibung')
251) if len(part.vat) == 1:
252) canvas.drawRightString(left+(14.3*cm), y-line_height+line_padding, 'Einzelpreis')
253) else:
254) canvas.drawRightString(left+(13.7*cm), y-line_height+line_padding, 'Einzelpreis')
255) canvas.drawRightString(left+(16.8*cm), y-line_height+line_padding, 'Gesamtpreis')
256) canvas.setLineWidth(0.01*cm)
257) canvas.line(left, y - line_height, right, y - line_height)
258) y -= line_height + 0.02*cm
259) odd=True
260) for el in part.entries:
261) subject = []
262) if len(part.vat) == 1:
263) subject = _splitToWidth(canvas, el['subject'], 10.3*cm, font, font_size)
264) else:
265) subject = _splitToWidth(canvas, el['subject'], 9.3*cm, font, font_size)
266) desc = []
267) if 'desc' in el and el['desc'] != '':
|
Blocksatz auch für Beschrei...
Bernd Wurst authored 16 years ago
|
268) desc = _splitToWidth(canvas, el['desc'], 11*cm, font, font_size)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
269)
270) # draw the background
271) if not odd:
272) canvas.setFillColorRGB(0.9, 0.9, 0.9)
273) else:
274) canvas.setFillColorRGB(1, 1, 1)
275) need_lines = len(subject) + len(desc)
276) 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)
277) canvas.setFillColorRGB(0, 0, 0)
278) y -= line_padding
279) (integer, decimals) = _niceCount(el['count'])
280) canvas.drawRightString(left+0.8*cm, y-font_height, integer)
281) if decimals:
282) canvas.drawString(left+0.8*cm, y-font_height, ',%s' % decimals)
283) if len(part.vat) == 1:
284) canvas.drawString(left+1.7*cm, y-font_height, subject[0])
285) canvas.drawRightString(left+14.3*cm, y-font_height, _formatPrice(el['price']))
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
|
Blocksatz auch für Beschrei...
Bernd Wurst authored 16 years ago
|
295) for line in desc[:-1]:
296) _drawJustifiedString(left+1.7*cm, y-(x * line_height)-font_height, line, canvas, 11*cm, font, font_size)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
297) x += 1
|
Blocksatz auch für Beschrei...
Bernd Wurst authored 16 years ago
|
298) canvas.drawString(left+1.7*cm, y-(x * line_height)-font_height, desc[-1])
299) x += 1
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
300) else:
301) canvas.drawString(left+1.7*cm, y-font_height, subject[0])
302) canvas.drawRightString(left+13.3*cm, y-font_height, _formatPrice(el['price']))
303) canvas.drawString(left+13.7*cm, y-font_height, str(part.vat[el['vat']][1]))
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) odd = not odd
317) y -= (need_lines * line_height) + line_padding
318) if part.summary:
319) y -= (0.3*cm)
320) if part.vatType == 'gross':
321) canvas.setFont(font+'-Bold', font_size)
322) if iv.tender:
323) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Gesamtbetrag:')
324) else:
325) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Rechnungsbetrag:')
326) canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(part.sum))
327) canvas.setFont(font, font_size)
328) y -= line_height + line_padding
329) summaries = []
330) if len(part.vat) == 1:
331) vat = part.vat.keys()[0]
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
332) (integer, decimals) = _niceCount( (vat * 100) )
333) vatstr = '%s' % integer
334) if decimals:
335) vatstr += ',%s' % decimals
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
336) if iv.tender:
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
337) 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
|
338) else:
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
339) 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
|
340) else:
341) for vat, vatdata in part.vat.iteritems():
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
342) (integer, decimals) = _niceCount( (vat * 100) )
343) vatstr = '%s' % integer
344) if decimals:
345) vatstr += ',%s' % decimals
346) 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
|
347) summaries.sort()
348) for line in summaries:
349) canvas.drawRightString(left + 14.5*cm, y-font_height, line[0])
350) canvas.drawRightString(left + 16.8*cm, y-font_height, line[1])
351) y -= line_height
352) else:
353) canvas.drawRightString(left + 14.5*cm, y-font_height, 'Nettobetrag:')
354) canvas.drawRightString(left + 16.8*cm, y-font_height, _formatPrice(part.sum))
355) y -= line_height
356) summaries = []
357) if len(part.vat) == 1:
358) vat = part.vat.keys()[0]
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
359) (integer, decimals) = _niceCount( (vat * 100) )
360) vatstr = '%s' % integer
361) if decimals:
362) vatstr += ',%s' % decimals
363) summaries.append(('zzgl. %s%% MwSt:' % vatstr, _formatPrice(vat*part.sum)))
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
364) else:
365) for vat, vatdata in part.vat.iteritems():
|
Trennung von Firmen-spezifi...
Bernd Wurst authored 16 years ago
|
366) (integer, decimals) = _niceCount( (vat * 100) )
367) vatstr = '%s' % integer
368) if decimals:
369) vatstr += ',%s' % decimals
370) summaries.append(('zzgl. %s%% MwSt (%s):' % (vatstr, vatdata[1]), _formatPrice(vat*vatdata[0])))
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
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:
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
388) my_font_size = font_size
389) canvas.setFont(font, my_font_size)
390) left, right = leftcontent, rightcontent
391) firsttime = True
392) headlines = []
393) if part.urgent:
394) left += 1.5*cm
395) right -= 1.5*cm
396) if part.headline:
397) headlines = _splitToWidth(canvas, part.headline, right-left, font, my_font_size)
398) for para in part.paragraphs:
399) lines = _splitToWidth(canvas, para, right-left, font, my_font_size)
400) if part.urgent:
401) need_height = len(lines) * line_height
402) if len(headlines) > 0:
403) need_height += len(headlines) * (line_height + 1) + line_padding
404) canvas.setFillColorRGB(0.95, 0.95, 0.95)
405) 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)
406) canvas.setFillColorRGB(0, 0, 0)
407) y -= line_padding*3
408) if part.headline and firsttime:
409) firsttime = False
410) canvas.setFont(font+'-Bold', my_font_size+1)
411) for line in headlines:
412) canvas.drawString(left, y-(font_height+1), line)
413) y -= line_height + 1
414) y -= line_padding
415) canvas.setFont(font, my_font_size)
|
InvoiceText als Blocksatz d...
Bernd Wurst authored 16 years ago
|
416) for line in lines[:-1]:
417) _drawJustifiedString(left, y-font_height, line, canvas, right-left, font, my_font_size)
|
Struktur verändern (broken!)
Bernd Wurst authored 16 years ago
|
418) y -= line_height
|
InvoiceText als Blocksatz d...
Bernd Wurst authored 16 years ago
|
419) canvas.drawString(left, y-font_height, lines[-1])
420) y -= line_height
421)
|