Aufgaben an Menschen: zuteilen, annehmen, ablehnen, bewerten
Auftrag vom 21.09.2026, Abschnitte 2 bis 5 -- der Serverteil.
DREI ARTEN ZU VERTEILEN, und der Unterschied zwischen den letzten
beiden ist der ganze Punkt:
einzeln eine Person, sie macht es
mehrere mehrere Personen, JEDE macht ihren Teil
pool mehrere sehen es, EINE nimmt es -- danach ist es fuer die
anderen weg, damit niemand doppelt arbeitet
EINE EIGENE TABELLE, KEINE SPALTEN AN DER AUFGABE. Abschnitt 4
verlangt ausdruecklich: *"Die Aufgabe muss in der Auswertung auf die
einzelnen zugewiesenen Personen aufgeteilt werden"* -- und gleichzeitig
soll "die urspruengliche gemeinsame Aufgabe ihre uebergeordnete
Struktur" behalten. Eine Aufgabe hat EINEN Titel und EINE Frist, aber
je Mensch einen eigenen Stand, einen eigenen Grund beim Ablehnen, ein
eigenes Erledigt-Datum und eine eigene Rueckmeldung. Das in Spalten zu
pressen hiesse, dieselbe Aufgabe mehrfach anzulegen.
`aufgaben.status` bleibt daneben unberuehrt. Zwei Ebenen, weil es zwei
Fragen sind: "Wie steht die Aufgabe?" und "Wie steht sie bei IHM?" Ein
einziges Feld koennte bei drei Leuten nicht gleichzeitig "angenommen"
und "abgelehnt" sein.
DER WICHTIGSTE EINZELNE HANDGRIFF -- und er steht nicht im Auftrag:
Wer eine Aufgabe BEKOMMEN hat, sieht sie jetzt immer. Bei "mehrere"
und "pool" bleibt `verantwortlich_id` leer, und die alten Sichtregeln
fragen genau danach. Ohne die Erweiterung stuende eine Aufgabe im
Resuemee der Leitung und waere fuer den, der sie machen soll,
unsichtbar -- der unangenehmste denkbare Fehler in einem
Aufgabensystem, und man sieht ihn nirgends. Die Erweiterung ist ein
ODER, kein UND: Sie erweitert die Sicht, die Haustrennung darueber
bleibt ein UND und wirkt weiter.
WAS SONST NOCH ENTSCHIEDEN WURDE, mit Grund im Code:
- Ablehnen braucht eine Begruendung (mind. 3 Zeichen). Ein leeres
Nein ist fuer den, der verteilt hat, keine Information -- er muss
dann nachfragen, und genau das sollte die Nachricht ersparen.
- "Verbesserungsmoeglichkeiten" braucht einen Text. Ein leeres
"kann besser" sagt nichts ausser, dass jemand unzufrieden war.
- Bewertet wird erst, wenn jemand FERTIG ist. Eine Rueckmeldung auf
etwas, das noch laeuft, ist keine Bewertung, sondern eine
Einmischung.
- Beim Pool wird VOR dem Schreiben gefragt, ob schon jemand zugesagt
hat -- sonst nehmen zwei im selben Moment dieselbe Aufgabe und
beide sehen "hat geklappt".
- Wer schon geantwortet hat, behaelt seinen Stand, wenn die Aufgabe
noch einmal gespeichert wird. Sonst muesste er ohne Grund erneut
zusagen.
- Wer nicht mehr dabei ist, faellt raus -- aber nur, solange er noch
nicht geantwortet hat. Jemandem eine angenommene Aufgabe
wegzunehmen, ohne dass er es erfaehrt, waere die unangenehmste Art,
Arbeit zu verlieren.
- "pool" mit einer Person wird "einzeln". Ein Pool aus einem
Menschen ist keiner.
`verantwortlich_id` bleibt und wird mitgefuehrt (einzeln = die Person,
pool = der Uebernehmer, mehrere = leer): Brett, Startseite und
Uebersicht gruppieren danach. Drei gewachsene Ansichten gleichzeitig
umzubauen waere der groessere Eingriff -- und im haeufigsten Fall
sagen beide dasselbe.
KEIN CHECK an der nachgetragenen Spalte `verteilart`, mit Absicht: Ein
CHECK auf einer nachgetragenen Spalte hiesse, die Tabelle neu zu bauen
-- der Weg, der in diesem Haus am 11.09. und heute schon Spalten
gekostet hat. Geprueft wird beim Schreiben.
pruef-zuteilung.mjs, 48 Aussagen -- ein Arbeitstag durchgespielt.
Ein Fehlschlag beim ersten Lauf, und er war lehrreich: "Cem hat keinen
eigenen Stand" schlug fehl, weil Cem die Aufgabe gar nicht SIEHT
(`null?.x` ist `undefined`, nicht `null`). Die Zusicherung konnte
"sieht sie nicht" und "sieht sie ohne Stand" nicht unterscheiden --
also pruefte sie beides nicht richtig. Dass er sie nicht sieht, ist
genau Abschnitt 1: *"Eine Modi darf nicht automatisch die
vollstaendige Aufgabenuebersicht aller anderen Modis sehen."* Beide
Faelle stehen jetzt einzeln da, mit einer Gegenprobe, dass seine Liste
ueberhaupt laedt.
Nachbarn gruen: pruef-verteilen 16/0, pruef-aufgabenbrett 49/0,
pruef-umstellung 18/0.
This commit is contained in:
@@ -28,6 +28,8 @@ const TEXT_MAX = 4000;
|
||||
|
||||
const jetzt = () => new Date().toISOString();
|
||||
|
||||
import { zuteilen, mitZuteilung } from "./workspace-zuteilung.js";
|
||||
|
||||
/* ---------- Schranke ---------------------------------------------------- */
|
||||
|
||||
function angemeldet(req, res, next) {
|
||||
@@ -67,7 +69,8 @@ aufgabenRouter.use("/workspace/api", angemeldet);
|
||||
DogFather und die Modis gehen unveraendert durch.
|
||||
===================================================================== */
|
||||
export function sichtbar(person) {
|
||||
const regel = sichtbarRoh(person);
|
||||
const roh = sichtbarRoh(person);
|
||||
const regel = mitZugeteilten(roh, person);
|
||||
if (!regel) return regel;
|
||||
/* AUF DER ADRESSE VON TEAM DOGI NUR TEAM DOGI (10.09.2026).
|
||||
|
||||
@@ -96,6 +99,29 @@ export function sichtbar(person) {
|
||||
};
|
||||
}
|
||||
|
||||
/** WER EINE AUFGABE BEKOMMEN HAT, SIEHT SIE -- immer (21.09.2026).
|
||||
*
|
||||
* Ohne das koennte man jemandem eine Aufgabe geben, die er nie zu
|
||||
* Gesicht bekommt: Bei "mehrere" und "pool" bleibt
|
||||
* `verantwortlich_id` leer, und die alten Regeln fragen genau danach.
|
||||
* Die Aufgabe stuende dann im Resuemee der Leitung und waere fuer den
|
||||
* Menschen, der sie machen soll, unsichtbar -- der unangenehmste
|
||||
* denkbare Fehler in einem Aufgabensystem.
|
||||
*
|
||||
* ODER, NICHT UND: Das erweitert die Sicht, es engt sie nicht ein.
|
||||
* Die Haustrennung darueber bleibt ein UND und wirkt weiterhin. */
|
||||
function mitZugeteilten(regel, person) {
|
||||
if (!regel || !person?.id) return regel;
|
||||
/* Wer ohnehin alles sieht, braucht die Erweiterung nicht -- und eine
|
||||
Bedingung, die immer wahr ist, macht die Abfrage nur langsamer. */
|
||||
if (regel.wo === "1=1") return regel;
|
||||
return {
|
||||
wo: `(${regel.wo} OR EXISTS (SELECT 1 FROM aufgaben_zuteilung z`
|
||||
+ ` WHERE z.aufgabe_id = a.id AND z.person_id = ?))`,
|
||||
werte: [...regel.werte, person.id],
|
||||
};
|
||||
}
|
||||
|
||||
/* Liefert WHERE-Bedingung und Werte, passend zur Rolle. An genau einer
|
||||
Stelle definiert, damit keine Abfrage sie versehentlich vergisst. */
|
||||
function sichtbarRoh(person) {
|
||||
@@ -222,6 +248,11 @@ const SPALTEN = `
|
||||
das lesen -- ein Nachladen je Zeile wäre bei zwanzig abgebrochenen
|
||||
Aufgaben zwanzig Anfragen. */
|
||||
a.abbruch_grund, a.abgebrochen_am, a.status_vorher,
|
||||
/* Wie sie verteilt wurde (21.09.2026) -- ohne das koennte die
|
||||
Oberflaeche "mehrere" und "pool" nicht unterscheiden, und genau
|
||||
daran haengt, ob eine uebernommene Aufgabe fuer die anderen noch
|
||||
offen ist. */
|
||||
a.verteilart,
|
||||
/* Die Vorlage, aus der sie entstanden ist (09.09.2026) -- damit das
|
||||
Vorlagenbrett zeigen kann, was schon geholt wurde. */
|
||||
a.vorlage,
|
||||
@@ -301,6 +332,13 @@ aufgabenRouter.get("/workspace/api/aufgaben", (req, res) => {
|
||||
sichtbare. */
|
||||
for (const r of reihen) r.darf_aendern = darfAendern(req.person, r);
|
||||
|
||||
/* WER HAT DIESE AUFGABE -- UND WIE STEHT SIE BEI IHM (21.09.2026).
|
||||
In EINER Abfrage fuer alle Zeilen; eine je Aufgabe waeren bei
|
||||
vierzig Karten vierzig Abfragen. Dazu je Zeile der eigene Stand
|
||||
und, beim Pool, wer sie schon genommen hat -- damit niemand
|
||||
doppelt arbeitet. */
|
||||
mitZuteilung(reihen, req.person);
|
||||
|
||||
res.json({
|
||||
aufgaben: reihen,
|
||||
/* Die Aufwandsstufen kommen mit: Eine zweite Liste im Browser
|
||||
@@ -772,11 +810,20 @@ aufgabenRouter.post("/workspace/api/aufgaben", gleicheHerkunft, (req, res) => {
|
||||
aus.frist ?? null, aus.kategorie ?? null, aus.kanal ?? null,
|
||||
jetzt(), req.person.id);
|
||||
|
||||
/* AN MENSCHEN VERTEILEN (21.09.2026, Abschnitt 3).
|
||||
Nur wer verteilen darf -- sonst koennte sich jemand selbst eine
|
||||
Aufgabe anlegen und sie dem halben Team zuschieben. */
|
||||
let verteilt = null;
|
||||
if (darfAufgabenVerteilen(req.person) && Array.isArray(req.body?.zuteilung)) {
|
||||
verteilt = zuteilen(Number(lastInsertRowid), req.body.zuteilung,
|
||||
req.body?.verteilart, req.person.id);
|
||||
}
|
||||
|
||||
protokolliere("aufgabe_angelegt", {
|
||||
personId: req.person.id, rolle: req.person.rolle, ip: echteIp(req),
|
||||
detail: `#${lastInsertRowid} ${aus.titel}`.slice(0, 120),
|
||||
});
|
||||
res.status(201).json({ id: Number(lastInsertRowid) });
|
||||
res.status(201).json({ id: Number(lastInsertRowid), zuteilung: verteilt });
|
||||
} catch (fehler) {
|
||||
console.error("[workspace] Aufgabe anlegen:", fehler?.message);
|
||||
res.status(503).json({ fehler: "nicht_verfuegbar" });
|
||||
@@ -818,6 +865,18 @@ aufgabenRouter.patch("/workspace/api/aufgaben/:id", gleicheHerkunft, (req, res)
|
||||
|
||||
db().prepare(`UPDATE aufgaben SET ${setz.join(", ")} WHERE id = ?`).run(...daten, id);
|
||||
|
||||
/* DIE ZUTEILUNG MITAENDERN (21.09.2026). Wer eine Aufgabe
|
||||
bearbeitet und dabei die Leute wechselt, meint genau das -- eine
|
||||
Aenderung, die nur den Titel mitnimmt und die Zuteilung stehen
|
||||
laesst, waere eine halbe Aenderung ohne Hinweis.
|
||||
|
||||
`zuteilen` behaelt dabei den Stand derer, die schon geantwortet
|
||||
haben: Ein zweites Speichern darf aus einem "angenommen" kein
|
||||
"offen" machen. */
|
||||
if (darfAufgabenVerteilen(req.person) && Array.isArray(req.body?.zuteilung)) {
|
||||
zuteilen(id, req.body.zuteilung, req.body?.verteilart, req.person.id);
|
||||
}
|
||||
|
||||
protokolliere("aufgabe_geaendert", {
|
||||
personId: req.person.id, rolle: req.person.rolle, ip: echteIp(req),
|
||||
detail: `#${id} ${felder.join(",")}`.slice(0, 120),
|
||||
|
||||
Reference in New Issue
Block a user