mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
medication_compliance_rollups lost its last reader when compliance moved to the schedule-anchored computation, yet every dose write still upserted it, a boot backfill refolded it, and the wipe and backup plans carried it. The per-dose hook keeps the one derived row that still hangs off a dose day, the supplement nutrients, under dose-day-refresh. The pending-row mints (today projection, reminder) no longer call it, since an untaken dose adds no nutrients. The import job finishes without its per-day recompute phase; its progress keeps touchedDays and rollupProcessed on the wire, inert and documented as deprecated. The backfill queue is retired on boot and migration 0414 drops the table under a bounded lock wait.
96 lines
2.8 KiB
TypeScript
96 lines
2.8 KiB
TypeScript
/**
|
|
* Local day keys from naive UTC timestamps, against a real Postgres.
|
|
*
|
|
* `measured_at` and `scheduled_for` hold UTC wall-clock time in `timestamp`
|
|
* columns. The dashboard streak and the medication-compliance backfill keyed
|
|
* them with a single `AT TIME ZONE tz`, which reads the value as local time
|
|
* and shifts it the wrong way. Both now agree with `userDayKey`: a reading at
|
|
* 23:30 UTC is the next day in Berlin and still the same day in Los Angeles,
|
|
* a reading at 03:00 UTC is the previous day in Los Angeles.
|
|
*/
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import { getPrismaClient, truncateAllTables } from "./setup";
|
|
import { readActivityDayKeys } from "@/lib/dashboard/summary-reads";
|
|
import { userDayKey } from "@/lib/tz/format";
|
|
|
|
vi.mock("@/lib/db-compat", () => ({
|
|
ensureDbCompatibility: vi.fn().mockResolvedValue(undefined),
|
|
}));
|
|
|
|
const prisma = getPrismaClient();
|
|
const USER = "local-day-keys";
|
|
const now = new Date();
|
|
/** UTC midnight ten days back. */
|
|
const D = Date.UTC(
|
|
now.getUTCFullYear(),
|
|
now.getUTCMonth(),
|
|
now.getUTCDate() - 10,
|
|
);
|
|
const LATE = new Date(D + 23.5 * 3_600_000); // 23:30 UTC on D
|
|
const EARLY = new Date(D + 3 * 3_600_000); // 03:00 UTC on D
|
|
const key = (ms: number) => new Date(ms).toISOString().slice(0, 10);
|
|
|
|
beforeEach(async () => {
|
|
await truncateAllTables(prisma);
|
|
await prisma.user.create({
|
|
data: {
|
|
id: USER,
|
|
username: USER,
|
|
email: `${USER}@example.test`,
|
|
timezone: "Europe/Berlin",
|
|
},
|
|
});
|
|
});
|
|
|
|
describe("readActivityDayKeys", () => {
|
|
beforeEach(async () => {
|
|
await prisma.measurement.createMany({
|
|
data: [
|
|
{ at: LATE, deleted: false },
|
|
{ at: EARLY, deleted: false },
|
|
{ at: new Date(D - 3 * 86_400_000), deleted: true },
|
|
].map(({ at, deleted }, i) => ({
|
|
id: `${USER}-m${i}`,
|
|
userId: USER,
|
|
type: "WEIGHT" as const,
|
|
source: "MANUAL" as const,
|
|
value: 80,
|
|
unit: "kg",
|
|
measuredAt: at,
|
|
deletedAt: deleted ? new Date() : null,
|
|
})),
|
|
});
|
|
});
|
|
|
|
const since = new Date(D - 5 * 86_400_000);
|
|
|
|
it("keys a late reading onto the next day east of UTC", async () => {
|
|
const keys = await readActivityDayKeys(
|
|
prisma,
|
|
USER,
|
|
"Europe/Berlin",
|
|
since,
|
|
now,
|
|
);
|
|
expect(keys).toEqual([key(D), key(D + 86_400_000)]);
|
|
expect(keys).toEqual(
|
|
[EARLY, LATE].map((at) => userDayKey(at, "Europe/Berlin")),
|
|
);
|
|
});
|
|
|
|
it("keys an early reading onto the previous day west of UTC", async () => {
|
|
const keys = await readActivityDayKeys(
|
|
prisma,
|
|
USER,
|
|
"America/Los_Angeles",
|
|
since,
|
|
now,
|
|
);
|
|
expect(keys).toEqual([key(D - 86_400_000), key(D)]);
|
|
expect(keys).toEqual(
|
|
[EARLY, LATE].map((at) => userDayKey(at, "America/Los_Angeles")),
|
|
);
|
|
});
|
|
});
|