diff --git a/src/app/api/insights/cards/route.ts b/src/app/api/insights/cards/route.ts index f070aa305..dd7052852 100644 --- a/src/app/api/insights/cards/route.ts +++ b/src/app/api/insights/cards/route.ts @@ -77,6 +77,7 @@ export const GET = apiHandler(async () => { in: ["WEIGHT", "BLOOD_PRESSURE_SYS", "BLOOD_PRESSURE_DIA", "PULSE"], }, measuredAt: { gte: ninetyDaysAgo }, + deletedAt: null, }, orderBy: { measuredAt: "asc" }, select: { type: true, value: true, measuredAt: true }, diff --git a/src/app/api/insights/generate/route.ts b/src/app/api/insights/generate/route.ts index 96c7e3413..eee951223 100644 --- a/src/app/api/insights/generate/route.ts +++ b/src/app/api/insights/generate/route.ts @@ -134,7 +134,7 @@ async function buildComparisonSnapshotForUser( const rows = await Promise.all( types.map(async (type) => { const measurements = await prisma.measurement.findMany({ - where: { userId, type }, + where: { userId, type, deletedAt: null }, orderBy: { measuredAt: "asc" }, select: { measuredAt: true, value: true }, }); diff --git a/src/app/api/insights/targets/route.ts b/src/app/api/insights/targets/route.ts index c613fbd32..46e195659 100644 --- a/src/app/api/insights/targets/route.ts +++ b/src/app/api/insights/targets/route.ts @@ -178,11 +178,15 @@ async function buildTargetsResponse(user: AuthedUser) { const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000); // Fetch all measurements in the last 30 days + the latest for each type + // Soft-delete filter mirrors the W-DELETED pattern: tombstoned rows + // must not contribute to tile averages / latest values once iOS sync + // starts emitting deletions. const recentMeasurements = await prisma.measurement.findMany({ where: { userId, type: { in: types }, measuredAt: { gte: thirtyDaysAgo }, + deletedAt: null, }, orderBy: { measuredAt: "desc" }, select: { type: true, value: true, measuredAt: true }, @@ -207,6 +211,7 @@ async function buildTargetsResponse(user: AuthedUser) { userId, type: { in: types }, measuredAt: { gte: oneYearAgo }, + deletedAt: null, }, orderBy: { measuredAt: "desc" }, distinct: ["type"], @@ -1193,7 +1198,7 @@ async function buildTargetsResponse(user: AuthedUser) { }; const thirtyDaysAgoGlucose = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000); const glucoseRows = await prisma.measurement.findMany({ - where: { userId, type: "BLOOD_GLUCOSE" }, + where: { userId, type: "BLOOD_GLUCOSE", deletedAt: null }, orderBy: { measuredAt: "desc" }, select: { value: true, measuredAt: true, glucoseContext: true }, }); diff --git a/src/lib/insights/features.ts b/src/lib/insights/features.ts index b77b53d52..d0e168481 100644 --- a/src/lib/insights/features.ts +++ b/src/lib/insights/features.ts @@ -377,8 +377,8 @@ export async function extractFeatures( : null; const measurements = await prisma.measurement.findMany({ where: sinceCutoff - ? { userId, measuredAt: { gte: sinceCutoff } } - : { userId }, + ? { userId, measuredAt: { gte: sinceCutoff }, deletedAt: null } + : { userId, deletedAt: null }, orderBy: { measuredAt: "asc" }, }); diff --git a/src/lib/insights/glp1-plateau.ts b/src/lib/insights/glp1-plateau.ts index e452c95f7..539ce74c5 100644 --- a/src/lib/insights/glp1-plateau.ts +++ b/src/lib/insights/glp1-plateau.ts @@ -74,6 +74,7 @@ export async function detectGlp1Plateau( userId, type: "WEIGHT", measuredAt: { gte: windowStart }, + deletedAt: null, }, orderBy: { measuredAt: "asc" }, select: { value: true, measuredAt: true }, diff --git a/src/lib/insights/pulse-status.ts b/src/lib/insights/pulse-status.ts index a5a5887ac..5dcb595a9 100644 --- a/src/lib/insights/pulse-status.ts +++ b/src/lib/insights/pulse-status.ts @@ -158,6 +158,7 @@ export async function generatePulseStatusForUser( where: { userId, type: "PULSE", + deletedAt: null, }, orderBy: { measuredAt: "desc" }, take: 365,