Modis verteilen Aufgaben statt sie zu bekommen -- und Angebote zur Entscheidung

Die drei Beurteilungs-Bereiche liefen bisher in die falsche Richtung: Sie
bewerteten die Modis. Filipe: "die modis sind ja da um mir zu helfen."
Also umgedreht.

WAS SICH GEDREHT HAT
- Alle 101 Punkte sind jetzt Beobachtungen ueber den Stream, nicht
  Pflichten des Modis ("Der Ton blieb verstaendlich" statt "Ton geprueft").
- Nur der Modi selbst drueckt auf seiner Liste. Wer sonst darauf zeigt,
  bekommt 403 und den Weg zur Team-Lage -- bewerten wird hier niemand.
- "Verbessern" landet als Eingang bei DogFather. Ein Klick macht daraus
  eine Aufgabe mit dem Satz des Modis im Text, oder eine Absage mit Grund.
  Beides schreibt eine Nachricht zurueck, damit der Modi sieht: angekommen.

ANGEBOTE
Neuer Bereich, in dem Modis planen und vorschlagen: Nutzen und Aufwand
statt Bewertung und Dringlichkeit, dazu ein Feld "was DogFather danach
tun muss". Wird ein Angebot angenommen, entstehen zwei Aufgaben -- eine
beim Modi zum Umsetzen, eine bei DogFather aus genau diesem Feld.

GEMESSEN
pruef-modi-checkliste  59 Pruefungen, 0 Fehler (neu geschrieben)
pruef-rollen          245 statt 244 -- der Zuwachs ist die neue
                      Angebote-Kachel, alle 11 Modi-Kacheln kommen an
pruef-modi-ideen       30, pruef-modi-verborgen 75, pruef-bereiche-lesend: gruen

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-10 12:52:45 +02:00
co-authored by Claude Opus 5
parent 6122ea6972
commit 05f262eb61
31 changed files with 1583 additions and 630 deletions
+63 -7
View File
@@ -169,6 +169,47 @@ export const BEREICHE = {
ohneCreatorBezug: true,
},
/* =====================================================================
DIE ANGEBOTE (10.09.2026, Wunsch Filipe)
*"ich brauch auch noch kategorien wie, angebote, wo die modis
sachen planen und auch entscheiden was ich machen muss wenn das und
das erledigt wird."*
Ein Modi schlaegt etwas vor -- eine Aktion, ein Format, eine Regel
-- und schreibt dazu, was DogFather dafuer tun muesste. DogFather
oder VanVan nimmt an oder lehnt ab; bei Annahme entstehen die
Aufgaben. Entschieden wird in der Team-Lage, an derselben Stelle
wie die uebrigen Rueckmeldungen: EIN Eingang, nicht zwei.
DIE ZWEI ZAHLEN SIND UMBENANNT, nicht neu erfunden: `bewertung`
(1-5) heisst hier NUTZEN, `dringlichkeit` heisst AUFWAND. Beide
Felder gibt es laengst; sie mit neuen Namen zu belegen ist besser,
als zwei weitere Spalten anzulegen, die dasselbe koennen. Damit
die Oberflaeche nicht "Dringlichkeit" ueber den Aufwand schreibt,
stehen die Namen hier.
KEIN `fuerAlle`, wie beim Ideen-Board: Wer die Angebote sieht,
entscheidet dieselbe Regel wie ueberall. */
angebote: {
name: "Angebote",
arten: {
aktion: "Aktion",
format: "Format",
regel: "Regel",
technik: "Technik",
sonstiges: "Sonstiges",
},
ober: "Vorschläge",
bewertung: true,
bewertungName: "Nutzen",
dringlichkeit: true,
dringlichkeitName: "Aufwand",
einsatzFeld: true,
einsatzName: "Was DogFather dafür tun müsste",
ohneCreatorBezug: true,
},
agentur: {
name: "Agentur",
arten: {
@@ -235,10 +276,12 @@ bereicheRouter.use("/workspace/api/bereich", angemeldet);
ZWEI SCHLOESSER, ABSICHTLICH: Hier haengt der ZUGANG zur Seite,
sichtbar() haengt die Bedingung an die ZEILEN. Faellt eines weg,
haelt das andere. */
bereicheRouter.use("/workspace/api/bereich/ideen", (req, res, next) => {
if (siehtModis(req.person)) return next();
return res.status(404).json({ fehler: "nicht_gefunden" });
});
for (const geschuetzt of ["ideen", "angebote"]) {
bereicheRouter.use(`/workspace/api/bereich/${geschuetzt}`, (req, res, next) => {
if (siehtModis(req.person)) return next();
return res.status(404).json({ fehler: "nicht_gefunden" });
});
}
/* ---------------------------------------------------------------------
UND UMGEKEHRT: Ein Modi kommt nur in SEINE Bereiche.
@@ -457,6 +500,9 @@ const SPALTEN = `
e.hook, e.format, e.saeule_id, e.geplant,
e.event_ende, e.event_aufgaben, e.event_regeln,
e.creator_extern,
/* Was DogFather dafuer tun muesste -- nur bei den Angeboten
gefuellt, siehe BEREICHE.angebote. */
e.einsatz,
${externSql("pc.name", "e.creator_extern")} AS creator_name,
pe.name AS erstellt_name,
(SELECT name FROM content_saeulen s WHERE s.id = e.saeule_id) AS saeule_name,
@@ -630,6 +676,15 @@ function pruefe(bereich, körper, { neu }) {
Konto; sichtbar bleibt er ueber erstellt_von (siehe sichtbar()). */
externPruefen(körper, aus, "creator", fehler);
/* Das Einsatz-Feld gibt es nur in Bereichen, die es kennen. Ein
Aufruf an der Oberflaeche vorbei soll nicht in jedem Bereich eine
Spalte fuellen koennen, die dort nichts bedeutet. */
if (einstellung.einsatzFeld && körper.einsatz !== undefined) {
const t = String(körper.einsatz ?? "").trim();
if (t.length > TEXT_MAX) fehler.push("Der Einsatz ist zu lang.");
else aus.einsatz = t || null;
}
/* Ein Agentur-Eintrag gehoert NIEMANDEM einzeln (07.09.2026).
Er gilt fuer alle, und genau deshalb sieht ihn auch jeder (siehe
@@ -704,13 +759,14 @@ bereicheRouter.post("/workspace/api/bereich/:bereich", gleicheHerkunft, (req, re
INSERT INTO eintraege
(bereich, art, titel, text, datum, bewertung, dringlichkeit, status,
creator_id, creator_extern, erstellt, erstellt_von, hook, format, saeule_id, geplant,
event_ende, event_aufgaben, event_regeln)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(
event_ende, event_aufgaben, event_regeln, einsatz)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(
bereich, aus.art, aus.titel, aus.text ?? null, aus.datum,
aus.bewertung ?? null, aus.dringlichkeit ?? "mittel", aus.status ?? "offen",
aus.creator_id ?? null, aus.creator_extern ?? null, jetzt(), req.person.id,
aus.hook ?? null, aus.format ?? null, aus.saeule_id ?? null, aus.geplant ?? null,
aus.event_ende ?? null, aus.event_aufgaben ?? null, aus.event_regeln ?? null);
aus.event_ende ?? null, aus.event_aufgaben ?? null, aus.event_regeln ?? null,
aus.einsatz ?? null);
protokolliere("eintrag_angelegt", {
personId: req.person.id, rolle: req.person.rolle, ip: echteIp(req),