Add a recurring month-day season window to DoseTime (seasonStartMmdd/
seasonEndMmdd): a med rests outside its window and re-arms automatically
every year. The pure ScheduleEngine gains a season filter plus one-year
overrides -- startEpochDay/endEpochDay act as early-start/extend brackets
for seasonal rows while staying hard bounds for tapers.
- Daily SupplyCheck nudges before a season opens (Start naa) and before it
closes (Forleng), handled by the new SeasonActionReceiver.
- Med list lists resting seasonal meds in a "Sesong (hviler)" section.
- Dose-time editor gains a season block and a "scroll for more" hint so
cyclic/season below the time picker are discoverable.
- Room migration v3->v4 (additive), backup DTO extended, engine/text tests.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extends DoseTime with two orthogonal filters, as the brief foresaw
('cyclic/taper extend from the same model'):
- Cyclic (cycleActiveDays/cycleLengthDays from anchor): N-on/M-off, e.g.
21/28 contraception. occursOn gains a cycle-window check; nextOccurrence
is now a uniform day-by-day scan over occursOn (replacing the interval
fast-path) so weekly/interval/cyclic/windowed all fall out of one
correct path.
- Validity window (startEpochDay/endEpochDay, inclusive): a taper is
several daily rows with descending amount and adjacent windows.
dailyConsumption now takes : cyclic scales by active/length, and
rows outside their window contribute 0 so a finished taper step stops
inflating days-of-supply.
UI: dose-time dialog gains a Syklisk section (på/av days) and is now
scrollable; a 'Lag nedtrapping' generator creates the windowed rows from
start dose / step-down / days-per-step / step-count. ScheduleText renders
'· syklus 21/28' and '· 11. juni–13. juni'.
Migration 2→3 is additive ADD COLUMNs with defaults matching the entity
(@ColumnInfo defaultValue), proven by an instrumented MigrationTestHelper
test. Backup DTO extended with defaults so v2 files still parse. 9 new
engine unit tests; versionCode 3 / 0.3.0.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
Milestone 4. AlarmScheduler is the only AlarmManager writer; one stable
PendingIntent requestCode per dose-time means re-arming replaces and can
never stack (the no-drift invariant is OS-enforced). DoseAlarmReceiver
handles both occurrence and escalation alarms idempotently and always
re-arms the next occurrence before anything else so the chain can't
break. nagCount lives in dose_log so the ~6-nag cap survives reboot.
SCHEDULE_EXACT_ALARM added maxSdk 32 (USE_EXACT_ALARM is 33+ only).
Emulator-verified (API 35): exact alarm armed (window=0,
policy_permission), fired on time, HIGH notification with Tatt/Utsett,
escalation armed +10 min, next day re-armed, Tatt → TAKEN + inventory
10→9 + escalation cancelled, reboot → BootReceiver re-armed everything.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Milestone 2. Medication / DoseTime / DoseLog per the brief's model.
DoseLog.doseTimeId is SET_NULL (schedule edits must not erase adherence
history) while medId CASCADEs; DoseLog.amount is snapshotted at logging
time so later dose changes don't rewrite the record. Inventory decrement
is a single SQL UPDATE clamped at 0 to stay race-free under escalating
notifications. Enums stored as TEXT; schema exported to app/schemas as
the migration baseline.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>