Update data model: flat proclamation groups, drop subscription levels; allow profile/license key without user
This commit is contained in:
+81
@@ -0,0 +1,81 @@
|
||||
-- Flatten ProclamationCategory hierarchy into a flat list, introduce
|
||||
-- ProclamationGroup (formerly child sub-categories), and remove
|
||||
-- SubscriptionLevel entirely.
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ProclamationGroup" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
CONSTRAINT "ProclamationGroup_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "ProclamationGroup_name_key" ON "ProclamationGroup"("name");
|
||||
|
||||
-- Seed groups from every distinct former sub-category name
|
||||
INSERT INTO "ProclamationGroup" ("name", "sortOrder")
|
||||
SELECT "name",
|
||||
ROW_NUMBER() OVER (ORDER BY "name") - 1
|
||||
FROM (
|
||||
SELECT DISTINCT "name" FROM "ProclamationCategory" WHERE "parentId" IS NOT NULL
|
||||
) AS d;
|
||||
|
||||
-- AddColumn (nullable during backfill)
|
||||
ALTER TABLE "Proclamation" ADD COLUMN "groupId" INTEGER;
|
||||
|
||||
-- Backfill: former child categories become the proclamation's group; the
|
||||
-- parent becomes its flat category.
|
||||
UPDATE "Proclamation" AS p
|
||||
SET "groupId" = g."id",
|
||||
"categoryId" = c."parentId"
|
||||
FROM "ProclamationCategory" AS c
|
||||
JOIN "ProclamationGroup" AS g ON g."name" = c."name"
|
||||
WHERE p."categoryId" = c."id" AND c."parentId" IS NOT NULL;
|
||||
|
||||
-- Backfill: proclamations that had no group (e.g. 'Custom (Client Specific)')
|
||||
-- default to the General group, if it exists.
|
||||
UPDATE "Proclamation"
|
||||
SET "groupId" = (SELECT "id" FROM "ProclamationGroup" WHERE "name" = 'General')
|
||||
WHERE "groupId" IS NULL;
|
||||
|
||||
-- Safety net: any proclamation still unmapped takes the first group.
|
||||
UPDATE "Proclamation"
|
||||
SET "groupId" = (SELECT "id" FROM "ProclamationGroup" ORDER BY "sortOrder" LIMIT 1)
|
||||
WHERE "groupId" IS NULL;
|
||||
|
||||
ALTER TABLE "Proclamation" ALTER COLUMN "groupId" SET NOT NULL;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Proclamation" ADD CONSTRAINT "Proclamation_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "ProclamationGroup"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- Remove former child categories (subscription-level join rows cascade)
|
||||
DELETE FROM "ProclamationCategory" WHERE "parentId" IS NOT NULL;
|
||||
|
||||
-- Drop self-relation
|
||||
ALTER TABLE "ProclamationCategory" DROP CONSTRAINT "ProclamationCategory_parentId_fkey";
|
||||
|
||||
-- DropIndex
|
||||
DROP INDEX "ProclamationCategory_parentId_name_key";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "ProclamationCategory" DROP COLUMN "parentId";
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "ProclamationCategory_name_key" ON "ProclamationCategory"("name");
|
||||
|
||||
-- Remove subscription levels entirely
|
||||
DROP TABLE "ProclamationCategorySubscriptionLevel";
|
||||
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "Proclamation" DROP CONSTRAINT "Proclamation_subscriptionLevelId_fkey";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Proclamation" DROP COLUMN "subscriptionLevelId";
|
||||
|
||||
-- DropTable
|
||||
DROP TABLE "SubscriptionLevel";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LicenseKey" DROP COLUMN "level";
|
||||
@@ -0,0 +1,28 @@
|
||||
-- DropForeignKey
|
||||
ALTER TABLE "LicenseKey" DROP CONSTRAINT "LicenseKey_userId_fkey";
|
||||
|
||||
-- DropIndex
|
||||
DROP INDEX "Profile_userId_key";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "LicenseKey" ADD COLUMN "email" TEXT,
|
||||
ALTER COLUMN "userId" DROP NOT NULL;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "Profile" ADD COLUMN "email" TEXT,
|
||||
ALTER COLUMN "userId" DROP NOT NULL;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LicenseKey_userId_idx" ON "LicenseKey"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "LicenseKey_email_idx" ON "LicenseKey"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Profile_userId_idx" ON "Profile"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Profile_email_idx" ON "Profile"("email");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "LicenseKey" ADD CONSTRAINT "LicenseKey_userId_fkey" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
+40
-50
@@ -25,7 +25,7 @@ model User {
|
||||
role UserRole? @relation(fields: [roleId], references: [id])
|
||||
sessions Session[]
|
||||
accounts Account[]
|
||||
profile Profile?
|
||||
profiles Profile[]
|
||||
licenseKeys LicenseKey[]
|
||||
userProclamations UserProclamations[]
|
||||
|
||||
@@ -37,28 +37,32 @@ model User {
|
||||
// a bunch of time trying to figure out how to customize the default Better-Auth model.
|
||||
model Profile {
|
||||
id String @id @default(uuid())
|
||||
userId String @unique
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
userId String?
|
||||
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
email String?
|
||||
firstName String
|
||||
lastName String
|
||||
phoneNumber String
|
||||
ghlContactId String? @map("ghl_contact_id")
|
||||
addresses Address[]
|
||||
|
||||
@@index([userId])
|
||||
@@index([email])
|
||||
}
|
||||
|
||||
model Address {
|
||||
id String @id @default(uuid())
|
||||
profileId String
|
||||
profile Profile @relation(fields: [profileId], references: [id], onDelete: Cascade)
|
||||
street String
|
||||
city String
|
||||
state String
|
||||
postalCode String
|
||||
country String
|
||||
type String @default("Mailing")
|
||||
isDefaultMailing Boolean @default(false)
|
||||
isDefaultBilling Boolean @default(false)
|
||||
isDefaultShipping Boolean @default(false)
|
||||
id String @id @default(uuid())
|
||||
profileId String
|
||||
profile Profile @relation(fields: [profileId], references: [id], onDelete: Cascade)
|
||||
street String
|
||||
city String
|
||||
state String
|
||||
postalCode String
|
||||
country String
|
||||
type String @default("Mailing")
|
||||
isDefaultMailing Boolean @default(false)
|
||||
isDefaultBilling Boolean @default(false)
|
||||
isDefaultShipping Boolean @default(false)
|
||||
}
|
||||
|
||||
model Session {
|
||||
@@ -123,9 +127,16 @@ model Proclamation {
|
||||
solfeggioFrequency SolfeggioFrequency @relation(fields: [solfeggioFrequencyId], references: [id])
|
||||
categoryId Int
|
||||
category ProclamationCategory @relation(fields: [categoryId], references: [id])
|
||||
groupId Int
|
||||
group ProclamationGroup @relation(fields: [groupId], references: [id])
|
||||
userProclamations UserProclamations[]
|
||||
subscriptionLevelId Int // Keeping old FK for migration stability
|
||||
subscriptionLevel SubscriptionLevel @relation(fields: [subscriptionLevelId], references: [id])
|
||||
}
|
||||
|
||||
model ProclamationGroup {
|
||||
id Int @id @default(autoincrement())
|
||||
name String @unique
|
||||
sortOrder Int @default(0)
|
||||
proclamations Proclamation[]
|
||||
}
|
||||
|
||||
model UserProclamations {
|
||||
@@ -142,40 +153,27 @@ model UserProclamations {
|
||||
model SolfeggioFrequency {
|
||||
id Int @id @default(autoincrement())
|
||||
name String @unique
|
||||
value Int @unique
|
||||
value Int @unique
|
||||
proclamations Proclamation[]
|
||||
}
|
||||
|
||||
model ProclamationCategory {
|
||||
id Int @id @default(autoincrement())
|
||||
name String
|
||||
sortOrder Int @default(0)
|
||||
parentId Int?
|
||||
parent ProclamationCategory? @relation("CategoryHierarchy", fields: [parentId], references: [id])
|
||||
children ProclamationCategory[] @relation("CategoryHierarchy")
|
||||
proclamations Proclamation[]
|
||||
subscriptionLevels ProclamationCategorySubscriptionLevel[]
|
||||
|
||||
@@unique([parentId, name])
|
||||
}
|
||||
|
||||
// Join table for ProclamationCategory -> SubscriptionLevel defaults
|
||||
model ProclamationCategorySubscriptionLevel {
|
||||
categoryId Int
|
||||
category ProclamationCategory @relation(fields: [categoryId], references: [id], onDelete: Cascade)
|
||||
subscriptionLevelId Int
|
||||
subscriptionLevel SubscriptionLevel @relation(fields: [subscriptionLevelId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@id([categoryId, subscriptionLevelId])
|
||||
id Int @id @default(autoincrement())
|
||||
name String @unique
|
||||
sortOrder Int @default(0)
|
||||
proclamations Proclamation[]
|
||||
}
|
||||
|
||||
model LicenseKey {
|
||||
id String @id @default(uuid())
|
||||
key String @unique
|
||||
active Boolean
|
||||
level String
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String?
|
||||
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
|
||||
email String?
|
||||
|
||||
@@index([userId])
|
||||
@@index([email])
|
||||
}
|
||||
|
||||
model ApiKey {
|
||||
@@ -187,14 +185,6 @@ model ApiKey {
|
||||
revokedAt DateTime?
|
||||
}
|
||||
|
||||
model SubscriptionLevel {
|
||||
id Int @id @default(autoincrement())
|
||||
name String
|
||||
description String?
|
||||
proclamations Proclamation[]
|
||||
categoryLevels ProclamationCategorySubscriptionLevel[]
|
||||
}
|
||||
|
||||
// Portal-editable 7-color palette per canonical solfeggio frequency id (1-9).
|
||||
// `solfeggioFrequencyId` is the canonical id the kiosk uses (see
|
||||
// v2-serializers.ts), not the DB autoincrement id of `SolfeggioFrequency`.
|
||||
@@ -203,4 +193,4 @@ model ColorPalette {
|
||||
colors Json // ["#RRGGBB", ... x7]
|
||||
|
||||
@@map("ColorPalette")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user