Import large Excel lists with duplicate checks, assign and kanban follow-up, convert to Person when ready; also fix OTP mobile mask order and SMS brand name to منتکت. Co-authored-by: Cursor <cursoragent@cursor.com>
114 lines
5.1 KiB
SQL
114 lines
5.1 KiB
SQL
-- CreateTable
|
|
CREATE TABLE "LeadStage" (
|
|
"id" TEXT NOT NULL,
|
|
"organizationId" TEXT NOT NULL,
|
|
"name" TEXT NOT NULL,
|
|
"position" INTEGER NOT NULL DEFAULT 0,
|
|
"color" TEXT NOT NULL DEFAULT 'teal',
|
|
"showOnBoard" BOOLEAN NOT NULL DEFAULT true,
|
|
"isConverted" BOOLEAN NOT NULL DEFAULT false,
|
|
"isLost" BOOLEAN NOT NULL DEFAULT false,
|
|
"isUnqualified" BOOLEAN NOT NULL DEFAULT false,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "LeadStage_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "Lead" (
|
|
"id" TEXT NOT NULL,
|
|
"organizationId" TEXT NOT NULL,
|
|
"title" TEXT NOT NULL,
|
|
"contactName" TEXT,
|
|
"mobile" TEXT NOT NULL,
|
|
"phone" TEXT,
|
|
"city" TEXT,
|
|
"region" TEXT,
|
|
"trade" TEXT,
|
|
"source" TEXT,
|
|
"notes" TEXT,
|
|
"estimatedValue" DECIMAL(18,2),
|
|
"stageId" TEXT NOT NULL,
|
|
"position" INTEGER NOT NULL DEFAULT 0,
|
|
"assigneeId" TEXT,
|
|
"createdById" TEXT,
|
|
"lastContactAt" TIMESTAMP(3),
|
|
"nextFollowUpAt" TIMESTAMP(3),
|
|
"convertedPersonId" TEXT,
|
|
"convertedAt" TIMESTAMP(3),
|
|
"archivedAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "Lead_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "LeadEvent" (
|
|
"id" TEXT NOT NULL,
|
|
"organizationId" TEXT NOT NULL,
|
|
"leadId" TEXT NOT NULL,
|
|
"type" TEXT NOT NULL,
|
|
"title" TEXT NOT NULL,
|
|
"body" TEXT,
|
|
"meta" JSONB,
|
|
"actorId" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT "LeadEvent_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateTable
|
|
CREATE TABLE "LeadImportJob" (
|
|
"id" TEXT NOT NULL,
|
|
"organizationId" TEXT NOT NULL,
|
|
"createdById" TEXT,
|
|
"fileName" TEXT,
|
|
"status" TEXT NOT NULL DEFAULT 'pending',
|
|
"totalCount" INTEGER NOT NULL DEFAULT 0,
|
|
"processedCount" INTEGER NOT NULL DEFAULT 0,
|
|
"successCount" INTEGER NOT NULL DEFAULT 0,
|
|
"duplicateCount" INTEGER NOT NULL DEFAULT 0,
|
|
"errorCount" INTEGER NOT NULL DEFAULT 0,
|
|
"rows" JSONB NOT NULL DEFAULT '[]',
|
|
"errorSamples" JSONB NOT NULL DEFAULT '[]',
|
|
"startedAt" TIMESTAMP(3),
|
|
"finishedAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
|
|
CONSTRAINT "LeadImportJob_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
-- CreateIndex
|
|
CREATE INDEX "LeadStage_organizationId_position_idx" ON "LeadStage"("organizationId", "position");
|
|
CREATE UNIQUE INDEX "LeadStage_organizationId_name_key" ON "LeadStage"("organizationId", "name");
|
|
|
|
CREATE UNIQUE INDEX "Lead_organizationId_mobile_key" ON "Lead"("organizationId", "mobile");
|
|
CREATE INDEX "Lead_organizationId_stageId_position_idx" ON "Lead"("organizationId", "stageId", "position");
|
|
CREATE INDEX "Lead_organizationId_assigneeId_idx" ON "Lead"("organizationId", "assigneeId");
|
|
CREATE INDEX "Lead_organizationId_nextFollowUpAt_idx" ON "Lead"("organizationId", "nextFollowUpAt");
|
|
CREATE INDEX "Lead_organizationId_lastContactAt_idx" ON "Lead"("organizationId", "lastContactAt");
|
|
CREATE INDEX "Lead_organizationId_archivedAt_idx" ON "Lead"("organizationId", "archivedAt");
|
|
CREATE INDEX "Lead_organizationId_createdAt_idx" ON "Lead"("organizationId", "createdAt");
|
|
CREATE INDEX "Lead_organizationId_city_idx" ON "Lead"("organizationId", "city");
|
|
CREATE INDEX "Lead_organizationId_trade_idx" ON "Lead"("organizationId", "trade");
|
|
CREATE INDEX "Lead_organizationId_source_idx" ON "Lead"("organizationId", "source");
|
|
|
|
CREATE INDEX "LeadEvent_leadId_createdAt_idx" ON "LeadEvent"("leadId", "createdAt");
|
|
CREATE INDEX "LeadEvent_organizationId_createdAt_idx" ON "LeadEvent"("organizationId", "createdAt");
|
|
|
|
CREATE INDEX "LeadImportJob_organizationId_status_createdAt_idx" ON "LeadImportJob"("organizationId", "status", "createdAt");
|
|
CREATE INDEX "LeadImportJob_status_createdAt_idx" ON "LeadImportJob"("status", "createdAt");
|
|
|
|
-- AddForeignKey
|
|
ALTER TABLE "LeadStage" ADD CONSTRAINT "LeadStage_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "Lead" ADD CONSTRAINT "Lead_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "Lead" ADD CONSTRAINT "Lead_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "LeadStage"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
ALTER TABLE "Lead" ADD CONSTRAINT "Lead_assigneeId_fkey" FOREIGN KEY ("assigneeId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
ALTER TABLE "Lead" ADD CONSTRAINT "Lead_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
ALTER TABLE "LeadEvent" ADD CONSTRAINT "LeadEvent_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "LeadEvent" ADD CONSTRAINT "LeadEvent_leadId_fkey" FOREIGN KEY ("leadId") REFERENCES "Lead"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "LeadImportJob" ADD CONSTRAINT "LeadImportJob_organizationId_fkey" FOREIGN KEY ("organizationId") REFERENCES "Organization"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|