mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
feat(nutrients): source-aware day totals; manual water write path
NutrientIntakeDay's composite primary key gains `source` (migration 0249_nutrient_intake_day_source): a manual water entry and the Apple-synced day total now live as two rows instead of the manual write being silently clobbered by the next Apple last-writer-wins sync. Every existing row already defaults to source=APPLE_HEALTH, so the migration is a pure PK-constraint change with no data rewrite. - POST /api/nutrients/batch keeps writing the APPLE_HEALTH row, byte-identical upsert semantics against the wider key. - GET /api/nutrients sums amounts within (nutrient, day) across sources before folding into the window summary. - POST /api/nutrients/water (new): manual water quick-add, add/set modes against the MANUAL row only, module-gated, rate-limited, idempotency-key aware, hard-evicts the dashboard snapshot cache. - GET /api/nutrients/daily (new): dense per-day series for one nutrient (summed across sources) plus the EFSA reference resolved against the caller's profile sex — omitted when sex is unknown. - catalog.ts gains resolveNutrientReference(), the sex-resolution helper both new routes and the insights cards share. docs/api/openapi.yaml regenerated for the two new routes.
This commit is contained in:
1 parent
bef3b9dd3f
commit
da2de015fe
15 files changed
+1075
-11
No files matched your search
@@ -267,10 +267,11 @@ describe("POST /api/nutrients/batch — upsert semantics", () => {
|
||||
|
||||
expect(prisma.nutrientIntakeDay.upsert).toHaveBeenCalledWith({
|
||||
where: {
|
||||
userId_day_nutrient: {
|
||||
userId_day_nutrient_source: {
|
||||
userId: "user-1",
|
||||
day,
|
||||
nutrient: "vitamin_d",
|
||||
source: "APPLE_HEALTH",
|
||||
},
|
||||
},
|
||||
create: {
|
||||
@@ -279,6 +280,7 @@ describe("POST /api/nutrients/batch — upsert semantics", () => {
|
||||
nutrient: "vitamin_d",
|
||||
amount: 22.5,
|
||||
unit: "ug",
|
||||
source: "APPLE_HEALTH",
|
||||
externalSourceVersion: "yazio-9.9",
|
||||
},
|
||||
update: {
|
||||
|
||||
@@ -165,11 +165,18 @@ async function postBatch(request: NextRequest): Promise<Response> {
|
||||
}
|
||||
|
||||
try {
|
||||
// v1.29 — `source` joined the composite PK (migration 0249) so a
|
||||
// manual water entry (source=MANUAL, written by
|
||||
// `POST /api/nutrients/water`) coexists with the Apple-synced day
|
||||
// total instead of one clobbering the other on the next sync. The
|
||||
// batch route always owns the APPLE_HEALTH row — byte-identical
|
||||
// upsert behaviour to pre-0249, just against the wider key.
|
||||
const key = {
|
||||
userId_day_nutrient: {
|
||||
userId_day_nutrient_source: {
|
||||
userId: user.id,
|
||||
day: entry.day,
|
||||
nutrient: entry.nutrient,
|
||||
source: "APPLE_HEALTH",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -189,6 +196,7 @@ async function postBatch(request: NextRequest): Promise<Response> {
|
||||
nutrient: entry.nutrient,
|
||||
amount: entry.amount,
|
||||
unit: definition.unit,
|
||||
source: "APPLE_HEALTH",
|
||||
externalSourceVersion: entry.externalSourceVersion ?? null,
|
||||
},
|
||||
update: {
|
||||
|
||||
Reference in new issue
Block a user