From 29785cc2a41b4566fc255fadcc32f47f8a1945ab Mon Sep 17 00:00:00 2001 From: Dogfather Date: Tue, 8 Sep 2026 11:27:08 +0200 Subject: [PATCH] Abgebrochene Aufgaben mahnen nicht mehr -- an zwoelf Stellen, nicht an einer Filipe, screen12: "die abgebrochenen sollen oben nicht mehr mit zaehlen die sollen ihre eigenen kategorie kriegen". DIE URSACHE war eine Bedingung, die harmlos aussieht: `a.status <> 'erledigt'`. Eine abgebrochene Aufgabe ist nicht "erledigt" -- also fiel sie durch, und zwar in JEDE Zahl, die "noch zu tun" bedeutet. Eine Aufgabe, die niemand mehr anfassen wird, mahnte weiter als ueberfaellig. Das ist die Kehrseite einer bewussten Entscheidung: "abgebrochen" steht absichtlich NICHT in STATUS, damit der normale Weg es nicht setzen kann. Genau deshalb rutscht es aber durch jede Pruefung, die nur gegen 'erledigt' vergleicht. FILIPE HAT EINE STELLE GESEHEN. Gesucht werden musste nach dem MUSTER: Es waren zwoelf, in sieben Dateien. workspace-aufgaben.js 2 ueberfaellig und heute (die Zahlen "oben") workspace-hinweise.js 2 die Hinweiszeilen der Startseite workspace-kalender.js 1 Aufgaben mit Frist im Kalender workspace-personen.js 1 "offene_aufgaben" je Person workspace-profil.js 1 dieselbe Zahl im Profil workspace-push.js 2 ERINNERUNGEN, die verschickt werden workspace-reports.js 3 Berichte Am schwersten wiegt workspace-push.js: Dort gingen Push-Nachrichten hinaus -- fuer Aufgaben, die laengst abgebrochen waren. `NOT IN ('erledigt', 'abgebrochen')` statt einer zweiten Ungleichung: Wer spaeter einen dritten Endzustand einfuehrt, ergaenzt eine Liste, statt eine Kette von `<>` zu verlaengern, bei der das Vergessen niemandem auffaellt. DIE EIGENE KATEGORIE, die Filipe verlangt hat, gibt es jetzt in der Schnittstelle (`abgebrochen`) und auf der Startseite -- hinten bei "Erledigt", weil beides dasselbe bedeutet: vom Tisch. GEGENPROBE an einer abgebrochenen Aufgabe mit Frist von gestern: alte Bedingung "<> erledigt" -> ueberfaellig = 3 neue Bedingung "NOT IN (erledigt, abg)" -> ueberfaellig = 2 Unterschied 1 = genau die abgebrochene. Die Schnittstelle liefert 2 und abgebrochen = 1. pruef-start-ansicht hat den Umbau bemerkt und "die Aufgabenzahlen stehen (7)" gemeldet -- sie zaehlt die Kategorien und erwartete sechs. Die Zahl steht in der Bedingung, nicht nur im Meldetext; deshalb faellt eine Kategorie, die still verschwindet, sofort auf. Auf 7 nachgezogen: EXIT=0, 140 Pruefungen. pruef-aufgabenbrett EXIT=0, 44. Co-Authored-By: Claude Opus 5 --- server/pruef-start-ansicht.mjs | 8 ++++++- server/workspace-aufgaben.js | 40 ++++++++++++++++++++++++++++++---- server/workspace-hinweise.js | 4 ++-- server/workspace-kalender.js | 2 +- server/workspace-personen.js | 2 +- server/workspace-profil.js | 2 +- server/workspace-push.js | 4 ++-- server/workspace-reports.js | 6 ++--- workspace/assets/js/start.js | 6 +++++ 9 files changed, 59 insertions(+), 15 deletions(-) diff --git a/server/pruef-start-ansicht.mjs b/server/pruef-start-ansicht.mjs index fad0ea33..1790b8f3 100644 --- a/server/pruef-start-ansicht.mjs +++ b/server/pruef-start-ansicht.mjs @@ -336,7 +336,13 @@ for (const [breite, wie] of [[1440, "Computer"], [390, "Handy"]]) { ok(r.dranZeilen.filter((z) => z.stufe !== "warnung") .every((z) => z.zahlFarbe !== "rgb(255, 154, 162)"), "und nur die"); - ok(r.zahlen === 6, `die Aufgabenzahlen stehen (${r.zahlen})`); + /* SIEBEN seit dem 08.09.2026: "Abgebrochen" ist als eigene Kategorie + dazugekommen (screen12). Vorher zaehlten abgebrochene Aufgaben + unsichtbar bei "Ueberfaellig" und "Heute faellig" mit. + Die Zahl steht bewusst hier in der Bedingung und nicht nur im + Meldetext -- eine Kategorie, die still verschwindet, faellt sonst + niemandem auf. */ + ok(r.zahlen === 7, `die Aufgabenzahlen stehen (${r.zahlen})`); ok(!r.zahlenLeer, "und nicht der Leer-Satz"); ok(r.ueber <= 0, `nichts steht über (${r.ueber}px, ${r.ueberstehend.join(", ")})`); ok(konsole.length === 0, `keine Fehler in der Konsole${konsole.length ? " -> " + konsole.join(" | ") : ""}`); diff --git a/server/workspace-aufgaben.js b/server/workspace-aufgaben.js index e9fb151e..09ce89fb 100644 --- a/server/workspace-aufgaben.js +++ b/server/workspace-aufgaben.js @@ -157,15 +157,47 @@ aufgabenRouter.get("/workspace/api/uebersicht", (req, res) => { .get(...werte, ...extra).n; const heute = jetzt().slice(0, 10); + + /* ABGEBROCHENE SIND NICHT "NOCH ZU TUN" (08.09.2026). + + Filipe, screen12: "die abgebrochenen sollen oben nicht mehr mit + zählen die sollen ihre eigenen kategorie kriegen". + + Hier stand nur "ungleich erledigt", und das war der Fehler: Eine + abgebrochene Aufgabe ist zwar nicht "erledigt", aber eben auch + nicht offen. Sie fiel damit in BEIDE Zahlen oben -- eine Aufgabe, + die niemand mehr anfassen wird, mahnte weiter als überfällig. + + DERSELBE FEHLER STAND AN ZWÖLF STELLEN in sieben Dateien, nicht + nur hier. Am schwersten wog `workspace-push.js`: Dort werden + Erinnerungen VERSCHICKT -- für Aufgaben, die längst abgebrochen + waren. Filipe hat eine Stelle gesehen; gesucht werden musste nach + dem Muster, nicht nach dem Symptom. + + Das ist die Kehrseite einer bewussten Entscheidung weiter unten in + dieser Datei: "abgebrochen" steht absichtlich NICHT in STATUS, + damit der normale Weg es nicht setzen kann. Genau deshalb rutscht + es aber durch jede Bedingung, die nur gegen 'erledigt' prüft -- + und davon gab es hier zwei. + + `NOT IN` statt einer zweiten Ungleichung: Wer später einen dritten + Endzustand einführt, ergänzt eine Liste, statt eine Kette von + `<>` zu verlängern, bei der das Vergessen niemandem auffällt. */ + const ERLEDIGT_ODER_WEG = " AND a.status NOT IN ('erledigt', 'abgebrochen')"; + res.json({ offen: zaehle(" AND a.status = 'offen'"), arbeit: zaehle(" AND a.status = 'arbeit'"), review: zaehle(" AND a.status = 'review'"), erledigt: zaehle(" AND a.status = 'erledigt'"), - /* Überfällig = Frist vorbei und noch nicht erledigt. Genau die Zahl, + /* Die eigene Kategorie, die Filipe verlangt hat. Sie steht bei den + abgeschlossenen, nicht bei den offenen -- die Aufgabe ist vom + Tisch, nur eben anders als durch Erledigen. */ + abgebrochen: zaehle(" AND a.status = 'abgebrochen'"), + /* Überfällig = Frist vorbei und noch offen. Genau die Zahl, die das Konzept auf dem Dashboard sehen will. */ - ueberfaellig: zaehle(" AND a.status <> 'erledigt' AND a.frist IS NOT NULL AND a.frist < ?", [heute]), - heute: zaehle(" AND a.status <> 'erledigt' AND a.frist = ?", [heute]), + ueberfaellig: zaehle(ERLEDIGT_ODER_WEG + " AND a.frist IS NOT NULL AND a.frist < ?", [heute]), + heute: zaehle(ERLEDIGT_ODER_WEG + " AND a.frist = ?", [heute]), }); } catch (fehler) { console.error("[workspace] Übersicht:", fehler?.message); @@ -315,7 +347,7 @@ aufgabenRouter.get("/workspace/api/uebersicht/creator", (req, res) => { (SELECT COUNT(*) FROM aufgaben a WHERE a.creator_id = p.id AND a.status = 'review') AS review, (SELECT COUNT(*) FROM aufgaben a - WHERE a.creator_id = p.id AND a.status <> 'erledigt' + WHERE a.creator_id = p.id AND a.status NOT IN ('erledigt', 'abgebrochen') AND a.frist IS NOT NULL AND a.frist < ?) AS ueberfaellig, (SELECT COUNT(*) FROM aufgaben a WHERE a.creator_id = p.id AND a.erledigt_am IS NOT NULL diff --git a/server/workspace-hinweise.js b/server/workspace-hinweise.js index bd331b35..a4c863db 100644 --- a/server/workspace-hinweise.js +++ b/server/workspace-hinweise.js @@ -91,13 +91,13 @@ hinweisRouter.get("/workspace/api/hinweise", (req, res) => { dazu("aufgaben_ueberfaellig", "warnung", "überfällig", "aufgaben.html", zaehle(`SELECT COUNT(*) n FROM aufgaben a - WHERE ${a.wo} AND a.status <> 'erledigt' + WHERE ${a.wo} AND a.status NOT IN ('erledigt', 'abgebrochen') AND a.frist IS NOT NULL AND a.frist < ?`, [...a.werte, heute])); dazu("aufgaben_heute", "offen", "heute fällig", "aufgaben.html", zaehle(`SELECT COUNT(*) n FROM aufgaben a - WHERE ${a.wo} AND a.status <> 'erledigt' AND a.frist = ?`, + WHERE ${a.wo} AND a.status NOT IN ('erledigt', 'abgebrochen') AND a.frist = ?`, [...a.werte, heute])); /* Aufgaben, die im Review haengen. Sie warten auf jemanden -- diff --git a/server/workspace-kalender.js b/server/workspace-kalender.js index bd6ca411..73684d1c 100644 --- a/server/workspace-kalender.js +++ b/server/workspace-kalender.js @@ -315,7 +315,7 @@ kalenderRouter.get("/workspace/api/termine", (req, res) => { const fristen = db().prepare(` SELECT a.id, a.titel, a.frist, a.status, a.prioritaet, pv.name AS verantwortlich_name FROM aufgaben a LEFT JOIN personen pv ON pv.id = a.verantwortlich_id - WHERE ${aufgabenWo.wo} AND a.frist IS NOT NULL AND a.status <> 'erledigt' + WHERE ${aufgabenWo.wo} AND a.frist IS NOT NULL AND a.status NOT IN ('erledigt', 'abgebrochen') AND a.frist >= ? AND a.frist <= ? ORDER BY a.frist`).all(...aufgabenWo.werte, von, bis); diff --git a/server/workspace-personen.js b/server/workspace-personen.js index 4ca4a98a..e22ca408 100644 --- a/server/workspace-personen.js +++ b/server/workspace-personen.js @@ -169,7 +169,7 @@ personenRouter.get("/workspace/api/verwaltung/personen", (req, res) => { (SELECT COUNT(*) FROM sitzungen s WHERE s.person_id = p.id) AS sitzungen, (SELECT COUNT(*) FROM aufgaben a WHERE (a.creator_id = p.id OR a.verantwortlich_id = p.id) - AND a.status <> 'erledigt') AS offene_aufgaben, + AND a.status NOT IN ('erledigt', 'abgebrochen')) AS offene_aufgaben, b.betreuer_id, (SELECT name FROM personen x WHERE x.id = b.betreuer_id) AS betreuer_name, (SELECT COUNT(*) FROM betreuung y WHERE y.betreuer_id = p.id) AS betreut_anzahl, diff --git a/server/workspace-profil.js b/server/workspace-profil.js index b0ac16ba..545da26e 100644 --- a/server/workspace-profil.js +++ b/server/workspace-profil.js @@ -139,7 +139,7 @@ profilRouter.get("/workspace/api/profil", (req, res) => { creator: db().prepare(` SELECT p.id, p.name, p.aktiv, p.letzter_login, (SELECT COUNT(*) FROM aufgaben a - WHERE a.creator_id = p.id AND a.status <> 'erledigt') AS offene_aufgaben, + WHERE a.creator_id = p.id AND a.status NOT IN ('erledigt', 'abgebrochen')) AS offene_aufgaben, (SELECT naechster_review FROM profile f WHERE f.person_id = p.id) AS naechster_review, (SELECT geaendert FROM profile f WHERE f.person_id = p.id) AS profil_geaendert FROM personen p WHERE p.rolle = 'creator'${nur} diff --git a/server/workspace-push.js b/server/workspace-push.js index e5d5dc90..70c6b939 100644 --- a/server/workspace-push.js +++ b/server/workspace-push.js @@ -241,7 +241,7 @@ export async function laufen() { /* --- Aufgaben, die morgen faellig sind ---------------------------- */ for (const a of d.prepare(` SELECT a.id, a.titel, a.verantwortlich_id FROM aufgaben a - WHERE a.status <> 'erledigt' AND a.frist = ? AND a.verantwortlich_id IS NOT NULL`).all(morgen)) { + WHERE a.status NOT IN ('erledigt', 'abgebrochen') AND a.frist = ? AND a.verantwortlich_id IS NOT NULL`).all(morgen)) { await senden(a.verantwortlich_id, "aufgabe_faellig", { titel: "Morgen fällig", text: a.titel, @@ -253,7 +253,7 @@ export async function laufen() { /* --- Aufgaben, die ueberfaellig sind ------------------------------ */ for (const a of d.prepare(` SELECT a.id, a.titel, a.frist, a.verantwortlich_id FROM aufgaben a - WHERE a.status <> 'erledigt' AND a.frist IS NOT NULL AND a.frist < ? + WHERE a.status NOT IN ('erledigt', 'abgebrochen') AND a.frist IS NOT NULL AND a.frist < ? AND a.verantwortlich_id IS NOT NULL`).all(heute)) { await senden(a.verantwortlich_id, "aufgabe_ueberfaellig", { titel: "Überfällig", diff --git a/server/workspace-reports.js b/server/workspace-reports.js index c305b50d..84d6d09c 100644 --- a/server/workspace-reports.js +++ b/server/workspace-reports.js @@ -123,15 +123,15 @@ reportRouter.get("/workspace/api/report", (req, res) => { erledigt_davor: erledigt(davorIso, abIso), angelegt: angelegt(abIso, jetztIso), angelegt_davor: angelegt(davorIso, abIso), - offen: zahl(`SELECT COUNT(*) AS n FROM aufgaben a WHERE a.status <> 'erledigt'${nurA}`, wertA), + offen: zahl(`SELECT COUNT(*) AS n FROM aufgaben a WHERE a.status NOT IN ('erledigt', 'abgebrochen')${nurA}`, wertA), ueberfaellig: zahl( `SELECT COUNT(*) AS n FROM aufgaben a - WHERE a.status <> 'erledigt' AND a.frist IS NOT NULL AND a.frist < ?${nurA}`, + WHERE a.status NOT IN ('erledigt', 'abgebrochen') AND a.frist IS NOT NULL AND a.frist < ?${nurA}`, [heute, ...wertA]), /* "Was blockiert?" aus dem Konzept: was liegt am laengsten offen? */ aeltester: db().prepare( `SELECT a.titel, a.frist, a.erstellt FROM aufgaben a - WHERE a.status <> 'erledigt'${nurA} ORDER BY a.erstellt LIMIT 3`).all(...wertA), + WHERE a.status NOT IN ('erledigt', 'abgebrochen')${nurA} ORDER BY a.erstellt LIMIT 3`).all(...wertA), }; /* --- Bereiche -------------------------------------------------------- */ diff --git a/workspace/assets/js/start.js b/workspace/assets/js/start.js index 03aefcf8..0a6fafd2 100644 --- a/workspace/assets/js/start.js +++ b/workspace/assets/js/start.js @@ -1104,6 +1104,12 @@ { schluessel: 'arbeit', name: 'In Arbeit' }, { schluessel: 'review', name: 'Review' }, { schluessel: 'erledigt', name: 'Erledigt' }, + /* ABGEBROCHEN als eigene Zahl (08.09.2026, screen12). Sie steht + hinten bei "Erledigt", weil beides dasselbe bedeutet: vom Tisch. + Vorher tauchte sie nirgends auf und schlug sich stattdessen + unsichtbar auf "Überfällig" und "Heute fällig" nieder -- eine + Aufgabe, die niemand mehr anfasst, mahnte weiter. */ + { schluessel: 'abgebrochen', name: 'Abgebrochen' }, ]; async function zahlenLaden() {