Bernd Wurst commited on 2024-02-14 08:44:25
Zeige 4 geänderte Dateien mit 125 Einfügungen und 113 Löschungen.
... | ... |
@@ -50,9 +51,9 @@ class InvoiceTable(object): |
50 | 51 |
self.vatType = vatType |
51 | 52 |
|
52 | 53 |
def validEntry(self, entry): |
53 |
- '''bekommt einen Eintrag und liefert einen Eintrag wenn ok, wirft ansonsten ValueError. |
|
54 |
+ """bekommt einen Eintrag und liefert einen Eintrag, wenn ok; wirft ansonsten ValueError. |
|
54 | 55 |
wird benutzt um z.B. die Summe auszurechnen oder ähnliches |
55 |
- ''' |
|
56 |
+ """ |
|
56 | 57 |
k = entry.keys() |
57 | 58 |
e = entry |
58 | 59 |
if not ('count' in k and 'unit' in k and 'subject' in k and 'price' in k and 'vat' in k): |
... | ... |
@@ -81,8 +82,8 @@ class InvoiceTable(object): |
81 | 82 |
return ret |
82 | 83 |
|
83 | 84 |
def addItem(self, data): |
84 |
- '''Fügt eine Zeile ein. data muss ein Dict mit passenden Keys und passenden |
|
85 |
- Typen sein''' |
|
85 |
+ """Fügt eine Zeile ein. data muss ein Dict mit passenden Keys und passenden |
|
86 |
+ Typen sein""" |
|
86 | 87 |
d = self.validEntry(data) |
87 | 88 |
if not d['vat'] in self.vat.keys(): |
88 | 89 |
self.vat[d['vat']] = [0, chr(65+len(self.vat))] |
... | ... |
@@ -94,8 +95,8 @@ class InvoiceTable(object): |
94 | 95 |
def addTitle(self, title): |
95 | 96 |
self.entries.append({'type': 'title', 'title': title, }) |
96 | 97 |
|
97 |
- def addPayment(self, type, amount, date): |
|
98 |
- self.payments.append({"type": type, "amount": amount, "date": date}) |
|
98 |
+ def addPayment(self, payment_type, amount, date): |
|
99 |
+ self.payments.append({"type": payment_type, "amount": amount, "date": date}) |
|
99 | 100 |
|
100 | 101 |
|
101 | 102 |
RECHNUNG = 380 |
... | ... |
@@ -108,8 +109,9 @@ VAT_KLEINUNTERNEHMER = 'E' |
108 | 109 |
VAT_INNERGEM = 'K' |
109 | 110 |
|
110 | 111 |
PAYMENT_LASTSCHRIFT = "59" |
111 |
-PAYMENT_UEBERWEISUNG = "30" |
|
112 |
+PAYMENT_UEBERWEISUNG = "58" |
|
112 | 113 |
PAYMENT_BANKKONTO = "42" |
114 |
+PAYMENT_ONLINE = "68" |
|
113 | 115 |
PAYMENT_BAR = "10" |
114 | 116 |
PAYMENT_KARTE = "48" |
115 | 117 |
|
... | ... |
@@ -179,6 +182,6 @@ class Invoice(object): |
179 | 182 |
self.date = datetime.date.today() |
180 | 183 |
|
181 | 184 |
def setDate(self, date): |
182 |
- if type(date) != datetime.date: |
|
185 |
+ if not isinstance(date, datetime.date): |
|
183 | 186 |
raise ValueError('date must be of type »datetime.date«') |
184 | 187 |
self.date = date |
... | ... |
@@ -17,19 +17,16 @@ |
17 | 17 |
# along with Bib2011. If not, see <http://www.gnu.org/licenses/>. |
18 | 18 |
|
19 | 19 |
import os.path |
20 |
- |
|
21 |
-import reportlab |
|
22 |
-from reportlab.lib import fonts |
|
23 |
- |
|
24 |
-from .InvoiceObjects import InvoiceTable, InvoiceText, InvoiceImage, GUTSCHRIFT |
|
25 | 20 |
import re |
26 | 21 |
|
22 |
+from reportlab.lib.pagesizes import A4 |
|
27 | 23 |
# reportlab imports |
28 | 24 |
from reportlab.lib.units import cm, inch |
29 |
-from reportlab.lib.pagesizes import A4 |
|
30 |
-from reportlab.pdfbase.ttfonts import TTFont, TTFError |
|
31 | 25 |
from reportlab.pdfbase import pdfmetrics |
32 |
-from reportlab.pdfgen import canvas as Canvas |
|
26 |
+from reportlab.pdfbase.ttfonts import TTFont, TTFError |
|
27 |
+from reportlab.pdfgen import canvas |
|
28 |
+ |
|
29 |
+from .InvoiceObjects import InvoiceTable, InvoiceText, InvoiceImage, GUTSCHRIFT |
|
33 | 30 |
|
34 | 31 |
|
35 | 32 |
def _formatPrice(price, symbol='€'): |
... | ... |
@@ -91,7 +89,7 @@ class PDF(object): |
91 | 89 |
_registerFonts() |
92 | 90 |
from io import BytesIO |
93 | 91 |
self.fd = BytesIO() |
94 |
- self.canvas = Canvas.Canvas(self.fd, pagesize=A4) |
|
92 |
+ self.canvas = canvas.Canvas(self.fd, pagesize=A4) |
|
95 | 93 |
|
96 | 94 |
self.invoice = invoice |
97 | 95 |
|
... | ... |
@@ -117,7 +114,8 @@ class PDF(object): |
117 | 114 |
while len(words) > 0: |
118 | 115 |
mywords = [words[0], ] |
119 | 116 |
del words[0] |
120 |
- while len(words) > 0 and self.canvas.stringWidth(' '.join(mywords) + ' ' + words[0], font, size) <= width: |
|
117 |
+ while len(words) > 0 and self.canvas.stringWidth(' '.join(mywords) + ' ' + words[0], font, |
|
118 |
+ size) <= width: |
|
121 | 119 |
mywords.append(words[0]) |
122 | 120 |
del words[0] |
123 | 121 |
lines.append(' '.join(mywords)) |
... | ... |
@@ -144,7 +140,7 @@ class PDF(object): |
144 | 140 |
|
145 | 141 |
def _partHeight(self, part): |
146 | 142 |
height = 0 |
147 |
- if type(part) == InvoiceText: |
|
143 |
+ if isinstance(part, InvoiceText): |
|
148 | 144 |
left, right = self.leftcontent, self.rightcontent |
149 | 145 |
if part.urgent: |
150 | 146 |
left += 1.5 * cm |
... | ... |
@@ -153,10 +149,12 @@ class PDF(object): |
153 | 149 |
# Rechne eine Zeile mehr für den Rahmen |
154 | 150 |
height += self.line_height |
155 | 151 |
if part.headline: |
156 |
- height += (len(self._splitToWidth(part.headline, right-left, self.font+'-Bold', self.default_font_size+1)) * self.line_height) + self.line_padding |
|
152 |
+ height += (len(self._splitToWidth(part.headline, right - left, self.font + '-Bold', |
|
153 |
+ self.default_font_size + 1)) * self.line_height) + self.line_padding |
|
157 | 154 |
for para in part.paragraphs: |
158 |
- height += (len(self._splitToWidth(para, right-left, self.font, self.default_font_size)) * self.line_height) + self.line_padding |
|
159 |
- elif type(part) == InvoiceTable: |
|
155 |
+ height += (len(self._splitToWidth(para, right - left, self.font, |
|
156 |
+ self.default_font_size)) * self.line_height) + self.line_padding |
|
157 |
+ elif isinstance(part, InvoiceTable): |
|
160 | 158 |
# Eine Zeile plus 2 mal line_padding für Tabellenkopf |
161 | 159 |
height = self.line_height + 2 * self.line_padding |
162 | 160 |
# Wenn nur ein Element (plus Summen) hin passt, reicht uns das |
... | ... |
@@ -183,12 +180,16 @@ class PDF(object): |
183 | 180 |
def _tableHead(self, part): |
184 | 181 |
self.canvas.setFont(self.font, self.font_size) |
185 | 182 |
self.canvas.drawString(self.leftcontent + (0.1 * cm), self.y - self.line_height + self.line_padding, 'Anz.') |
186 |
- self.canvas.drawString(self.leftcontent+(2.1*cm), self.y-self.line_height+self.line_padding, 'Beschreibung') |
|
183 |
+ self.canvas.drawString(self.leftcontent + (2.1 * cm), self.y - self.line_height + self.line_padding, |
|
184 |
+ 'Beschreibung') |
|
187 | 185 |
if len(part.vat) == 1: |
188 |
- self.canvas.drawRightString(self.leftcontent+(14.3*cm), self.y-self.line_height+self.line_padding, 'Einzelpreis') |
|
186 |
+ self.canvas.drawRightString(self.leftcontent + (14.3 * cm), self.y - self.line_height + self.line_padding, |
|
187 |
+ 'Einzelpreis') |
|
189 | 188 |
else: |
190 |
- self.canvas.drawRightString(self.leftcontent+(13.3*cm), self.y-self.line_height+self.line_padding, 'Einzelpreis') |
|
191 |
- self.canvas.drawRightString(self.leftcontent+(16.8*cm), self.y-self.line_height+self.line_padding, 'Gesamtpreis') |
|
189 |
+ self.canvas.drawRightString(self.leftcontent + (13.3 * cm), self.y - self.line_height + self.line_padding, |
|
190 |
+ 'Einzelpreis') |
|
191 |
+ self.canvas.drawRightString(self.leftcontent + (16.8 * cm), self.y - self.line_height + self.line_padding, |
|
192 |
+ 'Gesamtpreis') |
|
192 | 193 |
self.canvas.setLineWidth(0.01 * cm) |
193 | 194 |
self.canvas.line(self.leftcontent, self.y - self.line_height, self.rightcontent, self.y - self.line_height) |
194 | 195 |
self.y -= self.line_height + 0.02 * cm |
... | ... |
@@ -198,14 +198,15 @@ class PDF(object): |
198 | 198 |
'''Seitenumbruch''' |
199 | 199 |
self.num_pages += 1 |
200 | 200 |
self.canvas.setFont(self.font, self.default_font_size - 2) |
201 |
- self.canvas.drawRightString(self.rightcontent, self.bottomcontent + self.line_padding, 'Fortsetzung auf Seite %i' % self.num_pages) |
|
201 |
+ self.canvas.drawRightString(self.rightcontent, self.bottomcontent + self.line_padding, |
|
202 |
+ 'Fortsetzung auf Seite %i' % self.num_pages) |
|
202 | 203 |
self.canvas.showPage() |
203 | 204 |
self.basicPage() |
204 | 205 |
self.y = self.topcontent - self.font_size |
205 | 206 |
self.canvas.setFillColor((0, 0, 0)) |
206 | 207 |
self.canvas.setFont(self.font, self.font_size - 2) |
207 |
- self.canvas.drawCentredString(self.leftcontent + (self.rightcontent - self.leftcontent) / 2, self.y, '- Seite %i -' % self.num_pages) |
|
208 |
- |
|
208 |
+ self.canvas.drawCentredString(self.leftcontent + (self.rightcontent - self.leftcontent) / 2, self.y, |
|
209 |
+ '- Seite %i -' % self.num_pages) |
|
209 | 210 |
|
210 | 211 |
def _Footer(self): |
211 | 212 |
self.canvas.setStrokeColor((0, 0, 0)) |
... | ... |
@@ -230,7 +231,8 @@ class PDF(object): |
230 | 231 |
c = 0 |
231 | 232 |
for line in lines: |
232 | 233 |
c += 10 |
233 |
- self.canvas.drawString(self.leftcontent + ((self.rightcontent - self.leftcontent) // 3), self.bottomcontent - c, line) |
|
234 |
+ self.canvas.drawString(self.leftcontent + ((self.rightcontent - self.leftcontent) // 3), |
|
235 |
+ self.bottomcontent - c, line) |
|
234 | 236 |
|
235 | 237 |
if not self.invoice.debit: |
236 | 238 |
iban = self.invoice.seller_bank_data['iban'] |
... | ... |
@@ -243,7 +245,8 @@ class PDF(object): |
243 | 245 |
c = 0 |
244 | 246 |
for line in lines: |
245 | 247 |
c += 10 |
246 |
- self.canvas.drawString(self.leftcontent + ((self.rightcontent - self.leftcontent) // 3) * 2, self.bottomcontent - c, line) |
|
248 |
+ self.canvas.drawString(self.leftcontent + ((self.rightcontent - self.leftcontent) // 3) * 2, |
|
249 |
+ self.bottomcontent - c, line) |
|
247 | 250 |
|
248 | 251 |
def basicPage(self): |
249 | 252 |
# Set marker to top. |
... | ... |
@@ -276,7 +277,8 @@ class PDF(object): |
276 | 277 |
self.invoice.customer['address']['line1'] or '', |
277 | 278 |
self.invoice.customer['address']['line2'] or '', |
278 | 279 |
self.invoice.customer['address']['line3'] or '', |
279 |
- ((self.invoice.customer['address']['postcode'] or '') + ' ' + (self.invoice.customer['address']['city_name'] or '')).strip(), |
|
280 |
+ ((self.invoice.customer['address']['postcode'] or '') + ' ' + ( |
|
281 |
+ self.invoice.customer['address']['city_name'] or '')).strip(), |
|
280 | 282 |
]) |
281 | 283 |
for line in addresslines: |
282 | 284 |
self.canvas.drawString(x, self.y, line) |
... | ... |
@@ -292,7 +293,8 @@ class PDF(object): |
292 | 293 |
height=2 * cm, preserveAspectRatio=True, anchor='nw') |
293 | 294 |
self.y -= (2.5 * cm) |
294 | 295 |
self.canvas.setFont(self.font + "-Bold", self.font_size) |
295 |
- self.canvas.drawString(self.rightcolumn, self.y, self.invoice.seller['trade_name'] or self.invoice.seller['name']) |
|
296 |
+ self.canvas.drawString(self.rightcolumn, self.y, |
|
297 |
+ self.invoice.seller['trade_name'] or self.invoice.seller['name']) |
|
296 | 298 |
self.y -= (self.font_size + 5) |
297 | 299 |
self.canvas.setFont(self.font, self.font_size) |
298 | 300 |
lines = [ |
... | ... |
@@ -369,7 +368,7 @@ class PDF(object): |
369 | 368 |
if self.y - self._partHeight(part) < (self.bottomcontent + (0.5 * cm)): |
370 | 369 |
self._PageWrap() |
371 | 370 |
self.y = self.topcontent - self.font_size - self.line_padding * 3 |
372 |
- if type(part) == InvoiceTable: |
|
371 |
+ if isinstance(part, InvoiceTable): |
|
373 | 372 |
|
374 | 373 |
left = self.leftcontent |
375 | 374 |
right = self.rightcontent |
... | ... |
@@ -385,7 +384,6 @@ class PDF(object): |
385 | 384 |
self.canvas.setFont(self.font, font_size) |
386 | 385 |
self.y -= self.line_height + self.line_padding |
387 | 386 |
else: |
388 |
- subject = [] |
|
389 | 387 |
if len(part.vat) == 1: |
390 | 388 |
subject = self._splitToWidth(el['subject'], 9.8 * cm, self.font, font_size) |
391 | 389 |
else: |
... | ... |
@@ -405,11 +403,13 @@ class PDF(object): |
405 | 403 |
14.0 * cm, self.font, font_size)) |
406 | 404 |
need_lines = len(subject) + len(desc) |
407 | 405 |
# need page wrap? |
408 |
- if self.y - (need_lines+1 * (self.line_height + self.line_padding)) < (self.bottomcontent + 1*cm): |
|
406 |
+ if self.y - (need_lines + 1 * (self.line_height + self.line_padding)) < ( |
|
407 |
+ self.bottomcontent + 1 * cm): |
|
409 | 408 |
self.canvas.setFont(self.font + '-Italic', font_size) |
410 | 409 |
# Zwischensumme |
411 | 410 |
self.canvas.drawRightString(left + 14.5 * cm, self.y - self.font_height, 'Zwischensumme:') |
412 |
- self.canvas.drawRightString(left + 16.8*cm, self.y-self.font_height, _formatPrice(temp_sum)) |
|
411 |
+ self.canvas.drawRightString(left + 16.8 * cm, self.y - self.font_height, |
|
412 |
+ _formatPrice(temp_sum)) |
|
413 | 413 |
# page wrap |
414 | 414 |
self._PageWrap() |
415 | 415 |
self.y = self.topcontent - font_size - self.line_padding * 3 |
... | ... |
@@ -420,7 +420,8 @@ class PDF(object): |
420 | 420 |
# übertrag |
421 | 421 |
self.canvas.setFont(self.font + '-Italic', font_size) |
422 | 422 |
self.canvas.drawRightString(left + 14.5 * cm, self.y - self.font_height, 'Übertrag:') |
423 |
- self.canvas.drawRightString(left + 16.8*cm, self.y-self.font_height, _formatPrice(temp_sum)) |
|
423 |
+ self.canvas.drawRightString(left + 16.8 * cm, self.y - self.font_height, |
|
424 |
+ _formatPrice(temp_sum)) |
|
424 | 425 |
self.y -= self.font_height + self.line_padding * 3 |
425 | 426 |
self.canvas.setFont(self.font, self.default_font_size) |
426 | 427 |
|
... | ... |
@@ -433,7 +433,9 @@ class PDF(object): |
433 | 433 |
self.canvas.setFillColorRGB(0.9, 0.9, 0.9) |
434 | 434 |
else: |
435 | 435 |
self.canvas.setFillColorRGB(1, 1, 1) |
436 |
- self.canvas.rect(left, self.y - (need_lines*self.line_height)-(2*self.line_padding), height = (need_lines*self.line_height)+(2*self.line_padding), width = right-left, fill=1, stroke=0) |
|
436 |
+ self.canvas.rect(left, self.y - (need_lines * self.line_height) - (2 * self.line_padding), |
|
437 |
+ height=(need_lines * self.line_height) + (2 * self.line_padding), |
|
438 |
+ width=right - left, fill=1, stroke=0) |
|
437 | 439 |
self.canvas.setFillColorRGB(0, 0, 0) |
438 | 440 |
self.y -= self.line_padding |
439 | 441 |
self.canvas.drawRightString(left + 1.1 * cm, self.y - self.font_height, '%.0f' % el['count']) |
... | ... |
@@ -441,27 +443,34 @@ class PDF(object): |
441 | 443 |
self.canvas.drawString(left + 1.2 * cm, self.y - self.font_height, el['unit']) |
442 | 444 |
self.canvas.drawString(left + 2.2 * cm, self.y - self.font_height, subject[0]) |
443 | 445 |
if len(part.vat) == 1: |
444 |
- self.canvas.drawRightString(left+14.3*cm, self.y-self.font_height, _formatPrice(el['price'])) |
|
446 |
+ self.canvas.drawRightString(left + 14.3 * cm, self.y - self.font_height, |
|
447 |
+ _formatPrice(el['price'])) |
|
445 | 448 |
else: |
446 |
- self.canvas.drawRightString(left+13.3*cm, self.y-self.font_height, _formatPrice(el['price'])) |
|
447 |
- self.canvas.drawString(left+13.7*cm, self.y-self.font_height, str(part.vat[el['vat']][1])) |
|
449 |
+ self.canvas.drawRightString(left + 13.3 * cm, self.y - self.font_height, |
|
450 |
+ _formatPrice(el['price'])) |
|
451 |
+ self.canvas.drawString(left + 13.7 * cm, self.y - self.font_height, |
|
452 |
+ str(part.vat[el['vat']][1])) |
|
448 | 453 |
if el['tender']: |
449 | 454 |
self.canvas.drawRightString(left + 16.8 * cm, self.y - self.font_height, 'eventual') |
450 | 455 |
else: |
451 |
- self.canvas.drawRightString(left+16.8*cm, self.y-self.font_height, _formatPrice(el['total'])) |
|
456 |
+ self.canvas.drawRightString(left + 16.8 * cm, self.y - self.font_height, |
|
457 |
+ _formatPrice(el['total'])) |
|
452 | 458 |
subject = subject[1:] |
453 | 459 |
x = 1 |
454 | 460 |
for line in subject: |
455 |
- self.canvas.drawString(left+2.2*cm, self.y-(x * self.line_height)-self.font_height, line) |
|
461 |
+ self.canvas.drawString(left + 2.2 * cm, self.y - (x * self.line_height) - self.font_height, |
|
462 |
+ line) |
|
456 | 463 |
x += 1 |
457 | 464 |
for line in desc: |
458 |
- self.canvas.drawString(left+2.2*cm, self.y-(x * self.line_height)-self.font_height, line) |
|
465 |
+ self.canvas.drawString(left + 2.2 * cm, self.y - (x * self.line_height) - self.font_height, |
|
466 |
+ line) |
|
459 | 467 |
x += 1 |
460 | 468 |
odd = not odd |
461 | 469 |
self.y -= (need_lines * self.line_height) + self.line_padding |
462 | 470 |
if part.summary: |
463 | 471 |
need_lines = 5 |
464 |
- if self.y - (need_lines+1 * (self.line_height + self.line_padding)) < (self.bottomcontent + 1*cm): |
|
472 |
+ if self.y - (need_lines + 1 * (self.line_height + self.line_padding)) < ( |
|
473 |
+ self.bottomcontent + 1 * cm): |
|
465 | 474 |
self.canvas.setFont(self.font + '-Italic', font_size) |
466 | 475 |
# Zwischensumme |
467 | 476 |
self.canvas.drawRightString(left + 14.5 * cm, self.y - self.font_height, 'Zwischensumme:') |
... | ... |
@@ -498,15 +507,21 @@ class PDF(object): |
498 | 507 |
if len(part.vat) == 1: |
499 | 508 |
vat = list(part.vat.keys())[0] |
500 | 509 |
if self.invoice.tender: |
501 |
- summaries.append(('Im Gesamtbetrag sind %.1f%% MwSt enthalten:' % (vat*100), _formatPrice((part.sum/(vat+1))*vat))) |
|
510 |
+ summaries.append(('Im Gesamtbetrag sind %.1f%% MwSt enthalten:' % (vat * 100), |
|
511 |
+ _formatPrice((part.sum / (vat + 1)) * vat))) |
|
502 | 512 |
else: |
503 |
- summaries.append(('Im Rechnungsbetrag sind %.1f%% MwSt enthalten:' % (vat*100), _formatPrice((part.sum/(vat+1))*vat))) |
|
513 |
+ summaries.append(( |
|
514 |
+ 'Im Rechnungsbetrag sind %.1f%% MwSt enthalten:' % (vat * 100), |
|
515 |
+ _formatPrice((part.sum / (vat + 1)) * vat))) |
|
504 | 516 |
else: |
505 | 517 |
for vat, vatdata in part.vat.items(): |
506 | 518 |
if vat > 0: |
507 |
- summaries.append(('%s: Im Teilbetrag von %s sind %.1f%% MwSt enthalten:' % (vatdata[1], _formatPrice(vatdata[0]), vat*100), _formatPrice((vatdata[0]/(vat+1))*vat))) |
|
519 |
+ summaries.append(('%s: Im Teilbetrag von %s sind %.1f%% MwSt enthalten:' % ( |
|
520 |
+ vatdata[1], _formatPrice(vatdata[0]), vat * 100), |
|
521 |
+ _formatPrice((vatdata[0] / (vat + 1)) * vat))) |
|
508 | 522 |
else: |
509 |
- summaries.append(('%s: Durchlaufende Posten ohne Berechnung von MwSt.' % (vatdata[1]), 0.0)) |
|
523 |
+ summaries.append(('%s: Durchlaufende Posten ohne Berechnung von MwSt.' % ( |
|
524 |
+ vatdata[1]), 0.0)) |
|
510 | 525 |
summaries.append(('Nettobetrag:', _formatPrice(part.sum - (part.sum / (vat + 1)) * vat))) |
511 | 526 |
summaries.sort() |
512 | 527 |
for line in summaries: |
... | ... |
@@ -520,7 +535,8 @@ class PDF(object): |
520 | 535 |
self.y -= self.line_height |
521 | 536 |
summaries = [] |
522 | 537 |
if list(part.vat.keys())[0] == 0.0: |
523 |
- self.canvas.drawString(left, self.y-self.font_height, 'Dieser Beleg wurde ohne Ausweis von MwSt erstellt.') |
|
538 |
+ self.canvas.drawString(left, self.y - self.font_height, |
|
539 |
+ 'Dieser Beleg wurde ohne Ausweis von MwSt erstellt.') |
|
524 | 540 |
self.y -= self.line_height |
525 | 541 |
else: |
526 | 542 |
if len(part.vat) == 1: |
... | ... |
@@ -528,7 +544,8 @@ class PDF(object): |
528 | 544 |
summaries.append(('zzgl. %.1f%% MwSt:' % (vat * 100), _formatPrice(vat * part.sum))) |
529 | 545 |
else: |
530 | 546 |
for vat, vatdata in part.vat.items(): |
531 |
- summaries.append(('zzgl. %.1f%% MwSt (%s):' % (vat*100, vatdata[1]), _formatPrice(vat*vatdata[0]))) |
|
547 |
+ summaries.append(('zzgl. %.1f%% MwSt (%s):' % (vat * 100, vatdata[1]), |
|
548 |
+ _formatPrice(vat * vatdata[0]))) |
|
532 | 549 |
summaries.sort() |
533 | 550 |
for line in summaries: |
534 | 551 |
self.canvas.drawRightString(left + 14.5 * cm, self.y - self.font_height, line[0]) |
... | ... |
@@ -560,7 +577,8 @@ class PDF(object): |
560 | 577 |
if pay['date'] != self.invoice.date: |
561 | 578 |
descr += ' am %s' % (pay['date'].strftime('%d. %m. %Y')) |
562 | 579 |
self.canvas.drawRightString(left + 14.5 * cm, self.y - self.font_height, descr + ':') |
563 |
- self.canvas.drawRightString(left + 16.8*cm, self.y-self.font_height, _formatPrice(pay['amount'])) |
|
580 |
+ self.canvas.drawRightString(left + 16.8 * cm, self.y - self.font_height, |
|
581 |
+ _formatPrice(pay['amount'])) |
|
564 | 582 |
self.y -= self.line_height |
565 | 583 |
sum = part.sum |
566 | 584 |
if part.vatType == 'net': |
... | ... |
@@ -570,13 +588,14 @@ class PDF(object): |
570 | 588 |
rest = sum - paysum |
571 | 589 |
if part.payments and rest > 0: |
572 | 590 |
self.canvas.setFont(self.font + '-Bold', font_size) |
573 |
- self.canvas.drawRightString(left + 14.5*cm, self.y-self.font_height, 'Offener Rechnungsbetrag:') |
|
591 |
+ self.canvas.drawRightString(left + 14.5 * cm, self.y - self.font_height, |
|
592 |
+ 'Offener Rechnungsbetrag:') |
|
574 | 593 |
self.canvas.drawRightString(left + 16.8 * cm, self.y - self.font_height, _formatPrice(rest)) |
575 | 594 |
self.canvas.setFont(self.font, font_size) |
576 | 595 |
self.y -= self.line_height + self.line_padding |
577 | 596 |
|
578 | 597 |
self.y -= self.line_padding |
579 |
- elif type(part) == InvoiceText: |
|
598 |
+ elif isinstance(part, InvoiceText): |
|
580 | 599 |
my_font_size = font_size + part.fontsize # Relative Schriftgröße beachten |
581 | 600 |
self.canvas.setFont(self.font, my_font_size) |
582 | 601 |
left, right = self.leftcontent, self.rightcontent |
... | ... |
@@ -594,7 +613,9 @@ class PDF(object): |
594 | 613 |
if len(headlines) > 0: |
595 | 614 |
need_height += len(headlines) * (self._lineHeight(my_font_size) + 1) + self.line_padding |
596 | 615 |
self.canvas.setFillColorRGB(0.95, 0.95, 0.95) |
597 |
- self.canvas.rect(left-0.5*cm, self.y - (need_height+(6*self.line_padding)), height = need_height+(6*self.line_padding), width = right-left+1*cm, fill=1, stroke=1) |
|
616 |
+ self.canvas.rect(left - 0.5 * cm, self.y - (need_height + (6 * self.line_padding)), |
|
617 |
+ height=need_height + (6 * self.line_padding), width=right - left + 1 * cm, |
|
618 |
+ fill=1, stroke=1) |
|
598 | 619 |
self.canvas.setFillColorRGB(0, 0, 0) |
599 | 620 |
self.y -= self.line_padding * 3 |
600 | 621 |
if part.headline and firsttime: |
... | ... |
@@ -609,8 +630,7 @@ class PDF(object): |
609 | 630 |
self.canvas.drawString(left, self.y - self.font_height, line) |
610 | 631 |
self.y -= self._lineHeight(my_font_size) |
611 | 632 |
self.y -= self.line_padding * 3 |
612 |
- left, right = self.leftcontent, self.rightcontent |
|
613 |
- elif type(part) == InvoiceImage: |
|
633 |
+ elif isinstance(part, InvoiceImage): |
|
614 | 634 |
width = (part.imagedata.width / part.dpi) * inch |
615 | 635 |
height = width * (part.imagedata.height / part.imagedata.width) |
616 | 636 |
x = self.leftcontent |
... | ... |
@@ -636,23 +656,3 @@ class PDF(object): |
636 | 656 |
def InvoiceToPDF(iv): |
637 | 657 |
pdf = PDF(iv) |
638 | 658 |
return pdf.renderRechnung() |
639 |
- |
|
640 |
- |
|
641 |
- |
|
642 |
- |
|
643 |
-if __name__ == '__main__': |
|
644 |
- import datetime |
|
645 |
- from lib.Speicher import Speicher |
|
646 |
- from lib.BelegRechnung import BelegRechnung |
|
647 |
- s = Speicher() |
|
648 |
- import sys, os |
|
649 |
- renr = 'R2024-3149' |
|
650 |
- if len(sys.argv) > 1: |
|
651 |
- renr=sys.argv[1] |
|
652 |
- kb = s.getKassenbeleg(renr=renr) |
|
653 |
- |
|
654 |
- filename = BelegRechnung(kb) |
|
655 |
- print (filename) |
|
656 |
- |
|
657 |
- |
|
658 |
- |
... | ... |
@@ -2,8 +2,8 @@ |
2 | 2 |
|
3 | 3 |
from __future__ import division |
4 | 4 |
|
5 |
-from .InvoiceObjects import Invoice, InvoiceTable, InvoiceText, InvoiceImage, PAYMENT_UEBERWEISUNG |
|
6 | 5 |
from utils import format_price, split_to_width |
6 |
+from .InvoiceObjects import Invoice, InvoiceTable, InvoiceText, InvoiceImage, PAYMENT_UEBERWEISUNG |
|
7 | 7 |
|
8 | 8 |
|
9 | 9 |
def _breakLine(text, width=72): |
... | ... |
@@ -21,9 +21,9 @@ def _breakLine(text, width=72): |
21 | 21 |
return lines |
22 | 22 |
|
23 | 23 |
|
24 |
-def InvoiceToText(invoice : Invoice, bankdata=True): |
|
25 |
- ret = [] |
|
26 |
- ret.append(u'Rechnungsempfänger:') |
|
24 |
+def InvoiceToText(invoice: Invoice): |
|
25 |
+ ret = [u'Rechnungsempfänger:', |
|
26 |
+ ] |
|
27 | 27 |
addresslines = filter(None, [ |
28 | 28 |
invoice.customer['name'].strip(), |
29 | 29 |
invoice.customer['address']['line1'] or '', |
... | ... |
@@ -41,11 +41,11 @@ def InvoiceToText(invoice : Invoice, bankdata=True): |
41 | 41 |
|
42 | 42 |
ret.append('') |
43 | 43 |
for part in invoice.parts: |
44 |
- if type(part) == InvoiceTable: |
|
44 |
+ if isinstance(part, InvoiceTable): |
|
45 | 45 |
ret.append(InvoiceTableToText(part)) |
46 |
- elif type(part) == InvoiceText: |
|
46 |
+ elif isinstance(part, InvoiceText): |
|
47 | 47 |
ret.append(InvoiceTextToText(part)) |
48 |
- elif type(part) == InvoiceImage: |
|
48 |
+ elif isinstance(part, InvoiceImage): |
|
49 | 49 |
# ignore images |
50 | 50 |
pass |
51 | 51 |
else: |
... | ... |
@@ -75,14 +75,27 @@ def InvoiceTableToText(invoiceTable : InvoiceTable): |
75 | 75 |
unit = ' %s' % el['unit'] |
76 | 76 |
if len(invoiceTable.vat) < 2: |
77 | 77 |
subject = _breakLine(el['subject'], width=39) |
78 |
- ret.append(u'%5.2f %-3s %-39s %10s %10s' % (el['count'], unit, subject[0], format_price(el['price']), format_price(el['total']))) |
|
78 |
+ ret.append(u'%5.2f %-3s %-39s %10s %10s' % ( |
|
79 |
+ el['count'], unit, subject[0], format_price(el['price']), format_price(el['total']))) |
|
79 | 80 |
for i in range(1, len(subject)): |
80 | 81 |
ret.append(u' %s' % subject[i]) |
81 | 82 |
else: |
82 | 83 |
subject = _breakLine(el['subject'], width=41) |
83 |
- ret.append(u'%5.2f %-3s %-37s %10s %s %10s' % (el['count'], unit, subject[0], format_price(el['price']), invoiceTable.vat[el['vat']][1], format_price(el['total']))) |
|
84 |
+ ret.append(u'%5.2f %-3s %-37s %10s %s %10s' % ( |
|
85 |
+ el['count'], unit, subject[0], format_price(el['price']), invoiceTable.vat[el['vat']][1], |
|
86 |
+ format_price(el['total']))) |
|
84 | 87 |
for i in range(1, len(subject)): |
85 | 88 |
ret.append(u' %s' % subject[i]) |
89 |
+ if 'period_start' in el and el['period_start']: |
|
90 |
+ if 'period_end' in el and el['period_end']: |
|
91 |
+ desc = _breakLine('(%s - %s)' % |
|
92 |
+ (el['period_start'].strftime('%d.%m.%Y'), |
|
93 |
+ el['period_end'].strftime('%d.%m.%Y'))) |
|
94 |
+ else: |
|
95 |
+ desc = _breakLine('Leistungsdatum: %s' % |
|
96 |
+ (el['period_start'].strftime('%d.%m.%Y'))) |
|
97 |
+ for line in desc: |
|
98 |
+ ret.append(u' %s' % line) |
|
86 | 99 |
if 'desc' in el and el['desc']: |
87 | 100 |
desc = _breakLine(el['desc'], 39) |
88 | 101 |
for line in desc: |
... | ... |
@@ -94,10 +107,12 @@ def InvoiceTableToText(invoiceTable : InvoiceTable): |
94 | 107 |
summaries = [] |
95 | 108 |
if len(invoiceTable.vat) == 1: |
96 | 109 |
vat = list(invoiceTable.vat.keys())[0] |
97 |
- summaries.append(u' Im Rechnungsbetrag sind %.1f%% MwSt enthalten (%s)' % (vat * 100, format_price((invoiceTable.sum / (vat + 1)) * vat))) |
|
110 |
+ summaries.append(u' Im Rechnungsbetrag sind %.1f%% MwSt enthalten (%s)' % ( |
|
111 |
+ vat * 100, format_price((invoiceTable.sum / (vat + 1)) * vat))) |
|
98 | 112 |
else: |
99 | 113 |
for vat, vatdata in list(invoiceTable.vat.items()): |
100 |
- summaries.append(u' %s: Im Teilbetrag von %s sind %.1f%% MwSt enthalten (%s)' % (vatdata[1], format_price(vatdata[0]), vat * 100, format_price((vatdata[0] / (vat + 1)) * vat))) |
|
114 |
+ summaries.append(u' %s: Im Teilbetrag von %s sind %.1f%% MwSt enthalten (%s)' % ( |
|
115 |
+ vatdata[1], format_price(vatdata[0]), vat * 100, format_price((vatdata[0] / (vat + 1)) * vat))) |
|
101 | 116 |
summaries.sort() |
102 | 117 |
for line in summaries: |
103 | 118 |
ret.append(line) |
... | ... |
@@ -109,14 +124,16 @@ def InvoiceTableToText(invoiceTable : InvoiceTable): |
109 | 124 |
summaries.append((u'zzgl. %.1f%% MwSt: %11s' % (vat * 100, format_price(vat * invoiceTable.sum))).rjust(72)) |
110 | 125 |
elif len(invoiceTable.vat) > 1: |
111 | 126 |
for vat, vatdata in list(invoiceTable.vat.items()): |
112 |
- summaries.append((u'zzgl. %4.1f%% MwSt (%s): %11s' % (vat * 100, vatdata[1], format_price(vat * vatdata[0]))).rjust(72)) |
|
127 |
+ summaries.append( |
|
128 |
+ (u'zzgl. %4.1f%% MwSt (%s): %11s' % (vat * 100, vatdata[1], format_price(vat * vatdata[0]))).rjust( |
|
129 |
+ 72)) |
|
113 | 130 |
summaries.sort() |
114 | 131 |
for line in summaries: |
115 | 132 |
ret.append(line) |
116 |
- sum = invoiceTable.sum |
|
133 |
+ tablesum = invoiceTable.sum |
|
117 | 134 |
for vat, vatdata in list(invoiceTable.vat.items()): |
118 |
- sum += vat * vatdata[0] |
|
119 |
- ret.append((u'Rechnungsbetrag: %11s' % format_price(sum)).rjust(72)) |
|
135 |
+ tablesum += vat * vatdata[0] |
|
136 |
+ ret.append((u'Rechnungsbetrag: %11s' % format_price(tablesum)).rjust(72)) |
|
120 | 137 |
ret.append('') |
121 | 138 |
return '\n'.join(ret) |
122 | 139 |
|
... | ... |
@@ -18,9 +18,6 @@ |
18 | 18 |
|
19 | 19 |
import os.path, sys |
20 | 20 |
from decimal import Decimal |
21 |
-import datetime |
|
22 |
- |
|
23 |
-import re |
|
24 | 21 |
|
25 | 22 |
# Search for included submodule python-drafthorse |
26 | 23 |
atoms = os.path.abspath(os.path.dirname(__file__)).split('/') |
... | ... |
@@ -35,7 +32,7 @@ sys.path.insert(0, dir) |
35 | 32 |
from drafthorse.models.document import Document |
36 | 33 |
from drafthorse.models.accounting import ApplicableTradeTax |
37 | 34 |
from drafthorse.models.tradelines import LineItem |
38 |
-from .InvoiceObjects import InvoiceTable, InvoiceText, InvoiceImage, RECHNUNG, GUTSCHRIFT, KORREKTUR, \ |
|
35 |
+from .InvoiceObjects import InvoiceTable, InvoiceText, RECHNUNG, GUTSCHRIFT, KORREKTUR, \ |
|
39 | 36 |
VAT_REGULAR, VAT_KLEINUNTERNEHMER, VAT_INNERGEM, PAYMENT_UEBERWEISUNG, PAYMENT_LASTSCHRIFT |
40 | 37 |
from drafthorse.models.party import TaxRegistration, URIUniversalCommunication |
41 | 38 |
from drafthorse.models.payment import PaymentTerms |
... | ... |
@@ -104,9 +101,9 @@ def InvoiceToXML(invoice): |
104 | 101 |
line_id_count = 0 |
105 | 102 |
textparts = [] |
106 | 103 |
for part in invoice.parts: |
107 |
- if type(part) == InvoiceText: |
|
104 |
+ if isinstance(part, InvoiceText): |
|
108 | 105 |
textparts += part.paragraphs |
109 |
- if type(part) == InvoiceTable: |
|
106 |
+ if isinstance(part, InvoiceTable): |
|
110 | 107 |
for el in part.entries: |
111 | 108 |
line_id_count += 1 |
112 | 109 |
li = LineItem() |
... | ... |
@@ -236,19 +233,5 @@ def InvoiceToXML(invoice): |
236 | 233 |
return xml |
237 | 234 |
|
238 | 235 |
|
239 |
-if __name__ == '__main__': |
|
240 |
- import datetime |
|
241 |
- from lib.Speicher import Speicher |
|
242 |
- from lib.BelegRechnung import BelegRechnung |
|
243 |
- s = Speicher() |
|
244 |
- import sys, os |
|
245 |
- renr = 'R2024-3149' |
|
246 |
- if len(sys.argv) > 1: |
|
247 |
- renr=sys.argv[1] |
|
248 |
- kb = s.getKassenbeleg(renr=renr) |
|
249 |
- |
|
250 |
- filename = BelegRechnung(kb) |
|
251 |
- print(filename) |
|
252 |
- |
|
253 | 236 |
|
254 | 237 |
|
255 | 238 |