werkator/jvm build succeeded after 08:15
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>
72 lines
4.7 KiB
Markdown
72 lines
4.7 KiB
Markdown
# 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.
|