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

72 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.