diff --git a/server/pruef-bewerbung-aufgaben.mjs b/server/pruef-bewerbung-aufgaben.mjs index 46440bf0..d0d4b02b 100644 --- a/server/pruef-bewerbung-aufgaben.mjs +++ b/server/pruef-bewerbung-aufgaben.mjs @@ -1136,17 +1136,22 @@ melde("=== 6. Am echten Bildschirm ==="); /* DER KERN DER MELDUNG. */ await roh(`/workspace/api/aufgaben/${dId}/annehmen`, { methode: "POST", keks: modi.keks }); - const fertig = await roh(`/workspace/api/aufgaben/${dId}/mein-stand`, { - methode: "POST", keks: modi.keks, body: { zustand: "erledigt" } }); + /* UEBER DEN STATUS, nicht ueber `/mein-stand` (03.10.2026). + Den zweiten Weg gibt es nicht mehr: Er setzte den + Zuteilungszustand, ohne den Aufgabenstatus mitzuziehen -- + VanVans Meldung #8. Geprueft wird jetzt die Tuer, die es + noch gibt. */ + const fertig = await roh(`/workspace/api/aufgaben/${dId}`, { + methode: "PATCH", keks: modi.keks, body: { status: "erledigt" } }); ok(fertig.code === 409 && fertig.json?.fehler === "dauerhafte_aufgabe", `Frida kann sie nicht abhaken (${fertig.code}/${fertig.json?.fehler})`); /* GEGENPROBE 1: „Ich fange an" geht weiterhin. Auch eine stehende Aufgabe hat einen Anfang -- gesperrt ist nur das Abhaken, nicht die Arbeit. */ - const anfang = await roh(`/workspace/api/aufgaben/${dId}/mein-stand`, { - methode: "POST", keks: modi.keks, body: { zustand: "arbeit" } }); - ok(anfang.code === 200, `„Ich fange an" geht trotzdem (${anfang.code})`); + const anfang = await roh(`/workspace/api/aufgaben/${dId}`, { + methode: "PATCH", keks: modi.keks, body: { status: "arbeit" } }); + ok(anfang.code === 200, `anfangen geht trotzdem (${anfang.code})`); /* GEGENPROBE 2: Bei einer GEWOEHNLICHEN Aufgabe geht das Abhaken. Ohne sie hiesse „409" womoeglich nur, dass niemand je etwas @@ -1158,8 +1163,8 @@ melde("=== 6. Am echten Bildschirm ==="); const nId = normal.json?.aufgabe?.id ?? normal.json?.id; await roh(`/workspace/api/aufgaben/${nId}/annehmen`, { methode: "POST", keks: modi.keks }); - const ok2 = await roh(`/workspace/api/aufgaben/${nId}/mein-stand`, { - methode: "POST", keks: modi.keks, body: { zustand: "erledigt" } }); + const ok2 = await roh(`/workspace/api/aufgaben/${nId}`, { + methode: "PATCH", keks: modi.keks, body: { status: "erledigt" } }); ok(ok2.code === 200, `eine gewoehnliche Aufgabe haekt sie sehr wohl ab (${ok2.code})`); @@ -1193,8 +1198,8 @@ melde("=== 6. Am echten Bildschirm ==="); const a3 = await lesen(hand.keks); ok(beenden.code === 200 && !a3?.dauerhaft, `die rechte Hand beendet sie (${beenden.code}, danach ${a3?.dauerhaft})`); - const jetztFertig = await roh(`/workspace/api/aufgaben/${dId}/mein-stand`, { - methode: "POST", keks: modi.keks, body: { zustand: "erledigt" } }); + const jetztFertig = await roh(`/workspace/api/aufgaben/${dId}`, { + methode: "PATCH", keks: modi.keks, body: { status: "erledigt" } }); ok(jetztFertig.code === 200, `und danach laesst sie sich abhaken (${jetztFertig.code})`); } diff --git a/server/pruef-zuteilung.mjs b/server/pruef-zuteilung.mjs index 4adcee8b..7b55fe11 100644 --- a/server/pruef-zuteilung.mjs +++ b/server/pruef-zuteilung.mjs @@ -458,15 +458,21 @@ melde("\n=== Fertig machen und bewerten ==="); `eine dauerhafte Aufgabe (#${idDauer})`); await rufe(`/workspace/api/aufgaben/${idDauer}/annehmen`, { method: "POST", keks: anna }); - const ueberStand = await rufe(`/workspace/api/aufgaben/${idDauer}/mein-stand`, + /* ES GIBT NUR NOCH EINE TUER (03.10.2026). Hier standen zwei: + `/mein-stand` und der Status. Die erste ist weg -- sie setzte + den Zuteilungszustand, ohne den Aufgabenstatus mitzuziehen, + und war damit der zweite Zustand, den VanVans Meldung #8 + benannt hat. Dass sie zu war, hat nichts geheilt; dass es sie + nicht mehr gibt, schon. */ + const weg = await rufe(`/workspace/api/aufgaben/${idDauer}/mein-stand`, { method: "POST", keks: anna, body: { zustand: "erledigt" } }); - ok(ueberStand.code === 409 && ueberStand.json?.fehler === "dauerhafte_aufgabe", - `Tuer 1 (mein-stand) ist zu (${ueberStand.code} ${ueberStand.json?.fehler})`); + ok(weg.code === 404, + `den zweiten Weg (mein-stand) gibt es nicht mehr (${weg.code})`); const ueberStatus = await rufe(`/workspace/api/aufgaben/${idDauer}`, { method: "PATCH", keks: anna, body: { status: "erledigt" } }); ok(ueberStatus.code === 409 && ueberStatus.json?.fehler === "dauerhafte_aufgabe", - `Tuer 2 (Status) jetzt auch (${ueberStatus.code} ${ueberStatus.json?.fehler})` + `und der Status ist zu (${ueberStatus.code} ${ueberStatus.json?.fehler})` + " — das war VanVans Befund"); /* ANFANGEN DARF SIE SEHR WOHL. Auch eine stehende Aufgabe hat @@ -507,14 +513,40 @@ melde("\n=== Fertig machen und bewerten ==="); ok(wiederDa === "angenommen", ` zurueckgedreht steht Anna wieder auf „angenommen" (${wiederDa})`); - const arbeit = await rufe(`/workspace/api/aufgaben/${idPool}/mein-stand`, { method: "POST", keks: bea, - body: { zustand: "arbeit" } }); - /* DER WEG BLEIBT BESTEHEN, auch ohne Knopf: Er ist die Schranke - fuer den, der die Schnittstelle direkt anspricht. */ + /* ==== BEIDE ZUSTAENDE, NICHT NUR HTTP 200 (03.10.2026) ========== + + Hier stand der Weg ueber `/mein-stand` und daneben nur die + Frage, ob er mit 200 antwortet. GENAU DAS hat VanVans Fehler + durchgewunken: Die Zuteilung sprang auf „in Bearbeitung", der + Aufgabenstatus blieb auf „offen" -- und die Pruefung sagte ok, + weil sie ihn nie angesehen hat. + + Jetzt geht es ueber den Status, und gemessen werden BEIDE + Seiten. Eine Pruefung, die nur eine Haelfte ansieht, kann den + Widerspruch gar nicht finden. */ + const standVonBea = () => { + const x = new DatabaseSync(process.env.WORKSPACE_DB); + const a = x.prepare("SELECT status FROM aufgaben WHERE id = ?").get(idPool); + const z = x.prepare( + "SELECT zustand FROM aufgaben_zuteilung WHERE aufgabe_id = ? AND person_id = ?") + .get(idPool, idBea); + x.close(); + return { status: a?.status, zustand: z?.zustand }; + }; + const arbeit = await rufe(`/workspace/api/aufgaben/${idPool}`, { method: "PATCH", keks: bea, + body: { status: "arbeit" } }); + const beideArbeit = standVonBea(); ok(arbeit.code === 200, `Bea setzt "in Bearbeitung" (HTTP ${arbeit.code})`); - const fertig = await rufe(`/workspace/api/aufgaben/${idPool}/mein-stand`, { method: "POST", keks: bea, - body: { zustand: "erledigt" } }); + ok(beideArbeit.status === "arbeit" && beideArbeit.zustand === "arbeit", + ` und BEIDES steht auf "in Arbeit" (Aufgabe ${beideArbeit.status}, ` + + `Zuteilung ${beideArbeit.zustand}) — das war VanVans Befund`); + + const fertig = await rufe(`/workspace/api/aufgaben/${idPool}`, { method: "PATCH", keks: bea, + body: { status: "erledigt" } }); + const beideFertig = standVonBea(); ok(fertig.code === 200, `und danach "erledigt" (HTTP ${fertig.code})`); + ok(beideFertig.status === "erledigt" && beideFertig.zustand === "erledigt", + ` und wieder beides (Aufgabe ${beideFertig.status}, Zuteilung ${beideFertig.zustand})`); /* DIE DREI RUECKMELDUNGEN AUS ABSCHNITT 5. */ const leer = await rufe(`/workspace/api/aufgaben/${idPool}/bewerten`, { method: "POST", keks: chef, diff --git a/server/workspace-zuteilung.js b/server/workspace-zuteilung.js index 4616afc3..e154c198 100644 --- a/server/workspace-zuteilung.js +++ b/server/workspace-zuteilung.js @@ -760,61 +760,38 @@ for (const [weg, entscheidung] of [["annehmen", "ja"], ["ablehnen", "nein"]]) { }); } -/* ---- Meinen eigenen Stand setzen ------------------------------------ */ -zuteilungRouter.post("/workspace/api/aufgaben/:id/mein-stand", (req, res) => { - try { - const a = holen(req, res); if (!a) return; - const z = meine(a.id, req.person.id); - if (!z) return res.status(403).json({ fehler: "nicht_zugeteilt" }); +/* ==== HIER STAND `/mein-stand` (03.10.2026 entfernt) ============== - const ziel = String(req.body?.zustand ?? "").trim(); - /* NUR DIE DREI, DIE MAN SELBST SETZEN DARF. "offen" zurückzudrehen - hieße, die eigene Zusage zu löschen; "abgelehnt" hat einen - eigenen Weg, weil es eine Begründung braucht. */ - if (!["angenommen", "arbeit", "erledigt"].includes(ziel)) { - return res.status(400).json({ fehler: "ungueltiger_zustand" }); - } - if (z.zustand === "abgelehnt") return res.status(409).json({ fehler: "abgelehnt" }); + VanVan im Support, Meldung #8: „Wenn man auf ich fange an drückt + steht dort in Bearbeitung und wenn man auf fertig drückt dann wird + es zu erledigt. DIE AUFGABE BLEIBT ABER IM STATUS OFFEN STEHEN." - /* ==== EINE DAUERHAFTE AUFGABE WIRD NICHT FERTIG (30.09.2026) ==== + Gestern habe ich die zwei Knöpfe entfernt, die diese Route riefen, + und daneben geschrieben: „Der Weg bleibt bestehen — er ist die + Schranke, falls ihn jemand direkt anspricht." - VanVan im Support: „… dass die Aufgabe dauerhaft sein soll und - somit nicht vom Modi in den Status erledigt gesetzt werden - kann." + DAS WAR EINE AUSREDE, KEINE BEGRÜNDUNG. Eine Route ist keine + Schranke gegen sich selbst. Sie setzte weiterhin NUR + `aufgaben_zuteilung.zustand` und ließ `aufgaben.status` stehen — + also genau den Zustand, den VanVan gemeldet hat. Unsichtbar + gemacht, nicht abgeschafft. - Sie ist keine Aufgabe, die man abarbeitet, sondern eine, die - man TUT. „Neue begruessen" ist nicht fertig, wenn man es einmal - gemacht hat. + NACHGEMESSEN, BEVOR SIE WEGKAM: Kein einziger Aufruf mehr im + ausgelieferten Browsercode (`grep` über alle JS- und HTML-Dateien + des Workspace). Nur zwei Prüfungen benutzten sie — und eine davon + nickte den Fehler sogar ab: Sie setzte „in Bearbeitung" und prüfte + HTTP 200, nie den Aufgabenstatus daneben. - „ICH FANGE AN" BLEIBT ERLAUBT. Auch eine stehende Aufgabe hat - einen Anfang, und der Unterschied zwischen „angenommen" und „in - Arbeit" sagt etwas. Gesperrt ist nur das Abhaken. + WAS STATTDESSEN GILT: `PATCH /workspace/api/aufgaben/:id` mit + `{ status }`. Er setzt den Status UND zieht die Zuteilung mit + (`zuteilungenNachStatus`), kennt dieselbe Sperre für dauerhafte + Aufgaben und dieselbe Rechteprüfung. Eine Frage, eine Antwort. - DIE SPERRE STEHT HIER UND NICHT NUR IM BROWSER. Ein fehlender - Knopf ist eine Bitte; abgelehnt wird am Server -- wer die - Schnittstelle direkt anspricht, kaeme sonst durch. + ENTFERNT STATT AUSKOMMENTIERT — dieselbe Entscheidung wie bei + `/vorlagen/hilfe` am 01.09.: Eine Route, die niemand mehr aufruft, + wird beim nächsten Mal für lebenden Code gehalten und mitgepflegt. + ================================================================== */ - BEENDET WIRD SIE VON DER LEITUNG, ueber den Status der Aufgabe - selbst. Eine Pflicht, die niemand mehr beenden kann, waere eine - Falle statt einer Regel. */ - if (ziel === "erledigt" && a.dauerhaft) { - return res.status(409).json({ fehler: "dauerhafte_aufgabe" }); - } - - db().prepare(`UPDATE aufgaben_zuteilung - SET zustand = ?, erledigt_am = ? - WHERE id = ?`).run(ziel, ziel === "erledigt" ? jetzt() : null, z.id); - - protokolliere("aufgabe_stand", { - personId: req.person.id, rolle: req.person.rolle, ip: echteIp(req), - detail: `#${a.id} ${ziel}`.slice(0, 120), - }); - res.json({ ok: true, zustand: ziel }); - } catch (f) { - console.error("[zuteilung] mein-stand:", f?.message); - res.status(503).json({ fehler: "nicht_verfuegbar" }); - } -}); /* ---- Bewerten (Abschnitt 5) ----------------------------------------- */ zuteilungRouter.post("/workspace/api/aufgaben/:id/bewerten", (req, res) => { diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html index 6fdcd544..09f440b0 100644 --- a/workspace/anruf-probe.html +++ b/workspace/anruf-probe.html @@ -16,8 +16,8 @@ verdeckt. Gefunden hat es pruef-struktur. Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. --> - - + + - +