Stock, package size and prescription state move to inventory_item; medication is now a regimen (itemId FK RESTRICT — deleting a stock item can never silently take adherence history with it). Supply warnings aggregate consumption across all regimens sharing an item. New Lager screen with one-tap '+1 pakning' restock; med editor picks an existing item or creates one inline via the shared ItemFormState (one form, no drift). Backup format v2 mirrors the split and still restores v1 files by performing the same conversion the DB migration does. MIGRATION_1_2 statements are copied from the exported 2.json and proven by an instrumented MigrationTestHelper test on the emulator (validates against the schema AND asserts data survival) before it ever touches the phone's medical record. Heads-up: connectedAndroidTest must target the emulator (ANDROID_SERIAL) — the phone's release signature rejects debug test APKs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
351 lines
No EOL
10 KiB
JSON
351 lines
No EOL
10 KiB
JSON
{
|
|
"formatVersion": 1,
|
|
"database": {
|
|
"version": 2,
|
|
"identityHash": "9db9677c3732d2974727b2ffb1be788b",
|
|
"entities": [
|
|
{
|
|
"tableName": "inventory_item",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `strength` TEXT NOT NULL, `unit` TEXT NOT NULL, `form` TEXT NOT NULL, `atcCode` TEXT, `packageSize` REAL, `stockUnits` REAL NOT NULL, `lowStockLeadDays` INTEGER NOT NULL, `rxExpiryEpochDay` INTEGER, `refillsRemaining` INTEGER)",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "id",
|
|
"columnName": "id",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "name",
|
|
"columnName": "name",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "strength",
|
|
"columnName": "strength",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "unit",
|
|
"columnName": "unit",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "form",
|
|
"columnName": "form",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "atcCode",
|
|
"columnName": "atcCode",
|
|
"affinity": "TEXT"
|
|
},
|
|
{
|
|
"fieldPath": "packageSize",
|
|
"columnName": "packageSize",
|
|
"affinity": "REAL"
|
|
},
|
|
{
|
|
"fieldPath": "stockUnits",
|
|
"columnName": "stockUnits",
|
|
"affinity": "REAL",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "lowStockLeadDays",
|
|
"columnName": "lowStockLeadDays",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "rxExpiryEpochDay",
|
|
"columnName": "rxExpiryEpochDay",
|
|
"affinity": "INTEGER"
|
|
},
|
|
{
|
|
"fieldPath": "refillsRemaining",
|
|
"columnName": "refillsRemaining",
|
|
"affinity": "INTEGER"
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": true,
|
|
"columnNames": [
|
|
"id"
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"tableName": "medication",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `itemId` INTEGER NOT NULL, `withFood` INTEGER NOT NULL, `notes` TEXT NOT NULL, `active` INTEGER NOT NULL, FOREIGN KEY(`itemId`) REFERENCES `inventory_item`(`id`) ON UPDATE NO ACTION ON DELETE RESTRICT )",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "id",
|
|
"columnName": "id",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "itemId",
|
|
"columnName": "itemId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "withFood",
|
|
"columnName": "withFood",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "notes",
|
|
"columnName": "notes",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "active",
|
|
"columnName": "active",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": true,
|
|
"columnNames": [
|
|
"id"
|
|
]
|
|
},
|
|
"indices": [
|
|
{
|
|
"name": "index_medication_itemId",
|
|
"unique": false,
|
|
"columnNames": [
|
|
"itemId"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_medication_itemId` ON `${TABLE_NAME}` (`itemId`)"
|
|
}
|
|
],
|
|
"foreignKeys": [
|
|
{
|
|
"table": "inventory_item",
|
|
"onDelete": "RESTRICT",
|
|
"onUpdate": "NO ACTION",
|
|
"columns": [
|
|
"itemId"
|
|
],
|
|
"referencedColumns": [
|
|
"id"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"tableName": "dose_time",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `medId` INTEGER NOT NULL, `minuteOfDay` INTEGER NOT NULL, `amount` REAL NOT NULL, `daysOfWeekMask` INTEGER NOT NULL, `intervalDays` INTEGER NOT NULL, `anchorEpochDay` INTEGER, FOREIGN KEY(`medId`) REFERENCES `medication`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "id",
|
|
"columnName": "id",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "medId",
|
|
"columnName": "medId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "minuteOfDay",
|
|
"columnName": "minuteOfDay",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "amount",
|
|
"columnName": "amount",
|
|
"affinity": "REAL",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "daysOfWeekMask",
|
|
"columnName": "daysOfWeekMask",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "intervalDays",
|
|
"columnName": "intervalDays",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "anchorEpochDay",
|
|
"columnName": "anchorEpochDay",
|
|
"affinity": "INTEGER"
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": true,
|
|
"columnNames": [
|
|
"id"
|
|
]
|
|
},
|
|
"indices": [
|
|
{
|
|
"name": "index_dose_time_medId",
|
|
"unique": false,
|
|
"columnNames": [
|
|
"medId"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_dose_time_medId` ON `${TABLE_NAME}` (`medId`)"
|
|
}
|
|
],
|
|
"foreignKeys": [
|
|
{
|
|
"table": "medication",
|
|
"onDelete": "CASCADE",
|
|
"onUpdate": "NO ACTION",
|
|
"columns": [
|
|
"medId"
|
|
],
|
|
"referencedColumns": [
|
|
"id"
|
|
]
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"tableName": "dose_log",
|
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `medId` INTEGER NOT NULL, `doseTimeId` INTEGER, `scheduledAtMillis` INTEGER NOT NULL, `amount` REAL NOT NULL, `status` TEXT NOT NULL, `actionedAtMillis` INTEGER, `nagCount` INTEGER NOT NULL, FOREIGN KEY(`medId`) REFERENCES `medication`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`doseTimeId`) REFERENCES `dose_time`(`id`) ON UPDATE NO ACTION ON DELETE SET NULL )",
|
|
"fields": [
|
|
{
|
|
"fieldPath": "id",
|
|
"columnName": "id",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "medId",
|
|
"columnName": "medId",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "doseTimeId",
|
|
"columnName": "doseTimeId",
|
|
"affinity": "INTEGER"
|
|
},
|
|
{
|
|
"fieldPath": "scheduledAtMillis",
|
|
"columnName": "scheduledAtMillis",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "amount",
|
|
"columnName": "amount",
|
|
"affinity": "REAL",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "status",
|
|
"columnName": "status",
|
|
"affinity": "TEXT",
|
|
"notNull": true
|
|
},
|
|
{
|
|
"fieldPath": "actionedAtMillis",
|
|
"columnName": "actionedAtMillis",
|
|
"affinity": "INTEGER"
|
|
},
|
|
{
|
|
"fieldPath": "nagCount",
|
|
"columnName": "nagCount",
|
|
"affinity": "INTEGER",
|
|
"notNull": true
|
|
}
|
|
],
|
|
"primaryKey": {
|
|
"autoGenerate": true,
|
|
"columnNames": [
|
|
"id"
|
|
]
|
|
},
|
|
"indices": [
|
|
{
|
|
"name": "index_dose_log_medId",
|
|
"unique": false,
|
|
"columnNames": [
|
|
"medId"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_dose_log_medId` ON `${TABLE_NAME}` (`medId`)"
|
|
},
|
|
{
|
|
"name": "index_dose_log_doseTimeId",
|
|
"unique": false,
|
|
"columnNames": [
|
|
"doseTimeId"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_dose_log_doseTimeId` ON `${TABLE_NAME}` (`doseTimeId`)"
|
|
},
|
|
{
|
|
"name": "index_dose_log_doseTimeId_scheduledAtMillis",
|
|
"unique": false,
|
|
"columnNames": [
|
|
"doseTimeId",
|
|
"scheduledAtMillis"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_dose_log_doseTimeId_scheduledAtMillis` ON `${TABLE_NAME}` (`doseTimeId`, `scheduledAtMillis`)"
|
|
},
|
|
{
|
|
"name": "index_dose_log_status",
|
|
"unique": false,
|
|
"columnNames": [
|
|
"status"
|
|
],
|
|
"orders": [],
|
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_dose_log_status` ON `${TABLE_NAME}` (`status`)"
|
|
}
|
|
],
|
|
"foreignKeys": [
|
|
{
|
|
"table": "medication",
|
|
"onDelete": "CASCADE",
|
|
"onUpdate": "NO ACTION",
|
|
"columns": [
|
|
"medId"
|
|
],
|
|
"referencedColumns": [
|
|
"id"
|
|
]
|
|
},
|
|
{
|
|
"table": "dose_time",
|
|
"onDelete": "SET NULL",
|
|
"onUpdate": "NO ACTION",
|
|
"columns": [
|
|
"doseTimeId"
|
|
],
|
|
"referencedColumns": [
|
|
"id"
|
|
]
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"setupQueries": [
|
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '9db9677c3732d2974727b2ffb1be788b')"
|
|
]
|
|
}
|
|
} |