mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 14:32:03 +00:00
feat(medications): make low-stock alert reorder-lead-time aware
The low-stock alert fired when the projected runway dropped below the user threshold (default 7 days). For a sparse cadence — a weekly injection's 7-day floor is barely one dose-interval — the warning landed with about one dose left, too late to reorder before the supply ran out. Add an optional per-medication reorder lead time plus a user-level default (0–60 days, default 10) and widen the alert trigger to max(lowStockRunwayDays, leadDays + cadenceIntervalDays), so the warning lands before the last dose for any cadence. Because the trigger is a max() over the user floor it never shrinks anyone's current threshold; a daily med with no lead keeps its prior boundary. The push body and the card notice surface concrete dates — supply runs out around <date>, reorder by <date> — with a last-dose informational state and the days/units fallback when supply data is thin. Retire the stale fixed 4-dose count threshold on the GLP-1 details endpoint and route its card lowStock flag through the same runway evaluation so the card and the daily cron agree. Surface the lead default in the low-stock settings card with progressive disclosure; a single medication can override it. Additive schema: nullable Medication.reorderLeadDays (migration 0161, no backfill) and notificationPrefs.medication.reorderLeadDays. OpenAPI regenerated.
This commit is contained in:
1 parent
52bf985734
commit
08aa655be4
29 files changed
+1060
-97
No files matched your search
@@ -77,12 +77,15 @@ describe("GET /api/settings/reminder-thresholds", () => {
|
||||
lateMinutes: number;
|
||||
missedMinutes: number;
|
||||
lowStockRunwayDays: number | null;
|
||||
reorderLeadDays: number;
|
||||
};
|
||||
};
|
||||
expect(env.data).toEqual({
|
||||
lateMinutes: 120,
|
||||
missedMinutes: 240,
|
||||
lowStockRunwayDays: 7,
|
||||
// v1.17.0 — the per-user reorder lead default rides along.
|
||||
reorderLeadDays: 10,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { getReminderThresholds } from "@/lib/app-settings";
|
||||
import { apiHandler, requireAuth } from "@/lib/api-handler";
|
||||
import { annotate } from "@/lib/logging/context";
|
||||
import { prisma } from "@/lib/db";
|
||||
import { resolveLowStockRunwayDays } from "@/lib/validations/notification-prefs";
|
||||
import { parseNotificationPrefs } from "@/lib/validations/notification-prefs";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
@@ -22,11 +22,15 @@ export const GET = apiHandler(async () => {
|
||||
where: { id: user.id },
|
||||
select: { notificationPrefs: true },
|
||||
});
|
||||
const lowStockRunwayDays = resolveLowStockRunwayDays(
|
||||
row?.notificationPrefs ?? null,
|
||||
);
|
||||
const prefs = parseNotificationPrefs(row?.notificationPrefs ?? null);
|
||||
const lowStockRunwayDays = prefs.medication.lowStockRunwayDays;
|
||||
// v1.17.0 — the user-level reorder lead default rides along so the
|
||||
// medication cards can derive the same reorder-lead-aware trigger the
|
||||
// daily cron uses (per-medication overrides come from the list payload's
|
||||
// own `reorderLeadDays`).
|
||||
const reorderLeadDays = prefs.medication.reorderLeadDays;
|
||||
|
||||
annotate({ action: { name: "settings.reminder-thresholds.get" } });
|
||||
|
||||
return apiSuccess({ ...thresholds, lowStockRunwayDays });
|
||||
return apiSuccess({ ...thresholds, lowStockRunwayDays, reorderLeadDays });
|
||||
});
|
||||
Reference in new issue
Block a user