Put reminders on the plugin surface, with one service each to create, change, move, complete and reopen them #331
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
performance
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo#331
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A plugin may import only what
postulo.plugins.apinames, and Writing a plugin tells it never to write by saving a model. Interviews are on the surface with the services that move and settle them.Reminder(src/postulo/applications/models.py: an application or none,summary,due_at,done_at,notified_at) is not, nor ispostpone_reminder, so postulo-dav cannot keep reminders in step with a CalDAV task list (postulo/postulo-dav#12), asked for as: "The TODO component (tasks) is what best resembles … a reminder."What exists today
ReminderCreateView), Snooze on a quiet application (src/postulo/applications/views.py:865),POST /api/v1/reminders(src/postulo/api/routers/reminders.py:45), and insideschedule_interview, a day ahead (src/postulo/applications/services.py:428), and the offer path, for an answer date (services.py:666).PATCH, each followed bypostpone_reminder(services.py:567) when the time moved, which clearsnotified_atso it is announced again.reschedule_interviewmoves its reminder by hand (services.py:468).reminder.complete(), called from Done, the API, the two interview services and the offer path. Reopening exists only in the offer path, which clearsdone_atby hand (services.py:677); neither the page nor the API can undo Done, andReminderPatchdeliberately has nodone_at.Proposal
src/postulo/applications/services.py, each taking anactorasrecord_eventandreschedule_interviewdo:create_reminder(owner, *, summary, due, application=None, actor=""). It refuses another person's application and cuts the summary to the column's 250 characters, assuggestdoes. A date forduemeans nine in the morning (REMINDER_HOUR,views.py:678, as New reminder on a calendar day) in the owner's zone (the instance's when they set none), not the active one: a scheduled sync runs outside any request, and only the request middleware activates a zone (src/postulo/core/middleware.py:129).change_reminder(reminder, *, summary=…, application=…, actor=""), with the same refusal and cut.postpone_reminder(reminder, due, *, actor=""), today's service with an actor, taking a date ascreate_reminderdoes.complete_reminder(reminder, *, at=None, actor=""): the moment it was done, defaulting to now and never in the future, since a sync learns of a tick up to a day late.reopen_reminder(reminder, *, actor="").complete_reminderandchange_reminder(URL names the isolation sweep uses), so it imports the services under others.Reminder, read withReminder.objects.for_user(user), and the five services, as one group in_ELSEWHEREand__all__insrc/postulo/plugins/api.py.Decisions
Reminderhas no actor column;ApplicationEventhas one. (a) Add one, naming who last touched the reminder when it was not the person, shown beside it in words, on the API'sReminderOut, and in the export and import (REMINDER_FIELDS,src/postulo/core/export.py:229; aFORMAT_VERSIONbump with its note). (b) Take the actor and only log it. Recommend (a): a reminder ticked off by a phone should say so.change_statuson the surface. Recommend keeping it off. A phone's tick is a person's gesture read by a machine;suggest(..., suggested_status=...)is already on the surface, and accepting it moves the status throughchange_statuswith the plugin as the actor (src/postulo/applications/suggestions.py), so the person confirms. Alternative: put it on with an actor, letting a plugin move a status unasked.POST /reminders/{id}/reopenbeside/complete. Recommend (b): otherwise a phone can untick what the page cannot.postpone_reminder's rule, and a tick undone by mistake should not ring twice.Needed by
postulo/postulo-dav#12: reminders both ways with a task list, and a task made on the phone becoming a reminder.
Done when
atrefused, reopening, a move clearing the stamp.Reminderand the five services are onapi.__all__, each with its line in both of Writing a plugin's tables (tests/test_wiki_surface.py), named intests/test_plugin_surface.pybeside what a sync needs, withapi.Reminderthe core's own class. The publishedpostulo.plugins.testingcheck needs no change: it reads imports, not names.reminder_completeis (tests/test_page_coverage.py); rows for the view and the API call intests/security/test_isolation_sweep.py; the call under Every call on the wiki's The API (tests/test_wiki_surface.py).From the list of DAV plugin improvements of 2026-09-30.