mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
fix(measurements): keep computed scores out of the bulk delete
The row menu stopped offering edit and delete on a computed score (recovery, strain, stress), but the list still drew its selection checkbox and "select all" took it into the page, so the bulk bar could delete a page of scores, and the tombstones kept the recompute out. A computed row now has no checkbox on either layout and stays out of the page selection, and the bulk-delete route skips computed rows if a client sends them anyway. The iOS app treats these rows as read-only and does not rely on deleting them.
This commit is contained in:
1 parent
a4b14609bf
commit
048dbbee9f
6 files changed
+98
-9
No files matched your search
@@ -156,6 +156,20 @@ describe("POST /api/measurements/bulk-delete", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("leaves a computed score out of the selection it deletes", async () => {
|
||||
// The read is scoped like the write, so a computed row never reaches it.
|
||||
vi.mocked(prisma.measurement.findMany).mockResolvedValue([] as never);
|
||||
vi.mocked(prisma.measurement.updateMany).mockResolvedValue({
|
||||
count: 0,
|
||||
} as never);
|
||||
|
||||
await POST(postReq({ ids: ["score-1"] }));
|
||||
|
||||
expect(
|
||||
vi.mocked(prisma.measurement.findMany).mock.calls[0][0]?.where,
|
||||
).toMatchObject({ source: { not: "COMPUTED" } });
|
||||
});
|
||||
|
||||
it("collapses the rollup recompute to the unique (type, day) set, not per-row", async () => {
|
||||
// 4 deleted rows: 2× WEIGHT on the same UTC day, 1× WEIGHT next day,
|
||||
// 1× PULSE same day as the first → 3 distinct (type, day) keys.
|
||||
|
||||
@@ -81,9 +81,17 @@ async function postBulkDelete(request: NextRequest): Promise<Response> {
|
||||
// other half and the cuff's pulse, `bloodPressureSiblings`) into the same
|
||||
// statement, so the shared `deletedAt` lets the restore route bring the
|
||||
// reading back whole.
|
||||
//
|
||||
// A computed score (recovery, strain, stress) is skipped: the server
|
||||
// rewrites it from its inputs, and a tombstone kept the recompute out.
|
||||
const { affected, count } = await prisma.$transaction(async (tx) => {
|
||||
const selected = await tx.measurement.findMany({
|
||||
where: { id: { in: ids }, userId: user.id, deletedAt: null },
|
||||
where: {
|
||||
id: { in: ids },
|
||||
userId: user.id,
|
||||
deletedAt: null,
|
||||
source: { not: "COMPUTED" },
|
||||
},
|
||||
select: { id: true, type: true, source: true, measuredAt: true },
|
||||
});
|
||||
const siblings = await bloodPressureSiblings(tx, user.id, selected, "live");
|
||||
|
||||
Reference in new issue
Block a user