fix(seed): repair demo seed against the current schema

Two gaps stopped a fresh demo seed:

- medication_intake_events gained a NOT NULL updated_at column in the
  v1.7.0 sync keyset work. The raw INSERTs omitted it; set it alongside
  created_at on every intake row so the seed does not lean on the
  column's migration-only default.

- app_settings carried four columns on the schema (default_locale plus
  the telegram/ntfy/web-push global toggles) that never landed in the
  migration history — applied via db push to existing environments but
  never committed. A database built from migrations alone is missing
  them, and the admin settings read path selects default_locale, so a
  fresh deploy reports "column default_locale does not exist" on first
  read. Add an idempotent ADD COLUMN IF NOT EXISTS drift-fix migration
  mirroring 0025_user_locale_drift_fix: a no-op where the columns exist,
  a clean add on a migrations-only build.

Verified end to end against a fresh Postgres 16 built from the full
migration set: the seed completes and re-runs cleanly.
This commit is contained in:
Marc-André Bombeck committed 2026-06-01 17:31:45 +02:00
1 parent 65cfa2b83a
commit 65bbedd83d
2 files changed
+32 -12

No files matched your search

@@ -0,0 +1,20 @@
-- 0098_app_settings_global_toggles_drift_fix
-- Four `app_settings` columns have been on `prisma/schema.prisma` since the
-- per-channel global notification toggles + admin default-locale work but
-- never landed in the migration history (applied via `prisma db push` to
-- existing environments but not committed as a migration). The drift is
-- invisible on a database kept in sync via `db push`, but a database built
-- from migrations alone is missing the columns — and the admin settings
-- read path (`/api/admin/settings`) selects `default_locale`, so a fresh
-- deploy reports `column "default_locale" does not exist` on first read.
--
-- Same class of drift as 0025_user_locale_drift_fix. Each add uses
-- `IF NOT EXISTS` with the schema default, so the migration is a safe no-op
-- against any environment already carrying the columns and a clean add
-- against one built strictly from this migrations directory (CI test
-- containers, fresh deploys, demo seeds).
ALTER TABLE "app_settings"
ADD COLUMN IF NOT EXISTS "default_locale" TEXT NOT NULL DEFAULT 'de',
ADD COLUMN IF NOT EXISTS "telegram_global" BOOLEAN NOT NULL DEFAULT true,
ADD COLUMN IF NOT EXISTS "ntfy_global" BOOLEAN NOT NULL DEFAULT true,
ADD COLUMN IF NOT EXISTS "web_push_global" BOOLEAN NOT NULL DEFAULT true;
+12 -12
View File
@@ -247,14 +247,14 @@ async function seed() {
const takenTime = new Date(date);
takenTime.setHours(8, Math.floor(Math.random() * 45), 0);
await client.query(
`INSERT INTO medication_intake_events (id, user_id, medication_id, scheduled_for, taken_at, skipped, source, created_at)
VALUES ($1, $2, $3, $4, $5, false, 'WEB', $5)`,
`INSERT INTO medication_intake_events (id, user_id, medication_id, scheduled_for, taken_at, skipped, source, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, false, 'WEB', $5, $5)`,
[cuid(), userId, med1Id, date, takenTime],
);
} else {
await client.query(
`INSERT INTO medication_intake_events (id, user_id, medication_id, scheduled_for, taken_at, skipped, source, created_at)
VALUES ($1, $2, $3, $4, NULL, true, 'WEB', $4)`,
`INSERT INTO medication_intake_events (id, user_id, medication_id, scheduled_for, taken_at, skipped, source, created_at, updated_at)
VALUES ($1, $2, $3, $4, NULL, true, 'WEB', $4, $4)`,
[cuid(), userId, med1Id, date],
);
}
@@ -265,14 +265,14 @@ async function seed() {
const takenTime = new Date(date);
takenTime.setHours(8, Math.floor(5 + Math.random() * 50), 0);
await client.query(
`INSERT INTO medication_intake_events (id, user_id, medication_id, scheduled_for, taken_at, skipped, source, created_at)
VALUES ($1, $2, $3, $4, $5, false, 'WEB', $5)`,
`INSERT INTO medication_intake_events (id, user_id, medication_id, scheduled_for, taken_at, skipped, source, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, false, 'WEB', $5, $5)`,
[cuid(), userId, med2Id, date, takenTime],
);
} else {
await client.query(
`INSERT INTO medication_intake_events (id, user_id, medication_id, scheduled_for, taken_at, skipped, source, created_at)
VALUES ($1, $2, $3, $4, NULL, true, 'WEB', $4)`,
`INSERT INTO medication_intake_events (id, user_id, medication_id, scheduled_for, taken_at, skipped, source, created_at, updated_at)
VALUES ($1, $2, $3, $4, NULL, true, 'WEB', $4, $4)`,
[cuid(), userId, med2Id, date],
);
}
@@ -284,14 +284,14 @@ async function seed() {
const takenTime = new Date(date);
takenTime.setHours(20, Math.floor(Math.random() * 60), 0);
await client.query(
`INSERT INTO medication_intake_events (id, user_id, medication_id, scheduled_for, taken_at, skipped, source, created_at)
VALUES ($1, $2, $3, $4, $5, false, 'WEB', $5)`,
`INSERT INTO medication_intake_events (id, user_id, medication_id, scheduled_for, taken_at, skipped, source, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, false, 'WEB', $5, $5)`,
[cuid(), userId, med3Id, date, takenTime],
);
} else {
await client.query(
`INSERT INTO medication_intake_events (id, user_id, medication_id, scheduled_for, taken_at, skipped, source, created_at)
VALUES ($1, $2, $3, $4, NULL, true, 'WEB', $4)`,
`INSERT INTO medication_intake_events (id, user_id, medication_id, scheduled_for, taken_at, skipped, source, created_at, updated_at)
VALUES ($1, $2, $3, $4, NULL, true, 'WEB', $4, $4)`,
[cuid(), userId, med3Id, date],
);
}