Files
claude-codeandmhoennig 4356eb00ca
werkator/jvm build succeeded after 08:15
Erinnerungszeit je Konto einstellbar statt fest um 20:00 (#10)
Die Arbeitserinnerung kam bis hierher ausschließlich um 20:00 Ortszeit des Geräts und wurde bis 22:00 nachgeholt; beide Zeiten standen als Konstanten in `ReminderWindow`. Der Beginn ist jetzt je Konto einstellbar, das Nachholfenster leitet sich daraus ab.

## Entscheidungen

- **Kontoeinstellung, nicht Geräteeinstellung.** Der Ein-/Ausschalter für Push bleibt pro Gerät; die Uhrzeit gilt für alle Geräte desselben Kontos und steht neben Sprache und Arbeitstracker im gemeinsamen Formular mit Versionsprüfung.
- **Viertelstundenschritte zwischen 06:00 und 23:00**, Vorgabe 20:00. Ein Konto, das nichts ändert, wird unverändert erinnert.
- **Nachholen bleibt zwei Stunden, endet aber spätestens um Mitternacht.** Eine Erinnerung nennt das Datum, um das es geht, und darf nicht in den Folgetag wandern: bei 23:00 bleibt eine Stunde statt zwei. Push-TTL und `reminder_delivery.expires_at` folgen demselben Ende.
- Montag bis Freitag und die Prüfung unmittelbar vor dem Versand bleiben unverändert.

`ReminderWindow` hält Vorgabe, Grenzen, Schrittweite und Nachholdauer an einer Stelle. Dienst, Spaltenbedingung und `TimePicker` prüfen jeweils dagegen. Ein gespeicherter Wert außerhalb der angebotenen Zeiten hält die Erinnerung zurück, statt eine Stunde zu raten.

## Migration

`werkjournal:reminder-time` fügt `app_user.reminder_minute` mit `DEFAULT 1200 NOT NULL` hinzu; bestehende Zeilen behalten damit ihren Zeitplan, keine andere Spalte wird angefasst.

## Nachweise

Branch-Pipeline lokal grün (`tools/ci-jvm --without-firefox`): 25 Browser-Szenarien, 14 Push-Service-Szenarien, 22 Frontend-Tests, 68 Operations-Tests, JVM-Smoke PASS.

- `ReminderWindowTest`: Vorgabe erzeugt dasselbe Fenster wie zuvor; eine gewählte Zeit verschiebt Beginn und Ende; eine späte Zeit behält ihr Datum und verliert Nachholzeit an Mitternacht.
- `SettingsServiceTest`, `ReminderTimeMigrationTest`: Speichern, Ablehnen und der erhaltende Migrationsschritt mit befülltem Vorgängerstand.
- WJ-073/WJ-074 mit echtem Scheduler, Warteschlange und Testtransport; WJ-075 im Browser für Formular, Gerätehinweis und abgelehnte Eingabe.
- `tests/frontend/push-settings.test.cjs`: der Gerätehinweis nennt die übergebene Zeit statt einer festen Stunde.

Details: `docs/implementation/reminder-time.md`.

## Nebenbei

Die Erhaltungsprüfung in `AccountDeletionProofsTest` verglich ganze Zeilen und schlug deshalb bei jedem additiven Changeset an. Sie vergleicht jetzt die Spalten, die es vorher gab, und prüft die Zeilenzahl — die Absicht bleibt, ein zusätzliches Feld sieht nicht mehr wie eine Datenänderung aus.

## Offen

`docs/plans/ui-refresh-selectors.md` hat die neuen Selektoren bekommen; seine `BS:`-Zeilennummern und die Tag-Liste in Abschnitt 0 waren schon vorher veraltet und sind hier nicht nachgezogen.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: mhoennig <michael@hoennig.de>
Reviewed-on: #10
Co-authored-by: claude-code <4+claude-code@noreply.git.javagil.de>
2026-10-21 13:47:23 +02:00

4.7 KiB
Raw Permalink Blame History

Einstellbare Erinnerungszeit

Die Arbeitserinnerung kam bis hierher ausschließlich um 20:00 Ortszeit des Geräts und wurde bis 22:00 nachgeholt. Beide Zeiten standen als Konstanten in ReminderWindow. Diese Umsetzung macht den Beginn je Konto einstellbar und leitet das Nachholfenster daraus ab. Entschieden ist die Zeit damit eine Kontoeinstellung, nicht eine Geräteeinstellung: der Ein-/Ausschalter für Push bleibt pro Gerät, die Uhrzeit gilt für alle Geräte desselben Kontos und steht neben Sprache und Arbeitstracker im gemeinsamen Formular mit Versionsprüfung.

Angebotene Zeiten

Viertelstundenschritte zwischen 06:00 und 23:00. Die Vorgabe ist 20:00, also der bisherige feste Zeitplan: ein Konto, das nichts ändert, wird unverändert erinnert. Montag bis Freitag bleibt unverändert, ebenso die Prüfung unmittelbar vor dem Versand.

ReminderWindow hält Vorgabe, Grenzen, Schrittweite und Nachholdauer an einer Stelle und ist die einzige Quelle für das, was gültig ist. permits entscheidet; startOf/minuteOf wandeln zwischen der gespeicherten Minute des Tages und LocalTime. Dienst, Datenbank und Oberfläche prüfen jeweils selbst: SettingsService.save lehnt eine andere Zeit mit IllegalArgumentException ab, die Spalte app_user.reminder_minute trägt CHECK (reminder_minute BETWEEN 360 AND 1380 AND MOD(reminder_minute, 15) = 0), und die Oberfläche zeigt eine abgelehnte Eingabe am Feld an, ohne zu speichern.

Nachholen und Datum

Das Nachholfenster bleibt zwei Stunden, endet aber spätestens um Mitternacht. Eine Erinnerung nennt das Datum, um das es geht, und darf nicht in den Folgetag wandern: bei 23:00 bleibt daher eine Stunde zum Nachholen übrig, nicht zwei. Die TTL der Push-Nachricht und reminder_delivery.expires_at folgen demselben Ende, sodass eine liegengebliebene Zustellung mit dem Fenster verfällt und nicht später an einem anderen Tag ankommt.

Eine während des Tages geänderte Zeit wirkt sofort, weil ReminderEligibility die Fälligkeit unmittelbar vor jedem Versand neu auswertet. Eine bereits als sent vermerkte Erinnerung wird dadurch nicht wiederholt; eine noch offene Zustellung übernimmt das kleinere der beiden Fensterenden. Ein gespeicherter Wert, der nicht zu den angebotenen Zeiten gehört — erreichbar nur, wenn die Spalte unter Umgehung der Anwendung geschrieben würde — hält die Erinnerung zurück, statt eine Stunde zu raten; die Einstellungsseite zeigt in diesem Fall die Vorgabe an, sodass ein Speichern den Wert wieder in Ordnung bringt.

Migration

--changeset werkjournal:reminder-time fügt reminder_minute mit DEFAULT 1200 NOT NULL hinzu. Bestehende Zeilen erhalten damit 20:00, also ihren bisherigen Zeitplan; keine andere Spalte wird angefasst. ReminderTimeMigrationTest migriert einen befüllten Vorgängerstand, prüft, dass Konto und Sprache erhalten bleiben und reminder_minute auf 1200 steht, wiederholt die Migration zweimal und weist nach, dass die Spaltenbedingung Werte außerhalb des Rasters und NULL ablehnt, ohne den gespeicherten Wert zu verändern.

Oberfläche

SettingsView zeigt ein TimePicker unter „Arbeit erfassen“ mit Grenzen und Schrittweite aus ReminderWindow, dazu einen Hinweis auf Werktage, Nachholdauer und Mitternachtsgrenze. Die Zeit wird in der Sprache des Kontos formatiert. Der gerätebezogene Push-Abschnitt nannte den Zeitplan bisher als festen Text („Mo–Fr um 20 Uhr“); er bekommt die gespeicherte Zeit jetzt vom Server formatiert übergeben und wird nach dem Speichern neu aufgebaut, damit beide Angaben nicht auseinanderlaufen.

Nachweise

  • ReminderWindowTest: Vorgabe erzeugt dasselbe Fenster wie zuvor; eine gewählte Zeit verschiebt Beginn und Ende; eine späte Zeit behält ihr Datum und verliert Nachholzeit an Mitternacht; nur die angebotenen Zeiten werden akzeptiert, und gespeicherte Minuten wandeln in beide Richtungen zurück.
  • SettingsServiceTest: ein Konto beginnt bei 20:00, eine gewählte Zeit wird gespeichert und wieder gelesen, abgelehnte Zeiten lassen den gespeicherten Wert unverändert.
  • ReminderTimeMigrationTest: siehe Migration.
  • gherkin/push-tests.feature WJ-073 und WJ-074 mit echtem Scheduler, Warteschlange und Testtransport: zur Vorgabezeit kommt nichts mehr, wenn 17:30 gewählt ist, und die Erinnerung kommt am folgenden Werktag um 17:30 mit vollem Nachholfenster; bei 23:00 endet das Fenster um Mitternacht.
  • gherkin/ux-tests.feature WJ-075 im Browser: 20:00 steht im Formular, 17:30 wird gespeichert und nach erneutem Öffnen wieder angeboten, der Gerätehinweis nennt diese Zeit, und eine Zeit außerhalb der angebotenen wird am Feld abgelehnt, ohne den gespeicherten Wert zu ändern.
  • tests/frontend/push-settings.test.cjs: der Gerätehinweis nennt die übergebene Zeit und keine feste Stunde.