cms.c2sgmbh/src/migrations_backup/20251130_135459.ts
Martin Porwoll d18e58de40 chore: add jobs, backups, and migration history
Jobs:
- Add consentRetentionJob.ts for GDPR consent cleanup
- Add scheduler.ts for background job scheduling

Backups:
- Add database backup files for recovery

Migration backups:
- Archive old migration files for reference

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 08:24:26 +00:00

170 lines
9 KiB
TypeScript

import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
await db.execute(sql`
-- ENUMs für neue Collections
CREATE TYPE "public"."enum_posts_type" AS ENUM('blog', 'news', 'press', 'announcement');
CREATE TYPE "public"."enum_newsletter_subscribers_status" AS ENUM('pending', 'confirmed', 'unsubscribed', 'bounced');
-- Testimonials Collection
CREATE TABLE IF NOT EXISTS "testimonials" (
"id" serial PRIMARY KEY NOT NULL,
"tenant_id" integer,
"quote" varchar NOT NULL,
"author" varchar NOT NULL,
"role" varchar,
"company" varchar,
"image_id" integer,
"rating" numeric,
"source" varchar,
"source_url" varchar,
"date" timestamp(3) with time zone,
"is_active" boolean DEFAULT true,
"order" integer DEFAULT 0,
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
);
CREATE INDEX IF NOT EXISTS "testimonials_tenant_idx" ON "testimonials" USING btree ("tenant_id");
CREATE INDEX IF NOT EXISTS "testimonials_created_at_idx" ON "testimonials" USING btree ("created_at");
CREATE INDEX IF NOT EXISTS "testimonials_updated_at_idx" ON "testimonials" USING btree ("updated_at");
ALTER TABLE "testimonials" ADD CONSTRAINT "testimonials_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE set null ON UPDATE no action;
ALTER TABLE "testimonials" ADD CONSTRAINT "testimonials_image_id_media_id_fk" FOREIGN KEY ("image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
-- Newsletter Subscribers Collection
CREATE TABLE IF NOT EXISTS "newsletter_subscribers" (
"id" serial PRIMARY KEY NOT NULL,
"tenant_id" integer,
"email" varchar NOT NULL,
"first_name" varchar,
"last_name" varchar,
"status" "enum_newsletter_subscribers_status" DEFAULT 'pending',
"source" varchar,
"subscribed_at" timestamp(3) with time zone,
"confirmed_at" timestamp(3) with time zone,
"unsubscribed_at" timestamp(3) with time zone,
"confirmation_token" varchar,
"ip_address" varchar,
"user_agent" varchar,
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
);
CREATE INDEX IF NOT EXISTS "newsletter_subscribers_tenant_idx" ON "newsletter_subscribers" USING btree ("tenant_id");
CREATE INDEX IF NOT EXISTS "newsletter_subscribers_email_idx" ON "newsletter_subscribers" USING btree ("email");
CREATE INDEX IF NOT EXISTS "newsletter_subscribers_created_at_idx" ON "newsletter_subscribers" USING btree ("created_at");
ALTER TABLE "newsletter_subscribers" ADD CONSTRAINT "newsletter_subscribers_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE set null ON UPDATE no action;
-- Newsletter Subscribers Interests (hasMany select)
CREATE TABLE IF NOT EXISTS "newsletter_subscribers_interests" (
"order" integer NOT NULL,
"parent_id" integer NOT NULL,
"value" varchar,
"id" serial PRIMARY KEY NOT NULL
);
CREATE INDEX IF NOT EXISTS "newsletter_subscribers_interests_order_idx" ON "newsletter_subscribers_interests" USING btree ("order");
CREATE INDEX IF NOT EXISTS "newsletter_subscribers_interests_parent_idx" ON "newsletter_subscribers_interests" USING btree ("parent_id");
ALTER TABLE "newsletter_subscribers_interests" ADD CONSTRAINT "newsletter_subscribers_interests_parent_id_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."newsletter_subscribers"("id") ON DELETE cascade ON UPDATE no action;
-- Pages Rels (für Block-Relationships)
CREATE TABLE IF NOT EXISTS "pages_rels" (
"id" serial PRIMARY KEY NOT NULL,
"order" integer,
"parent_id" integer NOT NULL,
"path" varchar NOT NULL,
"categories_id" integer,
"testimonials_id" integer
);
CREATE INDEX IF NOT EXISTS "pages_rels_order_idx" ON "pages_rels" USING btree ("order");
CREATE INDEX IF NOT EXISTS "pages_rels_parent_idx" ON "pages_rels" USING btree ("parent_id");
CREATE INDEX IF NOT EXISTS "pages_rels_path_idx" ON "pages_rels" USING btree ("path");
ALTER TABLE "pages_rels" ADD CONSTRAINT "pages_rels_parent_id_pages_id_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."pages"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_rels" ADD CONSTRAINT "pages_rels_categories_id_categories_id_fk" FOREIGN KEY ("categories_id") REFERENCES "public"."categories"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "pages_rels" ADD CONSTRAINT "pages_rels_testimonials_id_testimonials_id_fk" FOREIGN KEY ("testimonials_id") REFERENCES "public"."testimonials"("id") ON DELETE cascade ON UPDATE no action;
-- Posts Rels (für Category Relationships)
CREATE TABLE IF NOT EXISTS "posts_rels" (
"id" serial PRIMARY KEY NOT NULL,
"order" integer,
"parent_id" integer NOT NULL,
"path" varchar NOT NULL,
"categories_id" integer
);
CREATE INDEX IF NOT EXISTS "posts_rels_order_idx" ON "posts_rels" USING btree ("order");
CREATE INDEX IF NOT EXISTS "posts_rels_parent_idx" ON "posts_rels" USING btree ("parent_id");
CREATE INDEX IF NOT EXISTS "posts_rels_path_idx" ON "posts_rels" USING btree ("path");
ALTER TABLE "posts_rels" ADD CONSTRAINT "posts_rels_parent_id_posts_id_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."posts"("id") ON DELETE cascade ON UPDATE no action;
ALTER TABLE "posts_rels" ADD CONSTRAINT "posts_rels_categories_id_categories_id_fk" FOREIGN KEY ("categories_id") REFERENCES "public"."categories"("id") ON DELETE cascade ON UPDATE no action;
-- Füge type-Feld zu posts hinzu (falls nicht vorhanden)
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'posts' AND column_name = 'type') THEN
ALTER TABLE "posts" ADD COLUMN "type" "enum_posts_type" DEFAULT 'blog';
END IF;
END $$;
-- Füge isFeatured-Feld zu posts hinzu (falls nicht vorhanden)
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'posts' AND column_name = 'is_featured') THEN
ALTER TABLE "posts" ADD COLUMN "is_featured" boolean DEFAULT false;
END IF;
END $$;
-- Füge excerpt-Feld zu posts hinzu (falls nicht vorhanden)
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'posts' AND column_name = 'excerpt') THEN
ALTER TABLE "posts" ADD COLUMN "excerpt" varchar;
END IF;
END $$;
-- Payload Locked Documents Rels erweitern
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'payload_locked_documents_rels' AND column_name = 'testimonials_id') THEN
ALTER TABLE "payload_locked_documents_rels" ADD COLUMN "testimonials_id" integer;
ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_testimonials_fk" FOREIGN KEY ("testimonials_id") REFERENCES "public"."testimonials"("id") ON DELETE cascade ON UPDATE no action;
CREATE INDEX "payload_locked_documents_rels_testimonials_id_idx" ON "payload_locked_documents_rels" USING btree ("testimonials_id");
END IF;
END $$;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'payload_locked_documents_rels' AND column_name = 'newsletter_subscribers_id') THEN
ALTER TABLE "payload_locked_documents_rels" ADD COLUMN "newsletter_subscribers_id" integer;
ALTER TABLE "payload_locked_documents_rels" ADD CONSTRAINT "payload_locked_documents_rels_newsletter_subscribers_fk" FOREIGN KEY ("newsletter_subscribers_id") REFERENCES "public"."newsletter_subscribers"("id") ON DELETE cascade ON UPDATE no action;
CREATE INDEX "payload_locked_documents_rels_newsletter_subscribers_id_idx" ON "payload_locked_documents_rels" USING btree ("newsletter_subscribers_id");
END IF;
END $$;
`)
}
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
await db.execute(sql`
DROP TABLE IF EXISTS "pages_rels" CASCADE;
DROP TABLE IF EXISTS "posts_rels" CASCADE;
DROP TABLE IF EXISTS "newsletter_subscribers_interests" CASCADE;
DROP TABLE IF EXISTS "newsletter_subscribers" CASCADE;
DROP TABLE IF EXISTS "testimonials" CASCADE;
ALTER TABLE "posts" DROP COLUMN IF EXISTS "type";
ALTER TABLE "posts" DROP COLUMN IF EXISTS "is_featured";
ALTER TABLE "posts" DROP COLUMN IF EXISTS "excerpt";
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "testimonials_id";
ALTER TABLE "payload_locked_documents_rels" DROP COLUMN IF EXISTS "newsletter_subscribers_id";
DROP TYPE IF EXISTS "enum_posts_type";
DROP TYPE IF EXISTS "enum_newsletter_subscribers_status";
`)
}