From 4c9dc2be5b26c5f2dbb2b11861626a2d34659970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 23 Oct 2026 11:30:28 +0200 Subject: [PATCH 1/4] test(medications): pin the dose correction and undo before they move --- ...on-intake-event.01-take-in-place.json.snap | 408 ++++++++++++ ...cation-intake-event.02-skip-flip.json.snap | 423 +++++++++++++ ...ion-intake-event.03-move-by-band.json.snap | 420 +++++++++++++ ...on-intake-event.04-pin-free-slot.json.snap | 457 ++++++++++++++ ...n-intake-event.05-pin-not-a-slot.json.snap | 442 +++++++++++++ ...ion-intake-event.06-pin-occupied.json.snap | 442 +++++++++++++ ...medication-intake-event.07-unpin.json.snap | 494 +++++++++++++++ ...on-intake-event.08-explicit-slot.json.snap | 533 ++++++++++++++++ ...ion-intake-event.09-before-start.json.snap | 518 ++++++++++++++++ ...dication-intake-event.10-invalid.json.snap | 534 ++++++++++++++++ ...tion-intake-event.11a-tombstoned.json.snap | 513 +++++++++++++++ ...ntake-event.11b-other-medication.json.snap | 513 +++++++++++++++ ...dication-intake-event.12a-writer.json.snap | 518 ++++++++++++++++ ...ication-intake-event.12b-manager.json.snap | 561 +++++++++++++++++ ...cation-intake-event.13-anonymous.json.snap | 532 ++++++++++++++++ ...edication-intake-event.21-delete.json.snap | 553 +++++++++++++++++ ...-intake-event.22-delete-one-shot.json.snap | 572 +++++++++++++++++ ...intake-event.23-other-medication.json.snap | 559 +++++++++++++++++ ...dication-intake-event.24a-writer.json.snap | 564 +++++++++++++++++ ...ication-intake-event.24b-manager.json.snap | 583 ++++++++++++++++++ ...cation-intake-event.25-anonymous.json.snap | 572 +++++++++++++++++ .../medication-intake-event.parity.test.ts | 384 ++++++++++++ .../routes/parity/medication-state.ts | 226 +++++++ 23 files changed, 11321 insertions(+) create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.01-take-in-place.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.02-skip-flip.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.03-move-by-band.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.04-pin-free-slot.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.05-pin-not-a-slot.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.06-pin-occupied.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.07-unpin.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.08-explicit-slot.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.09-before-start.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.10-invalid.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.11a-tombstoned.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.11b-other-medication.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.12a-writer.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.12b-manager.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.13-anonymous.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.21-delete.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.22-delete-one-shot.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.23-other-medication.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.24a-writer.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.24b-manager.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medication-intake-event.25-anonymous.json.snap create mode 100644 tests/integration/routes/parity/medication-intake-event.parity.test.ts create mode 100644 tests/integration/routes/parity/medication-state.ts diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.01-take-in-place.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.01-take-in-place.json.snap new file mode 100644 index 000000000..6ce397312 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.01-take-in-place.json.snap @@ -0,0 +1,408 @@ +{ + "status": 200, + "body": { + "data": { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.intake.update", + "entity_type": "intake_event", + "entity_id": "" + }, + "meta": { + "medication_id": "", + "units": 1, + "item_ids": [ + "" + ], + "auto_opened": 1 + }, + "warnings": null, + "error": null + } + ], + "effects": [ + { + "effect": "queueMedicationIntakeSync", + "args": [ + { + "userId": "", + "originDeviceToken": null + } + ] + } + ], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": [ + { + "units": 1, + "itemId": "" + } + ], + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": null, + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "29", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.02-skip-flip.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.02-skip-flip.json.snap new file mode 100644 index 000000000..f264ae601 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.02-skip-flip.json.snap @@ -0,0 +1,423 @@ +{ + "status": 200, + "body": { + "data": { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": [ + { + "units": 1, + "itemId": "" + } + ], + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.intake.update", + "entity_type": "intake_event", + "entity_id": "" + }, + "meta": { + "medication_id": "", + "units": 1, + "item_ids": [ + "" + ] + }, + "warnings": null, + "error": null + } + ], + "effects": [ + { + "effect": "queueMedicationIntakeSync", + "args": [ + { + "userId": "", + "originDeviceToken": null + } + ] + } + ], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": null, + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.03-move-by-band.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.03-move-by-band.json.snap new file mode 100644 index 000000000..cef0085b9 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.03-move-by-band.json.snap @@ -0,0 +1,420 @@ +{ + "status": 200, + "body": { + "data": { + "id": "", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "idempotencyKey": null, + "scheduledFor": "2026-10-14T20:00:00.000Z", + "source": "WEB", + "createdAt": "" + }, + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.intake.update", + "entity_type": "intake_event", + "entity_id": "" + }, + "meta": { + "medication_id": "" + }, + "warnings": null, + "error": null + } + ], + "effects": [ + { + "effect": "queueMedicationIntakeSync", + "args": [ + { + "userId": "", + "originDeviceToken": null + } + ] + } + ], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.04-pin-free-slot.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.04-pin-free-slot.json.snap new file mode 100644 index 000000000..292c4f3a2 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.04-pin-free-slot.json.snap @@ -0,0 +1,457 @@ +{ + "status": 200, + "body": { + "data": { + "id": "", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "idempotencyKey": null, + "scheduledFor": "2026-10-12T20:00:00.000Z", + "source": "WEB", + "createdAt": "" + }, + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.intake.update", + "entity_type": "intake_event", + "entity_id": "" + }, + "meta": { + "medication_id": "" + }, + "warnings": null, + "error": null + } + ], + "effects": [ + { + "effect": "queueMedicationIntakeSync", + "args": [ + { + "userId": "", + "originDeviceToken": null + } + ] + } + ], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.05-pin-not-a-slot.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.05-pin-not-a-slot.json.snap new file mode 100644 index 000000000..c6e364cd5 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.05-pin-not-a-slot.json.snap @@ -0,0 +1,442 @@ +{ + "status": 422, + "body": { + "data": null, + "error": "forceSlotInstant is not a scheduled slot of this medication", + "meta": { + "errorCode": "medications.intake.force_slot.invalid", + "requestId": "" + } + }, + "events": [ + { + "status": 422, + "action": { + "name": "medication.intake.force_slot.invalid" + }, + "meta": { + "medication_id": "", + "event_id": "" + }, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.06-pin-occupied.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.06-pin-occupied.json.snap new file mode 100644 index 000000000..5e081753f --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.06-pin-occupied.json.snap @@ -0,0 +1,442 @@ +{ + "status": 422, + "body": { + "data": null, + "error": "forceSlotInstant already carries a recorded dose action", + "meta": { + "errorCode": "medications.intake.force_slot.occupied", + "requestId": "" + } + }, + "events": [ + { + "status": 422, + "action": { + "name": "medication.intake.force_slot.occupied" + }, + "meta": { + "medication_id": "", + "event_id": "" + }, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.07-unpin.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.07-unpin.json.snap new file mode 100644 index 000000000..99fba82d2 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.07-unpin.json.snap @@ -0,0 +1,494 @@ +{ + "status": 200, + "body": { + "data": { + "id": "", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "idempotencyKey": null, + "scheduledFor": "2026-10-13T20:00:00.000Z", + "source": "WEB", + "createdAt": "" + }, + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.intake.update", + "entity_type": "intake_event", + "entity_id": "" + }, + "meta": { + "medication_id": "" + }, + "warnings": null, + "error": null + } + ], + "effects": [ + { + "effect": "queueMedicationIntakeSync", + "args": [ + { + "userId": "", + "originDeviceToken": null + } + ] + } + ], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.08-explicit-slot.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.08-explicit-slot.json.snap new file mode 100644 index 000000000..8ca547dfa --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.08-explicit-slot.json.snap @@ -0,0 +1,533 @@ +{ + "status": 200, + "body": { + "data": { + "id": "", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "idempotencyKey": null, + "scheduledFor": "2026-10-14T08:00:00.000Z", + "source": "WEB", + "createdAt": "" + }, + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.intake.update", + "entity_type": "intake_event", + "entity_id": "" + }, + "meta": { + "medication_id": "" + }, + "warnings": null, + "error": null + } + ], + "effects": [ + { + "effect": "queueMedicationIntakeSync", + "args": [ + { + "userId": "", + "originDeviceToken": null + } + ] + } + ], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.09-before-start.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.09-before-start.json.snap new file mode 100644 index 000000000..84475f2d0 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.09-before-start.json.snap @@ -0,0 +1,518 @@ +{ + "status": 422, + "body": { + "data": null, + "error": "takenAt is before the medication's start date", + "meta": { + "errorCode": "medications.intake.taken_at.before_start", + "requestId": "" + } + }, + "events": [ + { + "status": 422, + "action": { + "name": "medications.intake.event.update.before-start-date" + }, + "meta": { + "medication_id": "", + "event_id": "" + }, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.10-invalid.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.10-invalid.json.snap new file mode 100644 index 000000000..e78d84965 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.10-invalid.json.snap @@ -0,0 +1,534 @@ +{ + "status": 422, + "body": { + "data": null, + "error": "Validation failed", + "details": { + "issues": [ + { + "path": "takenAt", + "code": "invalid_format", + "message": "Invalid ISO datetime" + }, + { + "path": "skipped", + "code": "invalid_type", + "message": "Invalid input: expected boolean, received string" + } + ] + }, + "meta": { + "errorCode": "http.invalid", + "requestId": "" + } + }, + "events": [ + { + "status": 422, + "action": { + "name": "medications.intake.event.update.validation-failed" + }, + "meta": { + "issue_count": 2, + "medication_id": "", + "event_id": "", + "rejected_attempt": "medications.intake.event.update.validation-failed" + }, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.11a-tombstoned.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.11a-tombstoned.json.snap new file mode 100644 index 000000000..7a2824812 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.11a-tombstoned.json.snap @@ -0,0 +1,513 @@ +{ + "status": 404, + "body": { + "data": null, + "error": "Intake not found", + "meta": { + "errorCode": "http.not_found", + "requestId": "" + } + }, + "events": [ + { + "status": 404, + "action": null, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.11b-other-medication.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.11b-other-medication.json.snap new file mode 100644 index 000000000..7a2824812 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.11b-other-medication.json.snap @@ -0,0 +1,513 @@ +{ + "status": 404, + "body": { + "data": null, + "error": "Intake not found", + "meta": { + "errorCode": "http.not_found", + "requestId": "" + } + }, + "events": [ + { + "status": 404, + "action": null, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.12a-writer.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.12a-writer.json.snap new file mode 100644 index 000000000..5cc86ab63 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.12a-writer.json.snap @@ -0,0 +1,518 @@ +{ + "status": 403, + "body": { + "data": null, + "error": "Account access denied", + "meta": { + "errorCode": "sharing.access.denied", + "requestId": "" + } + }, + "events": [ + { + "status": 403, + "action": null, + "meta": { + "sharing_refusal": "insufficient_access" + }, + "warnings": null, + "error": { + "type": "SharingAccessDeniedError", + "message": "Account access denied" + } + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.12b-manager.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.12b-manager.json.snap new file mode 100644 index 000000000..d3b8934ca --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.12b-manager.json.snap @@ -0,0 +1,561 @@ +{ + "status": 200, + "body": { + "data": { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:50:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.intake.update", + "entity_type": "intake_event", + "entity_id": "" + }, + "meta": { + "medication_id": "" + }, + "warnings": null, + "error": null + } + ], + "effects": [ + { + "effect": "queueMedicationIntakeSync", + "args": [ + { + "userId": "", + "originDeviceToken": null + } + ] + } + ], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:50:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": "", + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": "2026-10-13T20:15:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.13-anonymous.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.13-anonymous.json.snap new file mode 100644 index 000000000..a1e963e0d --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.13-anonymous.json.snap @@ -0,0 +1,532 @@ +{ + "status": 401, + "body": { + "data": null, + "error": "Not authenticated", + "meta": { + "errorCode": "auth.missing", + "requestId": "" + } + }, + "events": [ + { + "status": 401, + "action": null, + "meta": null, + "warnings": null, + "error": { + "type": "HttpError", + "message": "Not authenticated" + } + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:50:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": "", + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": "2026-10-13T20:15:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.21-delete.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.21-delete.json.snap new file mode 100644 index 000000000..4658173e8 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.21-delete.json.snap @@ -0,0 +1,553 @@ +{ + "status": 200, + "body": { + "data": { + "deleted": true + }, + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.intake.delete", + "entity_type": "intake_event", + "entity_id": "" + }, + "meta": { + "medication_id": "" + }, + "warnings": null, + "error": null + } + ], + "effects": [ + { + "effect": "queueMedicationIntakeSync", + "args": [ + { + "userId": "", + "originDeviceToken": null + } + ] + } + ], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": false, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:50:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": "", + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": "2026-10-13T20:15:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.22-delete-one-shot.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.22-delete-one-shot.json.snap new file mode 100644 index 000000000..7bc6ba40a --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.22-delete-one-shot.json.snap @@ -0,0 +1,572 @@ +{ + "status": 200, + "body": { + "data": { + "deleted": true + }, + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.oneShot.reconciled" + }, + "meta": { + "medication_id": "", + "action": "activate" + }, + "warnings": null, + "error": null + } + ], + "effects": [ + { + "effect": "queueMedicationIntakeSync", + "args": [ + { + "userId": "", + "originDeviceToken": null + } + ] + } + ], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:50:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": "", + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": "2026-10-13T20:15:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + }, + { + "action": "medication.oneShot.reconciled", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "action": "activate" + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.23-other-medication.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.23-other-medication.json.snap new file mode 100644 index 000000000..c7950a1eb --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.23-other-medication.json.snap @@ -0,0 +1,559 @@ +{ + "status": 404, + "body": { + "data": null, + "error": "Intake not found", + "meta": { + "errorCode": "http.not_found", + "requestId": "" + } + }, + "events": [ + { + "status": 404, + "action": null, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:50:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": "", + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": "2026-10-13T20:15:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + }, + { + "action": "medication.oneShot.reconciled", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "action": "activate" + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.24a-writer.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.24a-writer.json.snap new file mode 100644 index 000000000..9ae53c9b8 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.24a-writer.json.snap @@ -0,0 +1,564 @@ +{ + "status": 403, + "body": { + "data": null, + "error": "Account access denied", + "meta": { + "errorCode": "sharing.access.denied", + "requestId": "" + } + }, + "events": [ + { + "status": 403, + "action": null, + "meta": { + "sharing_refusal": "insufficient_access" + }, + "warnings": null, + "error": { + "type": "SharingAccessDeniedError", + "message": "Account access denied" + } + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:50:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": "", + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": "2026-10-13T20:15:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + }, + { + "action": "medication.oneShot.reconciled", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "action": "activate" + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.24b-manager.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.24b-manager.json.snap new file mode 100644 index 000000000..32e1401fb --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.24b-manager.json.snap @@ -0,0 +1,583 @@ +{ + "status": 200, + "body": { + "data": { + "deleted": true + }, + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.intake.delete", + "entity_type": "intake_event", + "entity_id": "" + }, + "meta": { + "medication_id": "" + }, + "warnings": null, + "error": null + } + ], + "effects": [ + { + "effect": "queueMedicationIntakeSync", + "args": [ + { + "userId": "", + "originDeviceToken": null + } + ] + } + ], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:50:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": "", + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": "", + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": "2026-10-13T20:15:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + }, + { + "action": "medication.oneShot.reconciled", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "action": "activate" + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medication-intake-event.25-anonymous.json.snap b/tests/integration/routes/parity/__snapshots__/medication-intake-event.25-anonymous.json.snap new file mode 100644 index 000000000..9d3d932eb --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medication-intake-event.25-anonymous.json.snap @@ -0,0 +1,572 @@ +{ + "status": 401, + "body": { + "data": null, + "error": "Not authenticated", + "meta": { + "errorCode": "auth.missing", + "requestId": "" + } + }, + "events": [ + { + "status": 401, + "action": null, + "meta": null, + "warnings": null, + "error": { + "type": "HttpError", + "message": "Not authenticated" + } + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Parity one-shot", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Parity tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": "Morning", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "20:00", + "windowEnd": "22:00", + "label": "Evening", + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [ + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-10T09:00:00.000Z", + "takenAt": "2026-10-10T09:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T08:00:00.000Z", + "takenAt": "2026-10-11T08:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-11T20:00:00.000Z", + "takenAt": "2026-10-11T20:20:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T08:00:00.000Z", + "takenAt": "2026-10-12T08:05:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "2026-10-12T09:00:00.000Z" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-12T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "USER_PIN", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T08:00:00.000Z", + "takenAt": "2026-10-13T08:40:00.000Z", + "skipped": true, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:15:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-13T20:00:00.000Z", + "takenAt": "2026-10-13T20:50:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:45:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": null + }, + { + "id": "", + "userId": "", + "medicationId": "", + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z", + "skipped": false, + "autoMissed": false, + "autoRecorded": false, + "attributionSource": "AUTO", + "source": "WEB", + "idempotencyKey": null, + "createdAt": "", + "injectionSite": null, + "doseTaken": null, + "inventoryConsumption": null, + "externalId": null, + "updatedAt": "", + "syncVersion": "", + "deletedAt": "" + } + ], + "doseChanges": [], + "inventoryItems": [ + { + "id": "", + "userId": "", + "medicationId": "", + "state": "IN_USE", + "containerType": "OTHER", + "unitsTotal": "30", + "unitsRemaining": "30", + "firstUseAt": "2026-10-13T08:40:00.000Z", + "expiresAt": null, + "printedExpiry": null, + "purchasedAt": "2026-10-01T06:00:00.000Z", + "manufacturer": null, + "doseStrength": null, + "notes": null, + "notesEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [ + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": "", + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.delete", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "" + }, + "ipAddress": "unknown" + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": "", + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": "2026-10-13T20:15:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T08:00:00.000Z", + "takenAt": "2026-10-14T08:10:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor", + "takenAt" + ], + "previous": { + "scheduledFor": "2026-10-14T20:00:00.000Z", + "takenAt": "2026-10-14T20:30:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-12T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "scheduledFor" + ], + "previous": { + "scheduledFor": "2026-10-13T20:00:00.000Z" + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "skipped" + ], + "previous": { + "skipped": false + } + }, + "ipAddress": null + }, + { + "action": "medication.intake.update", + "userId": "", + "actorUserId": null, + "details": { + "eventId": "", + "medicationId": "", + "fields": [ + "takenAt" + ], + "previous": { + "takenAt": null + } + }, + "ipAddress": null + }, + { + "action": "medication.oneShot.reconciled", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "action": "activate" + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/medication-intake-event.parity.test.ts b/tests/integration/routes/parity/medication-intake-event.parity.test.ts new file mode 100644 index 000000000..415422a60 --- /dev/null +++ b/tests/integration/routes/parity/medication-intake-event.parity.test.ts @@ -0,0 +1,384 @@ +/** + * Parity for `PUT` and `DELETE /api/medications/{id}/intake/{eventId}` while + * the dose correction moves into `src/lib/medications/`. + * + * One record walks through the corrections the route tells apart, in order, + * each request seeing what the earlier ones stored: a take recorded in place, + * a take flipped to a skip, a correction that moves the dose to another slot + * (tombstone and converge), a pin onto a free slot, the two pin refusals, an + * unpin, an explicit slot, a take before the start day, a body the schema + * refuses, the not-found answers, and the same correction from a delegate who + * may only write and one who may manage. Then the deletes: the owner's, one + * that reactivates a one-shot medication, the not-found answer, and both + * delegates again. After each request the snapshot holds the response, the + * wide event, the recorded tails and every medication row of the accounts. + * + * The clock is pinned (`Date` only), so the snapshot is the same on every + * day it runs. + */ +import { afterAll, beforeAll, describe, it, vi } from "vitest"; + +import { DELETE, PUT } from "@/app/api/medications/[id]/intake/[eventId]/route"; + +import { anonymous, type RouteAuth } from "../../../kit/call-route"; +import { makeMedication, makeSession, makeUser } from "../../../kit/factories"; +import { getPrismaClient, truncateAllTables } from "../../setup"; +import { delegateOf, parityStep } from "./medication-state"; + +vi.mock("@/lib/logging/transports", async (importOriginal) => { + const actual = + await importOriginal(); + const { wideEventRecorder: recorder } = await import("../../../kit/parity"); + return { + ...actual, + emitIfSampled: (event: (typeof recorder.events)[number]) => { + recorder.events.push(event); + }, + }; +}); + +// The cross-device push the route queues on a timer, recorded instead of run +// (see `effectRecorder`). +vi.mock( + "@/lib/notifications/medication-intake-sync", + async (importOriginal) => { + const actual = + await importOriginal< + typeof import("@/lib/notifications/medication-intake-sync") + >(); + const { effectRecorder } = await import("../../../kit/parity"); + return { + ...actual, + queueMedicationIntakeSync: (...args: unknown[]) => { + effectRecorder.record("queueMedicationIntakeSync", args); + }, + }; + }, +); + +const prisma = getPrismaClient(); +const NOW = new Date("2026-10-15T12:00:00.000Z"); +const ROUTE = "/api/medications/{id}/intake/{eventId}"; +/** + * A correction that moves the dose answers with the row the shared slot write + * returns, which carries fewer fields than the registered event resource. The + * parity snapshot pins that answer as it is; the contract check is the + * route's own tests' business. + */ +const SLOT_MOVE_ANSWER = { + skip: "a slot move answers with the narrower slot-write row", +}; + +let ownerId: string; +let userIds: string[]; +let owner: RouteAuth; +let writer: { auth: RouteAuth; headers: Record }; +let manager: { auth: RouteAuth; headers: Record }; +let medicationId: string; +let oneShotId: string; +const events: Record = {}; + +async function put( + name: string, + eventId: string, + body: unknown, + options: { + auth?: RouteAuth; + headers?: Record; + medicationId?: string; + contract?: { skip: string }; + } = {}, +) { + return parityStep({ + name: `medication-intake-event.${name}`, + handler: PUT, + options: { + method: "PUT", + route: ROUTE, + params: { id: options.medicationId ?? medicationId, eventId }, + body, + auth: options.auth ?? owner, + headers: options.headers, + contract: options.contract, + }, + userIds, + now: NOW, + }); +} + +async function del( + name: string, + eventId: string, + options: { + auth?: RouteAuth; + headers?: Record; + medicationId?: string; + } = {}, +) { + return parityStep({ + name: `medication-intake-event.${name}`, + handler: DELETE, + options: { + method: "DELETE", + route: ROUTE, + params: { id: options.medicationId ?? medicationId, eventId }, + auth: options.auth ?? owner, + headers: options.headers, + }, + userIds, + now: NOW, + }); +} + +async function intake( + medication: string, + key: string, + data: { + scheduledFor: string; + takenAt?: string | null; + skipped?: boolean; + deletedAt?: string; + }, +) { + const row = await prisma.medicationIntakeEvent.create({ + data: { + userId: ownerId, + medicationId: medication, + scheduledFor: new Date(data.scheduledFor), + takenAt: data.takenAt ? new Date(data.takenAt) : null, + skipped: data.skipped ?? false, + deletedAt: data.deletedAt ? new Date(data.deletedAt) : null, + }, + }); + events[key] = row.id; +} + +beforeAll(async () => { + vi.useFakeTimers({ toFake: ["Date"], now: NOW }); + await truncateAllTables(prisma); + const user = await makeUser({ timezone: "UTC" }); + ownerId = user.id; + owner = await makeSession(user); + const created = new Date("2026-10-01T06:00:00.000Z"); + const medication = await makeMedication( + user, + { + name: "Parity tablet", + startsOn: new Date("2026-10-01"), + createdAt: created, + unitsPerDose: 1, + }, + [ + { windowStart: "08:00", windowEnd: "10:00", label: "Morning" }, + { windowStart: "20:00", windowEnd: "22:00", label: "Evening" }, + ], + ); + medicationId = medication.id; + await prisma.medicationInventoryItem.create({ + data: { + userId: ownerId, + medicationId, + unitsTotal: 30, + unitsRemaining: 30, + purchasedAt: created, + }, + }); + const oneShot = await makeMedication( + user, + { + name: "Parity one-shot", + startsOn: new Date("2026-10-01"), + createdAt: created, + oneShot: true, + active: false, + }, + [{ windowStart: "09:00", windowEnd: "11:00" }], + ); + oneShotId = oneShot.id; + + await intake(medicationId, "pending", { + scheduledFor: "2026-10-13T08:00:00.000Z", + }); + await intake(medicationId, "legacyTaken", { + scheduledFor: "2026-10-13T20:00:00.000Z", + takenAt: "2026-10-13T20:15:00.000Z", + }); + await intake(medicationId, "morningTaken", { + scheduledFor: "2026-10-14T08:00:00.000Z", + takenAt: "2026-10-14T08:10:00.000Z", + }); + await intake(medicationId, "eveningSkipped", { + scheduledFor: "2026-10-14T20:00:00.000Z", + skipped: true, + }); + await intake(medicationId, "tombstoned", { + scheduledFor: "2026-10-12T08:00:00.000Z", + takenAt: "2026-10-12T08:05:00.000Z", + deletedAt: "2026-10-12T09:00:00.000Z", + }); + await intake(medicationId, "forDelete", { + scheduledFor: "2026-10-11T08:00:00.000Z", + takenAt: "2026-10-11T08:20:00.000Z", + }); + await intake(medicationId, "forManagerDelete", { + scheduledFor: "2026-10-11T20:00:00.000Z", + takenAt: "2026-10-11T20:20:00.000Z", + }); + await intake(oneShotId, "oneShotDose", { + scheduledFor: "2026-10-10T09:00:00.000Z", + takenAt: "2026-10-10T09:30:00.000Z", + }); + + const w = await delegateOf(prisma, user, "WRITE"); + const m = await delegateOf(prisma, user, "MANAGE"); + writer = { auth: w.auth, headers: w.headers }; + manager = { auth: m.auth, headers: m.headers }; + userIds = [ownerId, w.delegate.id, m.delegate.id]; +}); + +afterAll(() => { + vi.useRealTimers(); +}); + +describe("PUT /api/medications/{id}/intake/{eventId} parity", () => { + it("01 a pending dose taken inside its own window", async () => { + await put("01-take-in-place", events.pending, { + takenAt: "2026-10-13T08:40:00.000Z", + }); + }); + + it("02 the same dose flipped to a skip", async () => { + await put("02-skip-flip", events.pending, { skipped: true }); + }); + + it("03 a take corrected into the other window, onto a skipped slot", async () => { + const res = await put( + "03-move-by-band", + events.morningTaken, + { takenAt: "2026-10-14T20:30:00.000Z" }, + { contract: SLOT_MOVE_ANSWER }, + ); + events.moved = (res.data as { id: string }).id; + }); + + it("04 a legacy take pinned onto a free slot", async () => { + const res = await put( + "04-pin-free-slot", + events.legacyTaken, + { forceSlotInstant: "2026-10-12T20:00:00.000Z" }, + { contract: SLOT_MOVE_ANSWER }, + ); + events.pinned = (res.data as { id: string }).id; + }); + + it("05 a pin onto an instant that is no slot", async () => { + await put("05-pin-not-a-slot", events.moved, { + forceSlotInstant: "2026-10-12T15:00:00.000Z", + }); + }); + + it("06 a pin onto a slot another dose holds", async () => { + await put("06-pin-occupied", events.moved, { + forceSlotInstant: "2026-10-12T20:00:00.000Z", + }); + }); + + it("07 an unpin", async () => { + const res = await put( + "07-unpin", + events.pinned, + { forceSlotInstant: null }, + { contract: SLOT_MOVE_ANSWER }, + ); + events.pinned = (res.data as { id: string }).id; + }); + + it("08 an explicit slot in the body", async () => { + const res = await put( + "08-explicit-slot", + events.moved, + { + scheduledFor: "2026-10-14T08:00:00.000Z", + takenAt: "2026-10-14T08:45:00.000Z", + }, + { contract: SLOT_MOVE_ANSWER }, + ); + events.moved = (res.data as { id: string }).id; + }); + + it("09 a take before the start day", async () => { + await put("09-before-start", events.pinned, { + takenAt: "2026-09-20T08:00:00.000Z", + }); + }); + + it("10 a body the schema refuses", async () => { + await put("10-invalid", events.pinned, { + takenAt: "yesterday", + skipped: "no", + }); + }); + + it("11 a tombstoned dose, and a dose under another medication", async () => { + await put("11a-tombstoned", events.tombstoned, { skipped: true }); + await put( + "11b-other-medication", + events.pinned, + { skipped: true }, + { medicationId: oneShotId }, + ); + }); + + it("12 a delegate who may write, and one who may manage", async () => { + await put( + "12a-writer", + events.pinned, + { takenAt: "2026-10-13T20:50:00.000Z" }, + writer, + ); + await put( + "12b-manager", + events.pinned, + { takenAt: "2026-10-13T20:50:00.000Z" }, + manager, + ); + }); + + it("13 no credentials", async () => { + await put( + "13-anonymous", + events.pinned, + { skipped: true }, + { + auth: anonymous, + }, + ); + }); +}); + +describe("DELETE /api/medications/{id}/intake/{eventId} parity", () => { + it("21 the owner undoes a dose", async () => { + await del("21-delete", events.forDelete); + }); + + it("22 undoing the only dose of a one-shot medication", async () => { + await del("22-delete-one-shot", events.oneShotDose, { + medicationId: oneShotId, + }); + }); + + it("23 a dose under another medication", async () => { + await del("23-other-medication", events.forManagerDelete, { + medicationId: oneShotId, + }); + }); + + it("24 a delegate who may write, and one who may manage", async () => { + await del("24a-writer", events.forManagerDelete, writer); + await del("24b-manager", events.forManagerDelete, manager); + }); + + it("25 no credentials", async () => { + await del("25-anonymous", events.forDelete, { auth: anonymous }); + }); +}); diff --git a/tests/integration/routes/parity/medication-state.ts b/tests/integration/routes/parity/medication-state.ts new file mode 100644 index 000000000..1103d75fa --- /dev/null +++ b/tests/integration/routes/parity/medication-state.ts @@ -0,0 +1,226 @@ +/** + * What a medication route leaves in the database, read back for a parity + * snapshot (see `tests/kit/parity.ts`). + * + * Whole rows, not a hand-picked select: a parity snapshot is meant to notice + * a column the moved code stops writing, and a select names only the columns + * somebody thought of. Two kinds of value are rewritten before the snapshot + * sees them, because their bytes differ between two runs of the same code: + * ciphertext (a fresh IV per write) reads as `` or ``, and + * a Prisma `Decimal` reads as its decimal string. + * + * Rows come back in an order decided by their content with generated ids + * blanked, never by the ids themselves, so two runs list them alike. + */ +import { Prisma, type User } from "@/generated/prisma/client"; +import type { AccountGrantAccess } from "@/generated/prisma/enums"; + +import { expect } from "vitest"; + +import { callRoute, type CallRouteOptions } from "../../../kit/call-route"; +import type { SessionFixture } from "../../../kit/factories"; +import { makeGrant, makeSession, makeUser } from "../../../kit/factories"; +import { + effectRecorder, + eventFacts, + expectParity, + stable, + wideEventRecorder, +} from "../../../kit/parity"; +import { getPrismaClient } from "../../setup"; + +type Client = ReturnType; + +/** + * A second account holding a grant of `access` over `owner`'s record, with + * its session switched onto that record and the headers a switched browser + * sends with every request. + */ +export async function delegateOf( + prisma: Client, + owner: Pick, + access: AccountGrantAccess, +): Promise<{ + delegate: User; + auth: SessionFixture; + headers: Record; +}> { + const delegate = await makeUser({ timezone: "UTC" }); + await makeGrant(owner, delegate, { access }); + const auth = await makeSession(delegate); + const switched = await prisma.session.update({ + where: { id: auth.sessionId }, + data: { actingAsUserId: owner.id }, + }); + return { + delegate, + auth, + headers: { + "x-healthlog-record-epoch": String(switched.recordEpoch), + "x-healthlog-record-scope": owner.id, + }, + }; +} + +const GENERATED_ID = + /^(c[a-z0-9]{24}|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/; +/** Audit rows the record guard writes without awaiting them. */ +const GUARD_TRAIL_ACTIONS = [ + "sharing.record.accessed", + "sharing.access.denied", +] as const; +const ORDER_BLIND_KEYS = new Set(["createdAt", "updatedAt", "syncVersion"]); + +/** A copy with ciphertext and decimals replaced by stable stand-ins. */ +export function plain(value: unknown): unknown { + if (value === null || value === undefined) return value; + if (value instanceof Date) return value; + if (Prisma.Decimal.isDecimal(value)) return value.toString(); + if (value instanceof Uint8Array) return ""; + if (Array.isArray(value)) return value.map(plain); + if (typeof value === "object") { + const out: Record = {}; + for (const [k, v] of Object.entries(value)) { + out[k] = /Encrypted$/.test(k) && v !== null ? "" : plain(v); + } + return out; + } + return value; +} + +function orderKey(value: unknown): string { + return JSON.stringify(value, (key, v: unknown) => { + if (ORDER_BLIND_KEYS.has(key)) return undefined; + if (typeof v === "string" && GENERATED_ID.test(v)) return ""; + return v; + }); +} + +/** Rows in content order, ids and stamps left out of the comparison. */ +export function sortRows(rows: readonly T[]): unknown[] { + return rows + .map(plain) + .map((row) => ({ row, key: orderKey(row) })) + .sort((a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0)) + .map(({ row }) => row); +} + +/** + * Every medication table a medication route writes, for the given accounts, + * plus the audit trail and the idempotency cache. The rows the record guard + * writes about a delegate (the day's access row, a refusal) are left out: the + * guard writes them fire-and-forget, so whether one has landed when the test + * reads is a race, not something the route decides. + */ +export async function medicationState(prisma: Client, userIds: string[]) { + const byUser = { userId: { in: userIds } }; + const byMedication = { medication: byUser }; + const [ + medications, + schedules, + revisions, + pauseEras, + courses, + intakes, + doseChanges, + inventoryItems, + inventoryEvents, + categories, + ingredients, + audit, + idempotency, + ] = await Promise.all([ + prisma.medication.findMany({ where: byUser }), + prisma.medicationSchedule.findMany({ where: byMedication }), + prisma.medicationScheduleRevision.findMany({ where: byMedication }), + prisma.medicationPauseEra.findMany({ where: byMedication }), + prisma.medicationCourse.findMany({ where: byMedication }), + prisma.medicationIntakeEvent.findMany({ where: byUser }), + prisma.medicationDoseChange.findMany({ where: byMedication }), + prisma.medicationInventoryItem.findMany({ where: byUser }), + prisma.medicationInventoryEvent.findMany({ where: byMedication }), + prisma.medicationCategoryAssignment.findMany({ where: byMedication }), + prisma.medicationIngredient.findMany({ where: byMedication }), + prisma.auditLog.findMany({ + where: { ...byUser, action: { notIn: [...GUARD_TRAIL_ACTIONS] } }, + select: { + action: true, + userId: true, + actorUserId: true, + details: true, + ipAddress: true, + }, + }), + prisma.idempotencyKey.findMany({ + where: byUser, + select: { + userId: true, + key: true, + method: true, + path: true, + responseStatus: true, + requestFingerprint: true, + expiresAt: true, + }, + }), + ]); + return { + medications: sortRows(medications), + schedules: sortRows(schedules), + revisions: sortRows(revisions), + pauseEras: sortRows(pauseEras), + courses: sortRows(courses), + intakes: sortRows(intakes), + doseChanges: sortRows(doseChanges), + inventoryItems: sortRows(inventoryItems), + inventoryEvents: sortRows(inventoryEvents), + categories: sortRows(categories), + ingredients: sortRows(ingredients), + audit: sortRows( + audit.map((row) => ({ + ...row, + details: row.details ? (JSON.parse(row.details) as unknown) : null, + })), + ), + idempotency: sortRows(idempotency), + }; +} + +export interface ParityCall { + /** Snapshot name, `.`. */ + name: string; + handler: Parameters[0]; + options: CallRouteOptions; + /** Accounts whose rows the snapshot reads back. */ + userIds: string[]; + /** The clock the test pinned; server stamps at or after it read ``. */ + now: Date; +} + +/** + * One request and everything it decided: the response, the wide event, the + * recorded tails and the rows read back afterwards, compared with the + * committed snapshot. Returns the response for a test that needs an id from + * it for the next case. + */ +export async function parityStep(call: ParityCall) { + wideEventRecorder.take(); + effectRecorder.take(); + const res = await callRoute(call.handler, call.options); + const events = wideEventRecorder.take(); + expect(events.length).toBeGreaterThan(0); + await expectParity( + call.name, + stable( + { + status: res.status, + body: res.body, + events: events.map(eventFacts), + effects: effectRecorder.take(), + stored: await medicationState(getPrismaClient(), call.userIds), + }, + { since: call.now }, + ), + ); + return res; +} From 62b050f711a91acf0375bcd6333abc9852ea494a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 23 Oct 2026 11:40:06 +0200 Subject: [PATCH 2/4] refactor(medications): move the dose correction and undo out of their route The PUT handler was one 390-line callback. The route keeps the record resolver, the 404, the body and its schema refusal; the correction moves verbatim into lib/medications/update-intake-event.ts, split along its stages in the order they always ran: the start-day floor, the slot attribution, the in-place edit or the move onto another slot, then the audit row, the event and the tails. The undo moves into delete-intake-event.ts. The route is 124 lines; no function in either module is over 140. The parity walk recorded before the move (medication-intake-event.parity) is unchanged. The sharing guard's audit, tombstone and overwrite legs read the route together with the modules it hands its bodies to, listed in one map that each route must still import, and the moved-dose provenance leg now also asserts the original source is carried. --- src/__tests__/sharing-surface-guard.test.ts | 101 +++- .../[id]/intake/[eventId]/route.ts | 453 ++-------------- src/lib/medications/delete-intake-event.ts | 115 ++++ src/lib/medications/update-intake-event.ts | 503 ++++++++++++++++++ 4 files changed, 734 insertions(+), 438 deletions(-) create mode 100644 src/lib/medications/delete-intake-event.ts create mode 100644 src/lib/medications/update-intake-event.ts diff --git a/src/__tests__/sharing-surface-guard.test.ts b/src/__tests__/sharing-surface-guard.test.ts index 863e0f139..35cfef028 100644 --- a/src/__tests__/sharing-surface-guard.test.ts +++ b/src/__tests__/sharing-surface-guard.test.ts @@ -421,6 +421,50 @@ function callsSymbol(rel: string, symbol: string): boolean { return callSites(rel).some((c) => c.name === symbol); } +/** + * Route modules whose handler bodies live in service modules under `lib/`. + * + * The route keeps the resolver call, so the verb and membership legs read the + * route alone. The legs about what a handler writes (the audit trail, the + * tombstone, the overwrite and destruction details, the provenance a moved + * dose keeps) ask the route AND the modules it hands the body to, because + * that is where the rows are written now. A leg reading only the route would + * go on passing for a reason that has nothing to do with the rule. Each + * listed module has to be imported by its route (leg below), so an entry + * cannot outlive the delegation it describes. + */ +const HANDLER_BODY_MODULES: Record = { + "app/api/medications/[id]/intake/[eventId]/route.ts": [ + "lib/medications/update-intake-event.ts", + "lib/medications/delete-intake-event.ts", + ], +}; + +/** The route and the service modules carrying its handler bodies. */ +function handlerModules(rel: string): string[] { + return [rel, ...(HANDLER_BODY_MODULES[rel] ?? [])]; +} + +function handlerCallsSymbol(rel: string, symbol: string): boolean { + return handlerModules(rel).some((m) => callsSymbol(m, symbol)); +} + +function handlerIdentifiers(rel: string): Set { + return new Set(handlerModules(rel).flatMap((m) => [...identifiers(m)])); +} + +function handlerAuditDetailKeys(rel: string): string[][] { + return handlerModules(rel).flatMap((m) => auditDetailKeysIn(m)); +} + +function handlerDirectAuditWrites(rel: string): string[] { + return handlerModules(rel).flatMap((m) => directAuditWritesIn(read(m), m)); +} + +function handlerText(rel: string): string { + return handlerModules(rel).map(read).join("\n"); +} + /** * v1.37.0 — the exported HTTP verbs whose bodies reach the record resolver at * a given level. @@ -2890,9 +2934,10 @@ describe("(e) the delegable write set is frozen", () => { expect(modules.length).toBeGreaterThan(0); for (const rel of modules) { - expect(callsSymbol(rel, "auditLog"), `${rel} never calls auditLog`).toBe( - true, - ); + expect( + handlerCallsSymbol(rel, "auditLog"), + `${rel} never calls auditLog`, + ).toBe(true); } }); @@ -2912,7 +2957,7 @@ describe("(e) the delegable write set is frozen", () => { for (const rel of modules) { expect( - directAuditWritesIn(read(rel), rel), + handlerDirectAuditWrites(rel), `${rel} writes an audit row without the helper`, ).toEqual([]); } @@ -3029,6 +3074,28 @@ describe("(g) the MANAGE route set is frozen", () => { expect(discovered).toEqual(expected); }); + it("reads each moved handler body where its route imports it from", () => { + // The map above widens what the audit and tombstone legs read. An entry + // naming a module the route no longer imports would widen it to code the + // handler does not run, so every entry is held to the route's imports, + // and every listed module has to carry an audit call of its own. + const entries = Object.entries(HANDLER_BODY_MODULES); + expect(entries.length).toBeGreaterThan(0); + for (const [route, modules] of entries) { + expect(DELEGABLE_ROUTES, route).toHaveProperty([route]); + for (const body of modules) { + const specifier = `@/${body.replace(/\.ts$/, "")}`; + expect(read(route), `${route} does not import ${specifier}`).toContain( + `"${specifier}"`, + ); + expect( + callsSymbol(body, "auditLog"), + `${body} writes no audit row`, + ).toBe(true); + } + } + }); + it("is a subset of the delegable set", () => { // A module cannot manage a record it may not read. The read list is where // each file's argument lives, so a manage entry with no read entry would @@ -3057,16 +3124,17 @@ describe("(g) the MANAGE route set is frozen", () => { expect(mutating.length).toBeGreaterThan(30); for (const rel of mutating) { - expect(callsSymbol(rel, "auditLog"), `${rel} never calls auditLog`).toBe( - true, - ); + expect( + handlerCallsSymbol(rel, "auditLog"), + `${rel} never calls auditLog`, + ).toBe(true); } }); it("no manage module reaches the audit table without the helper", () => { for (const rel of Object.keys(DELEGABLE_MANAGE_ROUTES)) { expect( - directAuditWritesIn(read(rel), rel), + handlerDirectAuditWrites(rel), `${rel} writes an audit row without the helper`, ).toEqual([]); } @@ -3085,7 +3153,7 @@ describe("(g) the MANAGE route set is frozen", () => { for (const rel of destructive) { const entry = DELEGABLE_MANAGE_ROUTES[rel]; - const tombstones = identifiers(rel).has("deletedAt"); + const tombstones = handlerIdentifiers(rel).has("deletedAt"); expect( tombstones || entry.conditions.includes("C3") || @@ -3106,7 +3174,7 @@ describe("(g) the MANAGE route set is frozen", () => { for (const [rel, { keys, why }] of members) { expect(why.trim().length, `${rel} has no reason`).toBeGreaterThan(0); expect(DELEGABLE_MANAGE_ROUTES, rel).toHaveProperty([rel]); - const carried = auditDetailKeysIn(rel); + const carried = handlerAuditDetailKeys(rel); expect(carried.length, `${rel} files no audit details`).toBeGreaterThan( 0, ); @@ -3129,10 +3197,10 @@ describe("(g) the MANAGE route set is frozen", () => { for (const rel of members) { if (rel in MANAGE_RECONSTRUCTION_BY_HAND) continue; expect( - callsSymbol(rel, "destroyedDetails"), + handlerCallsSymbol(rel, "destroyedDetails"), `${rel} carries C3 and never calls destroyedDetails`, ).toBe(true); - const named = auditDetailKeysIn(rel).some((keys) => + const named = handlerAuditDetailKeys(rel).some((keys) => keys.some((key) => /(^id$|Id$)/.test(key)), ); expect(named, `${rel} files no id on any audit details literal`).toBe( @@ -3147,7 +3215,7 @@ describe("(g) the MANAGE route set is frozen", () => { for (const rel of members) { expect( - callsSymbol(rel, "overwriteDetails"), + handlerCallsSymbol(rel, "overwriteDetails"), `${rel} carries C4 and never calls overwriteDetails`, ).toBe(true); } @@ -3328,7 +3396,7 @@ describe("(g) the MANAGE route set is frozen", () => { const medication = "app/api/medications/[id]/route.ts"; expect(manageModulesWith("C7")).toEqual([medication]); - const cadence = auditDetailKeysIn(medication).some( + const cadence = handlerAuditDetailKeys(medication).some( (keys) => keys.includes("replacedCadence") && keys.includes("tombstonedSlotCount"), @@ -3339,14 +3407,15 @@ describe("(g) the MANAGE route set is frozen", () => { expect(manageModulesWith("C8")).toEqual([dose]); // The hardcoded provenance this condition removed. A re-created row that // stamps `WEB` says a human typed a dose that arrived from a device. - expect(read(dose)).not.toContain('createSource: "WEB"'); + expect(handlerText(dose)).not.toContain('createSource: "WEB"'); + expect(handlerText(dose)).toContain("createSource: event.source"); expect(manageModulesWith("C9")).toEqual([ "app/api/medications/[id]/intake/import/route.ts", "app/api/medications/intake/dose-history-import/route.ts", ]); for (const rel of manageModulesWith("C9")) { - const joined = auditDetailKeysIn(rel).some((keys) => + const joined = handlerAuditDetailKeys(rel).some((keys) => keys.includes("jobId"), ); expect(joined, `${rel} enqueues work no audit row names`).toBe(true); diff --git a/src/app/api/medications/[id]/intake/[eventId]/route.ts b/src/app/api/medications/[id]/intake/[eventId]/route.ts index 4eaafb54d..3e5c5cd59 100644 --- a/src/app/api/medications/[id]/intake/[eventId]/route.ts +++ b/src/app/api/medications/[id]/intake/[eventId]/route.ts @@ -1,8 +1,6 @@ -import { prisma } from "@/lib/db"; import { apiHandler, requireRecordAuth } from "@/lib/api-handler"; import { annotate } from "@/lib/logging/context"; import { auditLog } from "@/lib/auth/audit"; -import { overwriteDetails } from "@/lib/sharing/audit-details"; import { apiSuccess, apiError, @@ -13,22 +11,14 @@ import { } from "@/lib/api-response"; import { updateIntakeEventSchema } from "@/lib/validations/medication"; import { - consumeForIntake, - restoreForIntake, -} from "@/lib/medications/inventory/consumption"; -import { reconcileOneShotState } from "@/lib/medications/lifecycle"; -import { invalidateUserMedications } from "@/lib/cache/invalidate"; -import { queueMedicationIntakeSync } from "@/lib/notifications/medication-intake-sync"; -import { refreshDoseSlot } from "@/lib/medications/dose-day-refresh"; -import { dayKeyForUserTz } from "@/lib/measurements/consolidation-tz"; + findEditableIntakeEvent, + updateIntakeEvent, +} from "@/lib/medications/update-intake-event"; import { - applyCanonicalSlotWrite, - findPinConflict, - resolveForcedSlotForWrite, - resolveSlotForWriteByBand, -} from "@/lib/medications/scheduling/slot-upsert"; + deleteIntakeEvent, + findDeletableIntakeEvent, +} from "@/lib/medications/delete-intake-event"; import { NextRequest } from "next/server"; -import { dateOnlyKey } from "@/lib/tz/date-only"; type RouteParams = { params: Promise<{ id: string; eventId: string }> }; @@ -41,13 +31,12 @@ export const PUT = apiHandler( const { id, eventId } = await params; - // v1.7.0 sync — a tombstoned event 404s on PUT; the `deletedAt: null` - // filter refuses to resurrect-edit a soft-deleted intake. - const event = await prisma.medicationIntakeEvent.findFirst({ - where: { id: eventId, deletedAt: null }, + const event = await findEditableIntakeEvent({ + userId: user.id, + medicationId: id, + eventId, }); - - if (!event || event.userId !== user.id || event.medicationId !== id) { + if (!event) { return apiError("Intake not found", 404); } @@ -87,341 +76,20 @@ export const PUT = apiHandler( return returnAllZodIssues(parsed.error, 422); } - const data = parsed.data; - - // v1.15.19 — start-date guard on an edited `takenAt` (audit P0-4). The - // schema bounds the instant to a plausible absolute range; this check - // adds the per-medication floor: a take cannot predate the day the - // medication starts (calendar-day comparison in the user's timezone, so - // a take in the early hours of the start day never false-rejects). - if (data.takenAt instanceof Date) { - const medication = await prisma.medication.findFirst({ - where: { id, userId: user.id }, - select: { startsOn: true }, - }); - if (medication?.startsOn) { - const takenDay = dayKeyForUserTz(data.takenAt, user.timezone); - const startsOnDay = dateOnlyKey(medication.startsOn); - if (takenDay < startsOnDay) { - annotate({ - action: { - name: "medications.intake.event.update.before-start-date", - }, - meta: { medication_id: id, event_id: eventId }, - }); - return apiError( - "takenAt is before the medication's start date", - 422, - { errorCode: "medications.intake.taken_at.before_start" }, - ); - } - } - } - - // The post-edit state of the row (current values where the body omits a - // field) — drives the re-attribution decision. - const nextTakenAt = - data.takenAt !== undefined ? data.takenAt : event.takenAt; - const nextSkipped = - data.skipped !== undefined ? data.skipped : event.skipped; - const takenOrSkippedChanged = - (data.takenAt !== undefined && - data.takenAt?.getTime() !== event.takenAt?.getTime()) || - (data.skipped !== undefined && data.skipped !== event.skipped); - - // v1.15.18 — re-run window-band attribution when the edit moves `takenAt` - // or `skipped`, so an edited time re-binds to the correct slot instead of - // leaving `scheduledFor` stale (audit HIGH-4). Precedence: - // 1. an explicit `scheduledFor` in the body wins (deliberate override); - // 2. else `forceSlotInstant` pins onto a named real slot (422 if it is - // not a slot of this med) — v1.15.20: standalone too, no takenAt / - // skipped change required ("Slot zuordnen" from the ledger kebab), - // and the row is stamped USER_PIN so the read ledger binds it by - // anchor instead of degrading the off-window take back to ad-hoc; - // 3. else an explicit `forceSlotInstant: null` UNPINS (v1.15.20, - // "Zuordnung lösen"): re-attribute the take by band on its takenAt - // (ad-hoc when no band matches). v1.16.0 — the release is itself a - // deliberate binding decision, so the row KEEPS `USER_PIN` - // provenance ("attribution user-fixed": onto a slot OR deliberately - // ad-hoc). The persisted marker is what keeps the nightly slot - // dedup from snapping the released row back into the cluster the - // user just detached it from; - // 4. else a taken edit attributes by band (slot anchor on match, the - // take's own time on a miss → ad-hoc), provenance AUTO; - // 5. a skip / pending edit keeps the existing `scheduledFor` anchor. - let resolvedScheduledFor: Date | undefined = data.scheduledFor; - let attributionSource: "AUTO" | "USER_PIN" | undefined; - if (resolvedScheduledFor === undefined) { - if ( - data.forceSlotInstant !== undefined && - data.forceSlotInstant !== null - ) { - const forced = await resolveForcedSlotForWrite({ - userId: user.id, - medicationId: id, - userTz: user.timezone, - slotInstant: data.forceSlotInstant, - }); - if (forced === null) { - annotate({ - action: { name: "medication.intake.force_slot.invalid" }, - meta: { medication_id: id, event_id: eventId }, - }); - return apiError( - "forceSlotInstant is not a scheduled slot of this medication", - 422, - { errorCode: "medications.intake.force_slot.invalid" }, - ); - } - // v1.16.0 — refuse to pin onto a slot another recorded action - // already serves (excluding the row being edited): the explicit- - // write last-write-wins rule would silently overwrite that dose - // record. The ledger UI only offers the pin for unserved slots, - // so this only fires for stale clients / raw API calls. - if ( - await findPinConflict({ - userId: user.id, - medicationId: id, - canonicalSlot: forced, - incomingTakenAt: nextSkipped ? null : nextTakenAt, - excludeEventId: eventId, - }) - ) { - annotate({ - action: { name: "medication.intake.force_slot.occupied" }, - meta: { medication_id: id, event_id: eventId }, - }); - return apiError( - "forceSlotInstant already carries a recorded dose action", - 422, - { errorCode: "medications.intake.force_slot.occupied" }, - ); - } - resolvedScheduledFor = forced; - attributionSource = "USER_PIN"; - } else if ( - (data.forceSlotInstant === null || takenOrSkippedChanged) && - nextTakenAt !== null && - !nextSkipped - ) { - const attribution = await resolveSlotForWriteByBand({ - userId: user.id, - medicationId: id, - userTz: user.timezone, - takenAt: nextTakenAt, - }); - // band.at on match; the take's own time on a miss (ad-hoc). - resolvedScheduledFor = attribution.slotInstant ?? nextTakenAt; - // v1.16.0 — an explicit unpin stays user-fixed (USER_PIN) even on - // the released row; a plain taken/skipped edit re-attributes AUTO. - attributionSource = - data.forceSlotInstant === null ? "USER_PIN" : "AUTO"; - } else if (data.forceSlotInstant === null) { - // Unpin on a row that is not a confirmed take (skip / pending): - // nothing to re-attribute, but the provenance still resets — a - // skip / pending row anchors on its slot by construction, so there - // is no user-fixed ad-hoc decision to persist. - attributionSource = "AUTO"; - } - // skip / pending edits leave `scheduledFor` on the existing anchor. - } - - const targetScheduledFor = resolvedScheduledFor ?? event.scheduledFor; - const slotMoved = - targetScheduledFor.getTime() !== event.scheduledFor.getTime(); - - // v1.16.10 — transition gate for the inventory hooks below. Only an - // edit moving the row INTO taken may consume; a row that was - // already taken keeps its stamp frozen (a stamped row would no-op - // anyway, and a pre-v1.16.10 taken row — NULL stamp, stock already - // moved by the legacy hook at take time — must never retro-consume - // on a time correction). - const wasTaken = event.takenAt !== null && !event.skipped; - - let updated; - if (!slotMoved) { - // The slot is unchanged — a bare in-place update can never collide with - // a sibling row (it is its own slot). - updated = await prisma.medicationIntakeEvent.update({ - where: { id: eventId }, - data: { - ...(data.takenAt !== undefined && { takenAt: data.takenAt }), - ...(data.skipped !== undefined && { skipped: data.skipped }), - // v1.15.20 — binding provenance: pin / unpin / band re-attribution - // stamps it even when the anchor itself did not move (e.g. a pin - // onto the slot the row already sits on, or an unpin whose band - // re-attribution lands on the same anchor). - ...(attributionSource !== undefined && { attributionSource }), - // v1.42.2 — an edit of the outcome is the person's own record. - ...((data.takenAt !== undefined || data.skipped !== undefined) && { - autoRecorded: false, - }), - // v1.7.0 sync — bump the reconciliation counter on every - // server-side mutation so the `/api/sync/changes` feed echoes a - // monotonic value to paired clients. - syncVersion: { increment: 1 }, - }, - }); - // v1.16.10 — inventory follows the post-edit state: an edit that - // moves the row INTO taken consumes; a row that stays taken keeps - // its stamp untouched (the stamp freezes what the original take - // pulled, even when `unitsPerDose` changed since, and a pre-stamp - // legacy row must not retro-consume); a row edited out of taken - // (skip flip, takenAt cleared) refunds its stamp. - if (nextTakenAt !== null && !nextSkipped) { - if (!wasTaken) { - await consumeForIntake({ - client: prisma, - userId: user.id, - medicationId: id, - eventId, - intakeAt: nextTakenAt, - }); - } - } else { - await restoreForIntake({ - client: prisma, - userId: user.id, - eventId, - }); - } - } else { - // The edit moved the dose to a different slot. Tombstone the original - // row (the iOS "a correction is a tombstone + re-insert" model the - // DELETE handler documents) and route the corrected dose through the - // shared canonical-slot upsert, which converges onto any row already at - // the target slot (a pending REMINDER row) rather than bare-updating - // into an occupied slot and risking a P2002 (audit HIGH-4). - // - // v1.16.10 — refund the source row's consumption stamp BEFORE the - // tombstone; the consume on the converged row below nets the move - // to exactly one consumption. - await restoreForIntake({ - client: prisma, - userId: user.id, - eventId, - }); - await prisma.medicationIntakeEvent.update({ - where: { id: eventId }, - data: { deletedAt: new Date(), syncVersion: { increment: 1 } }, - }); - const applied = await applyCanonicalSlotWrite({ - client: prisma, - userId: user.id, - medicationId: id, - canonicalSlot: targetScheduledFor, - takenAt: nextSkipped ? null : nextTakenAt, - skipped: nextSkipped, - isExplicitTaken: !nextSkipped && nextTakenAt !== null, - isExplicitSkip: nextSkipped, - idempotencyKey: null, - // The converged row keeps the ORIGINAL's provenance. This used - // to be a hardcoded `"WEB"`, which said "somebody typed this in the - // browser" about an Apple Health dose whose time was corrected. Under - // MANAGE the sentence would be wrong about a second person as well. - createSource: event.source, - attributionSource, - // v1.16.9 — a slot move is a re-binding, not a new dose: the - // original row's recorded injection site and dose override ride - // along onto the converged row instead of being tombstoned away. - injectionSite: event.injectionSite, - doseTaken: event.doseTaken, - }); - updated = applied.row; - // A taken source WITHOUT a stamp is a pre-v1.16.10 row whose - // stock moved through the legacy hook: the refund above was a - // no-op, so consuming on the converged row would double-charge — - // skip it. Every other taken outcome nets the move to exactly one - // consumption. - if ( - nextTakenAt !== null && - !nextSkipped && - (!wasTaken || event.inventoryConsumption !== null) - ) { - await consumeForIntake({ - client: prisma, - userId: user.id, - medicationId: id, - eventId: applied.row.id, - intakeAt: nextTakenAt, - }); - } - } - - await auditLog("medication.intake.update", { - userId: user.id, - ipAddress: getClientIp(request), - // What the correction moved. A dose edit changes when a dose is - // recorded as taken, which is exactly what a clinician reads back. - details: { - eventId, - medicationId: id, - ...overwriteDetails({ - before: { - scheduledFor: event.scheduledFor, - takenAt: event.takenAt, - skipped: event.skipped, - }, - // The slot-write result carries the canonical four. The injection - // site and the dose override are not compared here because the move - // path copies them onto the converged row by construction — there is - // no edit of them to report. - after: { - scheduledFor: updated.scheduledFor, - takenAt: updated.takenAt, - skipped: updated.skipped, - }, - }), - }, - }); - - annotate({ - action: { - name: "medication.intake.update", - entity_type: "intake_event", - entity_id: eventId, - }, - meta: { medication_id: id }, - }); - - // v1.4.34 — bust per-user medications + compliance + achievement - // caches so the next read reflects the edited event. - invalidateUserMedications(user.id, { evict: true }); - - // v1.4.39 — refresh the rollup row for both the old + new - // scheduledFor day-keys when the dose moved across a day boundary - // (band re-attribution can move it as well as an explicit edit); if the - // slot is unchanged the second call collapses to a no-op upsert. - await refreshDoseSlot({ - userId: user.id, + const outcome = await updateIntakeEvent({ + user, medicationId: id, - scheduledFor: event.scheduledFor, - tz: user.timezone, - }); - if (slotMoved) { - await refreshDoseSlot({ - userId: user.id, - medicationId: id, - scheduledFor: targetScheduledFor, - tz: user.timezone, - }); - } - - // v1.5.0 — re-evaluate the one-shot active flag. A skip-flip on the - // single live intake of a one-shot medication should reactivate it - // (the dose is no longer logged), and the reverse case should - // deactivate again. No-op for non-one-shot medications. - await reconcileOneShotState(prisma, id, user.id); - - // (#22) — silent cross-device intake sync: an edited dose must - // reconcile on the user's other iOS devices too. Coalesced per user, - // best-effort — never affects the response. - queueMedicationIntakeSync({ - userId: user.id, + eventId, + event, + data: parsed.data, + ipAddress: getClientIp(request), originDeviceToken: request.headers.get("x-device-id"), }); + if (!outcome.ok) { + return apiError(outcome.message, 422, { errorCode: outcome.errorCode }); + } - return apiSuccess(updated); + return apiSuccess(outcome.row); }, ); @@ -433,80 +101,21 @@ export const DELETE = apiHandler( const { id, eventId } = await params; - const event = await prisma.medicationIntakeEvent.findUnique({ - where: { id: eventId }, + const event = await findDeletableIntakeEvent({ + userId: user.id, + medicationId: id, + eventId, }); - - if (!event || event.userId !== user.id || event.medicationId !== id) { + if (!event) { return apiError("Intake not found", 404); } - // v1.16.10 — a deleted dose record refunds its consumption stamp - // (no-op for a never-consumed row; a re-delete finds it cleared). - await restoreForIntake({ - client: prisma, - userId: user.id, - eventId, - }); - - // v1.7.0 sync — soft-delete instead of a hard `delete`. An intake is - // an immutable fact, so a "correction" is a tombstone + re-insert - // (never an in-place edit). Setting `deletedAt` (+ bumping - // `syncVersion`) leaves the row in place so the `/api/sync/changes` - // feed surfaces the deletion as a tombstone keyed on the server `id` - // to paired clients offline at delete time. Every today / compliance - // / list read filters `deletedAt: null`, so the row is invisible to - // normal reads from here on. A re-delete re-bumps harmlessly. - await prisma.medicationIntakeEvent.update({ - where: { id: eventId }, - data: { - deletedAt: new Date(), - syncVersion: { increment: 1 }, - }, - }); - - const ip = getClientIp(request) ?? "unknown"; - await auditLog("medication.intake.delete", { - userId: user.id, - ipAddress: ip, - details: { eventId, medicationId: id }, - }); - - annotate({ - action: { - name: "medication.intake.delete", - entity_type: "intake_event", - entity_id: eventId, - }, - meta: { medication_id: id }, - }); - - // v1.4.34 — bust per-user medications + compliance + achievement - // caches so the next read reflects the deletion. - invalidateUserMedications(user.id, { evict: true }); - - // v1.4.39 — refresh the rollup row for the day the deleted - // event sat on. When that day now holds zero events the helper - // drops the rollup row entirely. - await refreshDoseSlot({ - userId: user.id, + await deleteIntakeEvent({ + user, medicationId: id, - scheduledFor: event.scheduledFor, - tz: user.timezone, - }); - - // v1.5.0 — re-evaluate the one-shot active flag. Deleting the - // single live intake of a one-shot medication reactivates it so - // the dashboard / lists / worker pick it back up. No-op for - // non-one-shot medications. - await reconcileOneShotState(prisma, id, user.id); - - // (#22) — silent cross-device intake sync: an undone dose must - // reconcile on the user's other iOS devices (the widget count and a - // pending Live Activity both change). Coalesced per user, - // best-effort — never affects the response. - queueMedicationIntakeSync({ - userId: user.id, + eventId, + event, + ipAddress: getClientIp(request) ?? "unknown", originDeviceToken: request.headers.get("x-device-id"), }); diff --git a/src/lib/medications/delete-intake-event.ts b/src/lib/medications/delete-intake-event.ts new file mode 100644 index 000000000..1a3c4b96f --- /dev/null +++ b/src/lib/medications/delete-intake-event.ts @@ -0,0 +1,115 @@ +/** + * Undo one recorded dose: `DELETE /api/medications/{id}/intake/{eventId}`. + * + * A soft delete: the row stays, the sync feed carries the tombstone, and the + * inventory stamp is refunded. The route authenticates (MANAGE over the + * `medications` section) and answers the 404; the rest runs here. + */ +import type { MedicationIntakeEvent } from "@/generated/prisma/client"; +import { prisma } from "@/lib/db"; +import { annotate } from "@/lib/logging/context"; +import { auditLog } from "@/lib/auth/audit"; +import type { SessionUser } from "@/lib/auth/session-user"; +import { restoreForIntake } from "@/lib/medications/inventory/consumption"; +import { reconcileOneShotState } from "@/lib/medications/lifecycle"; +import { invalidateUserMedications } from "@/lib/cache/invalidate"; +import { queueMedicationIntakeSync } from "@/lib/notifications/medication-intake-sync"; +import { refreshDoseSlot } from "@/lib/medications/dose-day-refresh"; + +/** + * The event under this medication and record, tombstoned or not (a re-delete + * re-bumps harmlessly), or null for the route's 404. + */ +export async function findDeletableIntakeEvent(input: { + userId: string; + medicationId: string; + eventId: string; +}): Promise { + const event = await prisma.medicationIntakeEvent.findUnique({ + where: { id: input.eventId }, + }); + if ( + !event || + event.userId !== input.userId || + event.medicationId !== input.medicationId + ) { + return null; + } + return event; +} + +export async function deleteIntakeEvent(input: { + user: Pick; + medicationId: string; + eventId: string; + event: MedicationIntakeEvent; + ipAddress: string; + originDeviceToken: string | null; +}): Promise { + const { user, medicationId: id, eventId, event } = input; + + // A deleted dose record refunds its consumption stamp (no-op for a + // never-consumed row; a re-delete finds it cleared). + await restoreForIntake({ + client: prisma, + userId: user.id, + eventId, + }); + + // Sync — soft-delete instead of a hard `delete`. An intake is an immutable + // fact, so a "correction" is a tombstone + re-insert (never an in-place + // edit). Setting `deletedAt` (+ bumping `syncVersion`) leaves the row in + // place so the `/api/sync/changes` feed surfaces the deletion as a + // tombstone keyed on the server `id` to paired clients offline at delete + // time. Every today / compliance / list read filters `deletedAt: null`, so + // the row is invisible to normal reads from here on. A re-delete re-bumps + // harmlessly. + await prisma.medicationIntakeEvent.update({ + where: { id: eventId }, + data: { + deletedAt: new Date(), + syncVersion: { increment: 1 }, + }, + }); + + await auditLog("medication.intake.delete", { + userId: user.id, + ipAddress: input.ipAddress, + details: { eventId, medicationId: id }, + }); + + annotate({ + action: { + name: "medication.intake.delete", + entity_type: "intake_event", + entity_id: eventId, + }, + meta: { medication_id: id }, + }); + + // Bust per-user medications + compliance + achievement caches so the next + // read reflects the deletion. + invalidateUserMedications(user.id, { evict: true }); + + // Refresh the rows derived from the day the deleted event sat on. + await refreshDoseSlot({ + userId: user.id, + medicationId: id, + scheduledFor: event.scheduledFor, + tz: user.timezone, + }); + + // Re-evaluate the one-shot active flag. Deleting the single live intake of + // a one-shot medication reactivates it so the dashboard / lists / worker + // pick it back up. No-op for non-one-shot medications. + await reconcileOneShotState(prisma, id, user.id); + + // (#22) — silent cross-device intake sync: an undone dose must reconcile on + // the user's other iOS devices (the widget count and a pending Live + // Activity both change). Coalesced per user, best-effort — never affects + // the response. + queueMedicationIntakeSync({ + userId: user.id, + originDeviceToken: input.originDeviceToken, + }); +} diff --git a/src/lib/medications/update-intake-event.ts b/src/lib/medications/update-intake-event.ts new file mode 100644 index 000000000..2e53b0900 --- /dev/null +++ b/src/lib/medications/update-intake-event.ts @@ -0,0 +1,503 @@ +/** + * Correct one recorded dose: `PUT /api/medications/{id}/intake/{eventId}`. + * + * The route authenticates (MANAGE over the `medications` section), finds the + * live event, and parses the body; everything from the start-date floor to the + * cross-device sync tail runs here, in the order it always ran. A correction + * that keeps the dose on its slot edits the row in place; one that moves it + * tombstones the original and converges onto the target slot through the + * shared canonical-slot write. + */ +import type { MedicationIntakeEvent } from "@/generated/prisma/client"; +import { prisma } from "@/lib/db"; +import { annotate } from "@/lib/logging/context"; +import { auditLog } from "@/lib/auth/audit"; +import { overwriteDetails } from "@/lib/sharing/audit-details"; +import type { SessionUser } from "@/lib/auth/session-user"; +import type { updateIntakeEventSchema } from "@/lib/validations/medication"; +import { + consumeForIntake, + restoreForIntake, +} from "@/lib/medications/inventory/consumption"; +import { reconcileOneShotState } from "@/lib/medications/lifecycle"; +import { invalidateUserMedications } from "@/lib/cache/invalidate"; +import { queueMedicationIntakeSync } from "@/lib/notifications/medication-intake-sync"; +import { refreshDoseSlot } from "@/lib/medications/dose-day-refresh"; +import { dayKeyForUserTz } from "@/lib/measurements/consolidation-tz"; +import { + applyCanonicalSlotWrite, + findPinConflict, + resolveForcedSlotForWrite, + resolveSlotForWriteByBand, +} from "@/lib/medications/scheduling/slot-upsert"; +import { dateOnlyKey } from "@/lib/tz/date-only"; +import type { z } from "zod/v4"; + +export type IntakeEventEdit = z.output; + +/** A coded 422 refusal the route answers with `apiError`. */ +export interface IntakeEditRefusal { + ok: false; + message: string; + errorCode: string; +} + +type AttributionSource = "AUTO" | "USER_PIN"; + +interface EditContext { + user: Pick; + medicationId: string; + eventId: string; + event: MedicationIntakeEvent; +} + +/** + * The live event a correction may edit, or null for the route's 404. A + * tombstoned event 404s on PUT; the `deletedAt: null` filter refuses to + * resurrect-edit a soft-deleted intake. + */ +export async function findEditableIntakeEvent(input: { + userId: string; + medicationId: string; + eventId: string; +}): Promise { + const event = await prisma.medicationIntakeEvent.findFirst({ + where: { id: input.eventId, deletedAt: null }, + }); + if ( + !event || + event.userId !== input.userId || + event.medicationId !== input.medicationId + ) { + return null; + } + return event; +} + +/** + * Start-date guard on an edited `takenAt` (audit P0-4). The schema bounds the + * instant to a plausible absolute range; this check adds the per-medication + * floor: a take cannot predate the day the medication starts (calendar-day + * comparison in the user's timezone, so a take in the early hours of the + * start day never false-rejects). + */ +async function refuseTakeBeforeStart( + ctx: EditContext, + data: IntakeEventEdit, +): Promise { + const { user, medicationId: id, eventId } = ctx; + if (data.takenAt instanceof Date) { + const medication = await prisma.medication.findFirst({ + where: { id, userId: user.id }, + select: { startsOn: true }, + }); + if (medication?.startsOn) { + const takenDay = dayKeyForUserTz(data.takenAt, user.timezone); + const startsOnDay = dateOnlyKey(medication.startsOn); + if (takenDay < startsOnDay) { + annotate({ + action: { + name: "medications.intake.event.update.before-start-date", + }, + meta: { medication_id: id, event_id: eventId }, + }); + return { + ok: false, + message: "takenAt is before the medication's start date", + errorCode: "medications.intake.taken_at.before_start", + }; + } + } + } + return null; +} + +/** + * Re-run window-band attribution when the edit moves `takenAt` or `skipped`, + * so an edited time re-binds to the correct slot instead of leaving + * `scheduledFor` stale (audit HIGH-4). Precedence: + * 1. an explicit `scheduledFor` in the body wins (deliberate override); + * 2. else `forceSlotInstant` pins onto a named real slot (422 if it is + * not a slot of this med), standalone too, no takenAt / skipped change + * required ("Slot zuordnen" from the ledger kebab), and the row is + * stamped USER_PIN so the read ledger binds it by anchor instead of + * degrading the off-window take back to ad-hoc; + * 3. else an explicit `forceSlotInstant: null` UNPINS ("Zuordnung lösen"): + * re-attribute the take by band on its takenAt (ad-hoc when no band + * matches). The release is itself a deliberate binding decision, so the + * row KEEPS `USER_PIN` provenance ("attribution user-fixed": onto a slot + * OR deliberately ad-hoc). The persisted marker is what keeps the + * nightly slot dedup from snapping the released row back into the + * cluster the user just detached it from; + * 4. else a taken edit attributes by band (slot anchor on match, the + * take's own time on a miss → ad-hoc), provenance AUTO; + * 5. a skip / pending edit keeps the existing `scheduledFor` anchor. + */ +async function resolveEditAttribution( + ctx: EditContext, + data: IntakeEventEdit, + next: { + nextTakenAt: Date | null; + nextSkipped: boolean; + takenOrSkippedChanged: boolean; + }, +): Promise< + | IntakeEditRefusal + | { + ok: true; + resolvedScheduledFor: Date | undefined; + attributionSource: AttributionSource | undefined; + } +> { + const { user, medicationId: id, eventId } = ctx; + const { nextTakenAt, nextSkipped, takenOrSkippedChanged } = next; + let resolvedScheduledFor: Date | undefined = data.scheduledFor; + let attributionSource: AttributionSource | undefined; + if (resolvedScheduledFor === undefined) { + if (data.forceSlotInstant !== undefined && data.forceSlotInstant !== null) { + const forced = await resolveForcedSlotForWrite({ + userId: user.id, + medicationId: id, + userTz: user.timezone, + slotInstant: data.forceSlotInstant, + }); + if (forced === null) { + annotate({ + action: { name: "medication.intake.force_slot.invalid" }, + meta: { medication_id: id, event_id: eventId }, + }); + return { + ok: false, + message: + "forceSlotInstant is not a scheduled slot of this medication", + errorCode: "medications.intake.force_slot.invalid", + }; + } + // Refuse to pin onto a slot another recorded action already serves + // (excluding the row being edited): the explicit-write last-write-wins + // rule would silently overwrite that dose record. The ledger UI only + // offers the pin for unserved slots, so this only fires for stale + // clients / raw API calls. + if ( + await findPinConflict({ + userId: user.id, + medicationId: id, + canonicalSlot: forced, + incomingTakenAt: nextSkipped ? null : nextTakenAt, + excludeEventId: eventId, + }) + ) { + annotate({ + action: { name: "medication.intake.force_slot.occupied" }, + meta: { medication_id: id, event_id: eventId }, + }); + return { + ok: false, + message: "forceSlotInstant already carries a recorded dose action", + errorCode: "medications.intake.force_slot.occupied", + }; + } + resolvedScheduledFor = forced; + attributionSource = "USER_PIN"; + } else if ( + (data.forceSlotInstant === null || takenOrSkippedChanged) && + nextTakenAt !== null && + !nextSkipped + ) { + const attribution = await resolveSlotForWriteByBand({ + userId: user.id, + medicationId: id, + userTz: user.timezone, + takenAt: nextTakenAt, + }); + // band.at on match; the take's own time on a miss (ad-hoc). + resolvedScheduledFor = attribution.slotInstant ?? nextTakenAt; + // An explicit unpin stays user-fixed (USER_PIN) even on the released + // row; a plain taken/skipped edit re-attributes AUTO. + attributionSource = data.forceSlotInstant === null ? "USER_PIN" : "AUTO"; + } else if (data.forceSlotInstant === null) { + // Unpin on a row that is not a confirmed take (skip / pending): + // nothing to re-attribute, but the provenance still resets — a + // skip / pending row anchors on its slot by construction, so there + // is no user-fixed ad-hoc decision to persist. + attributionSource = "AUTO"; + } + // skip / pending edits leave `scheduledFor` on the existing anchor. + } + return { ok: true, resolvedScheduledFor, attributionSource }; +} + +/** + * The slot is unchanged — a bare in-place update can never collide with a + * sibling row (it is its own slot). + */ +async function editIntakeInPlace( + ctx: EditContext, + data: IntakeEventEdit, + edit: { + attributionSource: AttributionSource | undefined; + nextTakenAt: Date | null; + nextSkipped: boolean; + wasTaken: boolean; + }, +) { + const { user, medicationId: id, eventId } = ctx; + const { attributionSource, nextTakenAt, nextSkipped, wasTaken } = edit; + const updated = await prisma.medicationIntakeEvent.update({ + where: { id: eventId }, + data: { + ...(data.takenAt !== undefined && { takenAt: data.takenAt }), + ...(data.skipped !== undefined && { skipped: data.skipped }), + // Binding provenance: pin / unpin / band re-attribution stamps it even + // when the anchor itself did not move (e.g. a pin onto the slot the row + // already sits on, or an unpin whose band re-attribution lands on the + // same anchor). + ...(attributionSource !== undefined && { attributionSource }), + // An edit of the outcome is the person's own record. + ...((data.takenAt !== undefined || data.skipped !== undefined) && { + autoRecorded: false, + }), + // Sync — bump the reconciliation counter on every server-side mutation + // so the `/api/sync/changes` feed echoes a monotonic value to paired + // clients. + syncVersion: { increment: 1 }, + }, + }); + // Inventory follows the post-edit state: an edit that moves the row INTO + // taken consumes; a row that stays taken keeps its stamp untouched (the + // stamp freezes what the original take pulled, even when `unitsPerDose` + // changed since, and a pre-stamp legacy row must not retro-consume); a row + // edited out of taken (skip flip, takenAt cleared) refunds its stamp. + if (nextTakenAt !== null && !nextSkipped) { + if (!wasTaken) { + await consumeForIntake({ + client: prisma, + userId: user.id, + medicationId: id, + eventId, + intakeAt: nextTakenAt, + }); + } + } else { + await restoreForIntake({ + client: prisma, + userId: user.id, + eventId, + }); + } + return updated; +} + +/** + * The edit moved the dose to a different slot. Tombstone the original row + * (the iOS "a correction is a tombstone + re-insert" model the DELETE handler + * documents) and route the corrected dose through the shared canonical-slot + * upsert, which converges onto any row already at the target slot (a pending + * REMINDER row) rather than bare-updating into an occupied slot and risking a + * P2002 (audit HIGH-4). + * + * The source row's consumption stamp is refunded BEFORE the tombstone; the + * consume on the converged row below nets the move to exactly one + * consumption. + */ +async function moveIntakeToSlot( + ctx: EditContext, + move: { + targetScheduledFor: Date; + attributionSource: AttributionSource | undefined; + nextTakenAt: Date | null; + nextSkipped: boolean; + wasTaken: boolean; + }, +) { + const { user, medicationId: id, eventId, event } = ctx; + const { + targetScheduledFor, + attributionSource, + nextTakenAt, + nextSkipped, + wasTaken, + } = move; + await restoreForIntake({ + client: prisma, + userId: user.id, + eventId, + }); + await prisma.medicationIntakeEvent.update({ + where: { id: eventId }, + data: { deletedAt: new Date(), syncVersion: { increment: 1 } }, + }); + const applied = await applyCanonicalSlotWrite({ + client: prisma, + userId: user.id, + medicationId: id, + canonicalSlot: targetScheduledFor, + takenAt: nextSkipped ? null : nextTakenAt, + skipped: nextSkipped, + isExplicitTaken: !nextSkipped && nextTakenAt !== null, + isExplicitSkip: nextSkipped, + idempotencyKey: null, + // The converged row keeps the ORIGINAL's provenance. This used to be a + // hardcoded `"WEB"`, which said "somebody typed this in the browser" + // about an Apple Health dose whose time was corrected. Under MANAGE the + // sentence would be wrong about a second person as well. + createSource: event.source, + attributionSource, + // A slot move is a re-binding, not a new dose: the original row's + // recorded injection site and dose override ride along onto the + // converged row instead of being tombstoned away. + injectionSite: event.injectionSite, + doseTaken: event.doseTaken, + }); + // A taken source WITHOUT a stamp is a legacy row whose stock moved through + // the old take-time hook: the refund above was a no-op, so consuming on the + // converged row would double-charge — skip it. Every other taken outcome + // nets the move to exactly one consumption. + if ( + nextTakenAt !== null && + !nextSkipped && + (!wasTaken || event.inventoryConsumption !== null) + ) { + await consumeForIntake({ + client: prisma, + userId: user.id, + medicationId: id, + eventId: applied.row.id, + intakeAt: nextTakenAt, + }); + } + return applied.row; +} + +/** Correct one dose; the event is the live row the route found. */ +export async function updateIntakeEvent( + input: EditContext & { + data: IntakeEventEdit; + ipAddress: string | null; + originDeviceToken: string | null; + }, +) { + const { user, medicationId: id, eventId, event, data } = input; + const ctx: EditContext = { user, medicationId: id, eventId, event }; + + const beforeStart = await refuseTakeBeforeStart(ctx, data); + if (beforeStart) return beforeStart; + + // The post-edit state of the row (current values where the body omits a + // field) — drives the re-attribution decision. + const nextTakenAt = data.takenAt !== undefined ? data.takenAt : event.takenAt; + const nextSkipped = data.skipped !== undefined ? data.skipped : event.skipped; + const takenOrSkippedChanged = + (data.takenAt !== undefined && + data.takenAt?.getTime() !== event.takenAt?.getTime()) || + (data.skipped !== undefined && data.skipped !== event.skipped); + + const attribution = await resolveEditAttribution(ctx, data, { + nextTakenAt, + nextSkipped, + takenOrSkippedChanged, + }); + if (!attribution.ok) return attribution; + const { resolvedScheduledFor, attributionSource } = attribution; + + const targetScheduledFor = resolvedScheduledFor ?? event.scheduledFor; + const slotMoved = + targetScheduledFor.getTime() !== event.scheduledFor.getTime(); + + // Transition gate for the inventory hooks. Only an edit moving the row INTO + // taken may consume; a row that was already taken keeps its stamp frozen (a + // stamped row would no-op anyway, and a legacy taken row — NULL stamp, stock + // already moved by the old hook at take time — must never retro-consume on + // a time correction). + const wasTaken = event.takenAt !== null && !event.skipped; + + const updated = !slotMoved + ? await editIntakeInPlace(ctx, data, { + attributionSource, + nextTakenAt, + nextSkipped, + wasTaken, + }) + : await moveIntakeToSlot(ctx, { + targetScheduledFor, + attributionSource, + nextTakenAt, + nextSkipped, + wasTaken, + }); + + await auditLog("medication.intake.update", { + userId: user.id, + ipAddress: input.ipAddress, + // What the correction moved. A dose edit changes when a dose is + // recorded as taken, which is exactly what a clinician reads back. + details: { + eventId, + medicationId: id, + ...overwriteDetails({ + before: { + scheduledFor: event.scheduledFor, + takenAt: event.takenAt, + skipped: event.skipped, + }, + // The slot-write result carries the canonical four. The injection + // site and the dose override are not compared here because the move + // path copies them onto the converged row by construction — there is + // no edit of them to report. + after: { + scheduledFor: updated.scheduledFor, + takenAt: updated.takenAt, + skipped: updated.skipped, + }, + }), + }, + }); + + annotate({ + action: { + name: "medication.intake.update", + entity_type: "intake_event", + entity_id: eventId, + }, + meta: { medication_id: id }, + }); + + // Bust per-user medications + compliance + achievement caches so the next + // read reflects the edited event. + invalidateUserMedications(user.id, { evict: true }); + + // Refresh the rows derived from both the old + new scheduledFor day-keys + // when the dose moved across a day boundary (band re-attribution can move + // it as well as an explicit edit); if the slot is unchanged the second call + // collapses to a no-op upsert. + await refreshDoseSlot({ + userId: user.id, + medicationId: id, + scheduledFor: event.scheduledFor, + tz: user.timezone, + }); + if (slotMoved) { + await refreshDoseSlot({ + userId: user.id, + medicationId: id, + scheduledFor: targetScheduledFor, + tz: user.timezone, + }); + } + + // Re-evaluate the one-shot active flag. A skip-flip on the single live + // intake of a one-shot medication should reactivate it (the dose is no + // longer logged), and the reverse case should deactivate again. No-op for + // non-one-shot medications. + await reconcileOneShotState(prisma, id, user.id); + + // (#22) — silent cross-device intake sync: an edited dose must reconcile on + // the user's other iOS devices too. Coalesced per user, best-effort — never + // affects the response. + queueMedicationIntakeSync({ + userId: user.id, + originDeviceToken: input.originDeviceToken, + }); + + return { ok: true as const, row: updated }; +} From 8bb58d8760085bdd0093eb7e4d28a99bf6bf5c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 23 Oct 2026 11:44:26 +0200 Subject: [PATCH 3/4] test(medications): pin the medication list and create before the create moves --- .../medications.01-list.json.snap | 170 +++ .../medications.02a-list-reader.json.snap | 170 +++ .../medications.02b-list-anonymous.json.snap | 95 ++ .../medications.11-plain.json.snap | 226 ++++ .../medications.12-full.json.snap | 334 ++++++ .../medications.13a-as-needed.json.snap | 344 ++++++ .../medications.13b-one-shot.json.snap | 455 +++++++ ...ications.13c-prn-and-legacy-days.json.snap | 599 ++++++++++ .../medications.13d-ended-window.json.snap | 645 ++++++++++ ...medications.14a-unknown-category.json.snap | 574 +++++++++ ...ons.14b-course-ends-before-start.json.snap | 583 +++++++++ ...tions.14c-one-shot-two-schedules.json.snap | 574 +++++++++ ...ications.14d-one-shot-recurrence.json.snap | 574 +++++++++ ...ications.14e-unstable-concept-id.json.snap | 589 +++++++++ .../medications.14f-invalid.json.snap | 593 +++++++++ .../medications.15a-mirror.json.snap | 706 +++++++++++ .../medications.15b-mirror-replay.json.snap | 704 +++++++++++ .../medications.16-mirror-cap.json.snap | 1061 +++++++++++++++++ ...medications.17a-idempotent-first.json.snap | 786 ++++++++++++ ...edications.17b-idempotent-replay.json.snap | 787 ++++++++++++ .../medications.18a-writer.json.snap | 856 +++++++++++++ .../medications.18b-reader.json.snap | 799 +++++++++++++ .../medications.19-anonymous.json.snap | 797 +++++++++++++ .../routes/parity/medication-state.ts | 17 +- .../routes/parity/medications.parity.test.ts | 344 ++++++ 25 files changed, 13381 insertions(+), 1 deletion(-) create mode 100644 tests/integration/routes/parity/__snapshots__/medications.01-list.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.02a-list-reader.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.02b-list-anonymous.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.11-plain.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.12-full.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.13a-as-needed.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.13b-one-shot.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.13c-prn-and-legacy-days.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.13d-ended-window.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.14a-unknown-category.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.14b-course-ends-before-start.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.14c-one-shot-two-schedules.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.14d-one-shot-recurrence.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.14e-unstable-concept-id.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.14f-invalid.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.15a-mirror.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.15b-mirror-replay.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.16-mirror-cap.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.17a-idempotent-first.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.17b-idempotent-replay.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.18a-writer.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.18b-reader.json.snap create mode 100644 tests/integration/routes/parity/__snapshots__/medications.19-anonymous.json.snap create mode 100644 tests/integration/routes/parity/medications.parity.test.ts diff --git a/tests/integration/routes/parity/__snapshots__/medications.01-list.json.snap b/tests/integration/routes/parity/__snapshots__/medications.01-list.json.snap new file mode 100644 index 000000000..f9dd28d2e --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.01-list.json.snap @@ -0,0 +1,170 @@ +{ + "status": 200, + "body": { + "data": [ + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": 1, + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "", + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + } + ], + "hasIngredients": false, + "category": "OTHER", + "categoryLabel": null, + "courses": [], + "courseCount": 0, + "previousCourseEndedOn": null, + "canStartCourse": false, + "lastTakenAt": null, + "todayEventCount": 0, + "nextDueAt": "2026-10-16T06:00:00.000Z", + "remindersActive": true, + "nextDueOverdue": false, + "nextDueScheduleId": "", + "courseStatus": "CURRENT", + "intakeActionable": true, + "stockUnitsRemaining": null, + "stockDosesRemaining": null, + "runwayDays": null + } + ], + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.list" + }, + "meta": { + "cache.medications.outcome": "miss", + "cache.medications.key_hash": "", + "count": 1 + }, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.02a-list-reader.json.snap b/tests/integration/routes/parity/__snapshots__/medications.02a-list-reader.json.snap new file mode 100644 index 000000000..1a1069321 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.02a-list-reader.json.snap @@ -0,0 +1,170 @@ +{ + "status": 200, + "body": { + "data": [ + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": 1, + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "", + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + } + ], + "hasIngredients": false, + "category": "OTHER", + "categoryLabel": null, + "courses": [], + "courseCount": 0, + "previousCourseEndedOn": null, + "canStartCourse": false, + "lastTakenAt": null, + "todayEventCount": 0, + "nextDueAt": "2026-10-16T06:00:00.000Z", + "remindersActive": true, + "nextDueOverdue": false, + "nextDueScheduleId": "", + "courseStatus": "CURRENT", + "intakeActionable": true, + "stockUnitsRemaining": null, + "stockDosesRemaining": null, + "runwayDays": null + } + ], + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.list" + }, + "meta": { + "cache.medications.outcome": "hit", + "cache.medications.key_hash": "", + "count": 1 + }, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.02b-list-anonymous.json.snap b/tests/integration/routes/parity/__snapshots__/medications.02b-list-anonymous.json.snap new file mode 100644 index 000000000..45da3b863 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.02b-list-anonymous.json.snap @@ -0,0 +1,95 @@ +{ + "status": 401, + "body": { + "data": null, + "error": "Not authenticated", + "meta": { + "errorCode": "auth.missing", + "requestId": "" + } + }, + "events": [ + { + "status": 401, + "action": null, + "meta": null, + "warnings": null, + "error": { + "type": "HttpError", + "message": "Not authenticated" + } + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.11-plain.json.snap b/tests/integration/routes/parity/__snapshots__/medications.11-plain.json.snap new file mode 100644 index 000000000..8882ea379 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.11-plain.json.snap @@ -0,0 +1,226 @@ +{ + "status": 201, + "body": { + "data": { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": 1, + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "", + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + } + ], + "category": "OTHER", + "categoryLabel": null, + "courses": [], + "courseCount": 0, + "previousCourseEndedOn": null, + "canStartCourse": false + }, + "error": null + }, + "events": [ + { + "status": 201, + "action": { + "name": "medication.create", + "entity_type": "medication", + "entity_id": "" + }, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.12-full.json.snap b/tests/integration/routes/parity/__snapshots__/medications.12-full.json.snap new file mode 100644 index 000000000..24775d467 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.12-full.json.snap @@ -0,0 +1,334 @@ +{ + "status": 201, + "body": { + "data": { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": 0.5, + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "", + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": 1, + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ], + "resolvedUnitsPerDose": 1 + } + ], + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "categoryLabel": "Heart and circulation", + "courses": [ + { + "id": "", + "startsOn": "2026-10-10", + "endsOn": "2026-12-31", + "status": "CURRENT", + "takenDoses": 0, + "note": null + } + ], + "courseCount": 1, + "previousCourseEndedOn": null, + "canStartCourse": false + }, + "error": null + }, + "events": [ + { + "status": 201, + "action": { + "name": "medication.create", + "entity_type": "medication", + "entity_id": "" + }, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.13a-as-needed.json.snap b/tests/integration/routes/parity/__snapshots__/medications.13a-as-needed.json.snap new file mode 100644 index 000000000..c23aca305 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.13a-as-needed.json.snap @@ -0,0 +1,344 @@ +{ + "status": 201, + "body": { + "data": { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": 1, + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "", + "schedules": [], + "category": "PAIN_RELIEF", + "categoryLabel": null, + "courses": [], + "courseCount": 0, + "previousCourseEndedOn": null, + "canStartCourse": false + }, + "error": null + }, + "events": [ + { + "status": 201, + "action": { + "name": "medication.create", + "entity_type": "medication", + "entity_id": "" + }, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.13b-one-shot.json.snap b/tests/integration/routes/parity/__snapshots__/medications.13b-one-shot.json.snap new file mode 100644 index 000000000..a43296040 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.13b-one-shot.json.snap @@ -0,0 +1,455 @@ +{ + "status": 201, + "body": { + "data": { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": 1, + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "", + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + } + ], + "category": "OTHER", + "categoryLabel": null, + "courses": [ + { + "id": "", + "startsOn": "2026-10-20", + "endsOn": "2026-10-20", + "status": "UPCOMING", + "takenDoses": 0, + "note": null + } + ], + "courseCount": 1, + "previousCourseEndedOn": null, + "canStartCourse": false + }, + "error": null + }, + "events": [ + { + "status": 201, + "action": { + "name": "medication.create", + "entity_type": "medication", + "entity_id": "" + }, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.13c-prn-and-legacy-days.json.snap b/tests/integration/routes/parity/__snapshots__/medications.13c-prn-and-legacy-days.json.snap new file mode 100644 index 000000000..81a5f1d0c --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.13c-prn-and-legacy-days.json.snap @@ -0,0 +1,599 @@ +{ + "status": 201, + "body": { + "data": { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": 1, + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "", + "schedules": [], + "recordedSchedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + } + ], + "category": "OTHER", + "categoryLabel": null, + "courses": [], + "courseCount": 0, + "previousCourseEndedOn": null, + "canStartCourse": false + }, + "error": null + }, + "events": [ + { + "status": 201, + "action": { + "name": "medication.create", + "entity_type": "medication", + "entity_id": "" + }, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.13d-ended-window.json.snap b/tests/integration/routes/parity/__snapshots__/medications.13d-ended-window.json.snap new file mode 100644 index 000000000..b12f37c1b --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.13d-ended-window.json.snap @@ -0,0 +1,645 @@ +{ + "status": 201, + "body": { + "data": { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": 1, + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "", + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + } + ], + "category": "OTHER", + "categoryLabel": null, + "courses": [ + { + "id": "", + "startsOn": "2026-10-05", + "endsOn": "2026-10-05", + "status": "ENDED", + "takenDoses": 0, + "note": null + } + ], + "courseCount": 1, + "previousCourseEndedOn": "2026-10-05", + "canStartCourse": true + }, + "error": null + }, + "events": [ + { + "status": 201, + "action": { + "name": "medication.create", + "entity_type": "medication", + "entity_id": "" + }, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.14a-unknown-category.json.snap b/tests/integration/routes/parity/__snapshots__/medications.14a-unknown-category.json.snap new file mode 100644 index 000000000..b55686124 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.14a-unknown-category.json.snap @@ -0,0 +1,574 @@ +{ + "status": 422, + "body": { + "data": null, + "error": "Unknown medication category", + "meta": { + "errorCode": "medications.category.unknown", + "requestId": "" + } + }, + "events": [ + { + "status": 422, + "action": null, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.14b-course-ends-before-start.json.snap b/tests/integration/routes/parity/__snapshots__/medications.14b-course-ends-before-start.json.snap new file mode 100644 index 000000000..5cc3ae9de --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.14b-course-ends-before-start.json.snap @@ -0,0 +1,583 @@ +{ + "status": 422, + "body": { + "data": null, + "error": "Validation failed", + "details": { + "issues": [ + { + "path": "endsOn", + "code": "custom", + "message": "endsOn must be on or after startsOn" + } + ] + }, + "meta": { + "errorCode": "http.invalid", + "requestId": "" + } + }, + "events": [ + { + "status": 422, + "action": null, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.14c-one-shot-two-schedules.json.snap b/tests/integration/routes/parity/__snapshots__/medications.14c-one-shot-two-schedules.json.snap new file mode 100644 index 000000000..688566769 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.14c-one-shot-two-schedules.json.snap @@ -0,0 +1,574 @@ +{ + "status": 422, + "body": { + "data": null, + "error": "A one-shot medication can have at most one schedule", + "meta": { + "errorCode": "http.invalid", + "requestId": "" + } + }, + "events": [ + { + "status": 422, + "action": null, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.14d-one-shot-recurrence.json.snap b/tests/integration/routes/parity/__snapshots__/medications.14d-one-shot-recurrence.json.snap new file mode 100644 index 000000000..85ecda70f --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.14d-one-shot-recurrence.json.snap @@ -0,0 +1,574 @@ +{ + "status": 422, + "body": { + "data": null, + "error": "A one-shot medication cannot have a recurrence (rrule or rollingIntervalDays)", + "meta": { + "errorCode": "http.invalid", + "requestId": "" + } + }, + "events": [ + { + "status": 422, + "action": null, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.14e-unstable-concept-id.json.snap b/tests/integration/routes/parity/__snapshots__/medications.14e-unstable-concept-id.json.snap new file mode 100644 index 000000000..a2b535824 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.14e-unstable-concept-id.json.snap @@ -0,0 +1,589 @@ +{ + "status": 422, + "body": { + "data": null, + "error": "Validation failed", + "details": { + "issues": [ + { + "path": "externalId", + "code": "custom", + "message": "external identifier must be stable across app restarts; received an object description (), which embeds a memory address and is a new value on every launch — serialise the identity itself, not the object's description" + } + ] + }, + "meta": { + "errorCode": "http.invalid", + "requestId": "" + } + }, + "events": [ + { + "status": 422, + "action": { + "name": "medication.external_id.rejected" + }, + "meta": { + "external_id_rejected": 1, + "external_id_shapes": "object_description", + "external_id_surface": "medication.create" + }, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.14f-invalid.json.snap b/tests/integration/routes/parity/__snapshots__/medications.14f-invalid.json.snap new file mode 100644 index 000000000..c0abd73eb --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.14f-invalid.json.snap @@ -0,0 +1,593 @@ +{ + "status": 422, + "body": { + "data": null, + "error": "Validation failed", + "details": { + "issues": [ + { + "path": "name", + "code": "too_small", + "message": "Too small: expected string to have >=1 characters" + }, + { + "path": "dose", + "code": "invalid_type", + "message": "Invalid input: expected string, received number" + }, + { + "path": "schedules", + "code": "invalid_type", + "message": "Invalid input: expected array, received string" + } + ] + }, + "meta": { + "errorCode": "http.invalid", + "requestId": "" + } + }, + "events": [ + { + "status": 422, + "action": null, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.15a-mirror.json.snap b/tests/integration/routes/parity/__snapshots__/medications.15a-mirror.json.snap new file mode 100644 index 000000000..302f69f2d --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.15a-mirror.json.snap @@ -0,0 +1,706 @@ +{ + "status": 201, + "body": { + "data": { + "id": "", + "userId": "", + "name": "Mirrored", + "dose": "50mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": 1, + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-concept-0001", + "createdAt": "", + "updatedAt": "", + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + } + ], + "category": "OTHER", + "categoryLabel": null, + "courses": [], + "courseCount": 0, + "previousCourseEndedOn": null, + "canStartCourse": false + }, + "error": null + }, + "events": [ + { + "status": 201, + "action": { + "name": "medication.create", + "entity_type": "medication", + "entity_id": "" + }, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirrored", + "dose": "50mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-concept-0001", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mirrored", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.15b-mirror-replay.json.snap b/tests/integration/routes/parity/__snapshots__/medications.15b-mirror-replay.json.snap new file mode 100644 index 000000000..25c308749 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.15b-mirror-replay.json.snap @@ -0,0 +1,704 @@ +{ + "status": 200, + "body": { + "data": { + "id": "", + "userId": "", + "name": "Mirrored", + "dose": "50mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": 1, + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-concept-0001", + "createdAt": "", + "updatedAt": "", + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + } + ], + "category": "OTHER", + "categoryLabel": null + }, + "error": null + }, + "events": [ + { + "status": 200, + "action": { + "name": "medication.create", + "entity_type": "medication", + "entity_id": "" + }, + "meta": { + "idempotent_replay": true + }, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirrored", + "dose": "50mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-concept-0001", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mirrored", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.16-mirror-cap.json.snap b/tests/integration/routes/parity/__snapshots__/medications.16-mirror-cap.json.snap new file mode 100644 index 000000000..a7712a941 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.16-mirror-cap.json.snap @@ -0,0 +1,1061 @@ +{ + "status": 422, + "body": { + "data": null, + "error": "This account already mirrors the maximum number of medications from an external source", + "meta": { + "errorCode": "medications.mirror.limit_exceeded", + "requestId": "" + } + }, + "events": [ + { + "status": 422, + "action": { + "name": "medication.mirror.limit_exceeded" + }, + "meta": { + "existing": 30 + }, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "Mirror 00", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-00", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 01", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-01", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 02", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-02", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 03", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-03", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 04", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-04", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 05", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-05", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 06", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-06", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 07", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-07", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 08", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-08", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 09", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-09", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 10", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-10", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 11", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-11", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 12", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-12", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 13", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-13", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 14", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-14", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 15", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-15", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 16", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-16", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 17", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-17", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 18", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-18", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 19", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-19", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 20", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-20", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 21", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-21", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 22", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-22", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 23", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-23", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 24", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-24", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 25", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-25", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 26", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-26", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 27", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-27", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 28", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-28", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirror 29", + "dose": "1mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-cap-29", + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [], + "revisions": [], + "pauseEras": [], + "courses": [], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [], + "ingredients": [], + "audit": [], + "idempotency": [] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.17a-idempotent-first.json.snap b/tests/integration/routes/parity/__snapshots__/medications.17a-idempotent-first.json.snap new file mode 100644 index 000000000..d6d186d9a --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.17a-idempotent-first.json.snap @@ -0,0 +1,786 @@ +{ + "status": 201, + "body": { + "data": { + "id": "", + "userId": "", + "name": "Retried", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": 1, + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "", + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + } + ], + "category": "OTHER", + "categoryLabel": null, + "courses": [], + "courseCount": 0, + "previousCourseEndedOn": null, + "canStartCourse": false + }, + "error": null + }, + "events": [ + { + "status": 201, + "action": { + "name": "medication.create", + "entity_type": "medication", + "entity_id": "" + }, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirrored", + "dose": "50mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-concept-0001", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Retried", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mirrored", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Retried", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [ + { + "userId": "", + "key": "", + "method": "POST", + "path": "/api/medications", + "responseStatus": 201, + "requestFingerprint": "717bc7f22eaede79d3d0ec9e0197c6fae152d91ae21b29662ebbe2b02d7bd896", + "expiresAt": "2026-10-16T12:00:00.000Z" + } + ] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.17b-idempotent-replay.json.snap b/tests/integration/routes/parity/__snapshots__/medications.17b-idempotent-replay.json.snap new file mode 100644 index 000000000..478f992f5 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.17b-idempotent-replay.json.snap @@ -0,0 +1,787 @@ +{ + "status": 201, + "body": { + "data": { + "id": "", + "userId": "", + "name": "Retried", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": 1, + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "", + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + } + ], + "category": "OTHER", + "categoryLabel": null, + "courses": [], + "courseCount": 0, + "previousCourseEndedOn": null, + "canStartCourse": false + }, + "error": null + }, + "events": [ + { + "status": 201, + "action": { + "name": "idempotency.replay" + }, + "meta": { + "method": "POST", + "path": "/api/medications" + }, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirrored", + "dose": "50mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-concept-0001", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Retried", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mirrored", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Retried", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [ + { + "userId": "", + "key": "", + "method": "POST", + "path": "/api/medications", + "responseStatus": 201, + "requestFingerprint": "717bc7f22eaede79d3d0ec9e0197c6fae152d91ae21b29662ebbe2b02d7bd896", + "expiresAt": "2026-10-16T12:00:00.000Z" + } + ] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.18a-writer.json.snap b/tests/integration/routes/parity/__snapshots__/medications.18a-writer.json.snap new file mode 100644 index 000000000..ca74c6b43 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.18a-writer.json.snap @@ -0,0 +1,856 @@ +{ + "status": 201, + "body": { + "data": { + "id": "", + "userId": "", + "name": "Brought by a delegate", + "dose": "20mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": 1, + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "", + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null, + "resolvedUnitsPerDose": 1 + } + ], + "category": "OTHER", + "categoryLabel": null, + "courses": [], + "courseCount": 0, + "previousCourseEndedOn": null, + "canStartCourse": false + }, + "error": null + }, + "events": [ + { + "status": 201, + "action": { + "name": "medication.create", + "entity_type": "medication", + "entity_id": "" + }, + "meta": null, + "warnings": null, + "error": null + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Brought by a delegate", + "dose": "20mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirrored", + "dose": "50mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-concept-0001", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Retried", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": "", + "details": { + "medicationId": "", + "name": "Brought by a delegate", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mirrored", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Retried", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [ + { + "userId": "", + "key": "", + "method": "POST", + "path": "/api/medications", + "responseStatus": 201, + "requestFingerprint": "717bc7f22eaede79d3d0ec9e0197c6fae152d91ae21b29662ebbe2b02d7bd896", + "expiresAt": "2026-10-16T12:00:00.000Z" + } + ] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.18b-reader.json.snap b/tests/integration/routes/parity/__snapshots__/medications.18b-reader.json.snap new file mode 100644 index 000000000..ee5305870 --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.18b-reader.json.snap @@ -0,0 +1,799 @@ +{ + "status": 403, + "body": { + "data": null, + "error": "Account access denied", + "meta": { + "errorCode": "sharing.access.denied", + "requestId": "" + } + }, + "events": [ + { + "status": 403, + "action": null, + "meta": { + "sharing_refusal": "insufficient_access" + }, + "warnings": null, + "error": { + "type": "SharingAccessDeniedError", + "message": "Account access denied" + } + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Brought by a delegate", + "dose": "20mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirrored", + "dose": "50mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-concept-0001", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Retried", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": "", + "details": { + "medicationId": "", + "name": "Brought by a delegate", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mirrored", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Retried", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [ + { + "userId": "", + "key": "", + "method": "POST", + "path": "/api/medications", + "responseStatus": 201, + "requestFingerprint": "717bc7f22eaede79d3d0ec9e0197c6fae152d91ae21b29662ebbe2b02d7bd896", + "expiresAt": "2026-10-16T12:00:00.000Z" + } + ] + } +} diff --git a/tests/integration/routes/parity/__snapshots__/medications.19-anonymous.json.snap b/tests/integration/routes/parity/__snapshots__/medications.19-anonymous.json.snap new file mode 100644 index 000000000..5a4de87eb --- /dev/null +++ b/tests/integration/routes/parity/__snapshots__/medications.19-anonymous.json.snap @@ -0,0 +1,797 @@ +{ + "status": 401, + "body": { + "data": null, + "error": "Not authenticated", + "meta": { + "errorCode": "auth.missing", + "requestId": "" + } + }, + "events": [ + { + "status": 401, + "action": null, + "meta": null, + "warnings": null, + "error": { + "type": "HttpError", + "message": "Not authenticated" + } + } + ], + "effects": [], + "stored": { + "medications": [ + { + "id": "", + "userId": "", + "name": "As needed", + "dose": "400mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": true, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Brought by a delegate", + "dose": "20mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Ended window", + "dose": "3mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Existing tablet", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-01T00:00:00.000Z", + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Full injection", + "dose": "1 pen", + "treatmentClass": "GLP1", + "dosesPerUnit": 4, + "unitsPerDose": "0.5", + "active": true, + "notificationsEnabled": false, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": true, + "autoMarkTakenSince": "", + "deliveryForm": "INJECTION", + "trackInjectionSites": true, + "allowedInjectionSites": [ + "ABDOMEN_LEFT", + "THIGH_RIGHT" + ], + "liveActivityEnabled": true, + "criticalAlarmEnabled": true, + "atcCode": "A10BJ06", + "rxNormCode": "1991302", + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": 7, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mirrored", + "dose": "50mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": "APPLE_HEALTH", + "externalId": "hk-concept-0001", + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Mixed schedules", + "dose": "2mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": false, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "One shot", + "dose": "1 dose", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "oneShot": true, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Plain tablet", + "dose": "5mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "userId": "", + "name": "Retried", + "dose": "10mg", + "treatmentClass": "GENERIC", + "dosesPerUnit": null, + "unitsPerDose": "1", + "active": true, + "notificationsEnabled": true, + "pausedAt": null, + "snoozedUntil": null, + "startsOn": null, + "endsOn": null, + "oneShot": false, + "asNeeded": false, + "trackIntake": true, + "autoMarkTaken": false, + "autoMarkTakenSince": null, + "deliveryForm": "ORAL", + "trackInjectionSites": false, + "allowedInjectionSites": [], + "liveActivityEnabled": false, + "criticalAlarmEnabled": false, + "atcCode": null, + "rxNormCode": null, + "lowStockNotifiedAt": null, + "lowStockNotifiedThresholdDays": null, + "reorderLeadDays": null, + "externalSource": null, + "externalId": null, + "createdAt": "", + "updatedAt": "" + } + ], + "schedules": [ + { + "id": "", + "medicationId": "", + "windowStart": "06:00", + "windowEnd": "07:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "06:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "PRN", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "07:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "07:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "09:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "08:00", + "windowEnd": "10:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "08:00" + ], + "reminderGraceMinutes": null, + "rrule": "FREQ=DAILY", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "09:00", + "windowEnd": "11:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "09:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "12:00", + "windowEnd": "13:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": null, + "timesOfDay": [ + "12:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": 3, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + }, + { + "id": "", + "medicationId": "", + "windowStart": "18:00", + "windowEnd": "20:00", + "label": "Evening", + "dose": "0.5 pen", + "unitsPerDose": "1", + "daysOfWeek": null, + "timesOfDay": [ + "18:30" + ], + "reminderGraceMinutes": 45, + "rrule": "FREQ=WEEKLY;BYDAY=MO", + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": [ + { + "end": "20:00", + "start": "18:00", + "timeOfDay": "18:30" + } + ] + }, + { + "id": "", + "medicationId": "", + "windowStart": "21:00", + "windowEnd": "22:00", + "label": null, + "dose": null, + "unitsPerDose": null, + "daysOfWeek": "i2;1,3,5", + "timesOfDay": [ + "21:00" + ], + "reminderGraceMinutes": null, + "rrule": null, + "rollingIntervalDays": null, + "scheduleType": "SCHEDULED", + "cyclicOnWeeks": null, + "cyclicOffWeeks": null, + "doseWindows": null + } + ], + "revisions": [], + "pauseEras": [], + "courses": [ + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-05T00:00:00.000Z", + "endsOn": "2026-10-05T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-10T00:00:00.000Z", + "endsOn": "2026-12-31T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + }, + { + "id": "", + "medicationId": "", + "userId": "", + "startsOn": "2026-10-20T00:00:00.000Z", + "endsOn": "2026-10-20T00:00:00.000Z", + "noteEncrypted": null, + "createdAt": "", + "updatedAt": "" + } + ], + "intakes": [], + "doseChanges": [], + "inventoryItems": [], + "inventoryEvents": [], + "categories": [ + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "OTHER", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "PAIN_RELIEF", + "updatedAt": "" + }, + { + "medicationId": "", + "category": "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13", + "updatedAt": "" + } + ], + "ingredients": [], + "audit": [ + { + "action": "medication.create", + "userId": "", + "actorUserId": "", + "details": { + "medicationId": "", + "name": "Brought by a delegate", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "As needed", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Ended window", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Full injection", + "autoMarkTaken": true + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mirrored", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Mixed schedules", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "One shot", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Plain tablet", + "autoMarkTaken": false + }, + "ipAddress": null + }, + { + "action": "medication.create", + "userId": "", + "actorUserId": null, + "details": { + "medicationId": "", + "name": "Retried", + "autoMarkTaken": false + }, + "ipAddress": null + } + ], + "idempotency": [ + { + "userId": "", + "key": "", + "method": "POST", + "path": "/api/medications", + "responseStatus": 201, + "requestFingerprint": "717bc7f22eaede79d3d0ec9e0197c6fae152d91ae21b29662ebbe2b02d7bd896", + "expiresAt": "2026-10-16T12:00:00.000Z" + } + ] + } +} diff --git a/tests/integration/routes/parity/medication-state.ts b/tests/integration/routes/parity/medication-state.ts index 1103d75fa..b73829783 100644 --- a/tests/integration/routes/parity/medication-state.ts +++ b/tests/integration/routes/parity/medication-state.ts @@ -186,6 +186,21 @@ export async function medicationState(prisma: Client, userIds: string[]) { }; } +/** + * A server cache reports the hash of the key it looked up, and the key holds + * the account id, so the hash differs on every run. Its presence is kept. + */ +function withoutCacheKeyHashes(facts: unknown): unknown { + if (!facts || typeof facts !== "object") return facts; + const { meta } = facts as { meta?: unknown }; + if (!meta || typeof meta !== "object") return facts; + const cleaned: Record = {}; + for (const [k, v] of Object.entries(meta)) { + cleaned[k] = /^cache\..+\.key_hash$/.test(k) ? "" : v; + } + return { ...facts, meta: cleaned }; +} + export interface ParityCall { /** Snapshot name, `.`. */ name: string; @@ -215,7 +230,7 @@ export async function parityStep(call: ParityCall) { { status: res.status, body: res.body, - events: events.map(eventFacts), + events: events.map(eventFacts).map(withoutCacheKeyHashes), effects: effectRecorder.take(), stored: await medicationState(getPrismaClient(), call.userIds), }, diff --git a/tests/integration/routes/parity/medications.parity.test.ts b/tests/integration/routes/parity/medications.parity.test.ts new file mode 100644 index 000000000..028bfffa6 --- /dev/null +++ b/tests/integration/routes/parity/medications.parity.test.ts @@ -0,0 +1,344 @@ +/** + * Parity for `GET` and `POST /api/medications` while the create moves into + * `src/lib/medications/`. + * + * One record walks through the cases the route tells apart, in order, each + * request seeing what the earlier ones stored: the list for its owner, for a + * reading delegate and for nobody; a plain create, a full one with a custom + * category, a course window and doses recorded automatically, an as-needed + * one, a one-shot one and a PRN schedule; the refusals (an unknown category, + * a course that ends before it starts, the two one-shot shapes, an unstable + * concept id, a body the schema refuses); a mirrored create, its replay, and + * the mirror cap on a second account; an idempotent retry; and creates by a + * delegate who may write and one who may only read. After each request the + * snapshot holds the response, the wide event and every medication row of + * the accounts. + * + * The clock is pinned (`Date` only), so the snapshot is the same on every + * day it runs. + */ +import { afterAll, beforeAll, describe, it, vi } from "vitest"; + +import { GET, POST } from "@/app/api/medications/route"; +import { encryptToBytes } from "@/lib/ai/coach/bytes-codec"; + +import { anonymous, type RouteAuth } from "../../../kit/call-route"; +import { makeMedication, makeSession, makeUser } from "../../../kit/factories"; +import { getPrismaClient, truncateAllTables } from "../../setup"; +import { delegateOf, parityStep } from "./medication-state"; + +vi.mock("@/lib/logging/transports", async (importOriginal) => { + const actual = + await importOriginal(); + const { wideEventRecorder: recorder } = await import("../../../kit/parity"); + return { + ...actual, + emitIfSampled: (event: (typeof recorder.events)[number]) => { + recorder.events.push(event); + }, + }; +}); + +const prisma = getPrismaClient(); +const NOW = new Date("2026-10-15T12:00:00.000Z"); +const ROUTE = "/api/medications"; +/** + * The create answers without the read-model fields (reminder state, course + * status, stock and runway) the registered medication resource declares. The + * parity snapshot pins that answer as it is; the contract check is the + * route's own tests' business. + */ +const CREATE_ANSWER = { + skip: "the create answers without the read-model fields of the resource", +}; +const CUSTOM_KEY = "custom:5b1f7c2e-4d3a-4b8e-9c61-2a7d0e9f4c13"; + +let ownerId: string; +let userIds: string[]; +let owner: RouteAuth; +let writer: { auth: RouteAuth; headers: Record }; +let reader: { auth: RouteAuth; headers: Record }; + +async function list( + name: string, + options: { auth?: RouteAuth; headers?: Record } = {}, +) { + await parityStep({ + name: `medications.${name}`, + handler: GET, + options: { + method: "GET", + route: ROUTE, + auth: options.auth ?? owner, + headers: options.headers, + }, + userIds, + now: NOW, + }); +} + +async function create( + name: string, + body: unknown, + options: { + auth?: RouteAuth; + headers?: Record; + userIds?: string[]; + } = {}, +) { + await parityStep({ + name: `medications.${name}`, + handler: POST, + options: { + method: "POST", + route: ROUTE, + body, + auth: options.auth ?? owner, + headers: options.headers, + contract: CREATE_ANSWER, + }, + userIds: options.userIds ?? userIds, + now: NOW, + }); +} + +const schedule = (windowStart: string, windowEnd: string, extra = {}) => ({ + windowStart, + windowEnd, + ...extra, +}); + +beforeAll(async () => { + vi.useFakeTimers({ toFake: ["Date"], now: NOW }); + await truncateAllTables(prisma); + const user = await makeUser({ timezone: "Europe/Berlin" }); + ownerId = user.id; + owner = await makeSession(user); + await makeMedication( + user, + { + name: "Existing tablet", + startsOn: new Date("2026-10-01"), + createdAt: new Date("2026-10-01T06:00:00.000Z"), + }, + [ + { + windowStart: "08:00", + windowEnd: "10:00", + timesOfDay: ["08:00"], + rrule: "FREQ=DAILY", + }, + ], + ); + await prisma.medicationCategoryLabel.create({ + data: { + userId: ownerId, + key: CUSTOM_KEY, + labelEncrypted: encryptToBytes("Heart and circulation"), + }, + }); + const w = await delegateOf(prisma, user, "WRITE"); + const r = await delegateOf(prisma, user, "READ"); + writer = { auth: w.auth, headers: w.headers }; + reader = { auth: r.auth, headers: r.headers }; + userIds = [ownerId, w.delegate.id, r.delegate.id]; +}); + +afterAll(() => { + vi.useRealTimers(); +}); + +describe("GET /api/medications parity", () => { + it("01 the owner's list", async () => { + await list("01-list"); + }); + + it("02 a reading delegate's view of it, and nobody's", async () => { + await list("02a-list-reader", reader); + await list("02b-list-anonymous", { auth: anonymous }); + }); +}); + +describe("POST /api/medications parity", () => { + it("11 a plain create", async () => { + await create("11-plain", { + name: "Plain tablet", + dose: "5mg", + schedules: [schedule("07:00", "09:00")], + }); + }); + + it("12 a full create with a custom category, a course and auto-take", async () => { + await create("12-full", { + name: "Full injection", + dose: "1 pen", + category: CUSTOM_KEY, + treatmentClass: "GLP1", + dosesPerUnit: 4, + unitsPerDose: 0.5, + reorderLeadDays: 7, + deliveryForm: "INJECTION", + trackInjectionSites: true, + allowedInjectionSites: ["ABDOMEN_LEFT", "THIGH_RIGHT"], + notificationsEnabled: false, + liveActivityEnabled: true, + criticalAlarmEnabled: true, + atcCode: "A10BJ06", + rxNormCode: "1991302", + startsOn: "2026-10-10", + endsOn: "2026-12-31", + autoMarkTaken: true, + schedules: [ + schedule("18:00", "20:00", { + label: "Evening", + dose: "0.5 pen", + unitsPerDose: 1, + timesOfDay: ["18:30"], + reminderGraceMinutes: 45, + rrule: "FREQ=WEEKLY;BYDAY=MO", + doseWindows: [{ timeOfDay: "18:30", start: "18:00", end: "20:00" }], + }), + ], + }); + }); + + it("13 an as-needed create, a one-shot one and a PRN schedule", async () => { + await create("13a-as-needed", { + name: "As needed", + dose: "400mg", + category: "PAIN_RELIEF", + asNeeded: true, + }); + await create("13b-one-shot", { + name: "One shot", + dose: "1 dose", + oneShot: true, + startsOn: "2026-10-20", + endsOn: "2026-11-20", + schedules: [schedule("09:00", "11:00")], + }); + await create("13c-prn-and-legacy-days", { + name: "Mixed schedules", + dose: "2mg", + trackIntake: false, + schedules: [ + schedule("06:00", "07:00", { scheduleType: "PRN" }), + schedule("21:00", "22:00", { daysOfWeek: [1, 3, 5], intervalWeeks: 2 }), + schedule("12:00", "13:00", { rollingIntervalDays: 3 }), + ], + }); + await create("13d-ended-window", { + name: "Ended window", + dose: "3mg", + endsOn: "2026-10-05", + schedules: [schedule("08:00", "09:00")], + }); + }); + + it("14 the refusals", async () => { + await create("14a-unknown-category", { + name: "Unknown category", + dose: "1mg", + category: "custom:0a6c2d4e-1111-4222-8333-944455556666", + schedules: [schedule("08:00", "09:00")], + }); + await create("14b-course-ends-before-start", { + name: "Backwards course", + dose: "1mg", + startsOn: "2026-10-20", + endsOn: "2026-10-10", + schedules: [schedule("08:00", "09:00")], + }); + await create("14c-one-shot-two-schedules", { + name: "One shot twice", + dose: "1mg", + oneShot: true, + startsOn: "2026-10-20", + schedules: [schedule("08:00", "09:00"), schedule("20:00", "21:00")], + }); + await create("14d-one-shot-recurrence", { + name: "One shot recurring", + dose: "1mg", + oneShot: true, + startsOn: "2026-10-20", + schedules: [schedule("08:00", "09:00", { rrule: "FREQ=DAILY" })], + }); + await create("14e-unstable-concept-id", { + name: "Phantom", + dose: "1mg", + externalSource: "APPLE_HEALTH", + externalId: "", + schedules: [schedule("08:00", "09:00")], + }); + await create("14f-invalid", { name: "", dose: 5, schedules: "daily" }); + }); + + it("15 a mirrored create and its replay", async () => { + const mirrored = { + name: "Mirrored", + dose: "50mg", + externalSource: "APPLE_HEALTH", + externalId: "hk-concept-0001", + schedules: [schedule("08:00", "09:00")], + }; + await create("15a-mirror", mirrored); + await create("15b-mirror-replay", { ...mirrored, name: "Renamed" }); + }); + + it("16 the mirror cap", async () => { + const capped = await makeUser({ timezone: "UTC" }); + await prisma.medication.createMany({ + data: Array.from({ length: 30 }, (_, i) => ({ + userId: capped.id, + name: `Mirror ${String(i).padStart(2, "0")}`, + dose: "1mg", + externalSource: "APPLE_HEALTH" as const, + externalId: `hk-cap-${String(i).padStart(2, "0")}`, + })), + }); + await create( + "16-mirror-cap", + { + name: "One too many", + dose: "1mg", + externalSource: "APPLE_HEALTH", + externalId: "hk-cap-30", + schedules: [schedule("08:00", "09:00")], + }, + { auth: await makeSession(capped), userIds: [capped.id] }, + ); + }); + + it("17 a retried create under one idempotency key", async () => { + const body = { + name: "Retried", + dose: "10mg", + schedules: [schedule("08:00", "09:00")], + }; + const headers = { + "idempotency-key": "6f9d2c4a-8b1e-4f3a-9d7c-5e2b1a0c9d8e", + }; + await create("17a-idempotent-first", body, { headers }); + await create("17b-idempotent-replay", body, { headers }); + }); + + it("18 a delegate who may write, and one who may only read", async () => { + const body = { + name: "Brought by a delegate", + dose: "20mg", + schedules: [schedule("08:00", "09:00")], + }; + await create("18a-writer", body, writer); + await create("18b-reader", body, reader); + }); + + it("19 no credentials", async () => { + await create( + "19-anonymous", + { name: "Nobody", dose: "1mg" }, + { + auth: anonymous, + }, + ); + }); +}); From 3a4e97733d92424d9f110b9a1e6978c44df20423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 23 Oct 2026 12:41:46 +0200 Subject: [PATCH 4/4] refactor(medications): move the medication create out of its route POST /api/medications keeps authentication, the body, the validation answer and the HTTP mapping; the create (the mirrored-medication dedupe and cap, the one-shot shape refusal, the initial course, the nested schedules, the insert and its tail) moves verbatim to lib/medications/create-medication.ts and answers created, existing or refused. The route falls from 541 to 94 lines. The parity walk recorded before the move is unchanged, and the sharing guard reads the service beside the route for the handler body. --- src/__tests__/sharing-surface-guard.test.ts | 1 + src/app/api/medications/route.ts | 481 +--------------- src/lib/medications/create-medication.ts | 583 ++++++++++++++++++++ 3 files changed, 601 insertions(+), 464 deletions(-) create mode 100644 src/lib/medications/create-medication.ts diff --git a/src/__tests__/sharing-surface-guard.test.ts b/src/__tests__/sharing-surface-guard.test.ts index 35cfef028..388368a6b 100644 --- a/src/__tests__/sharing-surface-guard.test.ts +++ b/src/__tests__/sharing-surface-guard.test.ts @@ -434,6 +434,7 @@ function callsSymbol(rel: string, symbol: string): boolean { * cannot outlive the delegation it describes. */ const HANDLER_BODY_MODULES: Record = { + "app/api/medications/route.ts": ["lib/medications/create-medication.ts"], "app/api/medications/[id]/intake/[eventId]/route.ts": [ "lib/medications/update-intake-event.ts", "lib/medications/delete-intake-event.ts", diff --git a/src/app/api/medications/route.ts b/src/app/api/medications/route.ts index 45ffb2e74..e65668ae3 100644 --- a/src/app/api/medications/route.ts +++ b/src/app/api/medications/route.ts @@ -1,8 +1,5 @@ -import { prisma } from "@/lib/db"; -import { Prisma } from "@/generated/prisma/client"; import { apiHandler, requireRecordAuth } from "@/lib/api-handler"; -import { annotate, getEvent } from "@/lib/logging/context"; -import { auditLog } from "@/lib/auth/audit"; +import { annotate } from "@/lib/logging/context"; import { apiError, apiSuccess, @@ -10,45 +7,15 @@ import { returnAllZodIssues, safeJson, } from "@/lib/api-response"; -import { - courseRefusalResponse, - resolveCourseFields, -} from "@/lib/medications/courses"; -import { - dateOfDayKey, - dayKeyOfDate, - validateCourses, -} from "@/lib/medications/course-window"; -import { DEFAULT_TIMEZONE, userDayKey } from "@/lib/tz/format"; -import { - createMedicationSchema, - isCustomMedicationCategoryKey, -} from "@/lib/validations/medication"; +import { createMedicationSchema } from "@/lib/validations/medication"; import { unstableExternalIdMeta, unstableExternalIdShape, } from "@/lib/validations/external-id"; -import { - isAssignableCategory, - resolveMedicationCategories, - setMedicationCategory, -} from "@/lib/medication-category"; -import { serializeScheduleRecurrence } from "@/lib/medication-schedule"; -import { invalidateUserMedications } from "@/lib/cache/invalidate"; import { readMedicationsListCached } from "@/lib/medications/list-read"; -import { serializeScheduleUnitsPerDose } from "@/lib/medications/schedule-units-dto"; +import { createMedication } from "@/lib/medications/create-medication"; import { withIdempotency } from "@/lib/idempotency"; import { NextRequest } from "next/server"; -import { scheduleWireFields } from "@/lib/medications/intake-tracking"; - -// v1.32.25 — blast-radius cap on externally-mirrored medications per user. -// A client that mints a fresh `externalId` for the same source concept on -// every sync sweep (a known iOS unstable-key bug class) never matches the -// idempotency triple, so each sweep would otherwise create a new mirror -// row unbounded. Apple's own medication list makes >30 genuinely distinct -// meds implausible, so this caps the damage a buggy client can do without -// breaking any legitimate use. -const APPLE_HEALTH_MIRROR_CAP = 30; export const GET = apiHandler(async () => { const { user } = await requireRecordAuth("read", "medications"); @@ -73,66 +40,12 @@ export const GET = apiHandler(async () => { return apiSuccess(result); }); -/** - * v1.28 — idempotent response for a re-mirrored medication. The create - * route returns the EXISTING row (status 200, vs 201 for a fresh create) - * when the caller re-posts a `(externalSource, externalId)` pair this - * user already mirrors — the iOS re-sync replays its full HealthKit - * medication list, and a replay must neither duplicate nor 500. Response - * shape mirrors the fresh-create envelope (schedules included, category - * joined, Decimal unwrapped); no audit row and no cache eviction because - * nothing was written. - */ -async function respondWithExistingMirror( - medication: Record & { - id: string; - unitsPerDose: unknown; - trackIntake: boolean; - schedules: Array<{ unitsPerDose: Prisma.Decimal | null }>; - }, -): Promise { - let category = "OTHER"; - let categoryLabel: string | null = null; - try { - const categories = await resolveMedicationCategories([medication.id]); - category = categories[medication.id]?.category ?? "OTHER"; - categoryLabel = categories[medication.id]?.categoryLabel ?? null; - } catch { - getEvent()?.addWarning("Medication categories could not be loaded"); - } - - annotate({ - action: { - name: "medication.create", - entity_type: "medication", - entity_id: medication.id, - }, - meta: { idempotent_replay: true }, - }); - - return apiSuccess({ - ...medication, - unitsPerDose: Number(medication.unitsPerDose), - // #219 — Decimal → number for the per-schedule column too. - // v1.39.1 (#1033) — record-only medications ship `schedules: []`. - ...scheduleWireFields( - medication.trackIntake, - serializeScheduleUnitsPerDose( - medication.schedules, - Number(medication.unitsPerDose), - ), - ), - category, - categoryLabel, - }); -} - /** * The create is wrapped in `withIdempotency` so a client replaying its offline * outbox after a lost success response replays the first answer instead of - * minting a second medication. The `(externalSource, externalId)` dedupe below - * only ever covered a MIRRORED create; a manually entered medication carries - * neither field and had nothing to collapse a retry onto. + * minting a second medication. The `(externalSource, externalId)` dedupe in + * `createMedication` only ever covered a MIRRORED create; a manually entered + * medication carries neither field and had nothing to collapse a retry onto. */ export const POST = apiHandler(withIdempotency<[NextRequest]>(postMedication)); @@ -165,377 +78,17 @@ async function postMedication(request: NextRequest): Promise { return returnAllZodIssues(parsed.error, 422); } - const { - name, - dose, - category, - treatmentClass, - dosesPerUnit, - unitsPerDose, - reorderLeadDays, - deliveryForm, - trackInjectionSites, - allowedInjectionSites, - notificationsEnabled, - liveActivityEnabled, - criticalAlarmEnabled, - atcCode, - rxNormCode, - externalSource, - externalId, - schedules, - startsOn, - endsOn, - oneShot, - asNeeded, - trackIntake, - autoMarkTaken, - } = parsed.data; - - // v1.40 (#1041) — a custom category must be one of this record's own. - if ( - category !== undefined && - !(await isAssignableCategory(user.id, category)) - ) { - return apiError("Unknown medication category", 422, { - errorCode: "medications.category.unknown", - }); - } - - // v1.28 — idempotent mirror create. A mirrored medication (Apple - // Health) is keyed by the `(userId, externalSource, externalId)` - // unique; a re-post of the same concept id (iOS re-sync, retry after a - // dropped response) returns the EXISTING medication with 200 instead - // of minting a duplicate or 500-ing on P2002. The pre-query covers the - // common replay; the P2002 catch around the create below covers the - // concurrent race. - if (externalSource !== undefined && externalId !== undefined) { - const existing = await prisma.medication.findFirst({ - where: { userId: user.id, externalSource, externalId }, - include: { schedules: true }, - }); - if (existing) { - return respondWithExistingMirror(existing); - } - - // v1.32.25 — growth guard. This point is only reached when the - // idempotency lookup MISSED, i.e. this is a genuinely NEW mirror row, - // not a replay of one the user already holds (a replay returned 200 - // above). An idempotent re-post of an existing mirror is therefore - // never blocked, even for a user already at the cap. Refuse only the - // minting of a fresh row once the user already holds the cap of - // Apple-Health-mirrored medications, so a client feeding a rotating - // key can no longer fill the list with duplicates. The count runs on - // the mirror-create-miss path only; native creates (no - // `externalSource`) never reach this branch and pay nothing. - const mirroredCount = await prisma.medication.count({ - where: { userId: user.id, externalSource: "APPLE_HEALTH" }, - }); - if (mirroredCount >= APPLE_HEALTH_MIRROR_CAP) { - annotate({ - action: { name: "medication.mirror.limit_exceeded" }, - meta: { existing: mirroredCount }, - }); - return apiError( - "This account already mirrors the maximum number of medications from an external source", - 422, - { errorCode: "medications.mirror.limit_exceeded" }, - ); - } - } - - // ── v1.5 route invariants for the new scheduling primitives ─────── - // - // The Zod layer already enforces `rrule` xor `rollingIntervalDays` - // (scheduleSchema.refine). The route layer enforces the cross-field - // invariants that span medication + schedules: - // - // 1. **One-shot consistency** — when `oneShot === true`: - // a. The medication has at most ONE schedule. - // b. The single schedule carries neither `rrule` nor - // `rollingIntervalDays` (a one-shot dose IS the schedule). - // c. `endsOn` is normalised to equal `startsOn` on write so the - // worker's date-range cap matches the one-and-only slot. - // - // 2. **Recurring default** — when `oneShot !== true` AND the - // schedule has no `rrule`, no `rollingIntervalDays`, and no - // legacy `daysOfWeek`, the route stamps `rrule = "FREQ=DAILY"` - // so the canonical recurrence engine has a clean shape going - // forward instead of falling through to the legacy parser. - // - // 3. **iOS contract dual-write** — when `timesOfDay` is absent or - // empty, the route stamps `[windowStart]` so the new engine - // always sees a populated `timesOfDay` while legacy iOS clients - // (v0.6.x) keep encoding the `windowStart` / `windowEnd` / - // `daysOfWeek` shape. Both shapes coexist through v1.5.x. - // 4. **As-needed (v1.16.11, #316)** — when `asNeeded === true` the - // medication carries ZERO schedules (the Zod refine already - // rejects a populated array, mutual exclusion with `oneShot` - // included). Every "never due / never reminded / never scored" - // surface follows structurally from the empty schedule list. - const scheduleInputs = schedules ?? []; - if (oneShot === true) { - if (scheduleInputs.length > 1) { - return apiError( - "A one-shot medication can have at most one schedule", - 422, - ); - } - const s = scheduleInputs[0]; - if (s && (s.rrule !== undefined || s.rollingIntervalDays !== undefined)) { - return apiError( - "A one-shot medication cannot have a recurrence (rrule or rollingIntervalDays)", - 422, - ); - } - } - - // Normalise endsOn for one-shot. Zod gives us `Date | null | undefined`. - const normalisedEndsOn = - oneShot === true && startsOn ? startsOn : (endsOn ?? undefined); - - // v1.40 (#1024) — a medication created with a window starts with one - // course; the row projects it. An end without a start has always meant - // "running since creation", so the course starts today (or on the end day, - // when that lies earlier). No window: no course, chronic since creation. - let initialCourse: { startsOn: Date; endsOn: Date | null } | null = null; - if (startsOn || normalisedEndsOn) { - const todayKey = userDayKey(new Date(), user.timezone || DEFAULT_TIMEZONE); - const endKey = normalisedEndsOn ? dayKeyOfDate(normalisedEndsOn) : null; - initialCourse = { - startsOn: - startsOn ?? - dateOfDayKey(endKey && endKey < todayKey ? endKey : todayKey), - endsOn: normalisedEndsOn ?? null, - }; - const refusal = validateCourses( - [initialCourse], - todayKey, - oneShot === true, - ); - if (refusal) { - const r = courseRefusalResponse(refusal); - return apiError(r.message, r.status, { errorCode: r.errorCode }); - } - } - - const createMedication = () => - prisma.medication.create({ - data: { - userId: user.id, - name, - dose, - // v1.4.25 — treatmentClass + dosesPerUnit are optional in the - // wire schema; Prisma fills the default GENERIC when omitted. - ...(treatmentClass !== undefined && { treatmentClass }), - ...(dosesPerUnit !== undefined && { dosesPerUnit }), - // v1.16.10 — units consumed per dose; Prisma defaults to 1 when omitted. - ...(unitsPerDose !== undefined && { unitsPerDose }), - // v1.17.0 — optional reorder lead override; null/omitted = inherit - // the user-level default in the low-stock alert. - ...(reorderLeadDays !== undefined && { reorderLeadDays }), - // v1.6.0 — route of administration; Prisma defaults to ORAL when omitted. - ...(deliveryForm !== undefined && { deliveryForm }), - // v1.8.5 — injection-site tracking opt-in + per-medication allowed - // sites; Prisma defaults to false / [] when omitted. - ...(trackInjectionSites !== undefined && { trackInjectionSites }), - ...(allowedInjectionSites !== undefined && { allowedInjectionSites }), - // v1.7.0 — iOS reminder flags; Prisma defaults both to false. - ...(liveActivityEnabled !== undefined && { liveActivityEnabled }), - ...(criticalAlarmEnabled !== undefined && { criticalAlarmEnabled }), - // v1.9.0 — optional drug-classification codes (ATC / RxNorm). - // Validated for format by Zod; stored verbatim when present. - ...(atcCode !== undefined && { atcCode }), - ...(rxNormCode !== undefined && { rxNormCode }), - // v1.28 — mirrored-medication provenance (Apple Health). Zod - // enforces the both-or-neither pairing; field-by-field like every - // other column. - ...(externalSource !== undefined && { externalSource }), - ...(externalId !== undefined && { externalId }), - // v1.5 — wizard's reminders toggle now ships through the create - // payload (was orphaned in the initial diff). Prisma defaults to - // true when omitted, matching the legacy form's behaviour. - ...(notificationsEnabled !== undefined && { notificationsEnabled }), - // v1.5 scheduling primitives — pass-through when supplied. - ...(startsOn !== undefined && { startsOn }), - ...(normalisedEndsOn !== undefined && { endsOn: normalisedEndsOn }), - ...(initialCourse && { - startsOn: initialCourse.startsOn, - endsOn: initialCourse.endsOn, - courses: { - create: { - userId: user.id, - startsOn: initialCourse.startsOn, - endsOn: initialCourse.endsOn, - }, - }, - }), - ...(oneShot !== undefined && { oneShot }), - // v1.16.11 — as-needed flag, field-by-field. An asNeeded create - // carries an empty `scheduleInputs`, so the nested create below - // persists zero schedule rows. - ...(asNeeded !== undefined && { asNeeded }), - // v1.39.1 (#1033) — intake tracking, field-by-field. Created off, - // the schedule is stored as a record from the start; the column - // default (true) covers every caller that does not send it. - ...(trackIntake !== undefined && { trackIntake }), - // v1.42.2 — auto-mark-taken, field-by-field. Created on, the - // auto-take job fills slots from this moment only. - ...(autoMarkTaken !== undefined && { - autoMarkTaken, - autoMarkTakenSince: autoMarkTaken ? new Date() : null, - }), - schedules: { - create: scheduleInputs.map((s) => { - // Invariant 2 — default to FREQ=DAILY when nothing else is set. - // v1.7.0 — PRN schedules carry no cadence, so never default - // them to FREQ=DAILY (they would otherwise project + remind). - const hasLegacyDays = (s.daysOfWeek?.length ?? 0) > 0; - const isPrn = s.scheduleType === "PRN"; - const defaultedRrule = - !oneShot && - !isPrn && - s.rrule === undefined && - s.rollingIntervalDays === undefined && - !hasLegacyDays - ? "FREQ=DAILY" - : s.rrule; - - // Invariant 3 — dual-write `timesOfDay` from windowStart when - // the legacy-shape iOS client doesn't send the new field. - const effectiveTimesOfDay = - s.timesOfDay && s.timesOfDay.length > 0 - ? s.timesOfDay - : [s.windowStart]; - - return { - windowStart: s.windowStart, - windowEnd: s.windowEnd, - label: s.label ?? null, - dose: s.dose ?? null, - // #219 — per-schedule inventory units. Field-by-field (no mass - // assignment); absent leaves the column NULL so the consume - // hook inherits the medication-level units_per_dose. - ...(s.unitsPerDose !== undefined && { - unitsPerDose: s.unitsPerDose, - }), - daysOfWeek: serializeScheduleRecurrence({ - daysOfWeek: s.daysOfWeek ?? [], - intervalWeeks: s.intervalWeeks ?? 1, - }), - // v1.5 first-class times-of-day. - timesOfDay: effectiveTimesOfDay, - ...(s.reminderGraceMinutes !== undefined && { - reminderGraceMinutes: s.reminderGraceMinutes, - }), - ...(defaultedRrule !== undefined && { rrule: defaultedRrule }), - ...(s.rollingIntervalDays !== undefined && { - rollingIntervalDays: s.rollingIntervalDays, - }), - // v1.7.0 — schedule type + cyclic weeks, field-by-field. - ...(s.scheduleType !== undefined && { - scheduleType: s.scheduleType, - }), - ...(s.cyclicOnWeeks !== undefined && { - cyclicOnWeeks: s.cyclicOnWeeks, - }), - ...(s.cyclicOffWeeks !== undefined && { - cyclicOffWeeks: s.cyclicOffWeeks, - }), - // v1.15.18 — per-dose configurable on-time windows. Stored as the - // validated `{ timeOfDay, start, end }[]` JSON; absent leaves the - // column NULL (every slot on the default ±1h derivation). - ...(s.doseWindows !== undefined && { - doseWindows: s.doseWindows, - }), - }; - }), - }, - }, - include: { schedules: true }, - }); - - let medication: Awaited>; - try { - medication = await createMedication(); - } catch (err: unknown) { - // v1.28 — P2002 on the mirror triple: a concurrent create of the - // same `(userId, externalSource, externalId)` won the race between - // the pre-query above and this insert. Resolve to the winning row - // and answer idempotently instead of 500-ing. Any other unique - // violation (there is none on this table today) rethrows. - const isP2002 = - typeof err === "object" && - err !== null && - "code" in err && - (err as { code: string }).code === "P2002"; - if (isP2002 && externalSource !== undefined && externalId !== undefined) { - const winner = await prisma.medication.findFirst({ - where: { userId: user.id, externalSource, externalId }, - include: { schedules: true }, - }); - if (winner) return respondWithExistingMirror(winner); - } - throw err; - } - - const normalizedCategory = await setMedicationCategory( - medication.id, - category, - ); - const categoryLabel = isCustomMedicationCategoryKey(normalizedCategory) - ? ((await resolveMedicationCategories([medication.id]))[medication.id] - ?.categoryLabel ?? null) - : null; - - await auditLog("medication.create", { - userId: user.id, + const outcome = await createMedication({ + user, + data: parsed.data, ipAddress: getClientIp(request), - details: { - medicationId: medication.id, - name, - // v1.42.2 — a medication created with its doses recorded - // automatically says so in its audit row. - autoMarkTaken: medication.autoMarkTaken, - }, }); - - annotate({ - action: { - name: "medication.create", - entity_type: "medication", - entity_id: medication.id, - }, - }); - - // v1.4.34 — bust per-user medications + compliance + achievement - // caches so the next read reflects the new schedule. - invalidateUserMedications(user.id, { evict: true }); - - return apiSuccess( - { - ...medication, - unitsPerDose: Number(medication.unitsPerDose), - // #219 — Decimal → number for the per-schedule column too. - // v1.39.1 (#1033) — record-only medications ship `schedules: []`. - ...scheduleWireFields( - medication.trackIntake, - serializeScheduleUnitsPerDose( - medication.schedules, - medication.unitsPerDose, - ), - ), - category: normalizedCategory, - categoryLabel, - // v1.40 (#1024) — the courses, as every medication read carries them. - ...( - await resolveCourseFields( - [medication], - new Date(), - user.timezone || DEFAULT_TIMEZONE, - ) - ).get(medication.id), - }, - 201, - ); + switch (outcome.kind) { + case "refused": + return apiError(outcome.message, outcome.status, outcome.meta); + case "existing": + return apiSuccess(outcome.body); + case "created": + return apiSuccess(outcome.body, 201); + } } diff --git a/src/lib/medications/create-medication.ts b/src/lib/medications/create-medication.ts new file mode 100644 index 000000000..4b9a370de --- /dev/null +++ b/src/lib/medications/create-medication.ts @@ -0,0 +1,583 @@ +/** + * Create a medication with its nested schedule: `POST /api/medications`. + * + * The route authenticates (WRITE over the `medications` section), reads the + * body and answers the schema refusal; everything from the category check to + * the cache eviction runs here, in the order it always ran. The result says + * what the route answers: a refusal, the existing row of a mirrored concept + * the record already holds, or the new row. + */ +import type { z } from "zod/v4"; + +import { prisma } from "@/lib/db"; +import type { Prisma } from "@/generated/prisma/client"; +import { annotate, getEvent } from "@/lib/logging/context"; +import { auditLog } from "@/lib/auth/audit"; +import type { SessionUser } from "@/lib/auth/session-user"; +import { + courseRefusalResponse, + resolveCourseFields, +} from "@/lib/medications/courses"; +import { + dateOfDayKey, + dayKeyOfDate, + validateCourses, +} from "@/lib/medications/course-window"; +import { DEFAULT_TIMEZONE, userDayKey } from "@/lib/tz/format"; +import { + isCustomMedicationCategoryKey, + type createMedicationSchema, +} from "@/lib/validations/medication"; +import { + isAssignableCategory, + resolveMedicationCategories, + setMedicationCategory, +} from "@/lib/medication-category"; +import { serializeScheduleRecurrence } from "@/lib/medication-schedule"; +import { invalidateUserMedications } from "@/lib/cache/invalidate"; +import { serializeScheduleUnitsPerDose } from "@/lib/medications/schedule-units-dto"; +import { scheduleWireFields } from "@/lib/medications/intake-tracking"; + +export type CreateMedicationInput = z.output; +type ScheduleInput = NonNullable[number]; + +/** + * Blast-radius cap on externally-mirrored medications per user. A client + * that mints a fresh `externalId` for the same source concept on every sync + * sweep (a known iOS unstable-key bug class) never matches the idempotency + * triple, so each sweep would otherwise create a new mirror row unbounded. + * Apple's own medication list makes >30 genuinely distinct meds implausible, + * so this caps the damage a buggy client can do without breaking any + * legitimate use. + */ +const APPLE_HEALTH_MIRROR_CAP = 30; + +export type CreateMedicationOutcome = + | { + kind: "refused"; + message: string; + status: number; + meta?: { errorCode: string }; + } + | { kind: "existing"; body: Record } + | { kind: "created"; body: Record }; + +/** + * Idempotent response for a re-mirrored medication. The create returns the + * EXISTING row (status 200, vs 201 for a fresh create) when the caller + * re-posts a `(externalSource, externalId)` pair this user already mirrors — + * the iOS re-sync replays its full HealthKit medication list, and a replay + * must neither duplicate nor 500. Response shape mirrors the fresh-create + * envelope (schedules included, category joined, Decimal unwrapped); no + * audit row and no cache eviction because nothing was written. + */ +async function existingMirrorBody( + medication: Record & { + id: string; + unitsPerDose: unknown; + trackIntake: boolean; + schedules: Array<{ unitsPerDose: Prisma.Decimal | null }>; + }, +): Promise { + let category = "OTHER"; + let categoryLabel: string | null = null; + try { + const categories = await resolveMedicationCategories([medication.id]); + category = categories[medication.id]?.category ?? "OTHER"; + categoryLabel = categories[medication.id]?.categoryLabel ?? null; + } catch { + getEvent()?.addWarning("Medication categories could not be loaded"); + } + + annotate({ + action: { + name: "medication.create", + entity_type: "medication", + entity_id: medication.id, + }, + meta: { idempotent_replay: true }, + }); + + return { + kind: "existing", + body: { + ...medication, + unitsPerDose: Number(medication.unitsPerDose), + // #219 — Decimal → number for the per-schedule column too. + // (#1033) — record-only medications ship `schedules: []`. + ...scheduleWireFields( + medication.trackIntake, + serializeScheduleUnitsPerDose( + medication.schedules, + Number(medication.unitsPerDose), + ), + ), + category, + categoryLabel, + }, + }; +} + +/** + * Idempotent mirror create. A mirrored medication (Apple Health) is keyed by + * the `(userId, externalSource, externalId)` unique; a re-post of the same + * concept id (iOS re-sync, retry after a dropped response) returns the + * EXISTING medication with 200 instead of minting a duplicate or 500-ing on + * P2002. The pre-query covers the common replay; the P2002 catch around the + * create covers the concurrent race. Null when the create goes ahead. + */ +async function existingMirrorOrCap( + userId: string, + externalSource: NonNullable, + externalId: string, +): Promise { + const existing = await prisma.medication.findFirst({ + where: { userId, externalSource, externalId }, + include: { schedules: true }, + }); + if (existing) { + return existingMirrorBody(existing); + } + + // Growth guard. This point is only reached when the idempotency lookup + // MISSED, i.e. this is a genuinely NEW mirror row, not a replay of one the + // user already holds (a replay returned 200 above). An idempotent re-post + // of an existing mirror is therefore never blocked, even for a user already + // at the cap. Refuse only the minting of a fresh row once the user already + // holds the cap of Apple-Health-mirrored medications, so a client feeding a + // rotating key can no longer fill the list with duplicates. The count runs + // on the mirror-create-miss path only; native creates (no `externalSource`) + // never reach this branch and pay nothing. + const mirroredCount = await prisma.medication.count({ + where: { userId, externalSource: "APPLE_HEALTH" }, + }); + if (mirroredCount >= APPLE_HEALTH_MIRROR_CAP) { + annotate({ + action: { name: "medication.mirror.limit_exceeded" }, + meta: { existing: mirroredCount }, + }); + return { + kind: "refused", + message: + "This account already mirrors the maximum number of medications from an external source", + status: 422, + meta: { errorCode: "medications.mirror.limit_exceeded" }, + }; + } + return null; +} + +/** + * Route invariants for the scheduling primitives. + * + * The Zod layer already enforces `rrule` xor `rollingIntervalDays` + * (scheduleSchema.refine). This layer enforces the cross-field invariants + * that span medication + schedules: + * + * 1. **One-shot consistency** — when `oneShot === true`: + * a. The medication has at most ONE schedule. + * b. The single schedule carries neither `rrule` nor + * `rollingIntervalDays` (a one-shot dose IS the schedule). + * c. `endsOn` is normalised to equal `startsOn` on write so the + * worker's date-range cap matches the one-and-only slot. + * + * 2. **Recurring default** — when `oneShot !== true` AND the schedule has + * no `rrule`, no `rollingIntervalDays`, and no legacy `daysOfWeek`, the + * create stamps `rrule = "FREQ=DAILY"` so the canonical recurrence + * engine has a clean shape going forward instead of falling through to + * the legacy parser. + * + * 3. **iOS contract dual-write** — when `timesOfDay` is absent or empty, + * the create stamps `[windowStart]` so the new engine always sees a + * populated `timesOfDay` while legacy iOS clients (v0.6.x) keep encoding + * the `windowStart` / `windowEnd` / `daysOfWeek` shape. Both shapes + * coexist. + * 4. **As-needed (#316)** — when `asNeeded === true` the medication carries + * ZERO schedules (the Zod refine already rejects a populated array, + * mutual exclusion with `oneShot` included). Every "never due / never + * reminded / never scored" surface follows structurally from the empty + * schedule list. + */ +function refuseOneShotShape( + oneShot: boolean | undefined, + scheduleInputs: readonly ScheduleInput[], +): CreateMedicationOutcome | null { + if (oneShot === true) { + if (scheduleInputs.length > 1) { + return { + kind: "refused", + message: "A one-shot medication can have at most one schedule", + status: 422, + }; + } + const s = scheduleInputs[0]; + if (s && (s.rrule !== undefined || s.rollingIntervalDays !== undefined)) { + return { + kind: "refused", + message: + "A one-shot medication cannot have a recurrence (rrule or rollingIntervalDays)", + status: 422, + }; + } + } + return null; +} + +/** + * A medication created with a window starts with one course; the row + * projects it (#1024). An end without a start has always meant "running + * since creation", so the course starts today (or on the end day, when that + * lies earlier). No window: no course, chronic since creation. + */ +function resolveInitialCourse( + timezone: string, + startsOn: Date | null | undefined, + normalisedEndsOn: Date | undefined, + oneShot: boolean | undefined, +): + | { initialCourse: { startsOn: Date; endsOn: Date | null } | null } + | { refusal: CreateMedicationOutcome } { + let initialCourse: { startsOn: Date; endsOn: Date | null } | null = null; + if (startsOn || normalisedEndsOn) { + const todayKey = userDayKey(new Date(), timezone || DEFAULT_TIMEZONE); + const endKey = normalisedEndsOn ? dayKeyOfDate(normalisedEndsOn) : null; + initialCourse = { + startsOn: + startsOn ?? + dateOfDayKey(endKey && endKey < todayKey ? endKey : todayKey), + endsOn: normalisedEndsOn ?? null, + }; + const refusal = validateCourses( + [initialCourse], + todayKey, + oneShot === true, + ); + if (refusal) { + const r = courseRefusalResponse(refusal); + return { + refusal: { + kind: "refused", + message: r.message, + status: r.status, + meta: { errorCode: r.errorCode }, + }, + }; + } + } + return { initialCourse }; +} + +/** One nested schedule row, field-by-field from the parsed input. */ +function scheduleCreateData(s: ScheduleInput, oneShot: boolean | undefined) { + // Invariant 2 — default to FREQ=DAILY when nothing else is set. PRN + // schedules carry no cadence, so never default them to FREQ=DAILY (they + // would otherwise project + remind). + const hasLegacyDays = (s.daysOfWeek?.length ?? 0) > 0; + const isPrn = s.scheduleType === "PRN"; + const defaultedRrule = + !oneShot && + !isPrn && + s.rrule === undefined && + s.rollingIntervalDays === undefined && + !hasLegacyDays + ? "FREQ=DAILY" + : s.rrule; + + // Invariant 3 — dual-write `timesOfDay` from windowStart when the + // legacy-shape iOS client doesn't send the new field. + const effectiveTimesOfDay = + s.timesOfDay && s.timesOfDay.length > 0 ? s.timesOfDay : [s.windowStart]; + + return { + windowStart: s.windowStart, + windowEnd: s.windowEnd, + label: s.label ?? null, + dose: s.dose ?? null, + // #219 — per-schedule inventory units. Field-by-field (no mass + // assignment); absent leaves the column NULL so the consume hook + // inherits the medication-level units_per_dose. + ...(s.unitsPerDose !== undefined && { + unitsPerDose: s.unitsPerDose, + }), + daysOfWeek: serializeScheduleRecurrence({ + daysOfWeek: s.daysOfWeek ?? [], + intervalWeeks: s.intervalWeeks ?? 1, + }), + // First-class times-of-day. + timesOfDay: effectiveTimesOfDay, + ...(s.reminderGraceMinutes !== undefined && { + reminderGraceMinutes: s.reminderGraceMinutes, + }), + ...(defaultedRrule !== undefined && { rrule: defaultedRrule }), + ...(s.rollingIntervalDays !== undefined && { + rollingIntervalDays: s.rollingIntervalDays, + }), + // Schedule type + cyclic weeks, field-by-field. + ...(s.scheduleType !== undefined && { + scheduleType: s.scheduleType, + }), + ...(s.cyclicOnWeeks !== undefined && { + cyclicOnWeeks: s.cyclicOnWeeks, + }), + ...(s.cyclicOffWeeks !== undefined && { + cyclicOffWeeks: s.cyclicOffWeeks, + }), + // Per-dose configurable on-time windows. Stored as the validated + // `{ timeOfDay, start, end }[]` JSON; absent leaves the column NULL + // (every slot on the default ±1h derivation). + ...(s.doseWindows !== undefined && { + doseWindows: s.doseWindows, + }), + }; +} + +/** The insert itself, field-by-field from the parsed input. */ +function insertMedication( + userId: string, + data: CreateMedicationInput, + shape: { + scheduleInputs: readonly ScheduleInput[]; + normalisedEndsOn: Date | undefined; + initialCourse: { startsOn: Date; endsOn: Date | null } | null; + }, +) { + const { + name, + dose, + treatmentClass, + dosesPerUnit, + unitsPerDose, + reorderLeadDays, + deliveryForm, + trackInjectionSites, + allowedInjectionSites, + notificationsEnabled, + liveActivityEnabled, + criticalAlarmEnabled, + atcCode, + rxNormCode, + externalSource, + externalId, + startsOn, + oneShot, + asNeeded, + trackIntake, + autoMarkTaken, + } = data; + const { scheduleInputs, normalisedEndsOn, initialCourse } = shape; + return prisma.medication.create({ + data: { + userId, + name, + dose, + // treatmentClass + dosesPerUnit are optional in the wire schema; Prisma + // fills the default GENERIC when omitted. + ...(treatmentClass !== undefined && { treatmentClass }), + ...(dosesPerUnit !== undefined && { dosesPerUnit }), + // Units consumed per dose; Prisma defaults to 1 when omitted. + ...(unitsPerDose !== undefined && { unitsPerDose }), + // Optional reorder lead override; null/omitted = inherit the + // user-level default in the low-stock alert. + ...(reorderLeadDays !== undefined && { reorderLeadDays }), + // Route of administration; Prisma defaults to ORAL when omitted. + ...(deliveryForm !== undefined && { deliveryForm }), + // Injection-site tracking opt-in + per-medication allowed sites; Prisma + // defaults to false / [] when omitted. + ...(trackInjectionSites !== undefined && { trackInjectionSites }), + ...(allowedInjectionSites !== undefined && { allowedInjectionSites }), + // iOS reminder flags; Prisma defaults both to false. + ...(liveActivityEnabled !== undefined && { liveActivityEnabled }), + ...(criticalAlarmEnabled !== undefined && { criticalAlarmEnabled }), + // Optional drug-classification codes (ATC / RxNorm). Validated for + // format by Zod; stored verbatim when present. + ...(atcCode !== undefined && { atcCode }), + ...(rxNormCode !== undefined && { rxNormCode }), + // Mirrored-medication provenance (Apple Health). Zod enforces the + // both-or-neither pairing; field-by-field like every other column. + ...(externalSource !== undefined && { externalSource }), + ...(externalId !== undefined && { externalId }), + // The wizard's reminders toggle ships through the create payload. + // Prisma defaults to true when omitted, matching the legacy form's + // behaviour. + ...(notificationsEnabled !== undefined && { notificationsEnabled }), + // Scheduling primitives — pass-through when supplied. + ...(startsOn !== undefined && { startsOn }), + ...(normalisedEndsOn !== undefined && { endsOn: normalisedEndsOn }), + ...(initialCourse && { + startsOn: initialCourse.startsOn, + endsOn: initialCourse.endsOn, + courses: { + create: { + userId, + startsOn: initialCourse.startsOn, + endsOn: initialCourse.endsOn, + }, + }, + }), + ...(oneShot !== undefined && { oneShot }), + // As-needed flag, field-by-field. An asNeeded create carries an empty + // `scheduleInputs`, so the nested create below persists zero schedule + // rows. + ...(asNeeded !== undefined && { asNeeded }), + // (#1033) — intake tracking, field-by-field. Created off, the schedule + // is stored as a record from the start; the column default (true) + // covers every caller that does not send it. + ...(trackIntake !== undefined && { trackIntake }), + // Auto-mark-taken, field-by-field. Created on, the auto-take job fills + // slots from this moment only. + ...(autoMarkTaken !== undefined && { + autoMarkTaken, + autoMarkTakenSince: autoMarkTaken ? new Date() : null, + }), + schedules: { + create: scheduleInputs.map((s) => scheduleCreateData(s, oneShot)), + }, + }, + include: { schedules: true }, + }); +} + +export async function createMedication(input: { + user: Pick; + data: CreateMedicationInput; + ipAddress: string | null; +}): Promise { + const { user, data } = input; + const { + name, + category, + externalSource, + externalId, + schedules, + startsOn, + endsOn, + oneShot, + } = data; + + // (#1041) — a custom category must be one of this record's own. + if ( + category !== undefined && + !(await isAssignableCategory(user.id, category)) + ) { + return { + kind: "refused", + message: "Unknown medication category", + status: 422, + meta: { errorCode: "medications.category.unknown" }, + }; + } + + if (externalSource !== undefined && externalId !== undefined) { + const mirror = await existingMirrorOrCap( + user.id, + externalSource, + externalId, + ); + if (mirror) return mirror; + } + + const scheduleInputs = schedules ?? []; + const oneShotRefusal = refuseOneShotShape(oneShot, scheduleInputs); + if (oneShotRefusal) return oneShotRefusal; + + // Normalise endsOn for one-shot. Zod gives us `Date | null | undefined`. + const normalisedEndsOn = + oneShot === true && startsOn ? startsOn : (endsOn ?? undefined); + + const course = resolveInitialCourse( + user.timezone, + startsOn, + normalisedEndsOn, + oneShot, + ); + if ("refusal" in course) return course.refusal; + const { initialCourse } = course; + + let medication: Awaited>; + try { + medication = await insertMedication(user.id, data, { + scheduleInputs, + normalisedEndsOn, + initialCourse, + }); + } catch (err: unknown) { + // P2002 on the mirror triple: a concurrent create of the same + // `(userId, externalSource, externalId)` won the race between the + // pre-query above and this insert. Resolve to the winning row and answer + // idempotently instead of 500-ing. Any other unique violation (there is + // none on this table today) rethrows. + const isP2002 = + typeof err === "object" && + err !== null && + "code" in err && + (err as { code: string }).code === "P2002"; + if (isP2002 && externalSource !== undefined && externalId !== undefined) { + const winner = await prisma.medication.findFirst({ + where: { userId: user.id, externalSource, externalId }, + include: { schedules: true }, + }); + if (winner) return existingMirrorBody(winner); + } + throw err; + } + + const normalizedCategory = await setMedicationCategory( + medication.id, + category, + ); + const categoryLabel = isCustomMedicationCategoryKey(normalizedCategory) + ? ((await resolveMedicationCategories([medication.id]))[medication.id] + ?.categoryLabel ?? null) + : null; + + await auditLog("medication.create", { + userId: user.id, + ipAddress: input.ipAddress, + details: { + medicationId: medication.id, + name, + // A medication created with its doses recorded automatically says so + // in its audit row. + autoMarkTaken: medication.autoMarkTaken, + }, + }); + + annotate({ + action: { + name: "medication.create", + entity_type: "medication", + entity_id: medication.id, + }, + }); + + // Bust per-user medications + compliance + achievement caches so the next + // read reflects the new schedule. + invalidateUserMedications(user.id, { evict: true }); + + return { + kind: "created", + body: { + ...medication, + unitsPerDose: Number(medication.unitsPerDose), + // #219 — Decimal → number for the per-schedule column too. + // (#1033) — record-only medications ship `schedules: []`. + ...scheduleWireFields( + medication.trackIntake, + serializeScheduleUnitsPerDose( + medication.schedules, + medication.unitsPerDose, + ), + ), + category: normalizedCategory, + categoryLabel, + // (#1024) — the courses, as every medication read carries them. + ...( + await resolveCourseFields( + [medication], + new Date(), + user.timezone || DEFAULT_TIMEZONE, + ) + ).get(medication.id), + }, + }; +}