From a7d098fcf2873ff0bdc4e008243844a6d3dc18a4 Mon Sep 17 00:00:00 2001 From: OKBoomer88 Date: Mon, 23 Mar 2026 08:34:31 +0800 Subject: [PATCH] Add custom schema --- packages/prisma/{.env => .env.example} | 0 .../migration.sql | 78 +++++++++++++++++++ packages/prisma/schema.prisma | 76 ++++++++++++++++++ 3 files changed, 154 insertions(+) rename packages/prisma/{.env => .env.example} (100%) create mode 100644 packages/prisma/migrations/20260313001400_add_business_full/migration.sql diff --git a/packages/prisma/.env b/packages/prisma/.env.example similarity index 100% rename from packages/prisma/.env rename to packages/prisma/.env.example diff --git a/packages/prisma/migrations/20260313001400_add_business_full/migration.sql b/packages/prisma/migrations/20260313001400_add_business_full/migration.sql new file mode 100644 index 00000000000000..77ad6e03990de1 --- /dev/null +++ b/packages/prisma/migrations/20260313001400_add_business_full/migration.sql @@ -0,0 +1,78 @@ +/* + Warnings: + + - A unique constraint covering the columns `[primaryBusinessId]` on the table `users` will be added. If there are existing duplicate values, this will fail. + +*/ +-- CreateEnum +CREATE TYPE "public"."BusinessStatus" AS ENUM ('ACTIVE', 'INACTIVE', 'PENDING_VERIFICATION', 'SUSPENDED'); + +-- AlterTable +ALTER TABLE "public"."Booking" ADD COLUMN "businessId" INTEGER; + +-- AlterTable +ALTER TABLE "public"."users" ADD COLUMN "primaryBusinessId" INTEGER; + +-- CreateTable +CREATE TABLE "public"."Service" ( + "id" SERIAL NOT NULL, + "businessId" INTEGER NOT NULL, + "name" TEXT NOT NULL, + "description" TEXT, + "price" INTEGER, + "duration" INTEGER, + "imageUrl" TEXT, + "isActive" BOOLEAN NOT NULL DEFAULT true, + "category" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Service_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."Business" ( + "id" SERIAL NOT NULL, + "name" TEXT NOT NULL, + "slug" TEXT NOT NULL, + "lineUserId" TEXT, + "smsPhoneNumber" TEXT, + "emailAddress" TEXT, + "businessPhone" TEXT, + "businessEmail" TEXT, + "lineVerified" BOOLEAN NOT NULL DEFAULT false, + "smsVerified" BOOLEAN NOT NULL DEFAULT false, + "emailVerified" BOOLEAN NOT NULL DEFAULT false, + "notifyViaLine" BOOLEAN NOT NULL DEFAULT true, + "notifyViaSms" BOOLEAN NOT NULL DEFAULT false, + "notifyViaEmail" BOOLEAN NOT NULL DEFAULT true, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + "status" "public"."BusinessStatus" NOT NULL DEFAULT 'ACTIVE', + + CONSTRAINT "Business_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE INDEX "Service_businessId_idx" ON "public"."Service"("businessId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Service_businessId_name_key" ON "public"."Service"("businessId", "name"); + +-- CreateIndex +CREATE UNIQUE INDEX "Business_slug_key" ON "public"."Business"("slug"); + +-- CreateIndex +CREATE INDEX "Business_lineUserId_idx" ON "public"."Business"("lineUserId"); + +-- CreateIndex +CREATE UNIQUE INDEX "users_primaryBusinessId_key" ON "public"."users"("primaryBusinessId"); + +-- AddForeignKey +ALTER TABLE "public"."Service" ADD CONSTRAINT "Service_businessId_fkey" FOREIGN KEY ("businessId") REFERENCES "public"."Business"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."users" ADD CONSTRAINT "users_primaryBusinessId_fkey" FOREIGN KEY ("primaryBusinessId") REFERENCES "public"."Business"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."Booking" ADD CONSTRAINT "Booking_businessId_fkey" FOREIGN KEY ("businessId") REFERENCES "public"."Business"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index 9c410085816422..cdc129b91c5518 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -367,6 +367,74 @@ model TravelSchedule { @@index([endDate]) } +//OKBOOMER: custom table for business services menu +model Service { + id Int @id @default(autoincrement()) + businessId Int + business Business @relation(fields: [businessId], references: [id]) + + name String // "Haircut", "Coloring + Treatment" + description String? + price Int? // 800 + duration Int? // minutes, e.g. 60 + imageUrl String? // hosted photo (upload to your server or Cloudinary) + isActive Boolean @default(true) + category String? // "Hair", "Nails", "Massage" + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@unique([businessId, name]) // unique name per business + @@index([businessId]) +} + +//OKBOOMER: custom table for business linkage +enum BusinessStatus { + ACTIVE + INACTIVE + PENDING_VERIFICATION + SUSPENDED +} + +model Business { + id Int @id @default(autoincrement()) + name String // e.g. "Salon XYZ" + slug String @unique // e.g. "salon-xyz" — stable identifier for LIFF ?business=... + lineUserId String? // Uxxxxxxxx... + smsPhoneNumber String? // optional phone for sms + emailAddress String? // optional notify email + businessPhone String? // Public customer contact (displayed in confirmations, etc.) + businessEmail String? // Public customer email (displayed in confirmations, etc.) + + // Verification + lineVerified Boolean @default(false) + smsVerified Boolean @default(false) + emailVerified Boolean @default(false) + + // Notification + notifyViaLine Boolean @default(true) + notifyViaSms Boolean @default(false) + notifyViaEmail Boolean @default(true) + + // Time stamps + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + // Status (Active/Inactive/Pending/Suspended) + status BusinessStatus @default(ACTIVE) + + // Admin who can manage this business (one-to-many) + primaryAdmin User? + //secondaryAdmin User? + + // Bookings tagged with this business + bookings Booking[] @relation("BusinessBookings") + + // Services offered (one-to-many) + services Service[] + + @@index([lineUserId]) +} + // It holds Personal Profiles of a User plus it has email, password and other core things.. model User { id Int @id @default(autoincrement()) @@ -486,6 +554,10 @@ model User { agents Agent[] holidaySettings UserHolidaySettings? + //OKBOOMER: business linkage + primaryBusinessId Int? @unique + primaryBusiness Business? @relation(fields: [primaryBusinessId], references: [id]) + autoOptInFeatures Boolean @default(false) @@unique([email]) @@ -899,6 +971,10 @@ model Booking { expenseLogs CreditExpenseLog[] report BookingReport? + //OKBOOMER: business linkage + businessId Int? + business Business? @relation("BusinessBookings", fields: [businessId], references: [id]) + // @@partial_index([reassignById]) @@index([eventTypeId])