Files
dogfather-universe/server/workspace-termin-regel.js
T
DogFatherGitandClaude Opus 5 d77dd216c5 Ein Termin von-bis belegt jeden Tag dazwischen
Zwei Fehler, nicht einer.

Der sichtbare: Die Kachel stand nur am Anfangstag. Wer im
Monatsraster auf den Mittwoch sah, sah nichts -- obwohl die Aktion
von Montag bis Freitag lief.

Der unsichtbare, und der ist der schlimmere: Der SERVER suchte
Eintraege, deren ANFANG im sichtbaren Fenster liegt. Eine Aktion vom
28.09. bis zum 05.10. kam im Oktober deshalb ueberhaupt nicht an --
nicht "nur am ersten Tag markiert", sondern gar nicht da. Wer im
Oktober plante, sah eine freie Woche, die belegt war. Jetzt
entscheidet die UEBERSCHNEIDUNG, nicht der Anfang.

Gebaut wurde es in nachTag() -- der einzigen Stelle, an der
Eintraege auf Tage verteilt werden. Monat, Woche, Liste und
Zeitstrahl holen sich alle dort; vier Ansichten einzeln
nachzuruesten waeren vier Stellen, an denen die fuenfte vergessen
wird.

Das Ende wird abgeleitet, nicht gepflegt: aus event_ende ODER aus
Uhrzeit plus Dauer. Ein Live von 22:00 ueber vier Stunden endet um
02:00 am naechsten Tag -- das stand bisher nirgends, obwohl die
Zahlen da waren.

Der Tagesdialog filterte selbst auf den Anfangstag. Im Raster war
der Mittwoch markiert, tippte man ihn an, stand da "An diesem Tag
steht nichts." Jetzt fragt er dieselbe Stelle wie das Raster.

pruef-zeitraum.mjs: 16 Pruefungen, beide Fehler einzeln, mit drei
Gegenproben (vor dem Anfang, nach dem Ende, Punkttermin).
pruef-terminregel.mjs weiterhin 35/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-20 19:20:18 +02:00

130 lines
5.7 KiB
JavaScript

/* =====================================================================
WANN EIN ZETTEL EINEN TERMIN HAT (17.09.2026)
EINE Regel, zwei Verwender -- und deshalb eine eigene Datei.
Seit heute zeigt der Kalender, was auf den Brettern steht und einen
Termin hat. Die Bedingung dafuer stand als SQL mitten in
workspace-kalender.js. Sobald die Brettkarte dasselbe sagen soll
("steht im Kalender am 24."), braeuchte sie eine zweite Fassung --
und zwei Fassungen derselben Regel laufen auseinander. Nicht sofort,
sondern beim naechsten Nachschaerfen, und dann zeigt die Karte etwas
anderes als der Kalender. Das ist schlimmer als beides wegzulassen:
Man glaubt der Anzeige ja.
Dieselbe Krankheit gab es im Haus schon zweimal -- die abgeschriebene
Spaltenliste (11.09., drei Spalten samt Inhalt verloren) und die
zweite Artenliste neben ARTNAME (im Kalender, ein BigMatch liess
sich anlegen und war danach unsichtbar).
DIE DATEI IMPORTIERT NICHTS. Muster wie treff-tabellen.js und
workspace-bewerbung-rollen.js: Ein Blatt ohne eigene Importe kann von
ueberall gelesen werden, ohne einen Ring zu bauen -- und ein Ring
aeussert sich in JavaScript nicht als Fehler, sondern als
`undefined` an einer Stelle, an der niemand damit rechnet.
-------------------------------------------------------------------
WARUM GENAU DIESE VIER FAELLE
`eintraege.datum` ist ein PFLICHTFELD und faellt auf HEUTE zurueck,
wenn niemand eins waehlt. Alle Eintraege in den Kalender zu nehmen
hiesse also: jeder je getippte Zettel steht an dem Tag, an dem ihn
jemand getippt hat. Nach einem Monat waere der Kalender ein
Protokoll und kein Plan -- und einer, in dem alles steht, sagt
nichts mehr.
geplant Eine Zusage: "Wird gemacht -- am 24.09." Das ist ein
Termin, den jemand jemandem gegeben hat.
event_ende Ein Zeitraum. Wer ein Ende eintraegt, meint eine
Veranstaltung, keine Notiz.
uhrzeit Wer eine Uhrzeit tippt, meint einen Zeitpunkt.
Niemand traegt aus Versehen 20:00 ein.
datum > heute Der Rueckfall ist IMMER heute oder frueher. Ein Datum
in der Zukunft kann nur Absicht sein.
Der letzte Fall ist der wichtigste und der unauffaelligste: Er
braucht kein neues Feld und keine Umgewoehnung.
===================================================================== */
/** Der massgebliche Tag eines Eintrags -- als SQL-Ausdruck.
*
* Eine Zusage schlaegt das Erfassungsdatum: Wer "am 24." sagt, meint
* den 24., auch wenn der Zettel am 3. entstanden ist. */
export const TERMIN_TAG_SQL = "COALESCE(e.geplant, e.datum)";
/** Der LETZTE Tag, an dem ein Eintrag noch laeuft -- als SQL-Ausdruck.
*
* Gebraucht seit dem 20.09.2026. Filipe: „wenn ich termine eintrage
* mit von bis, will ich dass die ganze zeit markiert ist und nicht
* nur der anfang."
*
* DER FEHLER SASS TIEFER ALS IN DER ANZEIGE. Der Kalender suchte
* Eintraege, deren ANFANG im sichtbaren Fenster liegt. Eine Aktion
* vom 28.09. bis zum 05.10. kam damit im Oktober ueberhaupt nicht an
* -- nicht „nur am ersten Tag markiert", sondern gar nicht da. Wer im
* Oktober plante, sah eine freie Woche, die belegt war.
*
* `MAX` und nicht `COALESCE(e.event_ende, ...)`: Ein Ende, das VOR
* dem Anfang liegt (vertippt, Anfang spaeter verschoben), wuerde
* sonst den Eintrag aus seinem eigenen Zeitraum werfen. Der leere
* Text sortiert vor jedem Datum -- ohne Ende gewinnt damit immer der
* Anfang, und das ist genau richtig. */
export const TERMIN_ENDE_SQL =
"MAX(COALESCE(e.event_ende, ''), COALESCE(e.geplant, e.datum))";
/** Die Bedingung als SQL. Erwartet GENAU EINEN Platzhalter: den
* heutigen Tag in Ortszeit (`heuteLokal()`).
*
* UTC waere hier falsch: Zwischen Mitternacht und zwei Uhr morgens
* liefert es in Deutschland den Vortag, und ein Zettel von heute
* staende dann ploetzlich im Kalender. */
export const TERMIN_BEDINGUNG_SQL = `(
e.geplant IS NOT NULL
OR e.event_ende IS NOT NULL
OR e.uhrzeit IS NOT NULL
OR e.datum > ?
)`;
/** Warum er drinsteht -- als SQL-Ausdruck. Die Reihenfolge ist die
* Rangfolge: Eine Zusage ist mehr als ein Zeitraum, ein Zeitraum mehr
* als eine Uhrzeit. */
export const TERMIN_GRUND_SQL = `CASE
WHEN e.geplant IS NOT NULL THEN 'zugesagt'
WHEN e.event_ende IS NOT NULL THEN 'zeitraum'
WHEN e.uhrzeit IS NOT NULL THEN 'uhrzeit'
ELSE 'termin'
END`;
/** Welche Zustaende NICHT in den Kalender gehoeren.
*
* Ein Kalender zeigt, was ansteht. Was gemacht oder abgelehnt ist,
* gehoert auf sein Brett -- nicht in die Planung der naechsten Woche. */
export const OHNE_ZUSTAENDE = ["erledigt", "abgelehnt"];
/** Dieselbe Frage in JavaScript -- fuer einen einzelnen Eintrag.
*
* Sie wird beim Ausliefern der Brettkarten gebraucht: Dort steht seit
* heute "im Kalender am 24.", und diese Auskunft MUSS dieselbe sein
* wie die des Kalenders. Beide Fassungen stehen deshalb in dieser
* Datei nebeneinander, damit eine Aenderung an der einen die andere
* ins Auge springen laesst -- und pruef-terminregel.mjs weist nach,
* dass sie fuer dieselben Zeilen dasselbe sagen.
*
* @param e Zeile aus `eintraege` (mit geplant, event_ende, uhrzeit,
* datum, status)
* @param heute Heutiger Tag in Ortszeit, "JJJJ-MM-TT"
* @returns {null|{tag, grund}} */
export function terminVon(e, heute) {
if (!e) return null;
if (OHNE_ZUSTAENDE.includes(e.status)) return null;
const grund = e.geplant ? "zugesagt"
: e.event_ende ? "zeitraum"
: e.uhrzeit ? "uhrzeit"
: (e.datum && heute && e.datum > heute) ? "termin"
: null;
if (!grund) return null;
return { tag: e.geplant || e.datum, grund };
}