Initial v2 commit: complete rebuild with unified API + React admin
Phase 1-14 complete: - Unified Express.js API (TypeScript, Prisma ORM, PostgreSQL 16) - React Admin GUI (Vite + Ant Design + Zustand) - JWT auth with refresh tokens - Influence: Campaigns, Representatives, Responses, Email Queue - Map: Locations, Cuts, Shifts, Canvassing System - NAR data import infrastructure (2025 format) - Listmonk newsletter integration - Landing page builder (GrapesJS) - MkDocs + Code Server integration - Volunteer portal with GPS tracking - Monitoring stack (Prometheus, Grafana, Alertmanager) - Pangolin tunnel integration Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
509
api/prisma/migrations/20260209192843_init/migration.sql
Normal file
509
api/prisma/migrations/20260209192843_init/migration.sql
Normal file
@@ -0,0 +1,509 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "UserRole" AS ENUM ('SUPER_ADMIN', 'INFLUENCE_ADMIN', 'MAP_ADMIN', 'USER', 'TEMP');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "UserStatus" AS ENUM ('ACTIVE', 'INACTIVE', 'SUSPENDED', 'EXPIRED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "UserCreatedVia" AS ENUM ('ADMIN', 'PUBLIC_SHIFT_SIGNUP', 'STANDARD');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "CampaignStatus" AS ENUM ('DRAFT', 'ACTIVE', 'PAUSED', 'ARCHIVED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "GovernmentLevel" AS ENUM ('FEDERAL', 'PROVINCIAL', 'MUNICIPAL', 'SCHOOL_BOARD');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "EmailMethod" AS ENUM ('SMTP', 'MAILTO');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "CampaignEmailStatus" AS ENUM ('SENT', 'FAILED', 'CLICKED', 'USER_INFO_CAPTURED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ResponseType" AS ENUM ('EMAIL', 'LETTER', 'PHONE_CALL', 'MEETING', 'SOCIAL_MEDIA', 'OTHER');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ResponseStatus" AS ENUM ('PENDING', 'APPROVED', 'REJECTED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "SupportLevel" AS ENUM ('1', '2', '3', '4');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "GeocodeProvider" AS ENUM ('MAPBOX', 'NOMINATIM', 'PHOTON', 'LOCATIONIQ', 'ARCGIS', 'UNKNOWN');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ShiftStatus" AS ENUM ('OPEN', 'FULL', 'CANCELLED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "SignupStatus" AS ENUM ('CONFIRMED', 'CANCELLED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "SignupSource" AS ENUM ('AUTHENTICATED', 'PUBLIC', 'ADMIN');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "CutCategory" AS ENUM ('CUSTOM', 'WARD', 'NEIGHBORHOOD', 'DISTRICT');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "users" (
|
||||
"id" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"password" TEXT NOT NULL,
|
||||
"name" TEXT,
|
||||
"phone" TEXT,
|
||||
"role" "UserRole" NOT NULL DEFAULT 'USER',
|
||||
"status" "UserStatus" NOT NULL DEFAULT 'ACTIVE',
|
||||
"permissions" JSONB,
|
||||
"createdVia" "UserCreatedVia" NOT NULL DEFAULT 'STANDARD',
|
||||
"expiresAt" TIMESTAMP(3),
|
||||
"expireDays" INTEGER,
|
||||
"lastLoginAt" TIMESTAMP(3),
|
||||
"emailVerified" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "users_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "refresh_tokens" (
|
||||
"id" TEXT NOT NULL,
|
||||
"token" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"expiresAt" TIMESTAMP(3) NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "refresh_tokens_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "campaigns" (
|
||||
"id" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"emailSubject" TEXT NOT NULL,
|
||||
"emailBody" TEXT NOT NULL,
|
||||
"callToAction" TEXT,
|
||||
"coverPhoto" TEXT,
|
||||
"status" "CampaignStatus" NOT NULL DEFAULT 'DRAFT',
|
||||
"allowSmtpEmail" BOOLEAN NOT NULL DEFAULT true,
|
||||
"allowMailtoLink" BOOLEAN NOT NULL DEFAULT true,
|
||||
"collectUserInfo" BOOLEAN NOT NULL DEFAULT true,
|
||||
"showEmailCount" BOOLEAN NOT NULL DEFAULT true,
|
||||
"showCallCount" BOOLEAN NOT NULL DEFAULT true,
|
||||
"allowEmailEditing" BOOLEAN NOT NULL DEFAULT false,
|
||||
"allowCustomRecipients" BOOLEAN NOT NULL DEFAULT false,
|
||||
"showResponseWall" BOOLEAN NOT NULL DEFAULT false,
|
||||
"highlightCampaign" BOOLEAN NOT NULL DEFAULT false,
|
||||
"targetGovernmentLevels" "GovernmentLevel"[],
|
||||
"createdByUserId" TEXT,
|
||||
"createdByUserEmail" TEXT,
|
||||
"createdByUserName" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "campaigns_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "representatives" (
|
||||
"id" TEXT NOT NULL,
|
||||
"postalCode" TEXT NOT NULL,
|
||||
"name" TEXT,
|
||||
"email" TEXT,
|
||||
"districtName" TEXT,
|
||||
"electedOffice" TEXT,
|
||||
"partyName" TEXT,
|
||||
"representativeSetName" TEXT,
|
||||
"url" TEXT,
|
||||
"photoUrl" TEXT,
|
||||
"offices" JSONB,
|
||||
"cachedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "representatives_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "campaign_emails" (
|
||||
"id" TEXT NOT NULL,
|
||||
"campaignId" TEXT NOT NULL,
|
||||
"campaignSlug" TEXT NOT NULL,
|
||||
"userId" TEXT,
|
||||
"userEmail" TEXT,
|
||||
"userName" TEXT,
|
||||
"userPostalCode" TEXT,
|
||||
"recipientEmail" TEXT NOT NULL,
|
||||
"recipientName" TEXT,
|
||||
"recipientTitle" TEXT,
|
||||
"recipientLevel" "GovernmentLevel",
|
||||
"emailMethod" "EmailMethod" NOT NULL,
|
||||
"subject" TEXT NOT NULL,
|
||||
"message" TEXT NOT NULL,
|
||||
"status" "CampaignEmailStatus" NOT NULL DEFAULT 'SENT',
|
||||
"senderIp" TEXT,
|
||||
"sentAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "campaign_emails_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "representative_responses" (
|
||||
"id" TEXT NOT NULL,
|
||||
"campaignId" TEXT NOT NULL,
|
||||
"campaignSlug" TEXT NOT NULL,
|
||||
"representativeName" TEXT NOT NULL,
|
||||
"representativeTitle" TEXT,
|
||||
"representativeLevel" "GovernmentLevel" NOT NULL,
|
||||
"representativeEmail" TEXT,
|
||||
"responseType" "ResponseType" NOT NULL,
|
||||
"responseText" TEXT NOT NULL,
|
||||
"userComment" TEXT,
|
||||
"screenshotUrl" TEXT,
|
||||
"submittedByUserId" TEXT,
|
||||
"submittedByName" TEXT,
|
||||
"submittedByEmail" TEXT,
|
||||
"isAnonymous" BOOLEAN NOT NULL DEFAULT false,
|
||||
"status" "ResponseStatus" NOT NULL DEFAULT 'PENDING',
|
||||
"isVerified" BOOLEAN NOT NULL DEFAULT false,
|
||||
"verificationToken" TEXT,
|
||||
"verificationSentAt" TIMESTAMP(3),
|
||||
"verifiedAt" TIMESTAMP(3),
|
||||
"verifiedBy" TEXT,
|
||||
"upvoteCount" INTEGER NOT NULL DEFAULT 0,
|
||||
"submittedIp" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "representative_responses_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "response_upvotes" (
|
||||
"id" TEXT NOT NULL,
|
||||
"responseId" TEXT NOT NULL,
|
||||
"userId" TEXT,
|
||||
"userEmail" TEXT,
|
||||
"upvotedIp" TEXT,
|
||||
|
||||
CONSTRAINT "response_upvotes_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "custom_recipients" (
|
||||
"id" TEXT NOT NULL,
|
||||
"campaignId" TEXT NOT NULL,
|
||||
"campaignSlug" TEXT NOT NULL,
|
||||
"recipientName" TEXT NOT NULL,
|
||||
"recipientEmail" TEXT NOT NULL,
|
||||
"recipientTitle" TEXT,
|
||||
"recipientOrganization" TEXT,
|
||||
"notes" TEXT,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "custom_recipients_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "postal_code_cache" (
|
||||
"id" TEXT NOT NULL,
|
||||
"postalCode" TEXT NOT NULL,
|
||||
"city" TEXT,
|
||||
"province" TEXT,
|
||||
"centroidLat" DECIMAL(10,8),
|
||||
"centroidLng" DECIMAL(11,8),
|
||||
"lastUpdated" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "postal_code_cache_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "email_logs" (
|
||||
"id" TEXT NOT NULL,
|
||||
"recipientEmail" TEXT NOT NULL,
|
||||
"senderName" TEXT NOT NULL,
|
||||
"senderEmail" TEXT NOT NULL,
|
||||
"subject" TEXT,
|
||||
"message" TEXT,
|
||||
"postalCode" TEXT,
|
||||
"status" TEXT NOT NULL DEFAULT 'sent',
|
||||
"senderIp" TEXT,
|
||||
"sentAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "email_logs_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "email_verifications" (
|
||||
"id" TEXT NOT NULL,
|
||||
"token" TEXT NOT NULL,
|
||||
"email" TEXT NOT NULL,
|
||||
"tempCampaignData" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"expiresAt" TIMESTAMP(3) NOT NULL,
|
||||
"used" BOOLEAN NOT NULL DEFAULT false,
|
||||
|
||||
CONSTRAINT "email_verifications_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "calls" (
|
||||
"id" TEXT NOT NULL,
|
||||
"representativeName" TEXT NOT NULL,
|
||||
"representativeTitle" TEXT,
|
||||
"phoneNumber" TEXT NOT NULL,
|
||||
"officeType" TEXT,
|
||||
"callerName" TEXT,
|
||||
"callerEmail" TEXT,
|
||||
"postalCode" TEXT,
|
||||
"campaignId" TEXT,
|
||||
"campaignSlug" TEXT,
|
||||
"callerIp" TEXT,
|
||||
"calledAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "calls_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "locations" (
|
||||
"id" TEXT NOT NULL,
|
||||
"latitude" DECIMAL(10,8),
|
||||
"longitude" DECIMAL(11,8),
|
||||
"firstName" TEXT,
|
||||
"lastName" TEXT,
|
||||
"email" TEXT,
|
||||
"phone" TEXT,
|
||||
"unitNumber" TEXT,
|
||||
"supportLevel" "SupportLevel",
|
||||
"address" TEXT,
|
||||
"sign" BOOLEAN NOT NULL DEFAULT false,
|
||||
"signSize" TEXT,
|
||||
"notes" TEXT,
|
||||
"geocodeConfidence" INTEGER,
|
||||
"geocodeProvider" "GeocodeProvider",
|
||||
"createdByUserId" TEXT,
|
||||
"updatedByUserId" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "locations_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "shifts" (
|
||||
"id" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"date" DATE NOT NULL,
|
||||
"startTime" TEXT NOT NULL,
|
||||
"endTime" TEXT NOT NULL,
|
||||
"location" TEXT,
|
||||
"maxVolunteers" INTEGER NOT NULL,
|
||||
"currentVolunteers" INTEGER NOT NULL DEFAULT 0,
|
||||
"status" "ShiftStatus" NOT NULL DEFAULT 'OPEN',
|
||||
"isPublic" BOOLEAN NOT NULL DEFAULT false,
|
||||
"createdBy" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "shifts_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "shift_signups" (
|
||||
"id" TEXT NOT NULL,
|
||||
"shiftId" TEXT NOT NULL,
|
||||
"shiftTitle" TEXT,
|
||||
"userId" TEXT,
|
||||
"userEmail" TEXT NOT NULL,
|
||||
"userName" TEXT,
|
||||
"userPhone" TEXT,
|
||||
"signupDate" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"status" "SignupStatus" NOT NULL DEFAULT 'CONFIRMED',
|
||||
"signupSource" "SignupSource" NOT NULL DEFAULT 'AUTHENTICATED',
|
||||
|
||||
CONSTRAINT "shift_signups_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "cuts" (
|
||||
"id" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"color" TEXT NOT NULL DEFAULT '#3388ff',
|
||||
"opacity" DECIMAL(3,2) NOT NULL DEFAULT 0.3,
|
||||
"category" "CutCategory",
|
||||
"isPublic" BOOLEAN NOT NULL DEFAULT false,
|
||||
"isOfficial" BOOLEAN NOT NULL DEFAULT false,
|
||||
"geojson" TEXT NOT NULL,
|
||||
"bounds" TEXT,
|
||||
"showLocations" BOOLEAN NOT NULL DEFAULT true,
|
||||
"exportEnabled" BOOLEAN NOT NULL DEFAULT true,
|
||||
"assignedTo" TEXT,
|
||||
"filterSettings" JSONB,
|
||||
"lastCanvassed" TIMESTAMP(3),
|
||||
"completionPercentage" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdByUserId" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "cuts_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "map_settings" (
|
||||
"id" TEXT NOT NULL,
|
||||
"latitude" DECIMAL(10,8),
|
||||
"longitude" DECIMAL(11,8),
|
||||
"zoom" INTEGER,
|
||||
"walkSheetTitle" TEXT,
|
||||
"walkSheetSubtitle" TEXT,
|
||||
"walkSheetFooter" TEXT,
|
||||
"qrCode1Url" TEXT,
|
||||
"qrCode1Label" TEXT,
|
||||
"qrCode2Url" TEXT,
|
||||
"qrCode2Label" TEXT,
|
||||
"qrCode3Url" TEXT,
|
||||
"qrCode3Label" TEXT,
|
||||
"createdBy" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "map_settings_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "landing_pages" (
|
||||
"id" TEXT NOT NULL,
|
||||
"slug" TEXT NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"blocks" JSONB NOT NULL,
|
||||
"htmlOutput" TEXT,
|
||||
"cssOutput" TEXT,
|
||||
"mkdocsPath" TEXT,
|
||||
"published" BOOLEAN NOT NULL DEFAULT false,
|
||||
"seoTitle" TEXT,
|
||||
"seoDescription" TEXT,
|
||||
"seoImage" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "landing_pages_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "page_blocks" (
|
||||
"id" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"label" TEXT NOT NULL,
|
||||
"schema" JSONB NOT NULL,
|
||||
"defaults" JSONB NOT NULL,
|
||||
"thumbnail" TEXT,
|
||||
"category" TEXT,
|
||||
"sortOrder" INTEGER NOT NULL DEFAULT 0,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "page_blocks_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "refresh_tokens_token_key" ON "refresh_tokens"("token");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "refresh_tokens_userId_idx" ON "refresh_tokens"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "campaigns_slug_key" ON "campaigns"("slug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "representatives_postalCode_idx" ON "representatives"("postalCode");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "campaign_emails_campaignId_idx" ON "campaign_emails"("campaignId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "campaign_emails_campaignSlug_idx" ON "campaign_emails"("campaignSlug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "representative_responses_campaignId_idx" ON "representative_responses"("campaignId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "representative_responses_campaignSlug_idx" ON "representative_responses"("campaignSlug");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "response_upvotes_responseId_userId_key" ON "response_upvotes"("responseId", "userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "response_upvotes_responseId_upvotedIp_key" ON "response_upvotes"("responseId", "upvotedIp");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "custom_recipients_campaignId_idx" ON "custom_recipients"("campaignId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "postal_code_cache_postalCode_key" ON "postal_code_cache"("postalCode");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "email_verifications_token_key" ON "email_verifications"("token");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "calls_campaignId_idx" ON "calls"("campaignId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "shift_signups_shiftId_idx" ON "shift_signups"("shiftId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "shift_signups_shiftId_userEmail_key" ON "shift_signups"("shiftId", "userEmail");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "landing_pages_slug_key" ON "landing_pages"("slug");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "refresh_tokens" ADD CONSTRAINT "refresh_tokens_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "campaigns" ADD CONSTRAINT "campaigns_createdByUserId_fkey" FOREIGN KEY ("createdByUserId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "campaign_emails" ADD CONSTRAINT "campaign_emails_campaignId_fkey" FOREIGN KEY ("campaignId") REFERENCES "campaigns"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "campaign_emails" ADD CONSTRAINT "campaign_emails_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "representative_responses" ADD CONSTRAINT "representative_responses_campaignId_fkey" FOREIGN KEY ("campaignId") REFERENCES "campaigns"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "representative_responses" ADD CONSTRAINT "representative_responses_submittedByUserId_fkey" FOREIGN KEY ("submittedByUserId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "response_upvotes" ADD CONSTRAINT "response_upvotes_responseId_fkey" FOREIGN KEY ("responseId") REFERENCES "representative_responses"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "response_upvotes" ADD CONSTRAINT "response_upvotes_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "custom_recipients" ADD CONSTRAINT "custom_recipients_campaignId_fkey" FOREIGN KEY ("campaignId") REFERENCES "campaigns"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "calls" ADD CONSTRAINT "calls_campaignId_fkey" FOREIGN KEY ("campaignId") REFERENCES "campaigns"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "locations" ADD CONSTRAINT "locations_createdByUserId_fkey" FOREIGN KEY ("createdByUserId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "locations" ADD CONSTRAINT "locations_updatedByUserId_fkey" FOREIGN KEY ("updatedByUserId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "shift_signups" ADD CONSTRAINT "shift_signups_shiftId_fkey" FOREIGN KEY ("shiftId") REFERENCES "shifts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "shift_signups" ADD CONSTRAINT "shift_signups_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "cuts" ADD CONSTRAINT "cuts_createdByUserId_fkey" FOREIGN KEY ("createdByUserId") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "locations" ADD COLUMN "buildingUse" INTEGER,
|
||||
ADD COLUMN "federalDistrict" TEXT,
|
||||
ADD COLUMN "postalCode" TEXT,
|
||||
ADD COLUMN "province" TEXT;
|
||||
@@ -0,0 +1,8 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "EditorMode" AS ENUM ('VISUAL', 'CODE');
|
||||
|
||||
-- AlterEnum
|
||||
ALTER TYPE "CampaignEmailStatus" ADD VALUE 'QUEUED';
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "landing_pages" ADD COLUMN "editorMode" "EditorMode" NOT NULL DEFAULT 'VISUAL';
|
||||
@@ -0,0 +1,8 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "MkdocsExportMode" AS ENUM ('THEMED', 'STANDALONE');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "landing_pages" ADD COLUMN "mkdocsExportMode" "MkdocsExportMode" NOT NULL DEFAULT 'THEMED',
|
||||
ADD COLUMN "mkdocsHideNav" BOOLEAN NOT NULL DEFAULT true,
|
||||
ADD COLUMN "mkdocsHideToc" BOOLEAN NOT NULL DEFAULT true,
|
||||
ADD COLUMN "mkdocsStubPath" TEXT;
|
||||
@@ -0,0 +1,25 @@
|
||||
-- CreateTable
|
||||
CREATE TABLE "site_settings" (
|
||||
"id" TEXT NOT NULL,
|
||||
"organizationName" TEXT NOT NULL DEFAULT 'Changemaker Lite',
|
||||
"organizationShortName" TEXT NOT NULL DEFAULT 'CML',
|
||||
"organizationLogoUrl" TEXT,
|
||||
"organizationFaviconUrl" TEXT,
|
||||
"adminColorPrimary" TEXT NOT NULL DEFAULT '#9d4edd',
|
||||
"adminColorBgBase" TEXT NOT NULL DEFAULT '#1a1025',
|
||||
"publicColorPrimary" TEXT NOT NULL DEFAULT '#3498db',
|
||||
"publicColorBgBase" TEXT NOT NULL DEFAULT '#0d1b2a',
|
||||
"publicColorBgContainer" TEXT NOT NULL DEFAULT '#1b2838',
|
||||
"publicHeaderGradient" TEXT NOT NULL DEFAULT 'linear-gradient(135deg, #005a9c 0%, #007acc 100%)',
|
||||
"footerText" TEXT NOT NULL DEFAULT 'Powered by Changemaker Lite',
|
||||
"loginSubtitle" TEXT NOT NULL DEFAULT 'Admin',
|
||||
"emailFromName" TEXT NOT NULL DEFAULT 'Changemaker Lite',
|
||||
"enableInfluence" BOOLEAN NOT NULL DEFAULT true,
|
||||
"enableMap" BOOLEAN NOT NULL DEFAULT true,
|
||||
"enableNewsletter" BOOLEAN NOT NULL DEFAULT true,
|
||||
"enableLandingPages" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "site_settings_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
@@ -0,0 +1,92 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "VisitOutcome" AS ENUM ('NOT_HOME', 'REFUSED', 'MOVED', 'ALREADY_VOTED', 'SPOKE_WITH', 'LEFT_LITERATURE', 'COME_BACK_LATER');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "CanvassSessionStatus" AS ENUM ('ACTIVE', 'COMPLETED', 'ABANDONED');
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "shifts" ADD COLUMN "cutId" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "canvass_sessions" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"cutId" TEXT NOT NULL,
|
||||
"shiftId" TEXT,
|
||||
"status" "CanvassSessionStatus" NOT NULL DEFAULT 'ACTIVE',
|
||||
"startedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"endedAt" TIMESTAMP(3),
|
||||
"startLatitude" DECIMAL(10,8),
|
||||
"startLongitude" DECIMAL(11,8),
|
||||
|
||||
CONSTRAINT "canvass_sessions_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "canvass_visits" (
|
||||
"id" TEXT NOT NULL,
|
||||
"locationId" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"shiftId" TEXT,
|
||||
"sessionId" TEXT,
|
||||
"outcome" "VisitOutcome" NOT NULL,
|
||||
"supportLevel" "SupportLevel",
|
||||
"signRequested" BOOLEAN NOT NULL DEFAULT false,
|
||||
"signSize" TEXT,
|
||||
"notes" TEXT,
|
||||
"durationSeconds" INTEGER,
|
||||
"visitedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "canvass_visits_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "canvass_sessions_userId_idx" ON "canvass_sessions"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "canvass_sessions_cutId_idx" ON "canvass_sessions"("cutId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "canvass_sessions_shiftId_idx" ON "canvass_sessions"("shiftId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "canvass_visits_locationId_idx" ON "canvass_visits"("locationId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "canvass_visits_userId_idx" ON "canvass_visits"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "canvass_visits_shiftId_idx" ON "canvass_visits"("shiftId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "canvass_visits_sessionId_idx" ON "canvass_visits"("sessionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "canvass_visits_visitedAt_idx" ON "canvass_visits"("visitedAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "shifts_cutId_idx" ON "shifts"("cutId");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "shifts" ADD CONSTRAINT "shifts_cutId_fkey" FOREIGN KEY ("cutId") REFERENCES "cuts"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "canvass_sessions" ADD CONSTRAINT "canvass_sessions_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "canvass_sessions" ADD CONSTRAINT "canvass_sessions_cutId_fkey" FOREIGN KEY ("cutId") REFERENCES "cuts"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "canvass_sessions" ADD CONSTRAINT "canvass_sessions_shiftId_fkey" FOREIGN KEY ("shiftId") REFERENCES "shifts"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "canvass_visits" ADD CONSTRAINT "canvass_visits_locationId_fkey" FOREIGN KEY ("locationId") REFERENCES "locations"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "canvass_visits" ADD CONSTRAINT "canvass_visits_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "canvass_visits" ADD CONSTRAINT "canvass_visits_shiftId_fkey" FOREIGN KEY ("shiftId") REFERENCES "shifts"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "canvass_visits" ADD CONSTRAINT "canvass_visits_sessionId_fkey" FOREIGN KEY ("sessionId") REFERENCES "canvass_sessions"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,59 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "TrackPointEvent" AS ENUM ('LOCATION_ADDED', 'VISIT_RECORDED', 'SESSION_STARTED', 'SESSION_ENDED');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "tracking_sessions" (
|
||||
"id" TEXT NOT NULL,
|
||||
"userId" TEXT NOT NULL,
|
||||
"canvassSessionId" TEXT,
|
||||
"startedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"endedAt" TIMESTAMP(3),
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"totalPoints" INTEGER NOT NULL DEFAULT 0,
|
||||
"totalDistanceM" DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||||
"lastLatitude" DECIMAL(10,8),
|
||||
"lastLongitude" DECIMAL(11,8),
|
||||
"lastRecordedAt" TIMESTAMP(3),
|
||||
|
||||
CONSTRAINT "tracking_sessions_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "track_points" (
|
||||
"id" TEXT NOT NULL,
|
||||
"trackingSessionId" TEXT NOT NULL,
|
||||
"latitude" DECIMAL(10,8) NOT NULL,
|
||||
"longitude" DECIMAL(11,8) NOT NULL,
|
||||
"accuracy" DOUBLE PRECISION,
|
||||
"recordedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"eventType" "TrackPointEvent",
|
||||
|
||||
CONSTRAINT "track_points_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "tracking_sessions_canvassSessionId_key" ON "tracking_sessions"("canvassSessionId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "tracking_sessions_userId_idx" ON "tracking_sessions"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "tracking_sessions_isActive_idx" ON "tracking_sessions"("isActive");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "tracking_sessions_isActive_lastRecordedAt_idx" ON "tracking_sessions"("isActive", "lastRecordedAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "track_points_trackingSessionId_recordedAt_idx" ON "track_points"("trackingSessionId", "recordedAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "track_points_recordedAt_idx" ON "track_points"("recordedAt");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "tracking_sessions" ADD CONSTRAINT "tracking_sessions_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "tracking_sessions" ADD CONSTRAINT "tracking_sessions_canvassSessionId_fkey" FOREIGN KEY ("canvassSessionId") REFERENCES "canvass_sessions"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "track_points" ADD CONSTRAINT "track_points_trackingSessionId_fkey" FOREIGN KEY ("trackingSessionId") REFERENCES "tracking_sessions"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,8 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "site_settings" ADD COLUMN IF NOT EXISTS "smtpHost" TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS "smtpPort" INTEGER NOT NULL DEFAULT 0,
|
||||
ADD COLUMN IF NOT EXISTS "smtpUser" TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS "smtpPass" TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS "smtpFromAddress" TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN IF NOT EXISTS "emailTestMode" BOOLEAN NOT NULL DEFAULT true,
|
||||
ADD COLUMN IF NOT EXISTS "testEmailRecipient" TEXT NOT NULL DEFAULT '';
|
||||
3
api/prisma/migrations/migration_lock.toml
Normal file
3
api/prisma/migrations/migration_lock.toml
Normal file
@@ -0,0 +1,3 @@
|
||||
# Please do not edit this file manually
|
||||
# It should be added in your version-control system (e.g., Git)
|
||||
provider = "postgresql"
|
||||
Reference in New Issue
Block a user