Test-Script lauffähig
Bernd Wurst authored 10 months ago
|
1) #!/usr/bin/python
2)
3) import datetime
4) import json
5) import os
6) import subprocess
7) import sys
8) import tempfile
9)
10) import qrcode
11)
12) sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
13)
14) from Invoice.InvoiceObjects import Invoice, RECHNUNG, InvoiceText, InvoiceTable, KORREKTUR, PAYMENT_LASTSCHRIFT, \
15) InvoiceImage
16) from Invoice.InvoiceToPDF import InvoiceToPDF
17) from Invoice.InvoiceToText import InvoiceToText
18) from Invoice.InvoiceToZUGFeRD import InvoiceToXML, attach_xml
19)
20) if __name__ == '__main__':
21) import rechnungsdaten
22) data = rechnungsdaten.data['data']
23) rechnung = rechnungsdaten.data['rechnung']
24) mandat = rechnungsdaten.data['mandat']
25) adresse = rechnungsdaten.data['adresse']
26) daten = rechnungsdaten.data['daten']
27)
28) rechnungsnummer = rechnung['id']
29) filename = 'pdf/rechnung_%05i.pdf' % rechnungsnummer
30)
31) referenzen = json.loads(rechnung['referenzen'])
32)
33) from io import StringIO
34) file = StringIO()
35) invoice = Invoice()
36) if 'leitwegid' in referenzen:
37) # Behörden-Rechnung, als XRECHNUNG ausgeben!
38) invoice.leitweg_id = referenzen['leitwegid']
39) if 'kundenreferenz' in referenzen:
40) invoice.buyer_reference = referenzen['kundenreferenz']
41) if 'bestellnummer' in referenzen:
42) invoice.order_number = referenzen['bestellnummer']
43) if 'vertragsnummer' in referenzen:
44) invoice.contract_number = referenzen['vertragsnummer']
45) invoice.seller['name'] = 'Bernd Wurst / Johannes Böck'
46) invoice.seller['trade_name'] = 'schokokeks.org GbR'
47) invoice.seller['email'] = 'xxxxxxx'
48) invoice.seller['website'] = 'www.schokokeks.org'
49) invoice.seller['phone'] = None
50) invoice.seller['address']['country_id'] = 'DE'
51) invoice.seller['address']['postcode'] = '71540'
52) invoice.seller['address']['city_name'] = 'Murrhardt'
53) invoice.seller['address']['line1'] = 'Köchersberg 32'
54) invoice.seller['address']['line2'] = None
55) invoice.seller['address']['line3'] = None
56) invoice.seller_vat_id = "DE255720588"
57) invoice.type = RECHNUNG
58) invoice.logo_image_file = os.path.join(os.path.dirname(__file__), "logo.png")
59) invoice.seller_bank_data['kontoinhaber'] = "schokokeks.org GbR"
60) invoice.seller_bank_data['iban'] = "DE91602911200041512006"
61) invoice.seller_bank_data['bic'] = "GENODES1VBK"
62) invoice.seller_bank_data['bankname'] = 'Volksbank'
63) invoice.id = str(rechnungsnummer)
64) invoice.customerno = rechnung['kunde']
65) invoice.customer['name'] = adresse['company'] or adresse['name']
66) invoice.customer['email'] = adresse['email']
67) invoice.customer['address']['country_id'] = adresse['country']
68) invoice.customer['address']['postcode'] = adresse['zip']
69) invoice.customer['address']['city_name'] = adresse['city']
70) lines = list(filter(None, [
71) adresse['name'] if adresse['company'] else None,
72) ] + adresse['address'].split('\n')))
73) while len(lines) < 3:
74) lines.append(None)
75) invoice.customer['address']['line1'] = lines[0]
76) invoice.customer['address']['line2'] = lines[1]
77) invoice.customer['address']['line3'] = lines[2]
78)
79) invoice.setDate(rechnung['datum'])
80)
81) for item in data:
82) if item['info_text']:
83) text = InvoiceText(item['info_text'], urgent=True, headline=item['info_headline'])
84) invoice.parts.append(text)
85)
86) vatType = 'net'
87) if data[0]['brutto']:
88) vatType = 'gross' # Entscheidet anhand des ersten Eintrags ob die Rechnung Netto oder Brutto gestellt wird
89) tab = InvoiceTable(vatType=vatType)
90)
|
Test-Script lauffähig
Bernd Wurst authored 10 months ago
|
92) for item in data:
93) # Der Betrag muss immer positiv sein, bei Gutschriften wird nur die Anzahl negativ.
94) count = float(item['anzahl'])
95) price = float(item['betrag'])
96) if price < 0:
97) count = -count
98) price = abs(price)
99) tab.addItem(
100) {'count': count,
101) 'unit': item['einheit'],
102) 'subject': item['beschreibung'],
103) 'price': price,
104) 'vat': item['mwst'] / 100,
105) 'period_start': item['datum'],
106) 'period_end': item['enddatum'],
107) }
108) )
109) invoice.parts.append(tab)
110)
111) if mandat:
112) print('''Abbuchung von:
113) Kontoinhaber: %s
114) IBAN: %s
115) BIC: %s
116) Bank: %s
117) ''' % (mandat["kontoinhaber"], mandat["iban"], mandat["bic"], mandat["bankname"]))
118) iban = mandat['iban']
119) iban = iban[:8] + '*' * 10 + iban[-4:]
120) pretty_iban = iban
121) for i in range(len(iban) - (len(iban) % 4), 0, -4):
122) pretty_iban = pretty_iban[:i] + ' ' + pretty_iban[i:]
123) invoice.debit = True
124) invoice.creditor_reference_id = mandat['glaeubiger_id']
125) invoice.debit_mandate_id = mandat["mandatsreferenz"]
126) invoice.buyer_bank_data['kontoinhaber'] = mandat['kontoinhaber']
127) invoice.buyer_bank_data['iban'] = mandat['iban']
128) invoice.buyer_bank_data['bic'] = mandat['bic']
129) invoice.buyer_bank_data['bankname'] = mandat['bankname']
130) text = None
131) if tab.sum < 0:
132) invoice.type = KORREKTUR
133) invoice.title = 'Korrekturrechnung'
134) text = InvoiceText("Der verbleibende Betrag wird in wenigen Tagen auf das uns bekannte Konto mit der IBAN %s bei der %s (BIC: %s) überwiesen." % (pretty_iban, mandat["bankname"], mandat["bic"]))
135) else:
136) invoice.payment_type = PAYMENT_LASTSCHRIFT
137) text = InvoiceText("Der fällige Betrag wird gemäß dem von Ihnen erteilten Lastschrift-Mandat in wenigen Tagen vom Konto mit der IBAN %s bei der %s (BIC: %s) abgebucht. Diese Kontodaten beruhen auf dem Mandat Nr. %s vom %s. Unsere Gläubiger-ID lautet %s." % (pretty_iban, mandat["bankname"], mandat["bic"], mandat["mandatsreferenz"], mandat["erteilt"], mandat["glaeubiger_id"]))
138) invoice.parts.append(text)
139) else:
140) if tab.sum < 0:
141) invoice.type = KORREKTUR
142) invoice.title = 'Korrekturrechnung'
143) text = InvoiceText('Der verbleibende Gutschriftsbetrag wird Ihnen in Kürze überwiesen. Sollten Sie uns noch keine Bankverbindung mitgeteilt haben, so bitten wir um eine formlose Nachricht.')
144) invoice.parts.append(text)
145) else:
146) invoice.due_date = datetime.date.today() + datetime.timedelta(days=14)
147) text = InvoiceText('Bitte begleichen Sie diese Rechnung umgehend nach Erhalt ohne Abzüge auf das unten angegebene Konto. Geben Sie im Verwendungszweck Ihrer Überweisung bitte die Rechnungsnummer %s an, damit Ihre Buchung korrekt zugeordnet werden kann.' % rechnungsnummer)
148) invoice.parts.append(text)
149) qr = qrcode.QRCode(box_size=10, border=0, error_correction=qrcode.constants.ERROR_CORRECT_M)
150) qr.add_data(f"BCD\n002\n1\nSCT\nGENODES1VBK\nschokokeks.org Hosting\nDE91602911200041512006\nEUR{tab.sum:.2f}\n\n\nRE {rechnungsnummer} vom {rechnung['datum']}")
151) qr.make()
152) img = qr.make_image()
153) pilimage = img.get_image()
154) imgpart = InvoiceImage(pilimage=pilimage, dpi=500, caption="Gerne können Sie diesen GiroCode für Ihre Banking-App verwenden.")
155) invoice.parts.append(imgpart)
156)
157) text = InvoiceText('Wir danken Ihnen, dass Sie unser Angebot in Anspruch genommen haben und hoffen weiterhin auf eine gute Zusammenarbeit. Dieser Rechnung liegen die Allgemeinen Geschäftsbedingungen zum Zeitpunkt des Rechnungsdatums zugrunde, die Sie unter https://www.schokokeks.org/agb abrufen können.')
158) invoice.parts.append(text)
159)
|
new feature: indentation fo...
Bernd Wurst authored 10 months ago
|
160) invoice.parts.append(InvoiceText('Das ist ein eingerückter Absatz mit etwas Text zum Testen der Line-Wrap-Funktion. Er hat auch eine Überschrift, um auch das zu zeigen.', headline='Schlussbemerkung', indent=2))
161)
|
Test-Script lauffähig
Bernd Wurst authored 10 months ago
|
162) textdata = InvoiceToText(invoice)
163) pdfdata = InvoiceToPDF(invoice)
164) xmldata = InvoiceToXML(invoice)
165) if xmldata:
166) try:
167) # PDF/A-Konvertierung
168) with (tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as tmp1,
169) tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as tmp2):
170) tmp1.write(pdfdata)
171) tmp1.close()
172) tmp2.close()
|
Ghostscript-Aufruf optimiert
Bernd Wurst authored 10 months ago
|
173) proc = subprocess.run(
174) f'gs -dPDFA=3 -sColorConversionStrategy=RGB -sDEVICE=pdfwrite -dPDFACompatibilityPolicy=1 -o {tmp2.name} {tmp1.name}',
175) capture_output=True, shell=True, check=True)
|