feat(reminders): add server-side completion route for Vorsorge reminders

Add POST /api/measurement-reminders/{id}/complete so a client can mark a
measurement reminder done on the server, rather than only dismissing the
notification locally. The route is the explicit user-action equivalent of
the cron auto-resolve: it routes through the one shared satisfaction
primitive, stamps lastSatisfiedAt, re-anchors the server-authoritative
nextDueAt, and fires no notification of its own.

Idempotent via the primitive's forward-only guard — completing an
already-completed or auto-satisfied reminder returns 200 with
completed=false so a repeat tap need not be special-cased. Owner-scoped;
a cross-user or tombstoned id 404s and never satisfies. No schema change:
lastSatisfiedAt already records the completion instant.

Extend the OpenAPI contract with the new path and the completion result
schema, and cover the route with unit tests (marks done, idempotent
no-op, owner-scoped 404, no double-notify).
This commit is contained in:
Marc-André Bombeck committed 2026-06-18 21:39:24 +02:00
1 parent ae3091df9e
commit 70f92558e6
5 files changed
+321

No files matched your search

+58
View File
@@ -5866,6 +5866,33 @@ paths:
"404": *a7
"422": *a3
"429": *a4
/api/measurement-reminders/{id}/complete:
post:
tags:
- MeasurementReminders
summary: Complete a Vorsorge reminder (v1.18.6)
description: "Explicit user-action completion (iOS #23): the app marks a reminder done server-side instead of only
dismissing it locally. Routes through the same satisfaction primitive as the cron auto-resolve — stamps
lastSatisfiedAt = now, re-anchors nextDueAt, fires no notification. Idempotent: completing an already-completed
/ auto-satisfied reminder returns 200 with completed=false. Owner-scoped."
parameters:
- in: path
name: id
schema:
type: string
required: true
responses:
"200":
description: Completion applied (completed=true) or already-satisfied no-op (completed=false); reminder carries the
canonical post-completion DTO.
content:
application/json:
schema:
$ref: "#/components/schemas/MeasurementReminderCompleteEnvelope"
"401": *a1
"404": *a7
"422": *a3
"429": *a4
/api/labs:
get:
tags:
@@ -18498,6 +18525,37 @@ components:
- data
- error
additionalProperties: false
MeasurementReminderCompleteEnvelope:
type: object
properties:
data:
$ref: "#/components/schemas/MeasurementReminderCompletion"
error:
type: "null"
meta:
type: object
properties:
requestId:
type: string
additionalProperties: false
required:
- data
- error
additionalProperties: false
MeasurementReminderCompletion:
type: object
properties:
completed:
type: boolean
reminder:
$ref: "#/components/schemas/MeasurementReminderDTO"
required:
- completed
- reminder
additionalProperties: false
description: Result of an explicit reminder completion. completed=true when this call advanced lastSatisfiedAt;
completed=false when an earlier satisfy or a matching reading had already fulfilled the current cycle
(idempotent no-op). reminder is the canonical post-completion DTO.
ListLabResultsEnvelope:
type: object
properties: