mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 06:06:10 +00:00
feat(vorsorge): make the mental-wellbeing screening plannable
PHQ9_SCORE / GAD7_SCORE join the Vorsorge reminder type allow-list as their own "Seelisches Wohlbefinden" group, with a 4-week default cadence (both instruments cover the last two weeks; 28 joins the interval presets). The reminders ride the existing activity-aware engine unchanged: they fire only when overdue, and a completed check-in auto-satisfies them — the assessment route now kicks the eventful reminder-satisfy worker, which resolves against the server-written score row; the 15-min cron stays the idempotent safety-net. The screening reminder's primary action opens the check-in page (a score is never typed in), and the dispatcher gates the reminder on the opt-in mental-health module so a disabled module never nags. OpenAPI spec regenerated for the widened MeasurementReminderType enum.
This commit is contained in:
1 parent
b6aedfeb61
commit
01beabb99b
16 files changed
+256
-30
No files matched your search
@@ -37,6 +37,12 @@ vi.mock("@/lib/ai/coach/bytes-codec", () => ({
|
||||
encryptToBytes: vi.fn(() => Buffer.from("ciphertext")),
|
||||
}));
|
||||
|
||||
// v1.27.6 — a completed check-in kicks the eventful Vorsorge satisfy worker
|
||||
// so a plannable screening reminder resolves immediately.
|
||||
vi.mock("@/lib/jobs/reminder-satisfy", () => ({
|
||||
enqueueReminderSatisfy: vi.fn().mockResolvedValue(undefined),
|
||||
}));
|
||||
|
||||
vi.mock("@/lib/auth/session", () => ({ getSession: vi.fn() }));
|
||||
vi.mock("@/lib/auth/audit", () => ({
|
||||
auditLog: vi.fn().mockResolvedValue(undefined),
|
||||
@@ -55,6 +61,7 @@ vi.mock("next/headers", () => ({
|
||||
}));
|
||||
|
||||
import { POST } from "../route";
|
||||
import { enqueueReminderSatisfy } from "@/lib/jobs/reminder-satisfy";
|
||||
import { getSession } from "@/lib/auth/session";
|
||||
import { requireModuleEnabled } from "@/lib/modules/gate";
|
||||
import { checkRateLimit } from "@/lib/rate-limit";
|
||||
@@ -200,6 +207,10 @@ describe("POST /api/mental-health/assessments", () => {
|
||||
expect(measArg.data.unit).toBe("score");
|
||||
expect(measArg.data.source).toBe("COMPUTED");
|
||||
expect(measArg.data.externalId).toBe("assessment:mha_2");
|
||||
|
||||
// The eventful Vorsorge satisfy worker is kicked so a plannable
|
||||
// screening reminder (PHQ9_SCORE / GAD7_SCORE) auto-resolves at once.
|
||||
expect(enqueueReminderSatisfy).toHaveBeenCalledWith("user-1");
|
||||
});
|
||||
|
||||
it("dedups a repeat externalId: returns the existing administration, writes nothing new", async () => {
|
||||
@@ -239,6 +250,8 @@ describe("POST /api/mental-health/assessments", () => {
|
||||
);
|
||||
expect(prisma.mentalHealthAssessment.create).not.toHaveBeenCalled();
|
||||
expect(prisma.measurement.create).not.toHaveBeenCalled();
|
||||
// No new trend point → nothing to satisfy either.
|
||||
expect(enqueueReminderSatisfy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("persists client provenance + externalId on a first write", async () => {
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
import { annotate } from "@/lib/logging/context";
|
||||
import { auditLog } from "@/lib/auth/audit";
|
||||
import { withIdempotency } from "@/lib/idempotency";
|
||||
import { enqueueReminderSatisfy } from "@/lib/jobs/reminder-satisfy";
|
||||
import { requireModuleEnabled } from "@/lib/modules/gate";
|
||||
import { checkRateLimit, rateLimitHeaders } from "@/lib/rate-limit";
|
||||
import { encryptToBytes } from "@/lib/ai/coach/bytes-codec";
|
||||
@@ -327,6 +328,12 @@ async function postAssessment(request: NextRequest): Promise<Response> {
|
||||
},
|
||||
});
|
||||
|
||||
// v1.27.6 — a screening can be planned as a Vorsorge reminder keyed on
|
||||
// PHQ9_SCORE / GAD7_SCORE. Kick the eventful satisfy worker so completing
|
||||
// a check-in resolves the reminder immediately (the ingest-route
|
||||
// precedent); the 15-min cron stays the idempotent safety-net.
|
||||
await enqueueReminderSatisfy(user.id);
|
||||
|
||||
await auditLog("mental-health.create", {
|
||||
userId: user.id,
|
||||
// The score band is non-sensitive; item answers are NEVER logged.
|
||||
|
||||
Reference in new issue
Block a user