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 |