mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 22:04:10 +00:00
fix(db): add migration for Favorites and Series collections
- Create migration with ENUMs and tables for BlogWoman collections - favorites table with category, badge, priceRange, affiliateNetwork enums - series table with localized fields (title, tagline, description) - Associated _rels and _locales tables - Set push: false to enforce migration-based schema changes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
49d317fc84
commit
ba1fc6eb00
3 changed files with 254 additions and 1 deletions
247
src/migrations/20260108_160000_add_blogwoman_collections.ts
Normal file
247
src/migrations/20260108_160000_add_blogwoman_collections.ts
Normal file
|
|
@ -0,0 +1,247 @@
|
||||||
|
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migration: Add BlogWoman Collections
|
||||||
|
*
|
||||||
|
* Creates:
|
||||||
|
* - favorites table (Affiliate-Produkte)
|
||||||
|
* - favorites_rels (relations to media)
|
||||||
|
* - series table (YouTube-Serien)
|
||||||
|
* - series_locales (localized fields)
|
||||||
|
* - series_rels (relations to media)
|
||||||
|
*/
|
||||||
|
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
|
||||||
|
await db.execute(sql`
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- ENUMS FOR FAVORITES
|
||||||
|
-- ============================================================
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE "public"."enum_favorites_category" AS ENUM('fashion', 'beauty', 'travel', 'tech', 'home');
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE "public"."enum_favorites_price_range" AS ENUM('budget', 'mid', 'premium', 'luxury');
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE "public"."enum_favorites_affiliate_network" AS ENUM('amazon', 'awin', 'ltk', 'direct', 'other');
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE "public"."enum_favorites_badge" AS ENUM('investment-piece', 'daily-driver', 'grfi-approved', 'new', 'bestseller');
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- FAVORITES TABLE
|
||||||
|
-- ============================================================
|
||||||
|
CREATE TABLE IF NOT EXISTS "favorites" (
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"tenant_id" integer,
|
||||||
|
"title" varchar NOT NULL,
|
||||||
|
"slug" varchar NOT NULL,
|
||||||
|
"description" varchar,
|
||||||
|
"category" "enum_favorites_category" NOT NULL,
|
||||||
|
"subcategory" varchar,
|
||||||
|
"price" numeric,
|
||||||
|
"price_range" "enum_favorites_price_range",
|
||||||
|
"affiliate_url" varchar NOT NULL,
|
||||||
|
"affiliate_network" "enum_favorites_affiliate_network",
|
||||||
|
"image_id" integer,
|
||||||
|
"badge" "enum_favorites_badge",
|
||||||
|
"featured" boolean DEFAULT false,
|
||||||
|
"is_active" boolean NOT NULL DEFAULT true,
|
||||||
|
"order" numeric DEFAULT 0,
|
||||||
|
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||||
|
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Add unique constraint for slug
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "favorites" ADD CONSTRAINT "favorites_slug_idx" UNIQUE ("slug");
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_table THEN null;
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- Foreign key for tenant
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "favorites" ADD CONSTRAINT "favorites_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- Foreign key for image
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "favorites" ADD CONSTRAINT "favorites_image_id_media_id_fk" FOREIGN KEY ("image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- Indexes
|
||||||
|
CREATE INDEX IF NOT EXISTS "favorites_tenant_idx" ON "favorites" USING btree ("tenant_id");
|
||||||
|
CREATE INDEX IF NOT EXISTS "favorites_image_idx" ON "favorites" USING btree ("image_id");
|
||||||
|
CREATE INDEX IF NOT EXISTS "favorites_created_at_idx" ON "favorites" USING btree ("created_at");
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- FAVORITES_RELS TABLE (for polymorphic relations)
|
||||||
|
-- ============================================================
|
||||||
|
CREATE TABLE IF NOT EXISTS "favorites_rels" (
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"order" integer,
|
||||||
|
"parent_id" integer NOT NULL,
|
||||||
|
"path" varchar NOT NULL,
|
||||||
|
"media_id" integer
|
||||||
|
);
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "favorites_rels" ADD CONSTRAINT "favorites_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."favorites"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "favorites_rels" ADD CONSTRAINT "favorites_rels_media_fk" FOREIGN KEY ("media_id") REFERENCES "public"."media"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS "favorites_rels_order_idx" ON "favorites_rels" USING btree ("order");
|
||||||
|
CREATE INDEX IF NOT EXISTS "favorites_rels_parent_idx" ON "favorites_rels" USING btree ("parent_id");
|
||||||
|
CREATE INDEX IF NOT EXISTS "favorites_rels_path_idx" ON "favorites_rels" USING btree ("path");
|
||||||
|
CREATE INDEX IF NOT EXISTS "favorites_rels_media_idx" ON "favorites_rels" USING btree ("media_id");
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- SERIES TABLE
|
||||||
|
-- ============================================================
|
||||||
|
CREATE TABLE IF NOT EXISTS "series" (
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"tenant_id" integer,
|
||||||
|
"slug" varchar NOT NULL,
|
||||||
|
"logo_id" integer,
|
||||||
|
"cover_image_id" integer,
|
||||||
|
"brand_color" varchar,
|
||||||
|
"accent_color" varchar,
|
||||||
|
"youtube_playlist_id" varchar,
|
||||||
|
"youtube_playlist_url" varchar,
|
||||||
|
"order" numeric DEFAULT 0,
|
||||||
|
"is_active" boolean NOT NULL DEFAULT true,
|
||||||
|
"updated_at" timestamp(3) with time zone DEFAULT now() NOT NULL,
|
||||||
|
"created_at" timestamp(3) with time zone DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Add unique constraint for slug
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "series" ADD CONSTRAINT "series_slug_idx" UNIQUE ("slug");
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_table THEN null;
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- Foreign keys
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "series" ADD CONSTRAINT "series_tenant_id_tenants_id_fk" FOREIGN KEY ("tenant_id") REFERENCES "public"."tenants"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "series" ADD CONSTRAINT "series_logo_id_media_id_fk" FOREIGN KEY ("logo_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "series" ADD CONSTRAINT "series_cover_image_id_media_id_fk" FOREIGN KEY ("cover_image_id") REFERENCES "public"."media"("id") ON DELETE set null ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- Indexes
|
||||||
|
CREATE INDEX IF NOT EXISTS "series_tenant_idx" ON "series" USING btree ("tenant_id");
|
||||||
|
CREATE INDEX IF NOT EXISTS "series_logo_idx" ON "series" USING btree ("logo_id");
|
||||||
|
CREATE INDEX IF NOT EXISTS "series_cover_image_idx" ON "series" USING btree ("cover_image_id");
|
||||||
|
CREATE INDEX IF NOT EXISTS "series_created_at_idx" ON "series" USING btree ("created_at");
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- SERIES_LOCALES TABLE (for localized fields)
|
||||||
|
-- ============================================================
|
||||||
|
CREATE TABLE IF NOT EXISTS "series_locales" (
|
||||||
|
"title" varchar NOT NULL,
|
||||||
|
"tagline" varchar,
|
||||||
|
"description" jsonb,
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"_locale" "_locales" NOT NULL,
|
||||||
|
"_parent_id" integer NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "series_locales" ADD CONSTRAINT "series_locales_parent_id_fk" FOREIGN KEY ("_parent_id") REFERENCES "public"."series"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- Unique constraint for parent + locale combination
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "series_locales" ADD CONSTRAINT "series_locales_locale_parent_id_unique" UNIQUE ("_locale", "_parent_id");
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
-- ============================================================
|
||||||
|
-- SERIES_RELS TABLE (for polymorphic relations)
|
||||||
|
-- ============================================================
|
||||||
|
CREATE TABLE IF NOT EXISTS "series_rels" (
|
||||||
|
"id" serial PRIMARY KEY NOT NULL,
|
||||||
|
"order" integer,
|
||||||
|
"parent_id" integer NOT NULL,
|
||||||
|
"path" varchar NOT NULL,
|
||||||
|
"media_id" integer
|
||||||
|
);
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "series_rels" ADD CONSTRAINT "series_rels_parent_fk" FOREIGN KEY ("parent_id") REFERENCES "public"."series"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "series_rels" ADD CONSTRAINT "series_rels_media_fk" FOREIGN KEY ("media_id") REFERENCES "public"."media"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS "series_rels_order_idx" ON "series_rels" USING btree ("order");
|
||||||
|
CREATE INDEX IF NOT EXISTS "series_rels_parent_idx" ON "series_rels" USING btree ("parent_id");
|
||||||
|
CREATE INDEX IF NOT EXISTS "series_rels_path_idx" ON "series_rels" USING btree ("path");
|
||||||
|
CREATE INDEX IF NOT EXISTS "series_rels_media_idx" ON "series_rels" USING btree ("media_id");
|
||||||
|
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
|
||||||
|
await db.execute(sql`
|
||||||
|
|
||||||
|
-- Drop tables in reverse order of dependencies
|
||||||
|
DROP TABLE IF EXISTS "series_rels";
|
||||||
|
DROP TABLE IF EXISTS "series_locales";
|
||||||
|
DROP TABLE IF EXISTS "series";
|
||||||
|
DROP TABLE IF EXISTS "favorites_rels";
|
||||||
|
DROP TABLE IF EXISTS "favorites";
|
||||||
|
|
||||||
|
-- Drop enums
|
||||||
|
DROP TYPE IF EXISTS "enum_favorites_category";
|
||||||
|
DROP TYPE IF EXISTS "enum_favorites_price_range";
|
||||||
|
DROP TYPE IF EXISTS "enum_favorites_affiliate_network";
|
||||||
|
DROP TYPE IF EXISTS "enum_favorites_badge";
|
||||||
|
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@ import * as migration_20251214_000000_add_priority_collections from './20251214_
|
||||||
import * as migration_20251214_010000_tenant_specific_collections from './20251214_010000_tenant_specific_collections';
|
import * as migration_20251214_010000_tenant_specific_collections from './20251214_010000_tenant_specific_collections';
|
||||||
import * as migration_20251216_073000_add_video_collections from './20251216_073000_add_video_collections';
|
import * as migration_20251216_073000_add_video_collections from './20251216_073000_add_video_collections';
|
||||||
import * as migration_20251216_080000_posts_featured_video_processed_fields from './20251216_080000_posts_featured_video_processed_fields';
|
import * as migration_20251216_080000_posts_featured_video_processed_fields from './20251216_080000_posts_featured_video_processed_fields';
|
||||||
|
import * as migration_20260108_160000_add_blogwoman_collections from './20260108_160000_add_blogwoman_collections';
|
||||||
|
|
||||||
export const migrations = [
|
export const migrations = [
|
||||||
{
|
{
|
||||||
|
|
@ -132,4 +133,9 @@ export const migrations = [
|
||||||
down: migration_20251216_080000_posts_featured_video_processed_fields.down,
|
down: migration_20251216_080000_posts_featured_video_processed_fields.down,
|
||||||
name: '20251216_080000_posts_featured_video_processed_fields',
|
name: '20251216_080000_posts_featured_video_processed_fields',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
up: migration_20260108_160000_add_blogwoman_collections.up,
|
||||||
|
down: migration_20260108_160000_add_blogwoman_collections.down,
|
||||||
|
name: '20260108_160000_add_blogwoman_collections',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,7 @@ export default buildConfig({
|
||||||
pool: {
|
pool: {
|
||||||
connectionString: env.DATABASE_URI,
|
connectionString: env.DATABASE_URI,
|
||||||
},
|
},
|
||||||
// push: false - Schema manuell erstellt
|
// push: false - Migrationen für Schema-Änderungen verwenden
|
||||||
push: false,
|
push: false,
|
||||||
}),
|
}),
|
||||||
// Sharp für Bildoptimierung
|
// Sharp für Bildoptimierung
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue