mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 06:40:50 +00:00
fix(documents): store stated dates at noon UTC
A report's stated date, a document's filing date and the date a committed lab reading or condition carries were written as UTC midnight, which is the previous evening west of UTC: a reading dated the 1st showed on the 31st. Date-only values are now stored at noon UTC through one helper in the time zone module, the convention the lab scan and the cycle engine already use. Rows written at midnight still read back to the same date. A document uploaded without a date files under the uploader's own day rather than the UTC one.
This commit is contained in:
1 parent
4ac05364fe
commit
838629276c
10 files changed
+111
-11
No files matched your search
@@ -232,6 +232,29 @@ describe("PATCH /api/documents/inbound/[id]", () => {
|
||||
expect("documentDate" in arg.data).toBe(false);
|
||||
});
|
||||
|
||||
it("stores an edited filing date at noon UTC so it reads back on that day everywhere", async () => {
|
||||
vi.mocked(prisma.inboundDocument.findFirst).mockResolvedValue({
|
||||
id: "doc-1",
|
||||
} as never);
|
||||
vi.mocked(prisma.inboundDocument.update).mockResolvedValue(
|
||||
docRow() as never,
|
||||
);
|
||||
vi.mocked(prisma.inboundDocument.findFirstOrThrow).mockResolvedValue(
|
||||
docRow() as never,
|
||||
);
|
||||
|
||||
const res = await PATCH(
|
||||
mkReq("doc-1", { documentDate: "2026-05-03" }) as never,
|
||||
ctx("doc-1") as never,
|
||||
);
|
||||
expect(res.status).toBe(200);
|
||||
const arg = vi.mocked(prisma.inboundDocument.update).mock.calls[0][0];
|
||||
// UTC midnight is the previous evening west of UTC.
|
||||
expect((arg.data.documentDate as Date).toISOString()).toBe(
|
||||
"2026-05-03T12:00:00.000Z",
|
||||
);
|
||||
});
|
||||
|
||||
it("422s on an empty update", async () => {
|
||||
const res = await PATCH(mkReq("doc-1", {}) as never, ctx("doc-1") as never);
|
||||
expect(res.status).toBe(422);
|
||||
|
||||
@@ -288,6 +288,14 @@ describe("POST /api/documents/inbound/[id]/extract — stored mode", () => {
|
||||
data: expect.objectContaining({ status: "EXTRACTED" }),
|
||||
}),
|
||||
);
|
||||
// The stated report date is a date-only value: stored at noon UTC, not
|
||||
// at UTC midnight (the previous evening west of UTC).
|
||||
const staged = tx.inboundDocument.update.mock.calls[0]![0] as {
|
||||
data: { reportDate: Date };
|
||||
};
|
||||
expect(staged.data.reportDate.toISOString()).toBe(
|
||||
"2026-08-01T12:00:00.000Z",
|
||||
);
|
||||
expect(auditLog).toHaveBeenCalledWith(
|
||||
"documents.inbound.extract",
|
||||
expect.objectContaining({
|
||||
|
||||
@@ -76,6 +76,7 @@ import {
|
||||
inboundStoredExtractSchema,
|
||||
inboundTextExtractSchema,
|
||||
} from "@/lib/validations/inbound-documents";
|
||||
import { dateOnlyAtNoonUtc } from "@/lib/tz/date-only";
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
@@ -111,7 +112,7 @@ async function stageExtraction(
|
||||
status: "EXTRACTED",
|
||||
providerType: result.providerType,
|
||||
reportDate: result.reportDate
|
||||
? new Date(`${result.reportDate}T00:00:00.000Z`)
|
||||
? dateOnlyAtNoonUtc(result.reportDate)
|
||||
: null,
|
||||
facts: {
|
||||
create: result.facts.map((f) => ({
|
||||
|
||||
@@ -41,6 +41,7 @@ import {
|
||||
toContentIndexSource,
|
||||
} from "@/lib/validations/inbound-documents";
|
||||
import type { Prisma } from "@/generated/prisma/client";
|
||||
import { dateOnlyAtNoonUtc } from "@/lib/tz/date-only";
|
||||
|
||||
type RouteParams = { params: Promise<{ id: string }> };
|
||||
|
||||
@@ -232,7 +233,7 @@ export const PATCH = apiHandler(
|
||||
if (parsed.data.kind !== undefined) data.kind = parsed.data.kind;
|
||||
if (parsed.data.documentDate !== undefined) {
|
||||
data.documentDate = parsed.data.documentDate
|
||||
? new Date(`${parsed.data.documentDate}T00:00:00.000Z`)
|
||||
? dateOnlyAtNoonUtc(parsed.data.documentDate)
|
||||
: null;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user