Files
HealthLog/prisma/migrations/0130_v1150_cycle_prediction/migration.sql
T
Marc-André BombeckandClaude Opus 4.8 a5946e6209 feat(cycle): add cycle-tracking schema foundation
Introduce the persistence layer for cycle tracking: eight enums
(CycleTrackingGoal, FlowLevel, OvulationTest, CervicalMucus,
HomeTestResult, ContraceptiveKind, CyclePhase, PredictionMethod) and
seven models.

CycleProfile is a 1:1 per-user settings row (lazily upserted on first
access via getOrCreateCycleProfile). MenstrualCycle and CycleDayLog are
the capture rows, carrying the MoodEntry soft-delete + syncVersion shape
so they ride the sync delta feed; CycleDayLog repeats the MoodEntry
dual-unique — the canonical (userId, date) key plus the NULL-distinct
(userId, source, externalId) key for HealthKit re-ingest. Free-text
notes encrypt at rest; queryable physiology (flow, BBT, OPK, mucus,
dates) stays plaintext for the rollup and correlation tier. The symptom
taxonomy (CycleSymptomCategory / CycleSymptom / CycleSymptomLink) clones
the mood-tag trio and seeds fifteen symptoms across three categories
with cycle.symptom.* i18n keys across all six locales. CyclePrediction
caches one forecast per user, regenerated debounced.

Migrations 0128-0130 are additive; the testcontainer integration suite
applies the full history from scratch and passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 08:19:32 +02:00

36 lines
1.3 KiB
SQL

-- v1.15.0 — cycle prediction cache.
--
-- One cached forecast per user, regenerated debounced /
-- stale-while-revalidate (the InsightNarrative + v1.8.7 assessment cache
-- pattern), NOT per-read. Derived data — not soft-deleted. The ranged
-- Low / High band is rendered as a band, never a single date.
--
-- Reversibility (down):
-- DROP TABLE IF EXISTS "cycle_predictions";
-- CreateTable
CREATE TABLE "cycle_predictions" (
"id" TEXT NOT NULL,
"user_id" TEXT NOT NULL,
"method" "prediction_method" NOT NULL,
"next_period_start" TEXT NOT NULL,
"next_period_start_low" TEXT NOT NULL,
"next_period_start_high" TEXT NOT NULL,
"fertile_window_start" TEXT,
"fertile_window_end" TEXT,
"predicted_ovulation" TEXT,
"confidence" DOUBLE PRECISION NOT NULL,
"cycles_observed" INTEGER NOT NULL,
"generated_at" TIMESTAMP(3) NOT NULL,
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(3) NOT NULL,
CONSTRAINT "cycle_predictions_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "cycle_predictions_user_id_key" ON "cycle_predictions"("user_id");
-- AddForeignKey
ALTER TABLE "cycle_predictions" ADD CONSTRAINT "cycle_predictions_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;