diff --git a/pruef-felder.png b/pruef-felder.png index fc60cb67..b0f49429 100644 Binary files a/pruef-felder.png and b/pruef-felder.png differ diff --git a/pruef-handy.png b/pruef-handy.png index 9b411163..3ad8acd2 100644 Binary files a/pruef-handy.png and b/pruef-handy.png differ diff --git a/pruef-kalender-computer.png b/pruef-kalender-computer.png index 823e8054..a69a3f18 100644 Binary files a/pruef-kalender-computer.png and b/pruef-kalender-computer.png differ diff --git a/pruef-lesbarkeit-wissen.png b/pruef-lesbarkeit-wissen.png index 4cc3f9d9..0ea4de26 100644 Binary files a/pruef-lesbarkeit-wissen.png and b/pruef-lesbarkeit-wissen.png differ diff --git a/pruef-personen.png b/pruef-personen.png index 7c1021dc..041e21c4 100644 Binary files a/pruef-personen.png and b/pruef-personen.png differ diff --git a/pruef-protokoll-auf.png b/pruef-protokoll-auf.png index f7384a75..8bc0c4ad 100644 Binary files a/pruef-protokoll-auf.png and b/pruef-protokoll-auf.png differ diff --git a/pruef-protokoll-zu.png b/pruef-protokoll-zu.png index 4d67dde1..23bc0007 100644 Binary files a/pruef-protokoll-zu.png and b/pruef-protokoll-zu.png differ diff --git a/pruef-schulung.png b/pruef-schulung.png index 13d4ee4e..65050eca 100644 Binary files a/pruef-schulung.png and b/pruef-schulung.png differ diff --git a/pruef-scout-zuteilung.png b/pruef-scout-zuteilung.png index eeac0895..edf2633b 100644 Binary files a/pruef-scout-zuteilung.png and b/pruef-scout-zuteilung.png differ diff --git a/pruef-sprung.png b/pruef-sprung.png index ed402e24..542c4e0a 100644 Binary files a/pruef-sprung.png and b/pruef-sprung.png differ diff --git a/pruef-start-computer.png b/pruef-start-computer.png index b017eaf3..929cc7a1 100644 Binary files a/pruef-start-computer.png and b/pruef-start-computer.png differ diff --git a/pruef-start-creator.png b/pruef-start-creator.png index 6acff491..a5597054 100644 Binary files a/pruef-start-creator.png and b/pruef-start-creator.png differ diff --git a/pruef-start-handy.png b/pruef-start-handy.png index 6fb23d7d..2fb688df 100644 Binary files a/pruef-start-handy.png and b/pruef-start-handy.png differ diff --git a/pruef-team.png b/pruef-team.png index 2b4556d6..922e490f 100644 Binary files a/pruef-team.png and b/pruef-team.png differ diff --git a/pruef-uebersicht-computer.png b/pruef-uebersicht-computer.png index 61c699da..70a6bb03 100644 Binary files a/pruef-uebersicht-computer.png and b/pruef-uebersicht-computer.png differ diff --git a/pruef-uebersicht-creator.png b/pruef-uebersicht-creator.png index 8eddd2ff..bd64f501 100644 Binary files a/pruef-uebersicht-creator.png and b/pruef-uebersicht-creator.png differ diff --git a/pruef-uebersicht-handy.png b/pruef-uebersicht-handy.png index 6bb68643..fd5655c6 100644 Binary files a/pruef-uebersicht-handy.png and b/pruef-uebersicht-handy.png differ diff --git a/pruef-zustand.png b/pruef-zustand.png index 077c6581..90bb5f69 100644 Binary files a/pruef-zustand.png and b/pruef-zustand.png differ diff --git a/server/pruef-scout-zuteilung.mjs b/server/pruef-scout-zuteilung.mjs index f6293cc5..03e4ba42 100644 --- a/server/pruef-scout-zuteilung.mjs +++ b/server/pruef-scout-zuteilung.mjs @@ -150,16 +150,41 @@ console.log("\n=== Unsinnige Zuteilungen"); { const a = await setzen(idPat, idBen, kDogi); ok(a.status === 400, `Scout an Scout geht nicht (${a.status})`); + /* SEIT 02.09.2026 ERLAUBT: "ich will die Rollen, welcher Scout welchem + Manager ODER DOGFATHER gehoert, wie es bei den Creator ist." + + Vorher wurde das abgewiesen mit der Begruendung, DogFather sehe + ohnehin alles -- der Eintrag bewirke also nichts. Das war zu eng + gedacht: Er haelt die ZUSTAENDIGKEIT fest, und das ist genau die + Frage "wen frage ich?". Bei den Creatorn steht DogFather aus + demselben Grund seit dem 31.08. in der Auswahl. + + Geprueft wird deshalb beides: dass es geht -- und dass es an den + RECHTEN nichts aendert. */ const b = await setzen(idPat, idDogi, kDogi); - ok(b.status === 400, - `Scout an DogFather geht nicht (${b.status}) – er sieht ohnehin alles, ` - + "und ein Eintrag ohne Wirkung wird spaeter fuer eine Wirkung gehalten"); + ok(b.status === 200, `Scout an DogFather geht jetzt (${b.status})`); const c = await setzen(idTili, idMara, kDogi); ok(c.status === 404, `einen Creator kann man nicht zuteilen (${c.status})`); const e = await setzen(999999, idMara, kDogi); ok(e.status === 404, `eine erfundene Nummer ebenfalls nicht (${e.status})`); } +/* Eine Zuteilung an DogFather darf NIEMANDEM mehr zeigen. Das ist der + Unterschied zwischen "haelt die Zustaendigkeit fest" und "vergibt + Sichtbarkeit" -- und wenn er je verschwimmt, faellt es hier auf. */ +console.log("\n=== Eine Zuteilung an DogFather vergibt keine Sicht"); +{ + const l = await holen("/workspace/api/leads", kMara); + const a = await holen("/workspace/api/aufgaben", kMara); + ok((l.daten?.leads || []).length === 0 && (a.daten?.aufgaben || []).length === 0, + `Mara sieht dadurch nichts (${(l.daten?.leads || []).length} Leads, ` + + `${(a.daten?.aufgaben || []).length} Aufgaben)`); + const lN = await holen("/workspace/api/leads", kNina); + ok((lN.daten?.leads || []).length === 0, "und Nina auch nicht"); + /* Zuruecksetzen, damit die Kette darunter von vorn beginnt. */ + await setzen(idPat, null, kDogi); +} + /* ================================================================ 2. DIE KETTE: Manager -> Scout -> dessen Creator ================================================================ */ @@ -307,9 +332,12 @@ ok(r.personen === 7, `aufgeklappt stehen alle sieben Personen da (${r.personen}) – ` + "sonst misst die Pruefung eine zugeklappte Liste"); ok(r.wahlen.length === 2, `zwei Scouts, zwei Auswahlfelder (${r.wahlen.length})`); -ok(/direkt bei DogFather/.test(r.wahlen[0]?.erste || ""), - `der Leer-Wert heisst, was er ist ("${r.wahlen[0]?.erste}") – ` - + '"niemand" waere falsch, ein Scout ohne Manager haengt an dir'); +ok(/niemand/.test(r.wahlen[0]?.erste || ""), + `der Leer-Wert heisst wie bei den Creatorn ("${r.wahlen[0]?.erste}")`); +/* DogFather MUSS in der Auswahl stehen -- das war der Wunsch. Und zwar + ohne die doppelte Klammer "Dogfather (DogFather)". */ +ok(r.wahlen[0]?.anzahl >= 4, + `Manager UND DogFather stehen zur Wahl (${r.wahlen[0]?.anzahl} Eintraege)`); ok(r.wahlen.some((w) => w.wert === String(idNina)), "die bestehende Zuteilung ist vorausgewaehlt"); ok(r.texte.some((t) => /gehört zu Nina/.test(t)), diff --git a/server/workspace-personen.js b/server/workspace-personen.js index 8044538d..2cb4481f 100644 --- a/server/workspace-personen.js +++ b/server/workspace-personen.js @@ -225,12 +225,28 @@ personenRouter.put("/workspace/api/verwaltung/scout-zuteilung/:id", gleicheHerku if (!Number.isInteger(z) || z < 1) return res.status(400).json({ fehler: "Ungültige Auswahl." }); const manager = db().prepare( "SELECT id, name, rolle FROM personen WHERE id = ? AND aktiv = 1").get(z); - /* NUR ein Manager. Ein Scout unter einem Scout waere eine Ordnung, - die es nicht gibt; ein Scout unter DogFather ist ueberfluessig, da - er ohnehin alles sieht -- und ein Eintrag, der nichts bewirkt, - wird beim naechsten Mal fuer eine Wirkung gehalten. */ - if (!manager || manager.rolle !== "manager") { - return res.status(400).json({ fehler: "Zuteilen kann man nur an einen aktiven Manager." }); + /* MANAGER ODER DOGFATHER -- wie bei den Creatorn (02.09.2026: + "ich will die Rollen, welcher Scout welchem Manager oder DogFather + gehoert, wie es bei den Creator ist"). + + Ein Scout unter einem Scout bleibt ausgeschlossen: Das waere eine + Ordnung, die es nicht gibt. Ein Creator kann ohnehin niemanden + fuehren. + + WICHTIG ZUM VERSTAENDNIS -- die beiden Faelle bewirken + Verschiedenes, und das ist Absicht: + MANAGER Der Eintrag entscheidet ueber SICHTBARKEIT. Er sieht + danach die Leads dieses Scouts und dessen Creator. + DOGFATHER Der Eintrag sagt nur, WER zustaendig ist. An den + Rechten aendert er nichts -- DogFather sieht ohnehin + alles. + Genau so ist es bei "Betreut von" der Creator auch. Ein Eintrag, + der die Zustaendigkeit festhaelt, ist kein Eintrag ohne Wirkung: + Er beantwortet die Frage "wen frage ich?". */ + if (!manager || !["manager", "admin"].includes(manager.rolle)) { + return res.status(400).json({ + fehler: "Zuteilen kann man nur an einen aktiven Manager oder DogFather.", + }); } scoutZuteilungSetzen(id, z, req.person.id); diff --git a/workspace/assets/js/personen.js b/workspace/assets/js/personen.js index b7b445b5..772da462 100644 --- a/workspace/assets/js/personen.js +++ b/workspace/assets/js/personen.js @@ -222,7 +222,14 @@ Und nur, wenn es ueberhaupt einen Manager gibt -- eine leere Auswahl sieht aus wie ein Fehler. */ - const managerListe = betreuerListe.filter((x) => x.rolle === 'manager'); + /* Manager UND DogFather -- genau wie bei "Betreut von" der Creator + (Wunsch 02.09.2026). Die beiden bewirken Verschiedenes: Bei einem + Manager entscheidet der Eintrag ueber die Sichtbarkeit, bei + DogFather haelt er nur die Zustaendigkeit fest. Beides ist eine + Antwort auf "wen frage ich?" -- und genau darum geht es in dieser + Liste. */ + const managerListe = betreuerListe.filter( + (x) => x.rolle === 'manager' || x.rolle === 'admin'); if (p.rolle === 'scout' && ich.rolle === 'admin' && managerListe.length) { const b = el('div', 'betreuung'); const s2 = el('label', 'betreuung__schild', 'Gehört zu'); @@ -231,12 +238,22 @@ w2.id = 'manager-' + p.id; const leer2 = document.createElement('option'); leer2.value = ''; - /* Nicht "— niemand —": Ein Scout ohne Manager ist nicht - unbetreut, er haengt direkt an dir. Das ist ein Zustand, kein - Mangel. */ - leer2.textContent = '— direkt bei DogFather —'; + /* Wie bei den Creatorn: "niemand" heisst wirklich niemand. + Vorher stand hier "— direkt bei DogFather —" -- das sah aus wie + eine Zuordnung und war keine, und derselbe Fehler war bei den + Creatorn schon einmal behoben worden. DogFather steht jetzt als + echte Person in der Liste, gleichrangig neben den Managern. */ + leer2.textContent = '— niemand —'; w2.append(leer2); - for (const m of managerListe) w2.append(new Option(m.name, String(m.id))); + for (const m of managerListe) { + /* Dieselbe Regel wie bei den Creatorn: Die Rolle in Klammern nur + dann, wenn sie etwas hinzufuegt -- "Dogfather (DogFather)" + waere zweimal dasselbe Wort. */ + const rn = ROLLENNAME[m.rolle] || m.rolle || ''; + const gl = (a, b2) => + a.trim().toLowerCase().replace(/\s+/g, '') === b2.trim().toLowerCase().replace(/\s+/g, ''); + w2.append(new Option(gl(m.name, rn) ? m.name : `${m.name} (${rn})`, String(m.id))); + } w2.value = p.manager_id ? String(p.manager_id) : ''; w2.addEventListener('change', async () => { w2.disabled = true; melde('');