57 lines
2 KiB
Kotlin
57 lines
2 KiB
Kotlin
|
|
package no.naiv.meddetsamme.data
|
||
|
|
|
||
|
|
import androidx.room.Entity
|
||
|
|
import androidx.room.ForeignKey
|
||
|
|
import androidx.room.Index
|
||
|
|
import androidx.room.PrimaryKey
|
||
|
|
|
||
|
|
enum class DoseStatus { PENDING, TAKEN, SKIPPED, SNOOZED }
|
||
|
|
|
||
|
|
/**
|
||
|
|
* One scheduled occurrence of a dose and what happened to it. Created PENDING
|
||
|
|
* when the reminder fires (the escalation anchor), resolved by user action.
|
||
|
|
*
|
||
|
|
* SNOOZED is a *resting* state between nags — the alarm layer treats it like
|
||
|
|
* PENDING (keeps nagging after the snooze interval) but the UI can distinguish
|
||
|
|
* "I saw it and deferred" from "never reacted".
|
||
|
|
*
|
||
|
|
* [doseTimeId] is nullable and SET_NULL on delete: editing a schedule away must
|
||
|
|
* not erase adherence history. [medId] CASCADE instead — deleting a med (vs.
|
||
|
|
* deactivating) is an explicit "forget everything" action.
|
||
|
|
*/
|
||
|
|
@Entity(
|
||
|
|
tableName = "dose_log",
|
||
|
|
foreignKeys = [
|
||
|
|
ForeignKey(
|
||
|
|
entity = Medication::class,
|
||
|
|
parentColumns = ["id"],
|
||
|
|
childColumns = ["medId"],
|
||
|
|
onDelete = ForeignKey.CASCADE,
|
||
|
|
),
|
||
|
|
ForeignKey(
|
||
|
|
entity = DoseTime::class,
|
||
|
|
parentColumns = ["id"],
|
||
|
|
childColumns = ["doseTimeId"],
|
||
|
|
onDelete = ForeignKey.SET_NULL,
|
||
|
|
),
|
||
|
|
],
|
||
|
|
indices = [
|
||
|
|
Index("medId"),
|
||
|
|
Index("doseTimeId"),
|
||
|
|
// The reminder layer's hot path: "is there already a log for this occurrence?"
|
||
|
|
Index(value = ["doseTimeId", "scheduledAtMillis"]),
|
||
|
|
Index("status"),
|
||
|
|
],
|
||
|
|
)
|
||
|
|
data class DoseLog(
|
||
|
|
@PrimaryKey(autoGenerate = true) val id: Long = 0,
|
||
|
|
val medId: Long,
|
||
|
|
val doseTimeId: Long?,
|
||
|
|
/** The occurrence this log is for (epoch millis of the scheduled local time). */
|
||
|
|
val scheduledAtMillis: Long,
|
||
|
|
/** Dose size at the time of logging — schedule edits must not rewrite history. */
|
||
|
|
val amount: Double,
|
||
|
|
val status: DoseStatus = DoseStatus.PENDING,
|
||
|
|
/** When the user last acted on it (Taken/Skipped/Snoozed), null while untouched. */
|
||
|
|
val actionedAtMillis: Long? = null,
|
||
|
|
)
|