Carry medication stock and its ledger through backup and restore

A restored account reported no supply at all. Every pack was gone, and
with it every low-stock reminder, on a feature that became first-class
when medication moved to one stock per drug.

The two travel together because the register itself paired them: without
the events the count "cannot be rebuilt even in principle", and without
the packs the events are a list of deltas against nothing.

The count comes back exactly as recorded, not recalculated from the
ledger. It is the value the server had resolved and the person was
shown, and every reminder already sent was computed from it. The fixture
makes the difference visible on purpose: thirty in, eight consumed, and
a remaining count of twenty-one, because somebody dropped one without
recording it. A restore that "corrected" that to twenty-two would
disagree with the account's own history and look like a bug fix while
doing it.

Both decimal columns cross the wire as strings. Half tablets are a real
prescription and a JSON number would round them.

The note follows the contract the side effects and dose changes beside
it already use, and the packs nest inside their drug, so a portable
restore minting fresh ids needs no remap.

Verified by breaking it: recomputing the remaining count from the ledger
fails the round trip with twenty-one against twenty-two.
This commit is contained in:
Marc-André Bombeck committed 2026-08-22 00:59:15 +02:00
1 parent f4e65c827a
commit 86231ed23e
6 files changed
+280 -4

No files matched your search

@@ -674,6 +674,49 @@ const handler = apiHandler(
: {}),
})),
},
// The packs, and the ledger behind their counts. Nested for
// the same reason as everything above it, and `unitsRemaining`
// is written VERBATIM rather than recomputed from the events —
// it is what the server had resolved and what the person was
// shown, and recomputing here would silently correct a count
// they may have adjusted by hand.
inventoryItems: {
create: m.inventoryItems.map((i) => ({
...(i.id ? { id: i.id } : {}),
userId: ownerId,
state: (i.state ?? "ACTIVE") as never,
containerType: (i.containerType ?? "OTHER") as never,
unitsTotal: i.unitsTotal,
unitsRemaining: i.unitsRemaining,
firstUseAt: i.firstUseAt ? new Date(i.firstUseAt) : null,
expiresAt: i.expiresAt ? new Date(i.expiresAt) : null,
printedExpiry: i.printedExpiry
? new Date(i.printedExpiry)
: null,
purchasedAt: i.purchasedAt ? new Date(i.purchasedAt) : null,
manufacturer: i.manufacturer ?? null,
doseStrength: i.doseStrength ?? null,
notes: null,
notesEncrypted:
i.notesEncrypted == null
? encryptNote(i.notes ?? null)
: decodeEncryptedBytes(i.notesEncrypted),
...(i.createdAt
? { createdAt: new Date(i.createdAt) }
: {}),
...(i.updatedAt
? { updatedAt: new Date(i.updatedAt) }
: {}),
})),
},
inventoryEvents: {
create: m.inventoryEvents.map((e) => ({
...(e.id ? { id: e.id } : {}),
delta: e.delta,
reason: e.reason,
occurredAt: new Date(e.occurredAt),
})),
},
},
});
restoredMedicationIds.add(created.id);