Sicherheitsfrage vor dem Erstellen, Datenordner, toter Aufruf raus
- "Rechnung endgueltig erstellen?" nennt Nummer, Kunde und Betrag und weist darauf hin, dass danach nur noch Storno oder Berichtigung bleibt (§ 14 Abs. 4 Nr. 4 UStG, § 31 Abs. 5 UStDV). Geprueft ist auch, dass "Nein" wirklich nichts schreibt - sonst waere die Frage eine Attrappe. - Als EXE legt das Programm sich beim ersten Start einen Ordner "Daten" neben die EXE (config.json). Ist dort nicht schreibbar (EXE unter "Programme"), weicht es nach LOCALAPPDATA aus. Lag die config.json noch direkt neben der EXE, zieht sie um - sonst faengt das Programm ohne Firmendaten neu an. - Aufruf von _storno_fortsetzen entfernt: die Methode gibt es nicht mehr, seit die Kette auf dem Storno-Blatt steht. War unerreichbar, waere aber beim naechsten Anfassen ein AttributeError geworden. - Pruefstaende raeumen ihren Wegwerf-Ordner weg und haben eine Reissleine (Abbruch nach zwei Minuten), damit kein Dialog mehr ewig offen steht. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EKvGkdNW1vKdnMPAM9Bp3X
This commit is contained in:
parent
3ea31b3421
commit
5c68278191
7 changed files with 165 additions and 9 deletions
56
config.py
56
config.py
|
|
@ -16,11 +16,59 @@ import sys
|
|||
# - eingefroren (.exe): config.json/rechnungen NEBEN der .exe (beschreibbar),
|
||||
# gebuendelte Ressourcen (Logo) liegen in sys._MEIPASS
|
||||
if getattr(sys, "frozen", False):
|
||||
BASE_DIR = os.path.dirname(sys.executable)
|
||||
RESOURCE_DIR = getattr(sys, "_MEIPASS", BASE_DIR)
|
||||
EXE_DIR = os.path.dirname(sys.executable)
|
||||
RESOURCE_DIR = getattr(sys, "_MEIPASS", EXE_DIR)
|
||||
else:
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
RESOURCE_DIR = BASE_DIR
|
||||
EXE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
RESOURCE_DIR = EXE_DIR
|
||||
|
||||
|
||||
def _beschreibbar(ordner):
|
||||
"""Kann in diesen Ordner geschrieben werden? Wird ausprobiert, nicht geraten."""
|
||||
try:
|
||||
os.makedirs(ordner, exist_ok=True)
|
||||
probe = os.path.join(ordner, ".schreibprobe")
|
||||
with open(probe, "w") as f:
|
||||
f.write("x")
|
||||
os.remove(probe)
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
def _daten_ordner():
|
||||
"""Der Ordner, den das Programm sich beim ersten Start selbst anlegt.
|
||||
|
||||
Alles, was das Programm schreibt, liegt darin beieinander - man sieht auf
|
||||
einen Blick, was von ihm stammt, und kann es mitnehmen oder sichern.
|
||||
|
||||
1. neben der EXE ein Unterordner "Daten"
|
||||
2. geht das nicht (EXE liegt z.B. unter "Programme"), dann
|
||||
der Ordner Rechnungstool unter LOCALAPPDATA
|
||||
|
||||
Was schon da ist, wird benutzt; was fehlt, wird angelegt. Lagen die Dateien
|
||||
noch direkt neben der EXE - so war es frueher -, ziehen sie mit um, statt
|
||||
dass das Programm ohne Firmendaten und Zaehler neu anfaengt.
|
||||
"""
|
||||
if not getattr(sys, "frozen", False):
|
||||
return EXE_DIR # aus der Quelle heraus bleibt alles, wo es ist
|
||||
kandidat = os.path.join(EXE_DIR, "Daten")
|
||||
if not _beschreibbar(kandidat):
|
||||
kandidat = os.path.join(os.environ.get("LOCALAPPDATA", EXE_DIR), "Rechnungstool")
|
||||
if not _beschreibbar(kandidat):
|
||||
return EXE_DIR # letzter Ausweg: wie frueher
|
||||
for name in ("config.json",):
|
||||
alt, neu_ = os.path.join(EXE_DIR, name), os.path.join(kandidat, name)
|
||||
if os.path.exists(alt) and not os.path.exists(neu_):
|
||||
try:
|
||||
os.replace(alt, neu_)
|
||||
print(f"[config] {name} in den Datenordner übernommen")
|
||||
except OSError:
|
||||
pass
|
||||
return kandidat
|
||||
|
||||
|
||||
BASE_DIR = _daten_ordner()
|
||||
CONFIG_PATH = os.path.join(BASE_DIR, "config.json")
|
||||
|
||||
# Leistungskatalog 1:1 aus der Excel-Vorlage (Rechnung Campinghof Bartl).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue