mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 06:06:10 +00:00
feat(backup): carry the mood day context through export and restore
- the completeness guard now binds a third model, MoodContext, to a named select; the four omitted columns each carry the reason the backup is right to drop them - the disaster-recovery arm carries the ciphertext, the portable arm the plain text, and every other column rides in both - the restore rebuilds the context after its entry, inside the same transaction, and a file written before contexts existed restores without one - the round trip asserts the restored row by value, zero included
This commit is contained in:
1 parent
a25ec211cd
commit
8eb36da228
5 files changed
+420
-3
No files matched your search
@@ -858,6 +858,50 @@ const handler = apiHandler(
|
||||
update: restoredData,
|
||||
});
|
||||
|
||||
// The day context, rebuilt after the entry so it can bind to
|
||||
// whatever id that entry actually got. Delete-then-write rather
|
||||
// than an upsert with a preserve-when-absent arm: the file
|
||||
// states the whole context or states that there was none, and a
|
||||
// restored entry carrying half a file's context and half a live
|
||||
// row's would be a state neither of them describes.
|
||||
await tx.moodContext.deleteMany({
|
||||
where: { moodEntryId: restored.id },
|
||||
});
|
||||
if (entry.context) {
|
||||
const context = entry.context;
|
||||
await tx.moodContext.create({
|
||||
data: {
|
||||
moodEntryId: restored.id,
|
||||
userId: ownerId,
|
||||
workStatus: context.workStatus ?? null,
|
||||
workMinutes: context.workMinutes ?? null,
|
||||
overtimeMinutes: context.overtimeMinutes ?? null,
|
||||
workLoad: context.workLoad ?? null,
|
||||
workSatisfaction: context.workSatisfaction ?? null,
|
||||
contactCircles: context.contactCircles ?? null,
|
||||
contactForm: context.contactForm ?? null,
|
||||
contactExtent: context.contactExtent ?? null,
|
||||
contactQuality: context.contactQuality ?? null,
|
||||
contactSupport: context.contactSupport ?? null,
|
||||
leisureCategories: context.leisureCategories ?? null,
|
||||
leisureMinutes: context.leisureMinutes ?? null,
|
||||
leisureJoy: context.leisureJoy ?? null,
|
||||
leisureRecovery: context.leisureRecovery ?? null,
|
||||
eventType: context.eventType ?? null,
|
||||
eventValence: context.eventValence ?? null,
|
||||
eventAt: context.eventAt ? new Date(context.eventAt) : null,
|
||||
// The note comes back the way every other dual-column
|
||||
// note does: ciphertext verbatim when the file carries
|
||||
// it, a portable file's plain text re-encrypted on the
|
||||
// way in.
|
||||
notesEncrypted:
|
||||
context.notesEncrypted == null
|
||||
? encryptNote(context.note ?? null)
|
||||
: decodeEncryptedBytes(context.notesEncrypted),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
await tx.moodEntryTagLink.deleteMany({
|
||||
where: { moodEntryId: restored.id },
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user