fix(migration): make 20260518_115657 idempotent — recreate missing group_visits_page and birthday_page tables

Tables group_visits_page, birthday_page and their _v counterparts were missing from the DB
despite prior migrations being marked applied. The updated migration uses CREATE TABLE IF NOT EXISTS,
DO/EXCEPTION blocks for enum types and FK constraints, and ADD COLUMN IF NOT EXISTS to recover
the full schema before adding form_id relationship columns.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Vadym Samoilenko 2026-05-18 12:03:36 +01:00
parent ff4ae6934c
commit 0925ab2052

View file

@ -1,18 +1,208 @@
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
// Step 1: create enum types if they don't exist (added by migration 20260515_162527 which may not have run cleanly)
await db.execute(sql`
ALTER TABLE "group_visits_page" ADD COLUMN "form_id" integer;
ALTER TABLE "group_visits_page" ADD CONSTRAINT "group_visits_page_form_id_forms_id_fk" FOREIGN KEY ("form_id") REFERENCES "forms"("id") ON DELETE SET NULL;
DO $$ BEGIN
CREATE TYPE "public"."enum_group_visits_page_status" AS ENUM('draft', 'published');
EXCEPTION WHEN duplicate_object THEN null; END $$;
ALTER TABLE "_group_visits_page_v" ADD COLUMN "form_id" integer;
ALTER TABLE "_group_visits_page_v" ADD CONSTRAINT "_group_visits_page_v_form_id_forms_id_fk" FOREIGN KEY ("form_id") REFERENCES "forms"("id") ON DELETE SET NULL;
DO $$ BEGIN
CREATE TYPE "public"."enum__group_visits_page_v_version_status" AS ENUM('draft', 'published');
EXCEPTION WHEN duplicate_object THEN null; END $$;
ALTER TABLE "birthday_page" ADD COLUMN "form_id" integer;
ALTER TABLE "birthday_page" ADD CONSTRAINT "birthday_page_form_id_forms_id_fk" FOREIGN KEY ("form_id") REFERENCES "forms"("id") ON DELETE SET NULL;
DO $$ BEGIN
CREATE TYPE "public"."enum_birthday_page_status" AS ENUM('draft', 'published');
EXCEPTION WHEN duplicate_object THEN null; END $$;
ALTER TABLE "_birthday_page_v" ADD COLUMN "form_id" integer;
ALTER TABLE "_birthday_page_v" ADD CONSTRAINT "_birthday_page_v_form_id_forms_id_fk" FOREIGN KEY ("form_id") REFERENCES "forms"("id") ON DELETE SET NULL;
DO $$ BEGIN
CREATE TYPE "public"."enum__birthday_page_v_version_status" AS ENUM('draft', 'published');
EXCEPTION WHEN duplicate_object THEN null; END $$;
`)
// Step 2: create group_visits_page_groups if missing (sub-table of group_visits_page)
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "group_visits_page_groups" (
"_order" integer NOT NULL,
"_parent_id" integer NOT NULL,
"id" varchar PRIMARY KEY NOT NULL,
"icon" varchar,
"title" varchar,
"description" varchar,
"min_people" varchar,
"discount" varchar
);
`)
// Step 3: create group_visits_page if missing
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "group_visits_page" (
"id" serial PRIMARY KEY NOT NULL,
"hero_title" varchar DEFAULT 'Групові відвідування',
"hero_subtitle" varchar DEFAULT 'Спеціальні умови для організованих груп. Мінімум 10 осіб — максимум вражень.',
"form_title" varchar DEFAULT 'Подати заявку на групове відвідування',
"form_subtitle" varchar DEFAULT 'Вкажіть кількість учасників та бажану дату — менеджер зателефонує і погодить деталі.',
"meta_title" varchar,
"meta_description" varchar,
"meta_image_id" integer,
"updated_at" timestamp(3) with time zone,
"created_at" timestamp(3) with time zone
);
`)
// Step 4: create birthday_page if missing
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "birthday_page" (
"id" serial PRIMARY KEY NOT NULL,
"hero_title" varchar DEFAULT 'Дні народження',
"hero_subtitle" varchar DEFAULT 'Зробіть свято незабутнім! Оберіть пакет і наші менеджери зв''яжуться з вами для уточнення деталей.',
"form_title" varchar DEFAULT 'Замовити святкування',
"form_subtitle" varchar DEFAULT 'Залиште заявку і наш менеджер зв''яжеться з вами протягом 30 хвилин',
"meta_title" varchar,
"meta_description" varchar,
"meta_image_id" integer,
"updated_at" timestamp(3) with time zone,
"created_at" timestamp(3) with time zone
);
`)
// Step 5: add _status columns if missing (added by migration 20260515_162527)
await db.execute(sql`
ALTER TABLE "group_visits_page" ADD COLUMN IF NOT EXISTS "_status" "enum_group_visits_page_status" DEFAULT 'draft';
ALTER TABLE "birthday_page" ADD COLUMN IF NOT EXISTS "_status" "enum_birthday_page_status" DEFAULT 'draft';
`)
// Step 6: add FKs on group_visits_page_groups if missing
await db.execute(sql`
DO $$ BEGIN
ALTER TABLE "group_visits_page_groups" ADD CONSTRAINT "group_visits_page_groups_parent_id_fk"
FOREIGN KEY ("_parent_id") REFERENCES "public"."group_visits_page"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION WHEN duplicate_object THEN null; END $$;
DO $$ BEGIN
ALTER TABLE "group_visits_page" ADD CONSTRAINT "group_visits_page_meta_image_id_media_id_fk"
FOREIGN KEY ("meta_image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION WHEN duplicate_object THEN null; END $$;
DO $$ BEGIN
ALTER TABLE "birthday_page" ADD CONSTRAINT "birthday_page_meta_image_id_media_id_fk"
FOREIGN KEY ("meta_image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION WHEN duplicate_object THEN null; END $$;
`)
// Step 7: create _group_visits_page_v if missing
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "_group_visits_page_v" (
"id" serial PRIMARY KEY NOT NULL,
"version_hero_title" varchar DEFAULT 'Групові відвідування',
"version_hero_subtitle" varchar DEFAULT 'Спеціальні умови для організованих груп. Мінімум 10 осіб — максимум вражень.',
"version_form_title" varchar DEFAULT 'Подати заявку на групове відвідування',
"version_form_subtitle" varchar DEFAULT 'Вкажіть кількість учасників та бажану дату — менеджер зателефонує і погодить деталі.',
"version_meta_title" varchar,
"version_meta_description" varchar,
"version_meta_image_id" integer,
"version__status" "enum__group_visits_page_v_version_status" DEFAULT 'draft',
"version_updated_at" timestamp(3) with time zone,
"version_created_at" timestamp(3) with time zone,
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"latest" boolean,
"autosave" boolean
);
`)
// Step 8: create _birthday_page_v if missing
await db.execute(sql`
CREATE TABLE IF NOT EXISTS "_birthday_page_v" (
"id" serial PRIMARY KEY NOT NULL,
"version_hero_title" varchar DEFAULT 'Дні народження',
"version_hero_subtitle" varchar DEFAULT 'Зробіть свято незабутнім! Оберіть пакет і наші менеджери зв''яжуться з вами для уточнення деталей.',
"version_form_title" varchar DEFAULT 'Замовити святкування',
"version_form_subtitle" varchar DEFAULT 'Залиште заявку і наш менеджер зв''яжеться з вами протягом 30 хвилин',
"version_meta_title" varchar,
"version_meta_description" varchar,
"version_meta_image_id" integer,
"version__status" "enum__birthday_page_v_version_status" DEFAULT 'draft',
"version_updated_at" timestamp(3) with time zone,
"version_created_at" timestamp(3) with time zone,
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"latest" boolean,
"autosave" boolean
);
`)
// Step 9: add FK from _group_visits_page_v_version_groups to _group_visits_page_v if missing
await db.execute(sql`
DO $$ BEGIN
ALTER TABLE "_group_visits_page_v_version_groups" ADD CONSTRAINT "_group_visits_page_v_version_groups_parent_id_fk"
FOREIGN KEY ("_parent_id") REFERENCES "public"."_group_visits_page_v"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION WHEN duplicate_object THEN null; END $$;
DO $$ BEGIN
ALTER TABLE "_group_visits_page_v" ADD CONSTRAINT "_group_visits_page_v_version_meta_image_id_media_id_fk"
FOREIGN KEY ("version_meta_image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION WHEN duplicate_object THEN null; END $$;
DO $$ BEGIN
ALTER TABLE "_birthday_page_v" ADD CONSTRAINT "_birthday_page_v_version_meta_image_id_media_id_fk"
FOREIGN KEY ("version_meta_image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
EXCEPTION WHEN duplicate_object THEN null; END $$;
`)
// Step 10: add indexes if missing
await db.execute(sql`
CREATE INDEX IF NOT EXISTS "group_visits_page_groups_order_idx" ON "group_visits_page_groups" USING btree ("_order");
CREATE INDEX IF NOT EXISTS "group_visits_page_groups_parent_id_idx" ON "group_visits_page_groups" USING btree ("_parent_id");
CREATE INDEX IF NOT EXISTS "group_visits_page_meta_meta_image_idx" ON "group_visits_page" USING btree ("meta_image_id");
CREATE INDEX IF NOT EXISTS "birthday_page_meta_meta_image_idx" ON "birthday_page" USING btree ("meta_image_id");
CREATE INDEX IF NOT EXISTS "group_visits_page__status_idx" ON "group_visits_page" USING btree ("_status");
CREATE INDEX IF NOT EXISTS "birthday_page__status_idx" ON "birthday_page" USING btree ("_status");
CREATE INDEX IF NOT EXISTS "_group_visits_page_v_version_groups_order_idx" ON "_group_visits_page_v_version_groups" USING btree ("_order");
CREATE INDEX IF NOT EXISTS "_group_visits_page_v_version_groups_parent_id_idx" ON "_group_visits_page_v_version_groups" USING btree ("_parent_id");
CREATE INDEX IF NOT EXISTS "_group_visits_page_v_version_meta_version_meta_image_idx" ON "_group_visits_page_v" USING btree ("version_meta_image_id");
CREATE INDEX IF NOT EXISTS "_group_visits_page_v_version_version__status_idx" ON "_group_visits_page_v" USING btree ("version__status");
CREATE INDEX IF NOT EXISTS "_group_visits_page_v_created_at_idx" ON "_group_visits_page_v" USING btree ("created_at");
CREATE INDEX IF NOT EXISTS "_group_visits_page_v_updated_at_idx" ON "_group_visits_page_v" USING btree ("updated_at");
CREATE INDEX IF NOT EXISTS "_group_visits_page_v_latest_idx" ON "_group_visits_page_v" USING btree ("latest");
CREATE INDEX IF NOT EXISTS "_group_visits_page_v_autosave_idx" ON "_group_visits_page_v" USING btree ("autosave");
CREATE INDEX IF NOT EXISTS "_birthday_page_v_version_meta_version_meta_image_idx" ON "_birthday_page_v" USING btree ("version_meta_image_id");
CREATE INDEX IF NOT EXISTS "_birthday_page_v_version_version__status_idx" ON "_birthday_page_v" USING btree ("version__status");
CREATE INDEX IF NOT EXISTS "_birthday_page_v_created_at_idx" ON "_birthday_page_v" USING btree ("created_at");
CREATE INDEX IF NOT EXISTS "_birthday_page_v_updated_at_idx" ON "_birthday_page_v" USING btree ("updated_at");
CREATE INDEX IF NOT EXISTS "_birthday_page_v_latest_idx" ON "_birthday_page_v" USING btree ("latest");
CREATE INDEX IF NOT EXISTS "_birthday_page_v_autosave_idx" ON "_birthday_page_v" USING btree ("autosave");
`)
// Step 11: original migration — add form_id columns
await db.execute(sql`
ALTER TABLE "group_visits_page" ADD COLUMN IF NOT EXISTS "form_id" integer;
ALTER TABLE "_group_visits_page_v" ADD COLUMN IF NOT EXISTS "version_form_id" integer;
ALTER TABLE "birthday_page" ADD COLUMN IF NOT EXISTS "form_id" integer;
ALTER TABLE "_birthday_page_v" ADD COLUMN IF NOT EXISTS "version_form_id" integer;
`)
// Step 12: add FK constraints for form_id
await db.execute(sql`
DO $$ BEGIN
ALTER TABLE "group_visits_page" ADD CONSTRAINT "group_visits_page_form_id_forms_id_fk"
FOREIGN KEY ("form_id") REFERENCES "forms"("id") ON DELETE SET NULL;
EXCEPTION WHEN duplicate_object THEN null; END $$;
DO $$ BEGIN
ALTER TABLE "_group_visits_page_v" ADD CONSTRAINT "_group_visits_page_v_form_id_forms_id_fk"
FOREIGN KEY ("version_form_id") REFERENCES "forms"("id") ON DELETE SET NULL;
EXCEPTION WHEN duplicate_object THEN null; END $$;
DO $$ BEGIN
ALTER TABLE "birthday_page" ADD CONSTRAINT "birthday_page_form_id_forms_id_fk"
FOREIGN KEY ("form_id") REFERENCES "forms"("id") ON DELETE SET NULL;
EXCEPTION WHEN duplicate_object THEN null; END $$;
DO $$ BEGIN
ALTER TABLE "_birthday_page_v" ADD CONSTRAINT "_birthday_page_v_form_id_forms_id_fk"
FOREIGN KEY ("version_form_id") REFERENCES "forms"("id") ON DELETE SET NULL;
EXCEPTION WHEN duplicate_object THEN null; END $$;
`)
}
@ -22,12 +212,12 @@ export async function down({ db, payload, req }: MigrateDownArgs): Promise<void>
ALTER TABLE "group_visits_page" DROP COLUMN IF EXISTS "form_id";
ALTER TABLE "_group_visits_page_v" DROP CONSTRAINT IF EXISTS "_group_visits_page_v_form_id_forms_id_fk";
ALTER TABLE "_group_visits_page_v" DROP COLUMN IF EXISTS "form_id";
ALTER TABLE "_group_visits_page_v" DROP COLUMN IF EXISTS "version_form_id";
ALTER TABLE "birthday_page" DROP CONSTRAINT IF EXISTS "birthday_page_form_id_forms_id_fk";
ALTER TABLE "birthday_page" DROP COLUMN IF EXISTS "form_id";
ALTER TABLE "_birthday_page_v" DROP CONSTRAINT IF EXISTS "_birthday_page_v_form_id_forms_id_fk";
ALTER TABLE "_birthday_page_v" DROP COLUMN IF EXISTS "form_id";
ALTER TABLE "_birthday_page_v" DROP COLUMN IF EXISTS "version_form_id";
`)
}