mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +00:00
fix(medications): a manual era cannot swallow tracked live history
The manual-era boundary anchors on the medication's creation instead of the current moment, so a backfilled era can only describe time before the app was tracking.
This commit is contained in:
1 parent
5639da4333
commit
44f344bf52
2 files changed
+35
-3
No files matched your search
@@ -233,6 +233,25 @@ describe("POST /api/medications/[id]/schedule-revisions", () => {
|
||||
expect(json.error).toMatch(/current plan/i);
|
||||
});
|
||||
|
||||
it("422s when no revision exists and the era reaches past createdAt", async () => {
|
||||
// With zero archived revisions the live plan has covered everything
|
||||
// since `createdAt` (2026-01-10); a manual era ending inside the
|
||||
// tracked window would re-score live compliance against the manual
|
||||
// snapshot. The boundary is createdAt, not "now".
|
||||
const res = await POST(
|
||||
postReq({
|
||||
...VALID_BODY,
|
||||
validFrom: "2026-01-01T00:00:00.000Z",
|
||||
validUntil: "2026-02-01T00:00:00.000Z",
|
||||
}),
|
||||
ROUTE_CTX,
|
||||
);
|
||||
expect(res.status).toBe(422);
|
||||
const json = await res.json();
|
||||
expect(json.error).toMatch(/current plan/i);
|
||||
expect(prisma.medicationScheduleRevision.create).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("creates a MANUAL revision with a daily snapshot entry", async () => {
|
||||
vi.mocked(prisma.medicationScheduleRevision.create).mockResolvedValue({
|
||||
id: "rev-new",
|
||||
|
||||
@@ -137,6 +137,14 @@ export const POST = apiHandler(
|
||||
const guard = await assertMedicationOwnership(id, user.id);
|
||||
if (guard) return guard;
|
||||
|
||||
const med = await prisma.medication.findUnique({
|
||||
where: { id },
|
||||
select: { createdAt: true },
|
||||
});
|
||||
if (!med) {
|
||||
return apiError("Medication not found", 404);
|
||||
}
|
||||
|
||||
const { data: body, error: jsonError } = await safeJson(request, {
|
||||
maxBytes: 16 * 1024,
|
||||
});
|
||||
@@ -162,13 +170,18 @@ export const POST = apiHandler(
|
||||
});
|
||||
|
||||
// "Before the current plan": the live era began at the newest
|
||||
// archived `validUntil`; with no archive it spans up to now, so a
|
||||
// manual era may cover anything up to this instant.
|
||||
// archived `validUntil`; with no archive the live plan has covered
|
||||
// everything since the medication was created (the era splitter
|
||||
// reads `[newest validUntil, ∞)` — or the whole range when no
|
||||
// revision exists), so a manual era must end at or before
|
||||
// `createdAt`. Allowing it to reach "now" would let the manual
|
||||
// snapshot swallow tracked live history and re-score compliance
|
||||
// against the wrong plan.
|
||||
const liveStart = existing.reduce(
|
||||
(latest, r) => (r.validUntil > latest ? r.validUntil : latest),
|
||||
new Date(0),
|
||||
);
|
||||
const liveBoundary = existing.length > 0 ? liveStart : new Date();
|
||||
const liveBoundary = existing.length > 0 ? liveStart : med.createdAt;
|
||||
if (validUntil.getTime() > liveBoundary.getTime()) {
|
||||
return apiError(
|
||||
"A manual era must end before the current plan begins",
|
||||
|
||||
Reference in new issue
Block a user