diff --git a/server/pruef-entwicklung.mjs b/server/pruef-entwicklung.mjs index 440f7014..c438c92d 100644 --- a/server/pruef-entwicklung.mjs +++ b/server/pruef-entwicklung.mjs @@ -469,6 +469,55 @@ console.log("\n=== Punkte je Person aussuchen ==="); ok(vonHand.status === 200 && vonHand.daten?.zugeteilt === 5, `die rechte Hand sucht ebenfalls aus (HTTP ${vonHand.status}, ${vonHand.daten?.zugeteilt})`); + /* ---- 4b. EINZELN ZUTRAGEN, DIREKT AM PUNKT (25.09.2026) -------- + + Filipe: „ich will sofort über diese aufgaben da spezifisch + zuteilen kann bitte. bei allen personnen." + + Das Auswahlfenster setzt die GANZE Liste; dieser Weg setzt EINEN + Punkt. Der Unterschied ist nicht nur Bequemlichkeit: Wuerde der + Knopf am Punkt die ganze Liste schicken, loeschte er die + Zutragung, die jemand anderes eine Sekunde vorher gemacht hat. + Genau das wird hier gemessen -- erst zutragen, dann pruefen, dass + die vorherigen unberuehrt sind. */ + { + const einer = alle[20].schluessel; + const vorZahl = (await karte(dogi.keks))?.gesamt || 0; + const weg = (an, s = einer, keks = dogi.keks) => + hole(`/workspace/api/entwicklung/person/${idModi}/punkt/${s}`, + { host: CREW, keks, methode: "PUT", rumpf: JSON.stringify({ an }) }); + + const a1 = await weg(true); + ok(a1.status === 200 && a1.daten?.zugetragen === true, + `ein einzelner Punkt laesst sich direkt am Punkt zutragen (HTTP ${a1.status})`); + ok(a1.daten?.gesamt === vorZahl + 1, + `und die neue Zahl kommt vom Server zurueck (${vorZahl} -> ${a1.daten?.gesamt})`); + + const k1 = await karte(dogi.keks); + const markiert1 = (k1?.bloecke || []).flatMap((b) => b.punkte) + .filter((pt) => pt.zugetragen).map((pt) => pt.schluessel); + ok(markiert1.includes(einer) && markiert1.length === vorZahl + 1, + `die vorher zugetragenen bleiben unberuehrt (${markiert1.length})`); + + /* ZWEIMAL DASSELBE IST KEIN FEHLER. Wer zweimal tippt oder zwei + Fenster offen hat, bekommt denselben Zustand -- nicht eine + Absage und nicht einen doppelten Eintrag. */ + const a2 = await weg(true); + ok(a2.status === 200 && a2.daten?.gesamt === a1.daten?.gesamt, + `zweimal zutragen aendert nichts (${a2.daten?.gesamt})`); + + const a3 = await weg(false); + ok(a3.status === 200 && a3.daten?.gesamt === vorZahl, + `und einzeln wieder wegnehmen ebenso (${a3.daten?.gesamt})`); + + const quatsch = await weg(true, "gibt_es_nicht"); + ok(quatsch.status === 400, + `Gegenprobe: ein erfundener Punkt wird abgewiesen (${quatsch.status})`); + const vonModi2 = await weg(true, einer, ayla.keks); + ok(vonModi2.status >= 400, + `Gegenprobe: ein Modi traegt nichts zu (${vonModi2.status})`); + } + /* ---- Gegenproben ------------------------------------------------- */ /* EIN ERFUNDENER SCHLUESSEL WIRD VERWORFEN. Ohne diesen Abgleich liesse sich beliebiger Text in die Tabelle schreiben -- er stuende diff --git a/server/workspace-entwicklung.js b/server/workspace-entwicklung.js index b108fac5..1ecbd90a 100644 --- a/server/workspace-entwicklung.js +++ b/server/workspace-entwicklung.js @@ -951,6 +951,72 @@ entwicklungRouter.get("/workspace/api/entwicklung/person/:id/punkte", } }); +/* ==== EINEN EINZELNEN PUNKT ZUTRAGEN (25.09.2026) ================== + + Filipe: „ich will sofort über diese aufgaben da spezifisch zuteilen + kann bitte. bei allen personnen." + + DAS AUSWAHLFENSTER BLEIBT -- es ist der Weg, wenn man jemanden neu + einrichtet und zwoelf Punkte auf einmal vergibt. Dieser Weg hier ist + der andere Fall, und er ist der haeufigere: Man liest eine + Beobachtung, denkt „das soll er machen", und will es in dem Moment + erledigen -- nicht ein Fenster aufmachen, in einer Liste von 68 + denselben Punkt suchen und wieder zumachen. + + EIN PUNKT, EIN AUFRUF. Anders als beim Fenster, das die ganze Liste + setzt: Hier geht es um EINE Entscheidung, und die soll auch dann + ankommen, wenn zwei Leute gleichzeitig an derselben Karte sitzen. + Wuerde dieser Weg die ganze Liste schicken, loeschte er die + Zutragung, die der andere eine Sekunde vorher gemacht hat. + + `INSERT OR IGNORE` / `DELETE`: Zweimal zutragen ist kein Fehler, + zweimal wegnehmen auch nicht. Wer zweimal tippt (oder zwei Fenster + offen hat), bekommt denselben Zustand, nicht einen Fehler. + ================================================================== */ +entwicklungRouter.put("/workspace/api/entwicklung/person/:id/punkt/:schluessel", + gleicheHerkunft, nurLeitung, express.json({ limit: "4kb" }), (req, res) => { + try { + const id = nummer(req.params.id); + const p = id && db().prepare("SELECT id, name, rolle FROM personen WHERE id = ?").get(id); + if (!p || !KARTEN_ROLLEN.includes(p.rolle)) { + return res.status(404).json({ fehler: "nicht_gefunden" }); + } + const schluessel = String(req.params.schluessel || ""); + /* NUR EIN SCHLUESSEL, DEN ES WIRKLICH GIBT -- sonst liesse sich + ueber diesen Weg beliebiger Text in die Tabelle schreiben, der + danach in keiner Liste steht und auch nicht wegzubekommen + ist. Dieselbe Pruefung wie beim Fenster. */ + if (!ENTWICKLUNG_FREMD.some((pt) => pt.schluessel === schluessel)) { + return res.status(400).json({ fehler: "unbekannter_punkt" }); + } + const an = req.body?.an === true; + if (an) { + db().prepare(`INSERT INTO entwicklung_zuteilung + (person_id, schluessel, seit, von_id) VALUES (?,?,?,?) + ON CONFLICT(person_id, schluessel) DO NOTHING`) + .run(id, schluessel, jetzt(), req.person.id); + } else { + db().prepare( + "DELETE FROM entwicklung_zuteilung WHERE person_id = ? AND schluessel = ?") + .run(id, schluessel); + } + + protokolliere(an ? "entwicklung_punkt_zugetragen" : "entwicklung_punkt_zurueck", { + personId: req.person.id, rolle: req.person.rolle, ip: echteIp(req), + detail: `${p.name}: ${schluessel}`.slice(0, 120), + }); + /* DIE NEUE ZAHL KOMMT MIT. Die Oberflaeche zeigt „3 von 12 + erledigt" -- rechnete sie selbst weiter, waere sie bei zwei + offenen Fenstern falsch, und niemand saehe, warum. */ + const gesamt = db().prepare( + "SELECT COUNT(*) AS n FROM entwicklung_zuteilung WHERE person_id = ?").get(id).n; + res.json({ ok: true, zugetragen: an, gesamt }); + } catch (f) { + console.error("[entwicklung] Punkt zutragen:", f?.message); + res.status(503).json({ fehler: "nicht_verfuegbar" }); + } + }); + entwicklungRouter.put("/workspace/api/entwicklung/person/:id/punkte", gleicheHerkunft, nurLeitung, express.json({ limit: "32kb" }), (req, res) => { try { diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html index 932bf84f..cb0886cc 100644 --- a/workspace/anruf-probe.html +++ b/workspace/anruf-probe.html @@ -16,15 +16,15 @@ verdeckt. Gefunden hat es pruef-struktur. Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. --> - - + + - +