mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 05:42:19 +00:00
fix(checkups): keep a missed rolling reminder due until it is measured
A rolling reminder ("every N days") is anchored on its last reading, but
the reminder tick rolled any cycle of a week or less on after a delivered
reminder, re-anchoring it on the send. A missed every-two-days blood
pressure reading therefore moved two days ahead each evening, read "in 2
days" on the card, and never showed as today or overdue.
A rolling reminder now stays due after its reminder, whatever its
interval, until a reading lands or it is done, skipped or snoozed. While
it stays open the repeat follows its interval, capped at a week, still in
its notify hour and under the per-day claim. Calendar rules that recur
within a week (a twice-daily course) keep rolling on; appointments are
unchanged.
holdsOpenAfterReminder stays the one definition for the tick and the
edit route. The daily digest asks the narrower question underneath it,
hasLongCycle, so a short rhythm still waits for its time of day on the
start page and is not pinned under the rail cap.
Refs #1369
This commit is contained in:
1 parent
d110f0456c
commit
ea3fcce80c
15 files changed
+530
-116
No files matched your search
@@ -272,8 +272,13 @@ describe("PATCH /api/measurement-reminders/[id] — nextDueAt honours explicit-n
|
||||
expect(persisted.nextDueAt).toEqual(new Date("2026-01-31T17:00:00Z"));
|
||||
});
|
||||
|
||||
it("re-enabling a disabled short-cycle reminder schedules it from now", async () => {
|
||||
const weekly = { ...BASE_ROW, intervalDays: 7, enabled: false };
|
||||
it("re-enabling a disabled weekly calendar rule schedules it from now", async () => {
|
||||
const weekly = {
|
||||
...BASE_ROW,
|
||||
intervalDays: null,
|
||||
rrule: "FREQ=WEEKLY",
|
||||
enabled: false,
|
||||
};
|
||||
findFirstMock.mockResolvedValue(weekly);
|
||||
|
||||
const res = await PATCH(makeRequest({ enabled: true }), params);
|
||||
@@ -303,6 +308,26 @@ describe("PATCH /api/measurement-reminders/[id] — nextDueAt honours explicit-n
|
||||
expect("nextDueAt" in persisted).toBe(false);
|
||||
});
|
||||
|
||||
it("re-enabling a missed short rolling reminder keeps its open slot", async () => {
|
||||
// Every two days, never measured: switching it off and on again is not
|
||||
// measuring it either.
|
||||
findFirstMock.mockResolvedValue({
|
||||
...BASE_ROW,
|
||||
intervalDays: 2,
|
||||
enabled: false,
|
||||
});
|
||||
|
||||
const res = await PATCH(makeRequest({ enabled: true }), params);
|
||||
expect(res.status).toBe(200);
|
||||
|
||||
const persisted = updateMock.mock.calls[0]?.[0]?.data as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
expect(persisted.enabled).toBe(true);
|
||||
expect("nextDueAt" in persisted).toBe(false);
|
||||
});
|
||||
|
||||
it("reads a resent first due date on the same calendar day as unchanged", async () => {
|
||||
// A booster row stores the dose instant plus N days; the web form sends
|
||||
// the same day back as local midnight. Same day in the profile zone, so
|
||||
|
||||
@@ -219,7 +219,7 @@ export const PATCH = apiHandler(
|
||||
const reEnabled = updateData.enabled === true && !existing.enabled;
|
||||
// Re-enabling a reminder that stays due after it is sent keeps the slot it
|
||||
// was on, overdue or not: switching it off and on again is not doing it.
|
||||
// A short-cycle reminder is scheduled from now, as before.
|
||||
// A calendar rule that recurs within the week is scheduled from now.
|
||||
const keepsOpenSlot =
|
||||
reEnabled &&
|
||||
!cadenceChanged &&
|
||||
|
||||
Reference in new issue
Block a user