Reminders: rewording one that was put off with Later clears its sent stamp, so it is announced again #445

Closed
opened 2026-10-01 10:46:45 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading the reminder edit view and checking the result with a unit test against the snapshot.

Related to #238.

Checked again on 2026-10-01 against main at 0a5cad587: still present. The code is now at applications/views.py:767-773 (ReminderUpdateView.form_valid); applications/forms.py, applications/services.py and applications/quiet.py have not moved, and the same unit test gives the same result.

The reminder edit page decides the reminder was moved when due_at is in form.changed_data. The field is shown and read back to the minute, but reminders made or moved by Later and by Snooze are stored with seconds, so every save of such a reminder counts as a move even when only the wording changed. The move clears notified_at, and a reminder already due and announced is announced a second time.

  • Where: applications/views.py:721-727 (ReminderUpdateView.form_valid, moved = "due_at" in form.changed_data), applications/forms.py:509-515 (ReminderForm, widget format %Y-%m-%dT%H:%M), applications/services.py:555-564 (later_time), applications/quiet.py:158-159 (snooze_until), applications/services.py:567-587 (postpone_reminder).
  • What happens: later_time and snooze_until return timezone.now() plus whole days, seconds included. The edit form's initial value keeps the seconds (the date-time widget drops only microseconds), while the posted value has none, so has_changed is true for an untouched time. form_valid then calls postpone_reminder, which sets notified_at = None, and the save truncates due_at to the minute. Checked: a reminder with seconds in due_at, already due and stamped as sent, edited with the same minute and new wording; after the save notified_at was None.
  • Why it matters: the scheduler picks up due reminders with no stamp, so the person receives the same reminder twice for having corrected a typo. It is the duplicate announcement #221 set out to prevent, reached through the edit page.
  • Fix: capture the stored due_at before the form binds (as ApplicationUpdateView keeps the status before the edit) and treat the reminder as moved only when the two differ once both are truncated to the minute. Separately, have later_time and snooze_until return times truncated to the minute, so stored and displayed precision agree.

Done when

  • tests/test_deadlines.py has a test that makes a reminder with later_time("tomorrow"), marks it as sent, posts the edit form with the same minute and new wording, and asserts notified_at is unchanged; the existing test that moves the time still sees the stamp cleared.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, reading the reminder edit view and checking the result with a unit test against the snapshot. Related to #238. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. The code is now at `applications/views.py:767-773` (`ReminderUpdateView.form_valid`); `applications/forms.py`, `applications/services.py` and `applications/quiet.py` have not moved, and the same unit test gives the same result. The reminder edit page decides the reminder was moved when `due_at` is in `form.changed_data`. The field is shown and read back to the minute, but reminders made or moved by *Later* and by *Snooze* are stored with seconds, so every save of such a reminder counts as a move even when only the wording changed. The move clears `notified_at`, and a reminder already due and announced is announced a second time. - **Where:** `applications/views.py:721-727` (`ReminderUpdateView.form_valid`, `moved = "due_at" in form.changed_data`), `applications/forms.py:509-515` (`ReminderForm`, widget format `%Y-%m-%dT%H:%M`), `applications/services.py:555-564` (`later_time`), `applications/quiet.py:158-159` (`snooze_until`), `applications/services.py:567-587` (`postpone_reminder`). - **What happens:** `later_time` and `snooze_until` return `timezone.now()` plus whole days, seconds included. The edit form's initial value keeps the seconds (the date-time widget drops only microseconds), while the posted value has none, so `has_changed` is true for an untouched time. `form_valid` then calls `postpone_reminder`, which sets `notified_at = None`, and the save truncates `due_at` to the minute. Checked: a reminder with seconds in `due_at`, already due and stamped as sent, edited with the same minute and new wording; after the save `notified_at` was `None`. - **Why it matters:** the scheduler picks up due reminders with no stamp, so the person receives the same reminder twice for having corrected a typo. It is the duplicate announcement #221 set out to prevent, reached through the edit page. - **Fix:** capture the stored `due_at` before the form binds (as `ApplicationUpdateView` keeps the status before the edit) and treat the reminder as moved only when the two differ once both are truncated to the minute. Separately, have `later_time` and `snooze_until` return times truncated to the minute, so stored and displayed precision agree. ## Done when - `tests/test_deadlines.py` has a test that makes a reminder with `later_time("tomorrow")`, marks it as sent, posts the edit form with the same minute and new wording, and asserts `notified_at` is unchanged; the existing test that moves the time still sees the stamp cleared.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:46:45 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#445
No description provided.