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() {