feat(calllog): kontaktadresse_id als Pflicht-FK + is_erledigt()-Methoden
- Migration V01_13: Spalte kontaktadresse_id auf call_logs mit Backfill über die erste Kontaktadresse des Projekts; Commit vor dem Systeminfo-Update (Muster wie V01_08) gegen 'database is locked'. - CallLog gehört zu genau einer Kontaktadresse (FK, Pflichtfeld); create/update validieren Existenz und Projekt-Zugehörigkeit. - is_erledigt() auf Kontaktadresse (mind. ein erledigend-Tag reicht) und Projekt (False ohne Kontakte, sonst alle erledigt); beide in to_dict() serialisiert. - Client: kontaktadresse_id in Notizmaske/Submit (required), Interfaces um is_erledigt erweitert. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
1 parent
24b492c5c1
commit
977b64292c
9 files changed
+174
-18
No files matched your search
@@ -275,6 +275,56 @@ def _db_V01_12():
|
||||
session.commit()
|
||||
|
||||
|
||||
def _db_V01_13():
|
||||
"""
|
||||
Fügt der Tabelle 'call_logs' die Spalte 'kontaktadresse_id' hinzu:
|
||||
Jede Gesprächsnotiz gehört zu genau einer Kontaktadresse
|
||||
(Fremdschlüssel -> kontaktadressen.id, Pflichtfeld).
|
||||
|
||||
Da SQLite kein nachträgliches NOT NULL auf einer bestehenden Spalte
|
||||
setzen kann, wird die Spalte als nullable angelegt und anschließend
|
||||
backgefüllt: Für bestehende CallLogs ohne Kontakt-Bezug wird die
|
||||
erste Kontaktadresse des gleichen Projekts eingetragen. Das NOT NULL
|
||||
ist im Modell deklariert und wird über die Server-Validierung in
|
||||
crm.model.call_log durchgesetzt.
|
||||
|
||||
Idempotent: Bei Neuinstallation hat create_all die Spalte bereits
|
||||
angelegt — in diesem Fall wird das ALTER TABLE übersprungen. Der
|
||||
Backfill und der Index sind ebenfalls idempotent.
|
||||
"""
|
||||
from sqlalchemy import text
|
||||
|
||||
result = session.execute(text("PRAGMA table_info(call_logs)"))
|
||||
spalten = {row[1] for row in result}
|
||||
if 'kontaktadresse_id' not in spalten:
|
||||
session.execute(text(
|
||||
"ALTER TABLE call_logs ADD COLUMN kontaktadresse_id INTEGER"
|
||||
))
|
||||
# Backfill: erste Kontaktadresse des Projekts eintragen, falls
|
||||
# noch keine kontaktadresse_id gesetzt ist.
|
||||
session.execute(text(
|
||||
"UPDATE call_logs SET kontaktadresse_id = ("
|
||||
" SELECT ka.id FROM kontaktadressen ka"
|
||||
" WHERE ka.projekt_id = call_logs.projekt_id"
|
||||
" LIMIT 1"
|
||||
") WHERE kontaktadresse_id IS NULL"
|
||||
))
|
||||
session.execute(text(
|
||||
"CREATE INDEX IF NOT EXISTS ix_call_logs_kontaktadresse_id"
|
||||
" ON call_logs (kontaktadresse_id)"
|
||||
))
|
||||
# Roh-SQL-Änderungen committen, BEVOR die Systeminfo aktualisiert wird
|
||||
# (dasselbe Muster wie _db_V01_08): Das Backfill-UPDATE öffnet eine
|
||||
# Schreib-Transaktion auf der Default-Bind-Verbindung —
|
||||
# SQLALCHEMY_DATABASE_URI zeigt auf dieselbe Datei wie der appdb-Bind.
|
||||
# Das ORM-Update der Systeminfo läuft über die appdb-Bind-Verbindung;
|
||||
# ohne dieses Commit blockiert die offene Transaktion das UPDATE
|
||||
# ('database is locked').
|
||||
session.commit()
|
||||
_updatesysteminfo('01.13')
|
||||
session.commit()
|
||||
|
||||
|
||||
def checkupdates():
|
||||
"""
|
||||
Ermittelt die aktuelle DB-Version aus der Systeminfo-Tabelle und führt alle
|
||||
|
||||
Reference in new issue
Block a user