Kanban: Checklisten und Voraussetzungen zwischen Aufgaben

- Checkliste je Aufgabe (Tabelle kanban_checklist): im Dialog anlegen,
  abhaken, entfernen; Karte zeigt den Fortschritt
- "Setzt voraus" (Tabelle kanban_dependencies): Aufgabe ist gesperrt und
  bleibt in "Offen", bis alle Voraussetzungen erledigt sind; nur innerhalb
  eines Projekts, Kreise und Selbstbezug werden abgelehnt; gelöschte
  Voraussetzungen entsperren, archivierte zählen als erledigt
- Ziehen einer gesperrten Karte aus "Offen" zeigt, worauf sie wartet
- Migrationen: Tabellen-Neuaufbau über Zwischennamen, damit Fremdschlüssel
  anderer Tabellen nicht auf die gelöschte Alt-Tabelle umgebogen werden
  (Test für ganz alte Datenbanken)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
guyg1474andClaude Opus 5.5 committed 2026-10-15 19:10:10 +02:00
1 parent a1a1998d1e
commit 9df0e38f52
10 files changed
+375 -28

No files matched your search

+26 -17
View File
@@ -32,6 +32,20 @@ def upgrade(conn) -> None:
conn.execute(f"PRAGMA user_version = {number}")
def _rebuild(conn, table: str, definition: str, columns: str, select: str, params=()) -> None:
"""Tabelle neu aufbauen: neue Tabelle unter Zwischennamen anlegen, Daten kopieren, alte löschen, umbenennen.
So herum bleiben Fremdschlüssel anderer Tabellen (z. B. Checkliste → Aufgaben) auf den ursprünglichen
Namen gerichtet. Würde man die alte Tabelle zuerst umbenennen, schriebe SQLite deren Verweise auf den
Zwischennamen um – und nach dem Löschen zeigten sie ins Leere.
select liest aus der alten Tabelle (unter ihrem ursprünglichen Namen).
"""
conn.execute(f"CREATE TABLE {table}_neu {definition}")
conn.execute(f"INSERT INTO {table}_neu ({columns}) {select}", params)
conn.execute(f"DROP TABLE {table}")
conn.execute(f"ALTER TABLE {table}_neu RENAME TO {table}")
# ---------- Schritt 1: Altbestand aus der Zeit vor der Versionsnummer ----------
# Diese Umstellungen prüfen noch selbst, ob sie nötig sind – eine Datenbank ohne Nummer kann
# auf jedem früheren Stand sein. Reihenfolge wie früher beim Start.
@@ -71,14 +85,12 @@ def _household(conn) -> None:
list_id = "COALESCE(list_id, ?)" if "list_id" in info else "?"
conn.execute("DROP INDEX IF EXISTS household_vorrat")
conn.execute("DROP INDEX IF EXISTS household_einkauf")
conn.execute("ALTER TABLE household_items RENAME TO household_items_alt")
conn.execute("CREATE TABLE household_items " + HOUSEHOLD_TABLE)
conn.execute(
f"""INSERT INTO household_items (id, key, name, list, list_id, quantity, unit, updated_at, updated_by)
SELECT id, key, name, list, {list_id}, quantity, {unit}, updated_at, updated_by FROM household_items_alt""",
_rebuild(
conn, "household_items", HOUSEHOLD_TABLE,
"id, key, name, list, list_id, quantity, unit, updated_at, updated_by",
f"SELECT id, key, name, list, {list_id}, quantity, {unit}, updated_at, updated_by FROM household_items",
(default,),
)
conn.execute("DROP TABLE household_items_alt")
def _household_checked(conn) -> None:
@@ -166,22 +178,19 @@ def _kanban_projects(conn) -> None:
columns = {r["name"] for r in conn.execute("PRAGMA table_info(kanban_tasks)")}
if "project_id" in columns:
return
conn.execute("ALTER TABLE kanban_tasks RENAME TO kanban_tasks_alt")
conn.execute("CREATE TABLE kanban_tasks " + KANBAN_TASKS_TABLE)
if conn.execute("SELECT COUNT(*) FROM kanban_tasks_alt").fetchone()[0]:
project = None
if conn.execute("SELECT COUNT(*) FROM kanban_tasks").fetchone()[0]:
now = now_iso()
project = conn.execute(
"INSERT INTO kanban_projects (name, position, created_at, updated_at) VALUES ('Allgemeines Board', 1, ?, ?)",
(now, now),
).lastrowid
conn.execute(
"""INSERT INTO kanban_tasks (id, project_id, title, description, status, assignee, position,
created_at, created_by, updated_at, updated_by)
SELECT id, ?, title, description, status, assignee, position, created_at, created_by, updated_at, updated_by
FROM kanban_tasks_alt""",
(project,),
)
conn.execute("DROP TABLE kanban_tasks_alt")
_rebuild(
conn, "kanban_tasks", KANBAN_TASKS_TABLE,
"id, project_id, title, description, status, assignee, position, created_at, created_by, updated_at, updated_by",
"SELECT id, ?, title, description, status, assignee, position, created_at, created_by, updated_at, updated_by FROM kanban_tasks",
(project,),
)
# ---------- Schritt 2: Datenschutz ----------