217 lines
8.0 KiB
SQL
217 lines
8.0 KiB
SQL
-- Datewise initial schema (PostgreSQL)
|
|
|
|
CREATE TABLE "Session" (
|
|
"id" TEXT NOT NULL,
|
|
"shop" TEXT NOT NULL,
|
|
"state" TEXT NOT NULL,
|
|
"isOnline" BOOLEAN NOT NULL DEFAULT false,
|
|
"scope" TEXT,
|
|
"expires" TIMESTAMP(3),
|
|
"accessToken" TEXT NOT NULL,
|
|
"userId" BIGINT,
|
|
"firstName" TEXT,
|
|
"lastName" TEXT,
|
|
"email" TEXT,
|
|
"accountOwner" BOOLEAN NOT NULL DEFAULT false,
|
|
"locale" TEXT,
|
|
"collaborator" BOOLEAN DEFAULT false,
|
|
"emailVerified" BOOLEAN DEFAULT false,
|
|
"refreshToken" TEXT,
|
|
"refreshTokenExpires" TIMESTAMP(3),
|
|
CONSTRAINT "Session_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE TABLE "Shop" (
|
|
"id" TEXT NOT NULL,
|
|
"domain" TEXT NOT NULL,
|
|
"currency" TEXT NOT NULL DEFAULT 'CAD',
|
|
"timezone" TEXT NOT NULL DEFAULT 'America/Toronto',
|
|
"settings" JSONB NOT NULL,
|
|
"configVersion" INTEGER NOT NULL DEFAULT 1,
|
|
"plan" TEXT NOT NULL DEFAULT 'free',
|
|
"feeProductId" TEXT,
|
|
"installedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"uninstalledAt" TIMESTAMP(3),
|
|
CONSTRAINT "Shop_pkey" PRIMARY KEY ("id")
|
|
);
|
|
CREATE UNIQUE INDEX "Shop_domain_key" ON "Shop"("domain");
|
|
|
|
CREATE TABLE "Location" (
|
|
"id" TEXT NOT NULL,
|
|
"shopId" TEXT NOT NULL,
|
|
"shopifyLocationId" TEXT,
|
|
"name" TEXT NOT NULL,
|
|
"address" TEXT NOT NULL,
|
|
"timezone" TEXT NOT NULL,
|
|
"lat" DOUBLE PRECISION,
|
|
"lng" DOUBLE PRECISION,
|
|
"enabled" BOOLEAN NOT NULL DEFAULT true,
|
|
"priority" INTEGER NOT NULL DEFAULT 1,
|
|
"pickupInstructions" TEXT,
|
|
"methods" JSONB NOT NULL,
|
|
"exceptions" JSONB NOT NULL DEFAULT '[]',
|
|
"zones" JSONB NOT NULL DEFAULT '[]',
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
CONSTRAINT "Location_pkey" PRIMARY KEY ("id")
|
|
);
|
|
CREATE INDEX "Location_shopId_idx" ON "Location"("shopId");
|
|
|
|
CREATE TABLE "ProductRule" (
|
|
"id" TEXT NOT NULL,
|
|
"shopId" TEXT NOT NULL,
|
|
"name" TEXT NOT NULL,
|
|
"enabled" BOOLEAN NOT NULL DEFAULT true,
|
|
"priority" INTEGER NOT NULL DEFAULT 10,
|
|
"target" JSONB NOT NULL,
|
|
"action" JSONB NOT NULL,
|
|
"message" TEXT,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
CONSTRAINT "ProductRule_pkey" PRIMARY KEY ("id")
|
|
);
|
|
CREATE INDEX "ProductRule_shopId_idx" ON "ProductRule"("shopId");
|
|
|
|
CREATE TABLE "PeakDay" (
|
|
"id" TEXT NOT NULL,
|
|
"shopId" TEXT NOT NULL,
|
|
"name" TEXT NOT NULL,
|
|
"dates" TEXT[],
|
|
"locationIds" TEXT[],
|
|
"methods" TEXT[],
|
|
"dailyCapacity" INTEGER,
|
|
"slotCapacity" INTEGER,
|
|
"extraPrepMinutes" INTEGER NOT NULL DEFAULT 0,
|
|
"cutoffDaysBefore" INTEGER,
|
|
"cutoffTime" TEXT,
|
|
"surcharge" INTEGER NOT NULL DEFAULT 0,
|
|
"waitlist" BOOLEAN NOT NULL DEFAULT false,
|
|
"message" TEXT,
|
|
CONSTRAINT "PeakDay_pkey" PRIMARY KEY ("id")
|
|
);
|
|
CREATE INDEX "PeakDay_shopId_idx" ON "PeakDay"("shopId");
|
|
|
|
CREATE TABLE "CapacityCounter" (
|
|
"shopId" TEXT NOT NULL,
|
|
"locationId" TEXT NOT NULL,
|
|
"method" TEXT NOT NULL,
|
|
"date" TEXT NOT NULL,
|
|
"slot" TEXT NOT NULL,
|
|
"count" INTEGER NOT NULL DEFAULT 0,
|
|
CONSTRAINT "CapacityCounter_pkey" PRIMARY KEY ("shopId","locationId","method","date","slot"),
|
|
CONSTRAINT "CapacityCounter_count_nonneg" CHECK ("count" >= 0)
|
|
);
|
|
|
|
CREATE TABLE "Hold" (
|
|
"token" TEXT NOT NULL,
|
|
"shopId" TEXT NOT NULL,
|
|
"locationId" TEXT NOT NULL,
|
|
"method" TEXT NOT NULL,
|
|
"date" TEXT NOT NULL,
|
|
"slot" TEXT NOT NULL,
|
|
"expiresAt" TIMESTAMP(3) NOT NULL,
|
|
"fee" INTEGER NOT NULL DEFAULT 0,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
CONSTRAINT "Hold_pkey" PRIMARY KEY ("token")
|
|
);
|
|
CREATE INDEX "Hold_shopId_locationId_method_date_idx" ON "Hold"("shopId", "locationId", "method", "date");
|
|
CREATE INDEX "Hold_expiresAt_idx" ON "Hold"("expiresAt");
|
|
|
|
CREATE TABLE "Booking" (
|
|
"id" TEXT NOT NULL,
|
|
"shopId" TEXT NOT NULL,
|
|
"orderId" TEXT,
|
|
"orderName" TEXT,
|
|
"status" TEXT NOT NULL,
|
|
"reviewReason" TEXT,
|
|
"method" TEXT NOT NULL,
|
|
"locationId" TEXT,
|
|
"date" TEXT,
|
|
"slotStart" TEXT,
|
|
"slotEnd" TEXT,
|
|
"timezone" TEXT NOT NULL,
|
|
"startUtc" TIMESTAMP(3),
|
|
"endUtc" TIMESTAMP(3),
|
|
"customerName" TEXT,
|
|
"customerEmail" TEXT,
|
|
"customerPhone" TEXT,
|
|
"address" JSONB,
|
|
"items" JSONB,
|
|
"fee" INTEGER NOT NULL DEFAULT 0,
|
|
"peakDayId" TEXT,
|
|
"rescheduleCount" INTEGER NOT NULL DEFAULT 0,
|
|
"configVersion" INTEGER NOT NULL,
|
|
"snapshot" JSONB NOT NULL,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
CONSTRAINT "Booking_pkey" PRIMARY KEY ("id")
|
|
);
|
|
CREATE UNIQUE INDEX "Booking_shopId_orderId_key" ON "Booking"("shopId", "orderId");
|
|
CREATE INDEX "Booking_shopId_date_idx" ON "Booking"("shopId", "date");
|
|
CREATE INDEX "Booking_shopId_status_idx" ON "Booking"("shopId", "status");
|
|
|
|
CREATE TABLE "BookingEvent" (
|
|
"id" TEXT NOT NULL,
|
|
"shopId" TEXT NOT NULL,
|
|
"bookingId" TEXT NOT NULL,
|
|
"actor" TEXT NOT NULL,
|
|
"action" TEXT NOT NULL,
|
|
"before" JSONB,
|
|
"after" JSONB,
|
|
"at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
CONSTRAINT "BookingEvent_pkey" PRIMARY KEY ("id")
|
|
);
|
|
CREATE INDEX "BookingEvent_bookingId_idx" ON "BookingEvent"("bookingId");
|
|
|
|
CREATE TABLE "WaitlistEntry" (
|
|
"id" TEXT NOT NULL,
|
|
"shopId" TEXT NOT NULL,
|
|
"locationId" TEXT NOT NULL,
|
|
"method" TEXT NOT NULL,
|
|
"date" TEXT NOT NULL,
|
|
"slot" TEXT NOT NULL,
|
|
"email" TEXT,
|
|
"phone" TEXT,
|
|
"name" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"offeredAt" TIMESTAMP(3),
|
|
"offerToken" TEXT,
|
|
CONSTRAINT "WaitlistEntry_pkey" PRIMARY KEY ("id")
|
|
);
|
|
CREATE INDEX "WaitlistEntry_shopId_locationId_method_date_idx" ON "WaitlistEntry"("shopId", "locationId", "method", "date");
|
|
|
|
CREATE TABLE "ReminderJob" (
|
|
"id" TEXT NOT NULL,
|
|
"shopId" TEXT NOT NULL,
|
|
"bookingId" TEXT NOT NULL,
|
|
"policyId" TEXT NOT NULL,
|
|
"channel" TEXT NOT NULL,
|
|
"sendAt" TIMESTAMP(3) NOT NULL,
|
|
"body" TEXT NOT NULL,
|
|
"status" TEXT NOT NULL DEFAULT 'pending',
|
|
"attempts" INTEGER NOT NULL DEFAULT 0,
|
|
"lastError" TEXT,
|
|
"sentAt" TIMESTAMP(3),
|
|
CONSTRAINT "ReminderJob_pkey" PRIMARY KEY ("id")
|
|
);
|
|
CREATE INDEX "ReminderJob_status_sendAt_idx" ON "ReminderJob"("status", "sendAt");
|
|
|
|
CREATE TABLE "ProcessedWebhook" (
|
|
"id" TEXT NOT NULL,
|
|
"topic" TEXT NOT NULL,
|
|
"shop" TEXT NOT NULL,
|
|
"receivedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
CONSTRAINT "ProcessedWebhook_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
ALTER TABLE "Location" ADD CONSTRAINT "Location_shopId_fkey" FOREIGN KEY ("shopId") REFERENCES "Shop"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "ProductRule" ADD CONSTRAINT "ProductRule_shopId_fkey" FOREIGN KEY ("shopId") REFERENCES "Shop"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "PeakDay" ADD CONSTRAINT "PeakDay_shopId_fkey" FOREIGN KEY ("shopId") REFERENCES "Shop"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "CapacityCounter" ADD CONSTRAINT "CapacityCounter_shopId_fkey" FOREIGN KEY ("shopId") REFERENCES "Shop"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "Hold" ADD CONSTRAINT "Hold_shopId_fkey" FOREIGN KEY ("shopId") REFERENCES "Shop"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "Booking" ADD CONSTRAINT "Booking_shopId_fkey" FOREIGN KEY ("shopId") REFERENCES "Shop"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "BookingEvent" ADD CONSTRAINT "BookingEvent_shopId_fkey" FOREIGN KEY ("shopId") REFERENCES "Shop"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "BookingEvent" ADD CONSTRAINT "BookingEvent_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "Booking"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "WaitlistEntry" ADD CONSTRAINT "WaitlistEntry_shopId_fkey" FOREIGN KEY ("shopId") REFERENCES "Shop"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "ReminderJob" ADD CONSTRAINT "ReminderJob_shopId_fkey" FOREIGN KEY ("shopId") REFERENCES "Shop"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "ReminderJob" ADD CONSTRAINT "ReminderJob_bookingId_fkey" FOREIGN KEY ("bookingId") REFERENCES "Booking"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|