diff --git a/api/prisma/migrations/20260408100000_sync_schema_from_db_push/migration.sql b/api/prisma/migrations/20260408100000_sync_schema_from_db_push/migration.sql new file mode 100644 index 0000000..4468b0c --- /dev/null +++ b/api/prisma/migrations/20260408100000_sync_schema_from_db_push/migration.sql @@ -0,0 +1,1497 @@ +-- ============================================================================= +-- Comprehensive schema sync: captures all schema evolution that happened via +-- `prisma db push` and was never written into a proper migration file. +-- +-- Generated by diffing the migration-created schema against the current +-- schema.prisma using `prisma migrate diff`. +-- +-- All operations are idempotent (IF NOT EXISTS / IF EXISTS / DO $$ ... $$) +-- so this migration is safe to run against both: +-- a) A fresh DB created by the prior 15 migrations (current prod state) +-- b) A DB that already had the db-push evolved schema applied +-- ============================================================================= + +-- ============================================================================= +-- SECTION 1: New ENUM types +-- ============================================================================= + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'PhoneType') THEN + CREATE TYPE "PhoneType" AS ENUM ('DIRECT', 'MOBILE', 'HOME', 'COMPANY', 'SITE'); + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'FaxType') THEN + CREATE TYPE "FaxType" AS ENUM ('FAX', 'COMPANY', 'SITE'); + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'BillingMethod') THEN + CREATE TYPE "BillingMethod" AS ENUM ('ACTUAL_RATES', 'FIXED_FEE', 'NOT_TO_EXCEED', 'OVERRIDE_RATE'); + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'BillingType') THEN + CREATE TYPE "BillingType" AS ENUM ('STANDARD', 'PROJECT'); + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'GenderType') THEN + CREATE TYPE "GenderType" AS ENUM ('MALE', 'FEMALE'); + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'USState') THEN + CREATE TYPE "USState" AS ENUM ( + 'AL','AK','AZ','AR','CA','CO','CT','DE','FL','GA','HI','ID','IL','IN', + 'IA','KS','KY','LA','ME','MD','MA','MI','MN','MS','MO','MT','NE','NV', + 'NH','NJ','NM','NY','NC','ND','OH','OK','OR','PA','RI','SC','SD','TN', + 'TX','UT','VT','VA','WA','WV','WI','WY' + ); + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'Country') THEN + CREATE TYPE "Country" AS ENUM ('US'); + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'OpportunityInterest') THEN + CREATE TYPE "OpportunityInterest" AS ENUM ('HOT', 'WARM', 'COLD'); + END IF; +END $$; + +-- ============================================================================= +-- SECTION 2: User table — evolve from initial flat schema to current model +-- ============================================================================= + +DO $$ BEGIN + -- Remove columns no longer in schema + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'User' AND column_name = 'emailVerified') THEN + ALTER TABLE "User" DROP COLUMN "emailVerified"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'User' AND column_name = 'name') THEN + ALTER TABLE "User" DROP COLUMN "name"; + END IF; + + -- Add new columns + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'User' AND column_name = 'firstName') THEN + ALTER TABLE "User" ADD COLUMN "firstName" TEXT; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'User' AND column_name = 'lastName') THEN + ALTER TABLE "User" ADD COLUMN "lastName" TEXT; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'User' AND column_name = 'title') THEN + ALTER TABLE "User" ADD COLUMN "title" TEXT; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'User' AND column_name = 'active') THEN + ALTER TABLE "User" ADD COLUMN "active" BOOLEAN NOT NULL DEFAULT true; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'User' AND column_name = 'hidden') THEN + ALTER TABLE "User" ADD COLUMN "hidden" BOOLEAN NOT NULL DEFAULT false; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'User' AND column_name = 'cwMemberId') THEN + ALTER TABLE "User" ADD COLUMN "cwMemberId" INTEGER; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'User' AND column_name = 'updatedBy') THEN + ALTER TABLE "User" ADD COLUMN "updatedBy" TEXT; + END IF; + + -- Make userId nullable (was NOT NULL in initial migration) + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'User' AND column_name = 'userId' AND is_nullable = 'NO' + ) THEN + ALTER TABLE "User" ALTER COLUMN "userId" DROP NOT NULL; + END IF; +END $$; + +-- Unique indexes for new User columns (idempotent) +CREATE UNIQUE INDEX IF NOT EXISTS "User_cwIdentifier_key" ON "User"("cwIdentifier"); +CREATE UNIQUE INDEX IF NOT EXISTS "User_cwMemberId_key" ON "User"("cwMemberId"); + +-- FK: User.cwMemberId -> CwMember.cwMemberId +DO $$ BEGIN + IF NOT EXISTS ( + SELECT 1 FROM information_schema.table_constraints + WHERE constraint_name = 'User_cwMemberId_fkey' + ) THEN + ALTER TABLE "User" ADD CONSTRAINT "User_cwMemberId_fkey" + FOREIGN KEY ("cwMemberId") REFERENCES "CwMember"("cwMemberId") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +-- ============================================================================= +-- SECTION 3: CatalogItem — change id TEXT→INTEGER, add uid PK, restructure +-- ============================================================================= + +-- Drop FKs that reference CatalogItem by old id column +DO $$ BEGIN + IF EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = '_LinkedItems_A_fkey') THEN + ALTER TABLE "_LinkedItems" DROP CONSTRAINT "_LinkedItems_A_fkey"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = '_LinkedItems_B_fkey') THEN + ALTER TABLE "_LinkedItems" DROP CONSTRAINT "_LinkedItems_B_fkey"; + END IF; +END $$; + +-- Drop old unique index that no longer applies +DROP INDEX IF EXISTS "CatalogItem_cwCatalogId_key"; + +-- Restructure CatalogItem +DO $$ BEGIN + -- Add uid PK column if missing + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'CatalogItem' AND column_name = 'uid') THEN + ALTER TABLE "CatalogItem" ADD COLUMN "uid" TEXT NOT NULL DEFAULT ''; + END IF; + + -- Swap PK from id to uid (only if id is still the primary key) + IF EXISTS ( + SELECT 1 FROM information_schema.table_constraints tc + JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name + WHERE tc.table_name = 'CatalogItem' AND tc.constraint_type = 'PRIMARY KEY' AND kcu.column_name = 'id' + ) THEN + ALTER TABLE "CatalogItem" DROP CONSTRAINT "CatalogItem_pkey"; + ALTER TABLE "CatalogItem" ADD CONSTRAINT "CatalogItem_pkey" PRIMARY KEY ("uid"); + END IF; + + -- Change id from TEXT to INTEGER (only if still TEXT) + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'CatalogItem' AND column_name = 'id' AND data_type = 'text' + ) THEN + ALTER TABLE "CatalogItem" DROP COLUMN "id"; + ALTER TABLE "CatalogItem" ADD COLUMN "id" INTEGER; + END IF; + + -- Drop old columns no longer in schema + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'CatalogItem' AND column_name = 'cwCatalogId') THEN + ALTER TABLE "CatalogItem" DROP COLUMN "cwCatalogId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'CatalogItem' AND column_name = 'category') THEN + ALTER TABLE "CatalogItem" DROP COLUMN "category"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'CatalogItem' AND column_name = 'categoryCwId') THEN + ALTER TABLE "CatalogItem" DROP COLUMN "categoryCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'CatalogItem' AND column_name = 'manufacturer') THEN + ALTER TABLE "CatalogItem" DROP COLUMN "manufacturer"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'CatalogItem' AND column_name = 'manufactureCwId') THEN + ALTER TABLE "CatalogItem" DROP COLUMN "manufactureCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'CatalogItem' AND column_name = 'subcategory') THEN + ALTER TABLE "CatalogItem" DROP COLUMN "subcategory"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'CatalogItem' AND column_name = 'subcategoryCwId') THEN + ALTER TABLE "CatalogItem" DROP COLUMN "subcategoryCwId"; + END IF; + + -- Add new columns + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'CatalogItem' AND column_name = 'classId') THEN + ALTER TABLE "CatalogItem" ADD COLUMN "classId" TEXT; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'CatalogItem' AND column_name = 'manufacturerId') THEN + ALTER TABLE "CatalogItem" ADD COLUMN "manufacturerId" INTEGER; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'CatalogItem' AND column_name = 'subcategoryId') THEN + ALTER TABLE "CatalogItem" ADD COLUMN "subcategoryId" INTEGER NOT NULL DEFAULT 0; + END IF; +END $$; + +CREATE UNIQUE INDEX IF NOT EXISTS "CatalogItem_id_key" ON "CatalogItem"("id"); + +-- ============================================================================= +-- SECTION 4: Company — change id TEXT→INTEGER, add uid PK, add columns +-- ============================================================================= + +-- Drop FKs that reference Company by old id +DO $$ BEGIN + IF EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Credential_companyId_fkey') THEN + ALTER TABLE "Credential" DROP CONSTRAINT "Credential_companyId_fkey"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'UnifiSite_companyId_fkey') THEN + ALTER TABLE "UnifiSite" DROP CONSTRAINT "UnifiSite_companyId_fkey"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Opportunity_companyId_fkey') THEN + ALTER TABLE "Opportunity" DROP CONSTRAINT "Opportunity_companyId_fkey"; + END IF; +END $$; + +DROP INDEX IF EXISTS "Company_cw_CompanyId_key"; +DROP INDEX IF EXISTS "Company_cw_Identifier_key"; + +DO $$ BEGIN + -- Add uid PK column if missing + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Company' AND column_name = 'uid') THEN + ALTER TABLE "Company" ADD COLUMN "uid" TEXT NOT NULL DEFAULT ''; + END IF; + + -- Swap PK from id to uid + IF EXISTS ( + SELECT 1 FROM information_schema.table_constraints tc + JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name + WHERE tc.table_name = 'Company' AND tc.constraint_type = 'PRIMARY KEY' AND kcu.column_name = 'id' + ) THEN + ALTER TABLE "Company" DROP CONSTRAINT "Company_pkey"; + ALTER TABLE "Company" ADD CONSTRAINT "Company_pkey" PRIMARY KEY ("uid"); + END IF; + + -- Change id from TEXT to INTEGER + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'Company' AND column_name = 'id' AND data_type = 'text' + ) THEN + ALTER TABLE "Company" DROP COLUMN "id"; + ALTER TABLE "Company" ADD COLUMN "id" INTEGER; + END IF; + + -- Drop old CW-specific columns + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Company' AND column_name = 'cw_CompanyId') THEN + ALTER TABLE "Company" DROP COLUMN "cw_CompanyId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Company' AND column_name = 'cw_Identifier') THEN + ALTER TABLE "Company" DROP COLUMN "cw_Identifier"; + END IF; + + -- Add new columns + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Company' AND column_name = 'dateDeleted') THEN + ALTER TABLE "Company" ADD COLUMN "dateDeleted" TIMESTAMP(3); + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Company' AND column_name = 'deleteFlag') THEN + ALTER TABLE "Company" ADD COLUMN "deleteFlag" BOOLEAN NOT NULL DEFAULT false; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Company' AND column_name = 'deletedAt') THEN + ALTER TABLE "Company" ADD COLUMN "deletedAt" TIMESTAMP(3); + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Company' AND column_name = 'deletedById') THEN + ALTER TABLE "Company" ADD COLUMN "deletedById" TEXT; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Company' AND column_name = 'enteredById') THEN + ALTER TABLE "Company" ADD COLUMN "enteredById" TEXT; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Company' AND column_name = 'phone') THEN + ALTER TABLE "Company" ADD COLUMN "phone" TEXT; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Company' AND column_name = 'taxExempt') THEN + ALTER TABLE "Company" ADD COLUMN "taxExempt" BOOLEAN NOT NULL DEFAULT false; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Company' AND column_name = 'taxId') THEN + ALTER TABLE "Company" ADD COLUMN "taxId" TEXT; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Company' AND column_name = 'website') THEN + ALTER TABLE "Company" ADD COLUMN "website" TEXT; + END IF; +END $$; + +CREATE UNIQUE INDEX IF NOT EXISTS "Company_id_key" ON "Company"("id"); + +-- ============================================================================= +-- SECTION 5: UnifiSite — change companyId from TEXT to INTEGER +-- ============================================================================= + +DO $$ BEGIN + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'UnifiSite' AND column_name = 'companyId' AND data_type = 'text' + ) THEN + ALTER TABLE "UnifiSite" DROP COLUMN "companyId"; + ALTER TABLE "UnifiSite" ADD COLUMN "companyId" INTEGER; + END IF; +END $$; + +-- ============================================================================= +-- SECTION 6: Opportunity — full restructure +-- ============================================================================= + +-- Drop FKs referencing Opportunity by old id/companyId +DO $$ BEGIN + IF EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'GeneratedQuotes_opportunityId_fkey') THEN + ALTER TABLE "GeneratedQuotes" DROP CONSTRAINT "GeneratedQuotes_opportunityId_fkey"; + END IF; +END $$; + +DROP INDEX IF EXISTS "Opportunity_cwOpportunityId_key"; + +DO $$ BEGIN + -- Add uid PK column if missing + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'uid') THEN + ALTER TABLE "Opportunity" ADD COLUMN "uid" TEXT NOT NULL DEFAULT ''; + END IF; + + -- Swap PK from id to uid + IF EXISTS ( + SELECT 1 FROM information_schema.table_constraints tc + JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name + WHERE tc.table_name = 'Opportunity' AND tc.constraint_type = 'PRIMARY KEY' AND kcu.column_name = 'id' + ) THEN + ALTER TABLE "Opportunity" DROP CONSTRAINT "Opportunity_pkey"; + ALTER TABLE "Opportunity" ADD CONSTRAINT "Opportunity_pkey" PRIMARY KEY ("uid"); + END IF; + + -- Change id from TEXT to INTEGER + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'Opportunity' AND column_name = 'id' AND data_type = 'text' + ) THEN + ALTER TABLE "Opportunity" DROP COLUMN "id"; + ALTER TABLE "Opportunity" ADD COLUMN "id" INTEGER; + END IF; + + -- Change companyId from TEXT to INTEGER + IF EXISTS ( + SELECT 1 FROM information_schema.columns + WHERE table_name = 'Opportunity' AND column_name = 'companyId' AND data_type = 'text' + ) THEN + ALTER TABLE "Opportunity" DROP COLUMN "companyId"; + ALTER TABLE "Opportunity" ADD COLUMN "companyId" INTEGER; + END IF; + + -- Drop old flat/CW columns + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'cwOpportunityId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "cwOpportunityId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'campaignCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "campaignCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'campaignName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "campaignName"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'closedByCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "closedByCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'closedByName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "closedByName"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'companyCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "companyCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'companyName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "companyName"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'contactCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "contactCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'contactName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "contactName"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'cwLastUpdated') THEN + ALTER TABLE "Opportunity" DROP COLUMN "cwLastUpdated"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'departmentCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "departmentCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'departmentName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "departmentName"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'locationCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "locationCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'locationName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "locationName"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'primarySalesRepCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "primarySalesRepCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'primarySalesRepIdentifier') THEN + ALTER TABLE "Opportunity" DROP COLUMN "primarySalesRepIdentifier"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'primarySalesRepName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "primarySalesRepName"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'priorityCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "priorityCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'priorityName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "priorityName"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'ratingCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "ratingCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'ratingName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "ratingName"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'secondarySalesRepCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "secondarySalesRepCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'secondarySalesRepIdentifier') THEN + ALTER TABLE "Opportunity" DROP COLUMN "secondarySalesRepIdentifier"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'secondarySalesRepName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "secondarySalesRepName"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'siteCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "siteCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'siteName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "siteName"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'statusCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "statusCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'statusName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "statusName"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'totalSalesTax') THEN + ALTER TABLE "Opportunity" DROP COLUMN "totalSalesTax"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'typeCwId') THEN + ALTER TABLE "Opportunity" DROP COLUMN "typeCwId"; + END IF; + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'typeName') THEN + ALTER TABLE "Opportunity" DROP COLUMN "typeName"; + END IF; + + -- Add new columns + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'closedById') THEN + ALTER TABLE "Opportunity" ADD COLUMN "closedById" TEXT; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'contactId') THEN + ALTER TABLE "Opportunity" ADD COLUMN "contactId" INTEGER; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'departmentId') THEN + ALTER TABLE "Opportunity" ADD COLUMN "departmentId" INTEGER; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'eneteredBy') THEN + ALTER TABLE "Opportunity" ADD COLUMN "eneteredBy" TEXT NOT NULL DEFAULT ''; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'interest') THEN + ALTER TABLE "Opportunity" ADD COLUMN "interest" "OpportunityInterest"; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'locationId') THEN + ALTER TABLE "Opportunity" ADD COLUMN "locationId" INTEGER; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'oppNarrative') THEN + ALTER TABLE "Opportunity" ADD COLUMN "oppNarrative" TEXT; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'primarySalesRepId') THEN + ALTER TABLE "Opportunity" ADD COLUMN "primarySalesRepId" TEXT; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'secondarySalesRepId') THEN + ALTER TABLE "Opportunity" ADD COLUMN "secondarySalesRepId" TEXT; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'siteId') THEN + ALTER TABLE "Opportunity" ADD COLUMN "siteId" INTEGER; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'statusId') THEN + ALTER TABLE "Opportunity" ADD COLUMN "statusId" INTEGER; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'taxCodeId') THEN + ALTER TABLE "Opportunity" ADD COLUMN "taxCodeId" INTEGER; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'typeId') THEN + ALTER TABLE "Opportunity" ADD COLUMN "typeId" INTEGER NOT NULL DEFAULT 0; + END IF; + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'updatedBy') THEN + ALTER TABLE "Opportunity" ADD COLUMN "updatedBy" TEXT NOT NULL DEFAULT ''; + END IF; +END $$; + +CREATE UNIQUE INDEX IF NOT EXISTS "Opportunity_id_key" ON "Opportunity"("id"); + +-- ============================================================================= +-- SECTION 7: New tables (all idempotent via IF NOT EXISTS) +-- ============================================================================= + +CREATE TABLE IF NOT EXISTS "CorporateLocation" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "updatedById" TEXT, + "addressLine1" TEXT, + "addressLine2" TEXT, + "city" TEXT, + "state" "USState", + "zipCode" TEXT, + "country" "Country", + "inactiveFlag" BOOLEAN NOT NULL DEFAULT false, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "CorporateLocation_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "CorporateLocation_id_key" ON "CorporateLocation"("id"); + +CREATE TABLE IF NOT EXISTS "InternalDepartment" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "createdById" TEXT, + "updatedById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "InternalDepartment_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "InternalDepartment_id_key" ON "InternalDepartment"("id"); + +CREATE TABLE IF NOT EXISTS "CompanyAddress" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "addressLine1" TEXT, + "addressLine2" TEXT, + "city" TEXT, + "state" "USState", + "zipCode" TEXT, + "country" "Country", + "phone" TEXT, + "fax" TEXT, + "inactiveFlag" BOOLEAN NOT NULL DEFAULT false, + "defaultFlag" BOOLEAN NOT NULL DEFAULT false, + "defaultMailFlag" BOOLEAN NOT NULL DEFAULT false, + "defaultBillFlag" BOOLEAN NOT NULL DEFAULT false, + "defaultShipFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "companyId" INTEGER NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "CompanyAddress_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "CompanyAddress_id_key" ON "CompanyAddress"("id"); + +CREATE TABLE IF NOT EXISTS "Contact" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "active" BOOLEAN NOT NULL DEFAULT true, + "default" BOOLEAN NOT NULL DEFAULT false, + "firstName" TEXT NOT NULL, + "lastName" TEXT NOT NULL, + "nickname" TEXT, + "title" TEXT, + "gender" "GenderType", + "birthday" TIMESTAMP(3), + "email" TEXT, + "phone" TEXT, + "phoneExtension" TEXT, + "phoneType" "PhoneType", + "companyAddressId" INTEGER, + "memberId" INTEGER, + "companyId" INTEGER, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "Contact_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "Contact_id_key" ON "Contact"("id"); + +CREATE TABLE IF NOT EXISTS "CatalogItemType" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "inactiveFlag" BOOLEAN NOT NULL DEFAULT false, + "defaultFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "CatalogItemType_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "CatalogItemType_id_key" ON "CatalogItemType"("id"); + +CREATE TABLE IF NOT EXISTS "CatalogCategory" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "inactiveFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "CatalogCategory_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "CatalogCategory_id_key" ON "CatalogCategory"("id"); + +CREATE TABLE IF NOT EXISTS "CatalogSubcategory" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "categoryId" INTEGER NOT NULL, + "inactiveFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "CatalogSubcategory_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "CatalogSubcategory_id_key" ON "CatalogSubcategory"("id"); + +CREATE TABLE IF NOT EXISTS "CatalogManufacturer" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "inactiveFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "CatalogManufacturer_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "CatalogManufacturer_id_key" ON "CatalogManufacturer"("id"); + +CREATE TABLE IF NOT EXISTS "Warehouse" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "inactiveFlag" BOOLEAN NOT NULL DEFAULT false, + "lockedFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "Warehouse_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "Warehouse_id_key" ON "Warehouse"("id"); + +CREATE TABLE IF NOT EXISTS "WarehouseBin" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "minQuantity" INTEGER NOT NULL, + "maxQuantity" INTEGER NOT NULL, + "inactiveFlag" BOOLEAN NOT NULL DEFAULT false, + "defaultFlag" BOOLEAN NOT NULL DEFAULT false, + "warehouseId" INTEGER, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "WarehouseBin_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "WarehouseBin_id_key" ON "WarehouseBin"("id"); + +CREATE TABLE IF NOT EXISTS "ProductInventory" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "qtyOnHand" INTEGER NOT NULL DEFAULT 0, + "warehouseBinId" INTEGER NOT NULL, + "itemId" INTEGER, + "warehouseId" INTEGER, + "updatedById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ProductInventory_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ProductInventory_id_key" ON "ProductInventory"("id"); + +CREATE TABLE IF NOT EXISTS "MinimumStockByWarehouse" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "minQty" INTEGER NOT NULL DEFAULT 0, + "warehouseId" INTEGER NOT NULL, + "itemId" INTEGER, + "updatedById" TEXT, + "enteredById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "MinimumStockByWarehouse_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "MinimumStockByWarehouse_id_key" ON "MinimumStockByWarehouse"("id"); + +CREATE TABLE IF NOT EXISTS "ProductData" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "qty" DOUBLE PRECISION NOT NULL DEFAULT 1, + "internalNote" TEXT, + "shortDescription" TEXT, + "description" TEXT, + "sequenceNumber" INTEGER, + "procurementNotes" TEXT, + "productNarrative" TEXT, + "unitPrice" DOUBLE PRECISION NOT NULL DEFAULT 0, + "unitCost" DOUBLE PRECISION NOT NULL DEFAULT 0, + "listPrice" DOUBLE PRECISION NOT NULL DEFAULT 0, + "discount" DOUBLE PRECISION NOT NULL DEFAULT 0, + "recurringRevenue" DOUBLE PRECISION NOT NULL DEFAULT 0, + "recurringCost" DOUBLE PRECISION NOT NULL DEFAULT 0, + "qtyPicked" INTEGER NOT NULL DEFAULT 0, + "qtyShipped" INTEGER NOT NULL DEFAULT 0, + "cancelReason" TEXT, + "cancelQty" DOUBLE PRECISION, + "billableFlag" BOOLEAN NOT NULL DEFAULT true, + "taxableFlag" BOOLEAN NOT NULL DEFAULT true, + "invoiceFlag" BOOLEAN NOT NULL DEFAULT true, + "recurringFlag" BOOLEAN NOT NULL DEFAULT false, + "poApprovedFlag" BOOLEAN NOT NULL DEFAULT false, + "calcPriceFlag" BOOLEAN NOT NULL DEFAULT true, + "calcCostFlag" BOOLEAN NOT NULL DEFAULT true, + "cancelFlag" BOOLEAN NOT NULL DEFAULT false, + "catalogItemId" INTEGER NOT NULL, + "corporateLocationId" INTEGER NOT NULL, + "serviceTicketId" INTEGER, + "opportunityId" INTEGER, + "updatedById" TEXT, + "createdById" TEXT, + "closedById" TEXT, + "cancelById" TEXT NOT NULL DEFAULT '', + "closedAt" TIMESTAMP(3), + "cancelledAt" TIMESTAMP(3), + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ProductData_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ProductData_id_key" ON "ProductData"("id"); + +CREATE TABLE IF NOT EXISTS "ServiceTicketLocation" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "defaultFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ServiceTicketLocation_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ServiceTicketLocation_id_key" ON "ServiceTicketLocation"("id"); + +CREATE TABLE IF NOT EXISTS "ServiceTicketSource" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "inactiveFlag" BOOLEAN NOT NULL DEFAULT false, + "defaultFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ServiceTicketSource_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ServiceTicketSource_id_key" ON "ServiceTicketSource"("id"); + +CREATE TABLE IF NOT EXISTS "ServiceTicketImpact" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "defaultFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ServiceTicketImpact_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ServiceTicketImpact_id_key" ON "ServiceTicketImpact"("id"); + +CREATE TABLE IF NOT EXISTS "ServiceTicketPriority" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "color" TEXT, + "description" TEXT, + "defaultFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ServiceTicketPriority_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ServiceTicketPriority_id_key" ON "ServiceTicketPriority"("id"); + +CREATE TABLE IF NOT EXISTS "ServiceTicketServerity" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "defaultFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ServiceTicketServerity_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ServiceTicketServerity_id_key" ON "ServiceTicketServerity"("id"); + +CREATE TABLE IF NOT EXISTS "ServiceTicketBoard" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "timeBillableFlag" BOOLEAN NOT NULL DEFAULT false, + "expenseBillableFlag" BOOLEAN NOT NULL DEFAULT false, + "productBillableFlag" BOOLEAN NOT NULL DEFAULT false, + "timeInvoiceableFlag" BOOLEAN NOT NULL DEFAULT false, + "expenseInvoiceableFlag" BOOLEAN NOT NULL DEFAULT false, + "productInvoiceableFlag" BOOLEAN NOT NULL DEFAULT false, + "autoAssignNewFlag" BOOLEAN NOT NULL DEFAULT false, + "autoAssignEmailCreatedFlag" BOOLEAN NOT NULL DEFAULT false, + "autoAssignPortalCreatedFlag" BOOLEAN NOT NULL DEFAULT false, + "projectFlag" BOOLEAN NOT NULL DEFAULT false, + "lockDescriptionFlag" BOOLEAN NOT NULL DEFAULT false, + "emailContactFlag" BOOLEAN NOT NULL DEFAULT false, + "emailResourceFlag" BOOLEAN NOT NULL DEFAULT false, + "resolutionSortOrder" CHAR(1) NOT NULL DEFAULT 'D', + "internalAnalysisSortOrder" CHAR(1) NOT NULL DEFAULT 'D', + "locationId" INTEGER NOT NULL, + "createdById" TEXT, + "updatedById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ServiceTicketBoard_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ServiceTicketBoard_id_key" ON "ServiceTicketBoard"("id"); + +CREATE TABLE IF NOT EXISTS "ServiceTicketType" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "inactiveFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ServiceTicketType_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ServiceTicketType_id_key" ON "ServiceTicketType"("id"); + +CREATE TABLE IF NOT EXISTS "ServiceTicket" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "summary" TEXT NOT NULL, + "addressLine1" TEXT, + "addressLine2" TEXT, + "city" TEXT, + "state" "USState", + "zipCode" TEXT, + "country" "Country", + "contactName" TEXT, + "phone" TEXT, + "phoneExtension" TEXT, + "phoneType" "PhoneType", + "email" TEXT, + "poNumber" TEXT, + "billCompleteFlag" BOOLEAN NOT NULL DEFAULT false, + "billUnapprovedFlag" BOOLEAN NOT NULL DEFAULT false, + "billingAmount" DOUBLE PRECISION NOT NULL DEFAULT 0.00, + "billingMethod" "BillingMethod" NOT NULL DEFAULT 'ACTUAL_RATES', + "timeBillableFlag" BOOLEAN NOT NULL DEFAULT true, + "expenseBillableFlag" BOOLEAN NOT NULL DEFAULT true, + "productBillableFlag" BOOLEAN NOT NULL DEFAULT true, + "timeInvoiceableFlag" BOOLEAN NOT NULL DEFAULT true, + "expenseInvoiceableFlag" BOOLEAN NOT NULL DEFAULT true, + "productInvoiceableFlag" BOOLEAN NOT NULL DEFAULT true, + "dateRequested" TIMESTAMP(3), + "billingType" "BillingType" NOT NULL DEFAULT 'STANDARD', + "billingInstructions" TEXT, + "rejectedFlag" BOOLEAN NOT NULL DEFAULT false, + "closedFlag" BOOLEAN NOT NULL DEFAULT false, + "redFlag" BOOLEAN NOT NULL DEFAULT false, + "publishFlag" BOOLEAN NOT NULL DEFAULT false, + "ticketOwnerId" TEXT, + "serviceTicketBoardId" INTEGER, + "severityId" INTEGER NOT NULL DEFAULT 0, + "impactId" INTEGER NOT NULL DEFAULT 0, + "priorityId" INTEGER NOT NULL DEFAULT 0, + "sourceId" INTEGER NOT NULL DEFAULT 0, + "locationId" INTEGER NOT NULL DEFAULT 0, + "parentId" INTEGER, + "companyId" INTEGER, + "contactId" INTEGER, + "companyAddressId" INTEGER, + "billingCompanyId" INTEGER, + "billingAddressId" INTEGER, + "createdById" TEXT, + "updatedById" TEXT, + "closedById" TEXT, + "rejectedAt" TIMESTAMP(3), + "closedAt" TIMESTAMP(3), + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ServiceTicket_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ServiceTicket_id_key" ON "ServiceTicket"("id"); + +CREATE TABLE IF NOT EXISTS "ServiceTicketNote" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "notes" TEXT NOT NULL, + "notesMd" TEXT NOT NULL, + "authorId" TEXT NOT NULL, + "problemFlag" BOOLEAN NOT NULL DEFAULT false, + "resolutionFlag" BOOLEAN NOT NULL DEFAULT false, + "internalAnalysisFlag" BOOLEAN NOT NULL DEFAULT false, + "internalMemberFlag" BOOLEAN NOT NULL DEFAULT false, + "createdByParentFlag" BOOLEAN NOT NULL DEFAULT false, + "mergedFlag" BOOLEAN NOT NULL DEFAULT false, + "bundledFlag" BOOLEAN NOT NULL DEFAULT false, + "serviceTicketId" INTEGER NOT NULL, + "createdById" TEXT, + "updatedById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ServiceTicketNote_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ServiceTicketNote_id_key" ON "ServiceTicketNote"("id"); + +CREATE TABLE IF NOT EXISTS "ServiceTicketFinalData" ( + "id" TEXT NOT NULL, + CONSTRAINT "ServiceTicketFinalData_pkey" PRIMARY KEY ("id") +); + +CREATE TABLE IF NOT EXISTS "OpportunityType" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "inactiveFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "OpportunityType_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "OpportunityType_id_key" ON "OpportunityType"("id"); + +CREATE TABLE IF NOT EXISTS "OpportunityStatus" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "inactiveFlag" BOOLEAN NOT NULL DEFAULT false, + "defaultFlag" BOOLEAN NOT NULL DEFAULT false, + "wonFlag" BOOLEAN NOT NULL DEFAULT false, + "lostFlag" BOOLEAN NOT NULL DEFAULT false, + "closeFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "OpportunityStatus_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "OpportunityStatus_id_key" ON "OpportunityStatus"("id"); + +CREATE TABLE IF NOT EXISTS "ScheduleStatus" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "color" TEXT, + "softFlag" BOOLEAN NOT NULL DEFAULT false, + "defaultFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ScheduleStatus_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ScheduleStatus_id_key" ON "ScheduleStatus"("id"); + +CREATE TABLE IF NOT EXISTS "ScheduleType" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "displayColor" TEXT, + "tableReference" TEXT, + "moduleId" CHAR(2), + "scheduleTypeId" CHAR(1), + "systemFlag" BOOLEAN NOT NULL DEFAULT false, + "displayFlag" BOOLEAN NOT NULL DEFAULT false, + "updatedById" TEXT, + "createdById" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "ScheduleType_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "ScheduleType_id_key" ON "ScheduleType"("id"); + +CREATE TABLE IF NOT EXISTS "ScheduleSpan" ( + "id" SERIAL NOT NULL, + "scheduleSpanId" CHAR(1), + "spanDesc" CHAR(20), + CONSTRAINT "ScheduleSpan_pkey" PRIMARY KEY ("id") +); + +CREATE TABLE IF NOT EXISTS "Schedule" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "memberId" TEXT, + "closedFlag" BOOLEAN NOT NULL DEFAULT false, + "reminderFlag" BOOLEAN NOT NULL DEFAULT false, + "allDayFlag" BOOLEAN NOT NULL DEFAULT false, + "acknowledgementFlag" BOOLEAN NOT NULL DEFAULT false, + "meetingFlag" BOOLEAN NOT NULL DEFAULT false, + "recurringFlag" BOOLEAN NOT NULL DEFAULT false, + "billableFlag" BOOLEAN NOT NULL DEFAULT false, + "acknowledgedById" TEXT, + "acknowledgedAt" TIMESTAMP(3), + "startDate" TIMESTAMP(3), + "endDate" TIMESTAMP(3), + "hoursScheduled" DOUBLE PRECISION, + "duration" INTEGER, + "hoursPerDay" DOUBLE PRECISION, + "reminderMinutes" INTEGER DEFAULT 15, + "statusId" INTEGER, + "typeId" INTEGER, + "scheduleSpanId" INTEGER, + "updatedById" TEXT, + "createdById" TEXT, + "closedById" TEXT, + "closedAt" TIMESTAMP(3), + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "Schedule_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "Schedule_id_key" ON "Schedule"("id"); + +CREATE TABLE IF NOT EXISTS "TaxCode" ( + "id" INTEGER NOT NULL, + "uid" TEXT NOT NULL, + "code" TEXT NOT NULL, + "codeCaption" TEXT NOT NULL, + "description" TEXT, + "rate" DOUBLE PRECISION, + "defaultFlag" BOOLEAN NOT NULL DEFAULT false, + "createdBy" TEXT NOT NULL DEFAULT '', + "updatedBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + CONSTRAINT "TaxCode_pkey" PRIMARY KEY ("uid") +); +CREATE UNIQUE INDEX IF NOT EXISTS "TaxCode_id_key" ON "TaxCode"("id"); +CREATE UNIQUE INDEX IF NOT EXISTS "TaxCode_code_key" ON "TaxCode"("code"); + +-- ============================================================================= +-- SECTION 8: Foreign keys (all idempotent via DO $$ ... $$) +-- ============================================================================= + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'UnifiSite_companyId_fkey') THEN + ALTER TABLE "UnifiSite" ADD CONSTRAINT "UnifiSite_companyId_fkey" + FOREIGN KEY ("companyId") REFERENCES "Company"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Company_deletedById_fkey') THEN + ALTER TABLE "Company" ADD CONSTRAINT "Company_deletedById_fkey" + FOREIGN KEY ("deletedById") REFERENCES "User"("cwIdentifier") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Company_enteredById_fkey') THEN + ALTER TABLE "Company" ADD CONSTRAINT "Company_enteredById_fkey" + FOREIGN KEY ("enteredById") REFERENCES "User"("cwIdentifier") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'CompanyAddress_updatedById_fkey') THEN + ALTER TABLE "CompanyAddress" ADD CONSTRAINT "CompanyAddress_updatedById_fkey" + FOREIGN KEY ("updatedById") REFERENCES "User"("cwIdentifier") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'CompanyAddress_companyId_fkey') THEN + ALTER TABLE "CompanyAddress" ADD CONSTRAINT "CompanyAddress_companyId_fkey" + FOREIGN KEY ("companyId") REFERENCES "Company"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Contact_companyAddressId_fkey') THEN + ALTER TABLE "Contact" ADD CONSTRAINT "Contact_companyAddressId_fkey" + FOREIGN KEY ("companyAddressId") REFERENCES "CompanyAddress"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Contact_companyId_fkey') THEN + ALTER TABLE "Contact" ADD CONSTRAINT "Contact_companyId_fkey" + FOREIGN KEY ("companyId") REFERENCES "Company"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'CatalogSubcategory_categoryId_fkey') THEN + ALTER TABLE "CatalogSubcategory" ADD CONSTRAINT "CatalogSubcategory_categoryId_fkey" + FOREIGN KEY ("categoryId") REFERENCES "CatalogCategory"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'WarehouseBin_warehouseId_fkey') THEN + ALTER TABLE "WarehouseBin" ADD CONSTRAINT "WarehouseBin_warehouseId_fkey" + FOREIGN KEY ("warehouseId") REFERENCES "Warehouse"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ProductInventory_warehouseBinId_fkey') THEN + ALTER TABLE "ProductInventory" ADD CONSTRAINT "ProductInventory_warehouseBinId_fkey" + FOREIGN KEY ("warehouseBinId") REFERENCES "WarehouseBin"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ProductInventory_itemId_fkey') THEN + ALTER TABLE "ProductInventory" ADD CONSTRAINT "ProductInventory_itemId_fkey" + FOREIGN KEY ("itemId") REFERENCES "CatalogItem"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ProductInventory_warehouseId_fkey') THEN + ALTER TABLE "ProductInventory" ADD CONSTRAINT "ProductInventory_warehouseId_fkey" + FOREIGN KEY ("warehouseId") REFERENCES "Warehouse"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'MinimumStockByWarehouse_warehouseId_fkey') THEN + ALTER TABLE "MinimumStockByWarehouse" ADD CONSTRAINT "MinimumStockByWarehouse_warehouseId_fkey" + FOREIGN KEY ("warehouseId") REFERENCES "Warehouse"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'MinimumStockByWarehouse_itemId_fkey') THEN + ALTER TABLE "MinimumStockByWarehouse" ADD CONSTRAINT "MinimumStockByWarehouse_itemId_fkey" + FOREIGN KEY ("itemId") REFERENCES "CatalogItem"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'CatalogItem_subcategoryId_fkey') THEN + ALTER TABLE "CatalogItem" ADD CONSTRAINT "CatalogItem_subcategoryId_fkey" + FOREIGN KEY ("subcategoryId") REFERENCES "CatalogSubcategory"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'CatalogItem_manufacturerId_fkey') THEN + ALTER TABLE "CatalogItem" ADD CONSTRAINT "CatalogItem_manufacturerId_fkey" + FOREIGN KEY ("manufacturerId") REFERENCES "CatalogManufacturer"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ProductData_serviceTicketId_fkey') THEN + ALTER TABLE "ProductData" ADD CONSTRAINT "ProductData_serviceTicketId_fkey" + FOREIGN KEY ("serviceTicketId") REFERENCES "ServiceTicket"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ProductData_opportunityId_fkey') THEN + ALTER TABLE "ProductData" ADD CONSTRAINT "ProductData_opportunityId_fkey" + FOREIGN KEY ("opportunityId") REFERENCES "Opportunity"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ProductData_catalogItemId_fkey') THEN + ALTER TABLE "ProductData" ADD CONSTRAINT "ProductData_catalogItemId_fkey" + FOREIGN KEY ("catalogItemId") REFERENCES "CatalogItem"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ProductData_corporateLocationId_fkey') THEN + ALTER TABLE "ProductData" ADD CONSTRAINT "ProductData_corporateLocationId_fkey" + FOREIGN KEY ("corporateLocationId") REFERENCES "CorporateLocation"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_severityId_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_severityId_fkey" + FOREIGN KEY ("severityId") REFERENCES "ServiceTicketServerity"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_impactId_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_impactId_fkey" + FOREIGN KEY ("impactId") REFERENCES "ServiceTicketImpact"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_priorityId_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_priorityId_fkey" + FOREIGN KEY ("priorityId") REFERENCES "ServiceTicketPriority"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_sourceId_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_sourceId_fkey" + FOREIGN KEY ("sourceId") REFERENCES "ServiceTicketSource"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_locationId_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_locationId_fkey" + FOREIGN KEY ("locationId") REFERENCES "ServiceTicketLocation"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_serviceTicketBoardId_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_serviceTicketBoardId_fkey" + FOREIGN KEY ("serviceTicketBoardId") REFERENCES "ServiceTicketBoard"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_ticketOwnerId_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_ticketOwnerId_fkey" + FOREIGN KEY ("ticketOwnerId") REFERENCES "User"("cwIdentifier") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_companyId_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_companyId_fkey" + FOREIGN KEY ("companyId") REFERENCES "Company"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_contactId_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_contactId_fkey" + FOREIGN KEY ("contactId") REFERENCES "Contact"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_companyAddressId_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_companyAddressId_fkey" + FOREIGN KEY ("companyAddressId") REFERENCES "CompanyAddress"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_billingCompanyId_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_billingCompanyId_fkey" + FOREIGN KEY ("billingCompanyId") REFERENCES "Company"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_billingAddressId_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_billingAddressId_fkey" + FOREIGN KEY ("billingAddressId") REFERENCES "CompanyAddress"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_closedById_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_closedById_fkey" + FOREIGN KEY ("closedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_createdById_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_createdById_fkey" + FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicket_updatedById_fkey') THEN + ALTER TABLE "ServiceTicket" ADD CONSTRAINT "ServiceTicket_updatedById_fkey" + FOREIGN KEY ("updatedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicketNote_authorId_fkey') THEN + ALTER TABLE "ServiceTicketNote" ADD CONSTRAINT "ServiceTicketNote_authorId_fkey" + FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicketNote_serviceTicketId_fkey') THEN + ALTER TABLE "ServiceTicketNote" ADD CONSTRAINT "ServiceTicketNote_serviceTicketId_fkey" + FOREIGN KEY ("serviceTicketId") REFERENCES "ServiceTicket"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'ServiceTicketBoard_locationId_fkey') THEN + ALTER TABLE "ServiceTicketBoard" ADD CONSTRAINT "ServiceTicketBoard_locationId_fkey" + FOREIGN KEY ("locationId") REFERENCES "CorporateLocation"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Opportunity_typeId_fkey') THEN + ALTER TABLE "Opportunity" ADD CONSTRAINT "Opportunity_typeId_fkey" + FOREIGN KEY ("typeId") REFERENCES "OpportunityType"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Opportunity_statusId_fkey') THEN + ALTER TABLE "Opportunity" ADD CONSTRAINT "Opportunity_statusId_fkey" + FOREIGN KEY ("statusId") REFERENCES "OpportunityStatus"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Opportunity_taxCodeId_fkey') THEN + ALTER TABLE "Opportunity" ADD CONSTRAINT "Opportunity_taxCodeId_fkey" + FOREIGN KEY ("taxCodeId") REFERENCES "TaxCode"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Opportunity_primarySalesRepId_fkey') THEN + ALTER TABLE "Opportunity" ADD CONSTRAINT "Opportunity_primarySalesRepId_fkey" + FOREIGN KEY ("primarySalesRepId") REFERENCES "User"("cwIdentifier") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Opportunity_secondarySalesRepId_fkey') THEN + ALTER TABLE "Opportunity" ADD CONSTRAINT "Opportunity_secondarySalesRepId_fkey" + FOREIGN KEY ("secondarySalesRepId") REFERENCES "User"("cwIdentifier") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Opportunity_companyId_fkey') THEN + ALTER TABLE "Opportunity" ADD CONSTRAINT "Opportunity_companyId_fkey" + FOREIGN KEY ("companyId") REFERENCES "Company"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Opportunity_contactId_fkey') THEN + ALTER TABLE "Opportunity" ADD CONSTRAINT "Opportunity_contactId_fkey" + FOREIGN KEY ("contactId") REFERENCES "Contact"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Opportunity_siteId_fkey') THEN + ALTER TABLE "Opportunity" ADD CONSTRAINT "Opportunity_siteId_fkey" + FOREIGN KEY ("siteId") REFERENCES "CompanyAddress"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Opportunity_locationId_fkey') THEN + ALTER TABLE "Opportunity" ADD CONSTRAINT "Opportunity_locationId_fkey" + FOREIGN KEY ("locationId") REFERENCES "CorporateLocation"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Opportunity_departmentId_fkey') THEN + ALTER TABLE "Opportunity" ADD CONSTRAINT "Opportunity_departmentId_fkey" + FOREIGN KEY ("departmentId") REFERENCES "InternalDepartment"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Schedule_statusId_fkey') THEN + ALTER TABLE "Schedule" ADD CONSTRAINT "Schedule_statusId_fkey" + FOREIGN KEY ("statusId") REFERENCES "ScheduleStatus"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Schedule_typeId_fkey') THEN + ALTER TABLE "Schedule" ADD CONSTRAINT "Schedule_typeId_fkey" + FOREIGN KEY ("typeId") REFERENCES "ScheduleType"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Schedule_scheduleSpanId_fkey') THEN + ALTER TABLE "Schedule" ADD CONSTRAINT "Schedule_scheduleSpanId_fkey" + FOREIGN KEY ("scheduleSpanId") REFERENCES "ScheduleSpan"("id") ON DELETE SET NULL ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'Credential_companyId_fkey') THEN + ALTER TABLE "Credential" ADD CONSTRAINT "Credential_companyId_fkey" + FOREIGN KEY ("companyId") REFERENCES "Company"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'GeneratedQuotes_opportunityId_fkey') THEN + ALTER TABLE "GeneratedQuotes" ADD CONSTRAINT "GeneratedQuotes_opportunityId_fkey" + FOREIGN KEY ("opportunityId") REFERENCES "Opportunity"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = '_LinkedItems_A_fkey') THEN + ALTER TABLE "_LinkedItems" ADD CONSTRAINT "_LinkedItems_A_fkey" + FOREIGN KEY ("A") REFERENCES "CatalogItem"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + END IF; +END $$; + +DO $$ BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = '_LinkedItems_B_fkey') THEN + ALTER TABLE "_LinkedItems" ADD CONSTRAINT "_LinkedItems_B_fkey" + FOREIGN KEY ("B") REFERENCES "CatalogItem"("uid") ON DELETE CASCADE ON UPDATE CASCADE; + END IF; +END $$; + +-- ============================================================================= +-- SECTION 9: Cleanup — drop temporary defaults added for idempotency, +-- enforce NOT NULL on new integer id columns, drop removed columns +-- ============================================================================= + +-- CatalogItem: drop defaults, enforce NOT NULL +ALTER TABLE "CatalogItem" ALTER COLUMN "uid" DROP DEFAULT; +ALTER TABLE "CatalogItem" ALTER COLUMN "id" SET NOT NULL; +ALTER TABLE "CatalogItem" ALTER COLUMN "subcategoryId" DROP DEFAULT; + +-- Company: drop defaults, enforce NOT NULL +ALTER TABLE "Company" ALTER COLUMN "uid" DROP DEFAULT; +ALTER TABLE "Company" ALTER COLUMN "id" SET NOT NULL; + +-- Opportunity: drop defaults, enforce NOT NULL, drop the old cwDateEntered column +DO $$ BEGIN + IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'Opportunity' AND column_name = 'cwDateEntered') THEN + ALTER TABLE "Opportunity" DROP COLUMN "cwDateEntered"; + END IF; +END $$; +ALTER TABLE "Opportunity" ALTER COLUMN "uid" DROP DEFAULT; +ALTER TABLE "Opportunity" ALTER COLUMN "id" SET NOT NULL; +ALTER TABLE "Opportunity" ALTER COLUMN "eneteredBy" DROP DEFAULT; +ALTER TABLE "Opportunity" ALTER COLUMN "typeId" DROP DEFAULT; +ALTER TABLE "Opportunity" ALTER COLUMN "updatedBy" DROP DEFAULT; + +-- ProductData: drop the sentinel default on cancelById +ALTER TABLE "ProductData" ALTER COLUMN "cancelById" DROP DEFAULT; + +-- ServiceTicket: drop sentinel defaults on FK columns +ALTER TABLE "ServiceTicket" ALTER COLUMN "severityId" DROP DEFAULT; +ALTER TABLE "ServiceTicket" ALTER COLUMN "impactId" DROP DEFAULT; +ALTER TABLE "ServiceTicket" ALTER COLUMN "priorityId" DROP DEFAULT; +ALTER TABLE "ServiceTicket" ALTER COLUMN "sourceId" DROP DEFAULT; +ALTER TABLE "ServiceTicket" ALTER COLUMN "locationId" DROP DEFAULT; + +-- TaxCode: drop sentinel default on createdBy +ALTER TABLE "TaxCode" ALTER COLUMN "createdBy" DROP DEFAULT;