fix(audit): name automatic dose recording in medication audit rows

Switching autoMarkTaken on or off now appears in the medication.update
row with its previous value, and medication.create records whether the
medication starts with doses recorded automatically.
This commit is contained in:
Marc-André Bombeck committed 2026-10-11 15:11:27 +02:00
1 parent fe782493a1
commit 38900656a3
3 files changed
+63 -1

No files matched your search

+4
View File
@@ -1134,6 +1134,9 @@ export const PUT = apiHandler(
active: existing.active,
asNeeded: existing.asNeeded,
trackIntake: existing.trackIntake,
// v1.42.2 — switching automatic recording on or off is a change
// to how doses are recorded, so the row names it.
autoMarkTaken: existing.autoMarkTaken,
endsOn: existing.endsOn,
},
after: {
@@ -1142,6 +1145,7 @@ export const PUT = apiHandler(
active: medication.active,
asNeeded: medication.asNeeded,
trackIntake: medication.trackIntake,
autoMarkTaken: medication.autoMarkTaken,
endsOn: medication.endsOn,
},
}),
+7 -1
View File
@@ -491,7 +491,13 @@ async function postMedication(request: NextRequest): Promise<Response> {
await auditLog("medication.create", {
userId: user.id,
ipAddress: getClientIp(request),
details: { medicationId: medication.id, name },
details: {
medicationId: medication.id,
name,
// v1.42.2 — a medication created with its doses recorded
// automatically says so in its audit row.
autoMarkTaken: medication.autoMarkTaken,
},
});
annotate({
@@ -377,6 +377,58 @@ describe("auto-mark-taken pass", () => {
select: { autoMarkTaken: true, autoMarkTakenSince: true },
});
expect(off).toEqual({ autoMarkTaken: false, autoMarkTakenSince: null });
// Each flip is named in the audit row with what it was before; the
// re-save that left it on names no change to it.
const audits = await prisma.auditLog.findMany({
where: { userId, action: "medication.update" },
orderBy: { createdAt: "asc" },
select: { details: true },
});
const details = audits.map(
(a) =>
JSON.parse(a.details ?? "{}") as {
fields: string[];
previous: Record<string, unknown>;
},
);
expect(details).toHaveLength(3);
// Two of the same timestamp: matched by content, not order.
const flips = details
.filter((d) => d.fields.includes("autoMarkTaken"))
.map((d) => d.previous.autoMarkTaken)
.sort();
expect(flips).toEqual([false, true]);
const resave = details.find((d) => d.fields.includes("name"));
expect(resave?.fields).not.toContain("autoMarkTaken");
});
it("the create audit row says whether doses are recorded automatically", async () => {
const prisma = getPrismaClient();
const userId = await makeUser();
const route = await import("@/app/api/medications/route");
at("2026-06-10T10:00:00.000Z");
const res = await (route.POST as Handler)(
new NextRequest("http://localhost/api/medications", {
method: "POST",
body: JSON.stringify({
name: "Vitamin D",
dose: "1 capsule",
autoMarkTaken: true,
schedules: [{ windowStart: "19:00", windowEnd: "19:00" }],
}),
headers: { "content-type": "application/json" },
}),
{ params: Promise.resolve({}) },
);
expect(res.status).toBe(201);
const audit = await prisma.auditLog.findFirstOrThrow({
where: { userId, action: "medication.create" },
select: { details: true },
});
expect(JSON.parse(audit.details ?? "{}")).toMatchObject({
autoMarkTaken: true,
});
});
});