Steuerrechnungstool: neuer Name und Erprobungshinweis wie im Rechnungstool
NAME Das Programm heisst jetzt Steuerrechnungstool - wie sein Repository (https://git.pcore.de/TheMockTv/Steuerrechnungstool). Umgestellt: Fenstertitel, Kopfzeile, "laeuft bereits"-Meldung, Startdatei, Spec-Datei (EXE-Name), Logzeile. NICHT umbenannt, mit Absicht: * "Beherbergungssteuer" als NAME DER STEUER - das ist ein Rechtsbegriff und steht weiter so in Berichten, Anmeldung und Oberflaeche. * LOCALAPPDATA\Beherbergungssteuer in ablage.py - dort liegt der Zeiger auf den Datenordner. Wer den umbenennt, kappt bestehenden Installationen den Weg zu ihren Daten. * Der lokale Ordner C:\claude\beherbergungssteuer - steht in Pruefstaenden und Spec-Dateien fest, eigener Schritt. HINWEIS hinweis.py aus dem Rechnungstool uebernommen (liegt in beiden Programmen gleich). Der Hinweis kommt beim Start, Ablehnen beendet das Programm ohne etwas zu vermerken, die Kenntnisnahme wird mit Benutzer, Zeit und Fassung in der Einstellungstabelle des Journals gespeichert. Neu: Menue Hilfe -> Info mit dem Text und der Signaturzeile. PRUEFSTAENDE Vier Prueflaeufe hatten gar keinen Dialogabfang - bisher fragte das Programm beim Start nichts. Jetzt bleiben sie sonst vor einem echten Fenster stehen. pruef_doppelte und pruef_storno_verrechnet haben einen bekommen, der bei UNBEKANNTEN Fragen abbricht statt still "ja" zu sagen. pruef_storno_journal und pruef_wache melden Hinweis und Freigabe ausdruecklich an. pruef_wache treibt ausserdem die Ereignisschleife an (update), sonst kaeme after_idle nie dran. pruef_wache: die Erwartung "im gemeinsamen Ordner liegt genau EINE Datei" ist auf die richtige Menge gebracht - Nummernbuch UND Schluessel der Mini-API, der seit dem 05.09.2026 dorthin gehoert. Alles darueber hinaus faellt weiter auf. ⚠️ pruef_wache bleibt ROT an einer Stelle, die NICHT von diesen Arbeiten kommt (vor dem Umbau gemessen, war schon rot): die Statuszeile soll nach einem Push "Rechnungstool meldet" zeigen, wird aber vom Ergebnis des Einlesens ueberschrieben. Dokumentiert in AUFGABE_BEWEISKETTE_PRUEFBAR.md. 5 von 6 Pruefstaenden gruen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V4t48uxDok5rJXhC9bX1Ax
This commit is contained in:
parent
f5f196151e
commit
40f53c85a0
7 changed files with 265 additions and 13 deletions
3
Steuerrechnungstool starten.bat
Normal file
3
Steuerrechnungstool starten.bat
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
@echo off
|
||||
cd /d "%~dp0"
|
||||
start "" pythonw app.py
|
||||
98
app.py
98
app.py
|
|
@ -1,12 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Beherbergungssteuer – Steuerjournal für den Campinghof Bartl.
|
||||
Steuerrechnungstool – Steuerjournal für den Campinghof Bartl.
|
||||
|
||||
Ersetzt die Excel-Mappe: Die Rechnungs-PDFs aus dem Rechnungstool sind die
|
||||
Quelle, das Programm liest sie ein, führt das Journal (SQLite) und schreibt
|
||||
auf Knopfdruck die Excel-Mappe fürs Amt.
|
||||
|
||||
Start: Doppelklick auf "Beherbergungssteuer starten.bat" oder `python app.py`
|
||||
Start: Doppelklick auf "Steuerrechnungstool starten.bat" oder `python app.py`
|
||||
"""
|
||||
|
||||
import os
|
||||
|
|
@ -25,6 +25,7 @@ from tkinter import ttk, filedialog, messagebox
|
|||
# zieht alte Dateien um; das darf nicht zweimal gleichzeitig laufen.
|
||||
# Nur beim echten Start: Pruefstaende importieren app als Modul und sollen
|
||||
# nicht an der Sperre des laufenden Programms scheitern.
|
||||
import hinweis
|
||||
from einzelinstanz import (eigene_pid_merken, einzelinstanz_pruefen,
|
||||
fenster_nach_vorn, laufende_pid_lesen)
|
||||
|
||||
|
|
@ -37,7 +38,7 @@ if __name__ == "__main__":
|
|||
_wurzel.withdraw()
|
||||
_wurzel.attributes("-topmost", True)
|
||||
messagebox.showerror(
|
||||
"Beherbergungssteuer läuft bereits",
|
||||
"Steuerrechnungstool läuft bereits",
|
||||
"Das Steuerjournal ist schon geöffnet, das Fenster ließ sich aber "
|
||||
"nicht nach vorn holen – bitte über die Taskleiste zurückwechseln.")
|
||||
_wurzel.destroy()
|
||||
|
|
@ -78,7 +79,7 @@ log = logging.getLogger("bst.app")
|
|||
class App(tk.Tk):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.title("Beherbergungssteuer – Campinghof Bartl")
|
||||
self.title("Steuerrechnungstool – Campinghof Bartl")
|
||||
self.geometry("1000x680")
|
||||
self.minsize(820, 520)
|
||||
|
||||
|
|
@ -94,26 +95,71 @@ class App(tk.Tk):
|
|||
self.suche = tk.StringVar()
|
||||
self.suche.trace_add("write", lambda *_: self.aktualisieren())
|
||||
os.makedirs(BERICHTE, exist_ok=True)
|
||||
|
||||
self._menue()
|
||||
self._kopfleiste()
|
||||
self._blaetter()
|
||||
self._statusleiste()
|
||||
|
||||
self.bind("<F5>", lambda _e: self.einlesen())
|
||||
self.bind("<Control-f>", lambda _e: self.suchfeld.focus_set())
|
||||
self.protocol("WM_DELETE_WINDOW", self._beenden)
|
||||
|
||||
self.aktualisieren()
|
||||
|
||||
# NICHTS laeuft an, bevor der Erprobungshinweis bestaetigt ist - sonst
|
||||
# stuenden beim Ablehnen Timer in der Warteschlange, die auf ein
|
||||
# Fenster zugreifen, das es nicht mehr gibt.
|
||||
self._briefkasten_stand = "?" # "?" = noch nicht nachgesehen
|
||||
self._push_kasten = queue.Queue() # Zettel aus dem API-Faden
|
||||
self._nachricht_stand = 0 # bis hierher sind Meldungen gelesen
|
||||
# after_idle statt after(0): laeuft, sobald Tk nichts mehr zu zeichnen hat -
|
||||
# also nachdem das Hauptfenster steht. Bei after(0) haengt der modale Dialog
|
||||
# an einem noch ungezeichneten Fenster und wirkt wie eingefroren; eine feste
|
||||
# Wartezeit dagegen erreicht ein Pruefstand nie, der keine Schleife dreht.
|
||||
self.after_idle(self._hinweis_pruefen)
|
||||
|
||||
# ------------------------------------------------- Erprobungshinweis
|
||||
def _hinweis_ablage(self):
|
||||
"""hinweis.py erwartet etwas mit .get() und []= - hier ist das die
|
||||
Einstellungstabelle des Journals.
|
||||
"""
|
||||
journal = self.journal
|
||||
|
||||
class Ablage:
|
||||
def get(self, schluessel, standard=""):
|
||||
return journal.hole(schluessel, standard)
|
||||
|
||||
def __setitem__(self, schluessel, wert):
|
||||
journal.setze(schluessel, str(wert))
|
||||
|
||||
return Ablage()
|
||||
|
||||
def _hinweis_pruefen(self):
|
||||
"""Hinweis auf die Erprobungsfassung. Ablehnen beendet das Programm."""
|
||||
self.update_idletasks() # Fenster fertig zeichnen lassen
|
||||
# Nach vorn holen, sonst liegt der Hinweis beim Start hinter dem
|
||||
# Hauptfenster und wirkt wie ein Programm, das haengen geblieben ist.
|
||||
self.lift()
|
||||
self.focus_force()
|
||||
ablage = self._hinweis_ablage()
|
||||
if not hinweis.angenommen(ablage):
|
||||
log.info("Erprobungshinweis: Kenntnisnahme noch offen (%s)", hinweis.FASSUNG)
|
||||
if not messagebox.askyesno(hinweis.TITEL,
|
||||
hinweis.text("steuerrechnungstool"),
|
||||
parent=self, default="no"):
|
||||
log.info("Erprobungshinweis abgelehnt - Programm wird beendet")
|
||||
self.destroy()
|
||||
return
|
||||
zeile = hinweis.vermerken(ablage)
|
||||
log.info("Erprobungshinweis: %s", zeile)
|
||||
self._start_fortsetzen()
|
||||
|
||||
def _start_fortsetzen(self):
|
||||
"""Der uebrige Start - laeuft erst nach der Kenntnisnahme an."""
|
||||
if self.pdf_ordner and os.path.isdir(self.pdf_ordner):
|
||||
self.after(200, lambda: self.einlesen(still=True))
|
||||
self.after(400, self._frage_gemeinsam_falls_noetig)
|
||||
# Beide Programme laufen nebeneinander: schreibt das Rechnungstool eine
|
||||
# Rechnung, meldet es das hier herein - siehe _wache_jetzt().
|
||||
self._briefkasten_stand = "?" # "?" = noch nicht nachgesehen
|
||||
self._push_kasten = queue.Queue() # Zettel aus dem API-Faden
|
||||
self.after(250, self._push_abholen)
|
||||
self._nachricht_stand = 0 # bis hierher sind Meldungen gelesen
|
||||
self.after(600, self._wache)
|
||||
# Beim Zurueckklicken sofort nachsehen statt zwei Sekunden zu warten.
|
||||
self.bind("<FocusIn>", lambda _e: self._wache_jetzt())
|
||||
|
|
@ -143,8 +189,38 @@ class App(tk.Tk):
|
|||
daten.add_command(label="Gemeinsamer Ordner (Nummernbuch)…",
|
||||
command=self.dlg_gemeinsam)
|
||||
leiste.add_cascade(label="Daten", menu=daten)
|
||||
|
||||
hilfe = tk.Menu(leiste, tearoff=0)
|
||||
hilfe.add_command(label="Info", command=self._info)
|
||||
leiste.add_cascade(label="Hilfe", menu=hilfe)
|
||||
self.config(menu=leiste)
|
||||
|
||||
def _info(self):
|
||||
"""Erprobungshinweis und Signatur - dauerhaft nachlesbar.
|
||||
|
||||
Ohne diese Seite waere die Kenntnisnahme ein Klick, den spaeter
|
||||
niemand mehr nachlesen kann.
|
||||
"""
|
||||
d = tk.Toplevel(self)
|
||||
d.title("Info")
|
||||
d.transient(self)
|
||||
d.resizable(False, False)
|
||||
rahmen = ttk.Frame(d, padding=18)
|
||||
rahmen.pack(fill="both", expand=True)
|
||||
ttk.Label(rahmen, text="Steuerrechnungstool", font=("Segoe UI", 11, "bold")
|
||||
).pack(anchor="w")
|
||||
ttk.Label(rahmen, justify="left", wraplength=460,
|
||||
text=hinweis.text("steuerrechnungstool")).pack(anchor="w", pady=(10, 0))
|
||||
zeile = hinweis.signatur(self._hinweis_ablage())
|
||||
if zeile:
|
||||
ttk.Label(rahmen, justify="left", wraplength=460, text=zeile
|
||||
).pack(anchor="w", pady=(12, 0))
|
||||
ttk.Button(rahmen, text="OK", width=10, command=d.destroy
|
||||
).pack(anchor="e", pady=(16, 0))
|
||||
d.bind("<Escape>", lambda _e: d.destroy())
|
||||
d.bind("<Return>", lambda _e: d.destroy())
|
||||
d.grab_set()
|
||||
|
||||
def _kopfleiste(self):
|
||||
leiste = ttk.Frame(self, padding=(10, 8))
|
||||
leiste.pack(fill="x")
|
||||
|
|
@ -737,7 +813,7 @@ class App(tk.Tk):
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
log.info("Beherbergungssteuer startet (Python %s)", sys.version.split()[0])
|
||||
log.info("Steuerrechnungstool startet (Python %s)", sys.version.split()[0])
|
||||
# Die Sperre selbst greift schon ganz oben, vor dem Datenordner.
|
||||
eigene_pid_merken()
|
||||
App().mainloop()
|
||||
|
|
|
|||
109
hinweis.py
Normal file
109
hinweis.py
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Der Hinweis auf die Erprobungsfassung - und die Kenntnisnahme des Nutzers.
|
||||
|
||||
WARUM ES DAS GIBT
|
||||
-----------------
|
||||
Beide Programme schreiben Belege, die steuerlich zaehlen. Solange sie erprobt
|
||||
werden, muss der Betreiber wissen, woran er ist: dass es eine Erprobungsfassung
|
||||
ist, dass fuer falsch ausgestellte Belege nicht gehaftet wird, und dass er jeden
|
||||
Beleg vor dem Herausgeben SELBST ansehen muss - dafuer gibt es die Vorschau.
|
||||
|
||||
Sein Wortlaut (06.09.2026):
|
||||
|
||||
"bei jedem oeffnen, solange wir die testen, ein popup, dass dies eine
|
||||
experimentelle software ist und ich keine haftung fuer irgendwelche falsch
|
||||
ausgestellten uebernehme. der user muss selbst pruefen ueber den vorschau
|
||||
button auf beiden tools, ob das alles seine richtigkeit hat. wenn nicht,
|
||||
auf dem link eine issue erstellen. und das alles auch noch mal in die info
|
||||
mit signatur: user hat dies gelesen und zur kenntnis genommen. wenn er nein
|
||||
drueckt oder ablehnt, schliesst sich die software und geht beim naechsten
|
||||
start wieder mit dem selben auf, bis er auf ja drueckt."
|
||||
|
||||
WIE ES WIRKT
|
||||
------------
|
||||
* Beim Start kommt der Hinweis, BEVOR gearbeitet werden kann.
|
||||
* "Nein" beendet das Programm. Es wird nichts geschrieben, nichts gespeichert.
|
||||
* "Ja" wird mit Benutzername, Zeitpunkt und Fassung in der Konfiguration
|
||||
vermerkt - das ist die Signatur. Danach kommt der Hinweis nicht mehr.
|
||||
* Aendert sich der TEXT (also FASSUNG), wird erneut gefragt. Eine Zustimmung
|
||||
gilt fuer das, was dagestanden hat, nicht fuer alles Kuenftige.
|
||||
* Unter "Info" steht derselbe Text dauerhaft, mit der Signaturzeile darunter.
|
||||
|
||||
Diese Datei liegt in BEIDEN Programmen gleich. Wer sie aendert, kopiert sie
|
||||
hinueber - sonst steht in zwei Programmen zweierlei.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import getpass
|
||||
|
||||
# Fassung des HINWEISTEXTES, nicht des Programms. Wird der Text geaendert,
|
||||
# gehoert dieses Datum mitgeaendert - dann wird die Kenntnisnahme neu eingeholt.
|
||||
FASSUNG = "2026-09-06"
|
||||
|
||||
# Wo Fehler gemeldet werden. Je Programm eine eigene Adresse.
|
||||
#
|
||||
# Das frueher "Beherbergungssteuer" genannte Programm heisst seit dem
|
||||
# 06.09.2026 STEUERRECHNUNGSTOOL - so wie sein Repository. Der lokale Ordner
|
||||
# heisst noch beherbergungssteuer: der Pfad steht in mehreren Pruefstaenden und
|
||||
# in den Spec-Dateien fest, das ist ein eigener Schritt.
|
||||
ISSUES = {
|
||||
"rechnungstool": "https://git.pcore.de/TheMockTv/rechnungstool",
|
||||
"steuerrechnungstool": "https://git.pcore.de/TheMockTv/Steuerrechnungstool",
|
||||
}
|
||||
|
||||
TITEL = "Erprobungsfassung – bitte lesen"
|
||||
|
||||
|
||||
def text(programm):
|
||||
"""Der Hinweistext. `programm` ist ein Schluessel aus ISSUES."""
|
||||
url = ISSUES.get(programm, "")
|
||||
return (
|
||||
"Diese Software ist eine ERPROBUNGSFASSUNG.\n\n"
|
||||
"Sie wird noch getestet. Für Belege, die falsch ausgestellt werden, "
|
||||
"wird keine Haftung übernommen.\n\n"
|
||||
"Prüfen Sie jeden Beleg selbst, bevor Sie ihn herausgeben oder "
|
||||
"verbuchen. Nutzen Sie dafür die Vorschau – in diesem Programm und im "
|
||||
"jeweils anderen. Stimmt etwas nicht, melden Sie es bitte als Fehler "
|
||||
"unter:\n\n"
|
||||
f" {url}\n\n"
|
||||
"Mit „Ja\" bestätigen Sie, dass Sie diesen Hinweis gelesen und zur "
|
||||
"Kenntnis genommen haben.\n"
|
||||
"Mit „Nein\" wird das Programm beendet; der Hinweis erscheint beim "
|
||||
"nächsten Start erneut."
|
||||
)
|
||||
|
||||
|
||||
def _stand(cfg):
|
||||
return (str(cfg.get("hinweis_fassung", "") or ""),
|
||||
str(cfg.get("hinweis_zeit", "") or ""),
|
||||
str(cfg.get("hinweis_benutzer", "") or ""))
|
||||
|
||||
|
||||
def angenommen(cfg):
|
||||
"""Hat der Nutzer GENAU DIESE Fassung schon zur Kenntnis genommen?"""
|
||||
fassung, zeit, benutzer = _stand(cfg)
|
||||
return fassung == FASSUNG and bool(zeit) and bool(benutzer)
|
||||
|
||||
|
||||
def vermerken(cfg):
|
||||
"""Die Kenntnisnahme festhalten. Gibt die Signaturzeile zurueck."""
|
||||
cfg["hinweis_fassung"] = FASSUNG
|
||||
cfg["hinweis_zeit"] = datetime.datetime.now().isoformat(timespec="seconds")
|
||||
try:
|
||||
cfg["hinweis_benutzer"] = getpass.getuser()
|
||||
except Exception: # noqa: BLE001 - ohne Benutzernamen ist es kein Grund zu scheitern
|
||||
cfg["hinweis_benutzer"] = "unbekannt"
|
||||
return signatur(cfg)
|
||||
|
||||
|
||||
def signatur(cfg):
|
||||
"""Die Zeile fuer den Info-Dialog - oder '' , wenn nichts vorliegt."""
|
||||
fassung, zeit, benutzer = _stand(cfg)
|
||||
if not (fassung and zeit and benutzer):
|
||||
return ""
|
||||
try:
|
||||
wann = datetime.datetime.fromisoformat(zeit).strftime("%d.%m.%Y um %H:%M")
|
||||
except ValueError:
|
||||
wann = zeit
|
||||
return (f"Gelesen und zur Kenntnis genommen von {benutzer} "
|
||||
f"am {wann} (Fassung {fassung}).")
|
||||
|
|
@ -51,6 +51,28 @@ import ablage # noqa: E402
|
|||
ablage.daten_ordner = lambda: tmp
|
||||
|
||||
import app as app_mod # noqa: E402 (liest ablage.daten_ordner beim Import)
|
||||
from tkinter import messagebox # noqa: E402
|
||||
|
||||
# Kein echtes Fenster im Pruefstand: sonst steht der Lauf vor einem Dialog, den
|
||||
# niemand anklickt. Der Erprobungshinweis wird hier bejaht - geprueft wird er
|
||||
# eigens in pruef_hinweis.py des Rechnungstools. Eine UNBEKANNTE Frage bricht
|
||||
# ab, statt still 'ja' zu sagen: sonst uebergeht der Lauf genau die Faelle,
|
||||
# wegen denen es die Pruefung gibt.
|
||||
_antworten = {"Erprobungsfassung": True, "jetzt erstellen?": True,
|
||||
"Fertig": False, "Hausnummer": True}
|
||||
|
||||
|
||||
def _askyesno(titel, text="", **kw):
|
||||
for schluessel, wert in _antworten.items():
|
||||
if schluessel in str(titel):
|
||||
return wert
|
||||
raise AssertionError(f"unangemeldeter Dialog: {titel!r}")
|
||||
|
||||
|
||||
messagebox.askyesno = _askyesno
|
||||
messagebox.showinfo = lambda *a, **k: None
|
||||
messagebox.showwarning = lambda *a, **k: None
|
||||
|
||||
from modell import Buchung, doppelte_nummern, summiere # noqa: E402
|
||||
|
||||
pruefe(app_mod.BASE_DIR == tmp, f"Pruefstand laeuft im Testordner ({app_mod.BASE_DIR})")
|
||||
|
|
|
|||
|
|
@ -63,9 +63,13 @@ import app as A # noqa: E402
|
|||
import bestand as BE # noqa: E402
|
||||
from tkinter import messagebox # noqa: E402
|
||||
|
||||
# Erprobungshinweis und Freigabe vor dem Beleg werden hier bejaht - geprueft
|
||||
# werden sie eigens in pruef_hinweis.py und pruef_freigabe.py des Rechnungstools.
|
||||
antworten = {"Fertig": False, "endgültig erstellen": True, "Hausnummer": True,
|
||||
"Storno wirklich": True, "Berichtigte Rechnung erstellen": True,
|
||||
"Berichtigung": True, "Storno erstellen": True}
|
||||
antworten["Erprobungsfassung"] = True
|
||||
antworten["jetzt erstellen?"] = True
|
||||
|
||||
|
||||
def askyesno(titel, text, **kw):
|
||||
|
|
|
|||
|
|
@ -61,6 +61,28 @@ import bericht_pdf # noqa: E402
|
|||
import firma as firma_lib # noqa: E402
|
||||
from pypdf import PdfReader # noqa: E402
|
||||
import app as app_mod # noqa: E402
|
||||
from tkinter import messagebox # noqa: E402
|
||||
|
||||
# Kein echtes Fenster im Pruefstand: sonst steht der Lauf vor einem Dialog, den
|
||||
# niemand anklickt. Der Erprobungshinweis wird hier bejaht - geprueft wird er
|
||||
# eigens in pruef_hinweis.py des Rechnungstools. Eine UNBEKANNTE Frage bricht
|
||||
# ab, statt still 'ja' zu sagen: sonst uebergeht der Lauf genau die Faelle,
|
||||
# wegen denen es die Pruefung gibt.
|
||||
_antworten = {"Erprobungsfassung": True, "jetzt erstellen?": True,
|
||||
"Fertig": False, "Hausnummer": True}
|
||||
|
||||
|
||||
def _askyesno(titel, text="", **kw):
|
||||
for schluessel, wert in _antworten.items():
|
||||
if schluessel in str(titel):
|
||||
return wert
|
||||
raise AssertionError(f"unangemeldeter Dialog: {titel!r}")
|
||||
|
||||
|
||||
messagebox.askyesno = _askyesno
|
||||
messagebox.showinfo = lambda *a, **k: None
|
||||
messagebox.showwarning = lambda *a, **k: None
|
||||
|
||||
from gui_monat import SPALTEN # noqa: E402
|
||||
|
||||
pruefe(app_mod.BASE_DIR == tmp, f"Pruefstand laeuft im Testordner ({app_mod.BASE_DIR})")
|
||||
|
|
|
|||
|
|
@ -71,6 +71,10 @@ messagebox.showinfo = lambda *a, **k: None
|
|||
messagebox.showwarning = lambda *a, **k: None
|
||||
|
||||
journal = JA.App()
|
||||
# Der Erprobungshinweis haengt an after(0) - ohne Ereignisschleife kaeme er nie
|
||||
# dran, und damit auch der verzoegerte Start nicht. update() treibt die Schleife
|
||||
# einmal an, genau wie es mainloop() taete. Abgekuerzt wird nichts.
|
||||
journal.update()
|
||||
journal.withdraw()
|
||||
journal.pdf_ordner = rechnungen
|
||||
journal.journal.setze("pdf_ordner", rechnungen)
|
||||
|
|
@ -85,8 +89,15 @@ pruefe(not gemeinsam.journal_laeuft(gemeinsam_ordner),
|
|||
journal._anmelden()
|
||||
pruefe(gemeinsam.journal_laeuft(gemeinsam_ordner),
|
||||
"nach der Anmeldung sieht man an der PID, dass es laeuft")
|
||||
pruefe(os.listdir(gemeinsam_ordner) == [gemeinsam.DATEINAME],
|
||||
f"im gemeinsamen Ordner liegt genau EINE Datei ({os.listdir(gemeinsam_ordner)})")
|
||||
# Die Absicht dieser Pruefung: im gemeinsamen Ordner liegt NICHTS Fremdes -
|
||||
# keine Herzschlagdateien, keine Zwischenstaende. Erlaubt sind genau zwei:
|
||||
# das Nummernbuch und der Schluessel der Mini-API, der seit dem Umbau vom
|
||||
# 05.09.2026 dorthin gehoert (beide Programme muessen ihn lesen koennen).
|
||||
# Alles darueber hinaus faellt weiterhin auf.
|
||||
ERLAUBT = {gemeinsam.DATEINAME, "api_schluessel.txt"}
|
||||
_liegt = set(os.listdir(gemeinsam_ordner))
|
||||
pruefe(_liegt <= ERLAUBT,
|
||||
f"im gemeinsamen Ordner liegt nichts Fremdes ({sorted(_liegt)})")
|
||||
|
||||
# ---- 1b. Die Mini-API: Port im Telefonbuch, und sie meldet sich -----------
|
||||
import api # noqa: E402
|
||||
|
|
@ -118,8 +129,12 @@ json.dump(roh, open(config.CONFIG_PATH, "w", encoding="utf-8"), ensure_ascii=Fal
|
|||
|
||||
import app as A # noqa: E402
|
||||
|
||||
# Erprobungshinweis und Freigabe vor dem Beleg werden hier bejaht - geprueft
|
||||
# werden sie eigens in pruef_hinweis.py und pruef_freigabe.py des Rechnungstools.
|
||||
antworten = {"Fertig": False, "endgültig erstellen": True, "Hausnummer": True,
|
||||
"Storno wirklich": True, "Storno verwerfen": True}
|
||||
antworten["Erprobungsfassung"] = True
|
||||
antworten["jetzt erstellen?"] = True
|
||||
|
||||
|
||||
def askyesno(titel, text, **kw):
|
||||
|
|
@ -132,6 +147,7 @@ def askyesno(titel, text, **kw):
|
|||
messagebox.askyesno = askyesno
|
||||
|
||||
tool = A.RechnungsApp()
|
||||
tool.update() # dasselbe fuer das Rechnungstool
|
||||
tool.cfg["output_dir"] = rechnungen
|
||||
tool.cfg["gemeinsam_ordner"] = gemeinsam_ordner
|
||||
tool._buch_oeffnen()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue