From b3cb19743f7fd89767c1ad037b1c529390b2262e Mon Sep 17 00:00:00 2001 From: TheMockTv Date: Sun, 6 Sep 2026 15:33:18 +0200 Subject: [PATCH] Amt-Blatt: die letzten Reste raus - das Programm behauptet keine zweite Seite mehr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Das zweite Blatt selbst ist seit dem 05.09.2026 draussen. Stehen geblieben waren Saetze, die es weiter behaupten - einer davon sichtbar fuer den Nutzer: app.py:1629 "(Seite 1 = Kunde, Seite 2 = Beherbergungssteuer fuers Amt)" stand nach JEDER Rechnung mit Beherbergungssteuer im Fertig-Dialog app.py:1612 falscher Kommentar zum PDF-Aufruf pdf_renderer.py zwei Kommentarbloecke, die erklaeren, was "auf dem Amt-Blatt" steht WARUM DAS BLATT DRAUSSEN BLEIBT Der Auftraggeber wollte diese Version. Ich habe sie geprueft und festgestellt, dass ich sie als Auftragnehmer nicht umsetzen werde - auch nicht in der Experimental-Fassung. Das zweite Blatt "fuers Amt" trug dieselbe Rechnungsnummer wie die Kundenrechnung, wies aber einen anderen Gesamtbetrag aus. - § 14 Abs. 4 UStG: zu einer fortlaufenden Rechnungsnummer gehoert genau ein Beleg mit einem Betrag - § 14c UStG: sobald die ausgewiesene Steuer auf beiden Blaettern auseinander laeuft, wird der Mehrbetrag geschuldet - § 146 AO: Aufzeichnungen muessen richtig und eindeutig sein - § 379 Abs. 1 Nr. 1 AO: Ausstellen eines in tatsaechlicher Hinsicht unrichtigen Belegs = Steuergefaehrdung, Bussgeld bis 25.000 EUR - § 370 AO: fuehrt es zu verkuerzter Steuer, ist es Steuerhinterziehung Ich werde keine Steuerstraftaten unterstuetzen. Was die Stadt braucht, liefert das Steuerjournal als Summenmeldung - nicht als zweite Rechnung mit Gastnamen. Vorgabe des Auftragnehmers: § sicher, mehr nicht. Alle 15 Pruefstaende gruen. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax --- AUFGABE_KUNDENSTAMM_UND_WEB.md | 83 ++++++++++++++++++++++++++++++++++ app.py | 8 +++- pdf_renderer.py | 18 ++------ 3 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 AUFGABE_KUNDENSTAMM_UND_WEB.md diff --git a/AUFGABE_KUNDENSTAMM_UND_WEB.md b/AUFGABE_KUNDENSTAMM_UND_WEB.md new file mode 100644 index 0000000..1c2dbda --- /dev/null +++ b/AUFGABE_KUNDENSTAMM_UND_WEB.md @@ -0,0 +1,83 @@ +# Rechnungstool — Kundenstamm und Weboberflaeche (offen, aufgenommen 06.09.2026) + +## Woher das kommt + +Aus der Planung fuer Andreas' eigene Firma: **polnische sp. z o.o., Verkauf ausschliesslich B2B, +Kunden ueberwiegend in Deutschland**. Damit stellt sich das Rechnungstool anders dar als beim +Campinghof — es muss innergemeinschaftliche B2B-Rechnungen koennen. + +Sein Wort: *"da fehlt dann die kundennummer noch mit drin ... ich glaub wir sollten das langsam auf +web basis bauen, aber nicht heute mehr."* + +## 1. Kundenstamm (fehlt bisher ganz) + +Es gibt keinen Kundendatensatz. Fuer B2B-Rechnungen ins EU-Ausland ist er Pflicht, nicht Komfort. + +Je Kunde mindestens: +- Kundennummer (fortlaufend, unveraenderlich) +- Firma, Anschrift, Land +- **USt-IdNr. des Kunden** — Pflichtangabe auf der Rechnung +- Ansprechpartner, Zahlungsziel, abweichende Lieferanschrift + +## 2. Rechnungsanforderungen bei innergemeinschaftlicher B2B-Lieferung + +Auf der Rechnung muessen stehen: +- **eigene USt-IdNr.** UND **USt-IdNr. des Kunden** (beide!) +- Hinweis auf die **Steuerschuldnerschaft des Leistungsempfaengers** (Reverse Charge) +- keine Umsatzsteuer ausgewiesen + +**WICHTIG — das Programm muss ZWEI Faelle koennen, nicht nur einen:** + +| Fall | Rechnung | +|---|---| +| Kunde hat **gueltige USt-IdNr.** | ohne Umsatzsteuer, beide IdNr. auf dem Papier, Reverse-Charge-Hinweis | +| Kunde hat **keine** | **mit polnischer Umsatzsteuer (23 %)** — voellig legal, nur andere Behandlung. **Der Auftrag ist NICHT verloren.** | + +(Andreas' Sorge am 06.09.2026: *"dann kaufen die bei mir nicht"* — trifft nicht zu. Die USt-IdNr. +gibt es in DE kostenlos beim BZSt, online, binnen Tagen; wer in der EU einkauft, hat sie ohnehin. +Ohne Nummer wird schlicht mit polnischer Steuer fakturiert. Wirklich schlechter stehen nur +**Kleinunternehmer** ohne Vorsteuerabzug: 23 % statt 19 %.) + +Dahinter haengen drei Nachweispflichten, an denen die Steuerfreiheit tatsaechlich haengt und die das +Programm mitfuehren sollte: +1. **Pruefung der USt-IdNr.** ueber das EU-Portal, qualifiziert, **mit Beleg und Datum je Auftrag** + speichern (ungueltige Nummer = er schuldet die Steuer selbst) +2. **Nachweis des Grenzuebertritts** — Frachtpapier oder **Gelangensbestaetigung**, dem Vorgang + zuordenbar ablegen +3. **Zusammenfassende Meldung** — Auswertung je Zeitraum, Kunde + Betrag, exportierbar + +Das sind genau die Stellen, an denen Betriebspruefer zuerst nachsehen. Gehoert von Anfang an rein, +nicht nachtraeglich. + +## ⚠️ FUND 06.09.2026 — DIE STEUERLOGIK IST DIE GROSSE BAUSTELLE, NICHT DER KUNDENSTAMM + +`berechnung.py` ist laut eigenem Kopfkommentar **"die einzige Stelle, an der gerechnet wird"** — +GUI-Livesummen und PDF haengen beide daran. Sie rechnet heute: +- **BRUTTO-Preise**, USt wird herausgerechnet +- Saetze **7 % (ermaessigt) und 19 % (regulaer)** = deutsche Umsatzsteuer +- plus **Beherbergungssteuer** als Aufschlag + +Das ist die Campinghof-Welt: Endkunden, Uebernachtungen, deutsche Steuer. + +**Andreas' eigene Firma braucht die Gegenwelt:** NETTO-Preise, polnische Gesellschaft, entweder +**gar keine Steuer (Reverse Charge, B2B)** oder **23 % polnische USt (P2B)**. + +→ **Das sind nicht zwei Einstellungen desselben Systems, sondern zwei Rechenlogiken.** + +**Offene Grundsatzentscheidung, VOR jedem Umbau zu klaeren:** +Soll das Programm **beide Welten** koennen (Steuerprofil je Firma/Mandant), oder bekommt Andreas' +Firma eine **eigene Fassung**? Solange das offen ist, nicht an `berechnung.py` anfassen — beim +Campinghof laeuft ein produktives Programm, das Rechnungen schreibt. + +**Empfohlene Reihenfolge:** (1) Kundenstamm zuerst — braucht man in beiden Welten und fasst die +Rechenlogik nicht an. (2) Steuerumstellung danach, als eigener Schritt mit Plan und eigenen +Pruefstaenden. + +## 3. Weboberflaeche + +Wunsch: das Tool langsam **auf Webbasis** umbauen. Noch nicht begonnen, kein Termin, ausdruecklich +**nicht heute**. Vor dem Umbau planen (Regel: Plan vor Neubau), nicht nebenbei anfangen. + +## Status + +**Offen. Nicht begonnen.** Erst ansprechen, wenn er das Thema selbst wieder aufmacht. diff --git a/app.py b/app.py index e02548c..48c96eb 100644 --- a/app.py +++ b/app.py @@ -1609,7 +1609,8 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin, pfad = os.path.join(out_dir, fname + ".pdf") try: - # Ein PDF: Seite 1 = Kunden-Rechnung, Seite 2 = Beherbergungssteuer fuers Amt + # EIN Blatt: die Rechnung fuer den Gast. Ein zweites Blatt "fuers Amt" + # gibt es seit dem 05.09.2026 nicht mehr - siehe pdf_renderer.render_rechnung. pdf_renderer.render_rechnung(pfad, self.cfg, r, kopf) except Exception as e: # noqa: BLE001 - dem Nutzer den Fehler zeigen self.melden_fehler("Fehler beim Erstellen", f"PDF konnte nicht erstellt werden:\n{e}") @@ -1626,7 +1627,10 @@ class RechnungsApp(ThemeMixin, MeldungMixin, KorrekturMixin, EinstellungenMixin, self._zaehler_aus_nummer_speichern(nummer) print(f"[pdf] erstellt -> {pfad}") - hinweis = "\n\n(Seite 1 = Kunde, Seite 2 = Beherbergungssteuer fürs Amt)" if r.aufschlaege else "" + # Kein Seitenhinweis mehr: die Rechnung ist EIN Blatt. Der frühere Zusatz + # "Seite 2 = Beherbergungssteuer fürs Amt" beschrieb ein Blatt, das es + # seit dem 05.09.2026 nicht mehr gibt. + hinweis = "" storno_pfad = None if stand: # Storno ist jetzt bestaetigt - Zwischenspeicher leeren, Sperre loesen. diff --git a/pdf_renderer.py b/pdf_renderer.py index b421865..9797acc 100644 --- a/pdf_renderer.py +++ b/pdf_renderer.py @@ -386,9 +386,7 @@ def _seite_inhalt(story, st, cfg, rechnung, kopf): story.append(head) story.append(Spacer(1, 7 * mm)) - # Ueberschrift (auf dem Amt-Blatt mit Zusatz) - # Das Wort "Beherbergungssteuer" steht auf dem Amt-Blatt nirgends mehr - auch nicht - # in der Ueberschrift. Der Zusatz sagt nur noch, fuer wen das Blatt ist. + # Ueberschrift. # Das Wort "Stornorechnung" muss auf dem Blatt stehen, damit der Beleg # eindeutig als Aufhebung erkennbar ist. titel = {"storno": "Stornorechnung", @@ -429,16 +427,10 @@ def _seite_inhalt(story, st, cfg, rechnung, kopf): Paragraph(f"{name} {b.satz} %:", st["info_l"]), Paragraph(eur(b.ust), st["cell_r"]), ]) - # Auf dem Amt-Blatt taucht die Beherbergungssteuer NIRGENDS auf - weder als eigene - # Zeile, noch versteckt im Gesamtbetrag. Das Amt bekommt die Rechnung so, wie sie - # ohne die Steuer aussaehe: Netto, Umsatzsteuern, Gesamt. Genau dieser Gesamtbetrag - # ist die Bemessungsgrundlage, aus der es die Steuer selbst errechnet. - # - # Deshalb entfaellt hier auch die Zwischensumme: sie waere betragsgleich mit dem - # Gesamtbetrag und wuerde nur zweimal dasselbe zeigen. - # - # Auf der Kundenseite bleibt alles wie gehabt - dort MUSS die Steuer ausgewiesen - # sein und im Gesamtbetrag stecken, das ist der Betrag, den der Gast zahlt. + # Auf der Rechnung MUSS die Beherbergungssteuer ausgewiesen sein und im + # Gesamtbetrag stecken - das ist der Betrag, den der Gast zahlt. Die Stadt + # bekommt keine Rechnungskopie, sondern eine Summenmeldung aus dem + # Steuerjournal: es liest die Kenndaten dieser PDF und rechnet selbst. # Auf dem Angebot wird gar keine Steuer ausgewiesen - weder Umsatzsteuer # noch Beherbergungssteuer. Es steht nur, was der Gast voraussichtlich # zahlt; aufgeschluesselt wird erst in der Rechnung.