initial commit
This commit is contained in:
1
packages/db/prisma/.env
Executable file
1
packages/db/prisma/.env
Executable file
@@ -0,0 +1 @@
|
||||
DATABASE_URL=postgresql://postgres:mypassword@localhost:5432/dentalapp
|
||||
1
packages/db/prisma/.env.example
Executable file
1
packages/db/prisma/.env.example
Executable file
@@ -0,0 +1 @@
|
||||
DATABASE_URL=postgresql://postgres:mypassword@localhost:5432/dentalapp
|
||||
505
packages/db/prisma/migrations/20260114221729/migration.sql
Executable file
505
packages/db/prisma/migrations/20260114221729/migration.sql
Executable file
@@ -0,0 +1,505 @@
|
||||
-- CreateEnum
|
||||
CREATE TYPE "PatientStatus" AS ENUM ('ACTIVE', 'INACTIVE', 'UNKNOWN');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ProcedureSource" AS ENUM ('COMBO', 'MANUAL');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ClaimStatus" AS ENUM ('PENDING', 'APPROVED', 'CANCELLED', 'REVIEW', 'VOID');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "MissingTeethStatus" AS ENUM ('No_missing', 'endentulous', 'Yes_missing');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "ServiceLineStatus" AS ENUM ('PENDING', 'PARTIALLY_PAID', 'PAID', 'UNPAID', 'ADJUSTED', 'OVERPAID', 'DENIED');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "PdfTitleKey" AS ENUM ('INSURANCE_CLAIM', 'INSURANCE_CLAIM_PREAUTH', 'ELIGIBILITY_STATUS', 'CLAIM_STATUS', 'OTHER');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "PaymentStatus" AS ENUM ('PENDING', 'PARTIALLY_PAID', 'PAID', 'OVERPAID', 'DENIED', 'VOID');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "PaymentMethod" AS ENUM ('EFT', 'CHECK', 'CASH', 'CARD', 'OTHER');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "NotificationTypes" AS ENUM ('BACKUP', 'CLAIM', 'PAYMENT', 'ETC');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "CommunicationChannel" AS ENUM ('sms', 'voice');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "CommunicationDirection" AS ENUM ('outbound', 'inbound');
|
||||
|
||||
-- CreateEnum
|
||||
CREATE TYPE "CommunicationStatus" AS ENUM ('queued', 'sent', 'delivered', 'failed', 'completed', 'busy', 'no_answer');
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "User" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"username" TEXT NOT NULL,
|
||||
"password" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Patient" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"firstName" TEXT NOT NULL,
|
||||
"lastName" TEXT NOT NULL,
|
||||
"dateOfBirth" DATE NOT NULL,
|
||||
"gender" TEXT NOT NULL,
|
||||
"phone" TEXT NOT NULL,
|
||||
"email" TEXT,
|
||||
"address" TEXT,
|
||||
"city" TEXT,
|
||||
"zipCode" TEXT,
|
||||
"insuranceProvider" TEXT,
|
||||
"insuranceId" TEXT,
|
||||
"groupNumber" TEXT,
|
||||
"policyHolder" TEXT,
|
||||
"allergies" TEXT,
|
||||
"medicalConditions" TEXT,
|
||||
"status" "PatientStatus" NOT NULL DEFAULT 'UNKNOWN',
|
||||
"userId" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "Patient_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Appointment" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"patientId" INTEGER NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"staffId" INTEGER NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"date" DATE NOT NULL,
|
||||
"startTime" TEXT NOT NULL,
|
||||
"endTime" TEXT NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"notes" TEXT,
|
||||
"status" TEXT NOT NULL DEFAULT 'scheduled',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"eligibilityStatus" "PatientStatus" NOT NULL DEFAULT 'UNKNOWN',
|
||||
|
||||
CONSTRAINT "Appointment_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Staff" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"email" TEXT,
|
||||
"role" TEXT NOT NULL,
|
||||
"phone" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "Staff_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "AppointmentProcedure" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"appointmentId" INTEGER NOT NULL,
|
||||
"patientId" INTEGER NOT NULL,
|
||||
"procedureCode" TEXT NOT NULL,
|
||||
"procedureLabel" TEXT,
|
||||
"fee" DECIMAL(10,2),
|
||||
"category" TEXT,
|
||||
"toothNumber" TEXT,
|
||||
"toothSurface" TEXT,
|
||||
"oralCavityArea" TEXT,
|
||||
"source" "ProcedureSource" NOT NULL DEFAULT 'MANUAL',
|
||||
"comboKey" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "AppointmentProcedure_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Claim" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"patientId" INTEGER NOT NULL,
|
||||
"appointmentId" INTEGER NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"staffId" INTEGER NOT NULL,
|
||||
"patientName" TEXT NOT NULL,
|
||||
"memberId" TEXT NOT NULL,
|
||||
"dateOfBirth" DATE NOT NULL,
|
||||
"remarks" TEXT NOT NULL,
|
||||
"missingTeethStatus" "MissingTeethStatus" NOT NULL DEFAULT 'No_missing',
|
||||
"missingTeeth" JSONB,
|
||||
"serviceDate" TIMESTAMP(3) NOT NULL,
|
||||
"insuranceProvider" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
"status" "ClaimStatus" NOT NULL DEFAULT 'PENDING',
|
||||
|
||||
CONSTRAINT "Claim_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ServiceLine" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"claimId" INTEGER,
|
||||
"paymentId" INTEGER,
|
||||
"procedureCode" TEXT NOT NULL,
|
||||
"procedureDate" DATE NOT NULL,
|
||||
"oralCavityArea" TEXT,
|
||||
"toothNumber" TEXT,
|
||||
"toothSurface" TEXT,
|
||||
"totalBilled" DECIMAL(10,2) NOT NULL,
|
||||
"totalPaid" DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
"totalAdjusted" DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
"totalDue" DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
"status" "ServiceLineStatus" NOT NULL DEFAULT 'UNPAID',
|
||||
|
||||
CONSTRAINT "ServiceLine_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ClaimFile" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"claimId" INTEGER NOT NULL,
|
||||
"filename" TEXT NOT NULL,
|
||||
"mimeType" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "ClaimFile_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "InsuranceCredential" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"siteKey" TEXT NOT NULL,
|
||||
"username" TEXT NOT NULL,
|
||||
"password" TEXT NOT NULL,
|
||||
|
||||
CONSTRAINT "InsuranceCredential_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PdfGroup" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"title" TEXT NOT NULL,
|
||||
"titleKey" "PdfTitleKey" NOT NULL DEFAULT 'OTHER',
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"patientId" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "PdfGroup_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "PdfFile" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"filename" TEXT NOT NULL,
|
||||
"pdfData" BYTEA NOT NULL,
|
||||
"uploadedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"groupId" INTEGER NOT NULL,
|
||||
|
||||
CONSTRAINT "PdfFile_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Payment" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"claimId" INTEGER,
|
||||
"patientId" INTEGER NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"updatedById" INTEGER,
|
||||
"totalBilled" DECIMAL(10,2) NOT NULL,
|
||||
"totalPaid" DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
"totalAdjusted" DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
"totalDue" DECIMAL(10,2) NOT NULL,
|
||||
"status" "PaymentStatus" NOT NULL DEFAULT 'PENDING',
|
||||
"notes" TEXT,
|
||||
"icn" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "Payment_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "ServiceLineTransaction" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"paymentId" INTEGER NOT NULL,
|
||||
"serviceLineId" INTEGER NOT NULL,
|
||||
"transactionId" TEXT,
|
||||
"paidAmount" DECIMAL(10,2) NOT NULL,
|
||||
"adjustedAmount" DECIMAL(10,2) NOT NULL DEFAULT 0.00,
|
||||
"method" "PaymentMethod" NOT NULL,
|
||||
"receivedDate" TIMESTAMP(3) NOT NULL,
|
||||
"payerName" TEXT,
|
||||
"notes" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "ServiceLineTransaction_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "DatabaseBackup" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "DatabaseBackup_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "BackupDestination" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"path" TEXT NOT NULL,
|
||||
"isActive" BOOLEAN NOT NULL DEFAULT true,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "BackupDestination_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "Notification" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"type" "NotificationTypes" NOT NULL,
|
||||
"message" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"read" BOOLEAN NOT NULL DEFAULT false,
|
||||
|
||||
CONSTRAINT "Notification_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "CloudFolder" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"parentId" INTEGER,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "CloudFolder_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "CloudFile" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"mimeType" TEXT,
|
||||
"fileSize" BIGINT NOT NULL,
|
||||
"folderId" INTEGER,
|
||||
"isComplete" BOOLEAN NOT NULL DEFAULT false,
|
||||
"totalChunks" INTEGER,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
||||
|
||||
CONSTRAINT "CloudFile_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "CloudFileChunk" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"fileId" INTEGER NOT NULL,
|
||||
"seq" INTEGER NOT NULL,
|
||||
"data" BYTEA NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "CloudFileChunk_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "communications" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"patientId" INTEGER NOT NULL,
|
||||
"userId" INTEGER,
|
||||
"channel" "CommunicationChannel" NOT NULL,
|
||||
"direction" "CommunicationDirection" NOT NULL,
|
||||
"status" "CommunicationStatus" NOT NULL,
|
||||
"body" TEXT,
|
||||
"callDuration" INTEGER,
|
||||
"twilioSid" TEXT,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "communications_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Patient_insuranceId_idx" ON "Patient"("insuranceId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Patient_createdAt_idx" ON "Patient"("createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Appointment_patientId_idx" ON "Appointment"("patientId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Appointment_date_idx" ON "Appointment"("date");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "AppointmentProcedure_appointmentId_idx" ON "AppointmentProcedure"("appointmentId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "AppointmentProcedure_patientId_idx" ON "AppointmentProcedure"("patientId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "InsuranceCredential_userId_idx" ON "InsuranceCredential"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "InsuranceCredential_userId_siteKey_key" ON "InsuranceCredential"("userId", "siteKey");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "PdfGroup_patientId_idx" ON "PdfGroup"("patientId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "PdfGroup_titleKey_idx" ON "PdfGroup"("titleKey");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "PdfFile_groupId_idx" ON "PdfFile"("groupId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Payment_claimId_key" ON "Payment"("claimId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Payment_claimId_idx" ON "Payment"("claimId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Payment_patientId_idx" ON "Payment"("patientId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Payment_createdAt_idx" ON "Payment"("createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ServiceLineTransaction_paymentId_idx" ON "ServiceLineTransaction"("paymentId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "ServiceLineTransaction_serviceLineId_idx" ON "ServiceLineTransaction"("serviceLineId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "DatabaseBackup_userId_idx" ON "DatabaseBackup"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "DatabaseBackup_createdAt_idx" ON "DatabaseBackup"("createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Notification_userId_idx" ON "Notification"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "Notification_createdAt_idx" ON "Notification"("createdAt");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "CloudFolder_parentId_idx" ON "CloudFolder"("parentId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "CloudFolder_userId_parentId_name_key" ON "CloudFolder"("userId", "parentId", "name");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "CloudFile_folderId_idx" ON "CloudFile"("folderId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "CloudFileChunk_fileId_seq_idx" ON "CloudFileChunk"("fileId", "seq");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "CloudFileChunk_fileId_seq_key" ON "CloudFileChunk"("fileId", "seq");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Patient" ADD CONSTRAINT "Patient_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Appointment" ADD CONSTRAINT "Appointment_patientId_fkey" FOREIGN KEY ("patientId") REFERENCES "Patient"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Appointment" ADD CONSTRAINT "Appointment_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Appointment" ADD CONSTRAINT "Appointment_staffId_fkey" FOREIGN KEY ("staffId") REFERENCES "Staff"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Staff" ADD CONSTRAINT "Staff_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "AppointmentProcedure" ADD CONSTRAINT "AppointmentProcedure_appointmentId_fkey" FOREIGN KEY ("appointmentId") REFERENCES "Appointment"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "AppointmentProcedure" ADD CONSTRAINT "AppointmentProcedure_patientId_fkey" FOREIGN KEY ("patientId") REFERENCES "Patient"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Claim" ADD CONSTRAINT "Claim_patientId_fkey" FOREIGN KEY ("patientId") REFERENCES "Patient"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Claim" ADD CONSTRAINT "Claim_appointmentId_fkey" FOREIGN KEY ("appointmentId") REFERENCES "Appointment"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Claim" ADD CONSTRAINT "Claim_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Claim" ADD CONSTRAINT "Claim_staffId_fkey" FOREIGN KEY ("staffId") REFERENCES "Staff"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ServiceLine" ADD CONSTRAINT "ServiceLine_claimId_fkey" FOREIGN KEY ("claimId") REFERENCES "Claim"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ServiceLine" ADD CONSTRAINT "ServiceLine_paymentId_fkey" FOREIGN KEY ("paymentId") REFERENCES "Payment"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ClaimFile" ADD CONSTRAINT "ClaimFile_claimId_fkey" FOREIGN KEY ("claimId") REFERENCES "Claim"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "InsuranceCredential" ADD CONSTRAINT "InsuranceCredential_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PdfGroup" ADD CONSTRAINT "PdfGroup_patientId_fkey" FOREIGN KEY ("patientId") REFERENCES "Patient"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "PdfFile" ADD CONSTRAINT "PdfFile_groupId_fkey" FOREIGN KEY ("groupId") REFERENCES "PdfGroup"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Payment" ADD CONSTRAINT "Payment_claimId_fkey" FOREIGN KEY ("claimId") REFERENCES "Claim"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Payment" ADD CONSTRAINT "Payment_patientId_fkey" FOREIGN KEY ("patientId") REFERENCES "Patient"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Payment" ADD CONSTRAINT "Payment_updatedById_fkey" FOREIGN KEY ("updatedById") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ServiceLineTransaction" ADD CONSTRAINT "ServiceLineTransaction_paymentId_fkey" FOREIGN KEY ("paymentId") REFERENCES "Payment"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "ServiceLineTransaction" ADD CONSTRAINT "ServiceLineTransaction_serviceLineId_fkey" FOREIGN KEY ("serviceLineId") REFERENCES "ServiceLine"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "DatabaseBackup" ADD CONSTRAINT "DatabaseBackup_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "BackupDestination" ADD CONSTRAINT "BackupDestination_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "Notification" ADD CONSTRAINT "Notification_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "CloudFolder" ADD CONSTRAINT "CloudFolder_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "CloudFolder"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "CloudFolder" ADD CONSTRAINT "CloudFolder_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "CloudFile" ADD CONSTRAINT "CloudFile_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "CloudFile" ADD CONSTRAINT "CloudFile_folderId_fkey" FOREIGN KEY ("folderId") REFERENCES "CloudFolder"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "CloudFileChunk" ADD CONSTRAINT "CloudFileChunk_fileId_fkey" FOREIGN KEY ("fileId") REFERENCES "CloudFile"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "communications" ADD CONSTRAINT "communications_patientId_fkey" FOREIGN KEY ("patientId") REFERENCES "Patient"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "communications" ADD CONSTRAINT "communications_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
||||
@@ -0,0 +1,22 @@
|
||||
-- AlterTable
|
||||
ALTER TABLE "Appointment" ADD COLUMN "procedureCodeNotes" TEXT;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE "NpiProvider" (
|
||||
"id" SERIAL NOT NULL,
|
||||
"userId" INTEGER NOT NULL,
|
||||
"npiNumber" TEXT NOT NULL,
|
||||
"providerName" TEXT NOT NULL,
|
||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
CONSTRAINT "NpiProvider_pkey" PRIMARY KEY ("id")
|
||||
);
|
||||
|
||||
-- CreateIndex
|
||||
CREATE INDEX "NpiProvider_userId_idx" ON "NpiProvider"("userId");
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "NpiProvider_userId_npiNumber_key" ON "NpiProvider"("userId", "npiNumber");
|
||||
|
||||
-- AddForeignKey
|
||||
ALTER TABLE "NpiProvider" ADD CONSTRAINT "NpiProvider_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
3
packages/db/prisma/migrations/migration_lock.toml
Executable file
3
packages/db/prisma/migrations/migration_lock.toml
Executable 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"
|
||||
12
packages/db/prisma/prisma.config.ts
Executable file
12
packages/db/prisma/prisma.config.ts
Executable file
@@ -0,0 +1,12 @@
|
||||
import dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { defineConfig, env } from "prisma/config";
|
||||
|
||||
dotenv.config({ path: path.resolve(__dirname, ".env") });
|
||||
|
||||
export default defineConfig({
|
||||
schema: "schema.prisma",
|
||||
datasource: {
|
||||
url: env("DATABASE_URL"),
|
||||
},
|
||||
});
|
||||
506
packages/db/prisma/schema.prisma
Executable file
506
packages/db/prisma/schema.prisma
Executable file
@@ -0,0 +1,506 @@
|
||||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
|
||||
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
output = "../generated/prisma"
|
||||
}
|
||||
|
||||
generator zod {
|
||||
provider = "prisma-zod-generator"
|
||||
output = "../shared/" // Zod schemas will be generated here inside `db/shared`
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
}
|
||||
|
||||
model User {
|
||||
id Int @id @default(autoincrement())
|
||||
username String @unique
|
||||
password String
|
||||
patients Patient[]
|
||||
appointments Appointment[]
|
||||
staff Staff[]
|
||||
npiProviders NpiProvider[]
|
||||
claims Claim[]
|
||||
insuranceCredentials InsuranceCredential[]
|
||||
updatedPayments Payment[] @relation("PaymentUpdatedBy")
|
||||
backups DatabaseBackup[]
|
||||
backupDestinations BackupDestination[]
|
||||
notifications Notification[]
|
||||
cloudFolders CloudFolder[]
|
||||
cloudFiles CloudFile[]
|
||||
communications Communication[]
|
||||
}
|
||||
|
||||
model Patient {
|
||||
id Int @id @default(autoincrement())
|
||||
firstName String
|
||||
lastName String
|
||||
dateOfBirth DateTime @db.Date
|
||||
gender String
|
||||
phone String
|
||||
email String?
|
||||
address String?
|
||||
city String?
|
||||
zipCode String?
|
||||
insuranceProvider String?
|
||||
insuranceId String?
|
||||
groupNumber String?
|
||||
policyHolder String?
|
||||
allergies String?
|
||||
medicalConditions String?
|
||||
status PatientStatus @default(UNKNOWN)
|
||||
userId Int
|
||||
createdAt DateTime @default(now())
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
appointments Appointment[]
|
||||
procedures AppointmentProcedure[]
|
||||
claims Claim[]
|
||||
groups PdfGroup[]
|
||||
payment Payment[]
|
||||
communications Communication[]
|
||||
documents PatientDocument[]
|
||||
|
||||
@@index([insuranceId])
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
||||
enum PatientStatus {
|
||||
ACTIVE
|
||||
INACTIVE
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
model Appointment {
|
||||
id Int @id @default(autoincrement())
|
||||
patientId Int
|
||||
userId Int
|
||||
staffId Int
|
||||
title String
|
||||
date DateTime @db.Date
|
||||
startTime String // Store time as "hh:mm"
|
||||
endTime String // Store time as "hh:mm"
|
||||
type String // e.g., "checkup", "cleaning", "filling", etc.
|
||||
notes String?
|
||||
procedureCodeNotes String?
|
||||
status String @default("scheduled") // "scheduled", "completed", "cancelled", "no-show"
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
eligibilityStatus PatientStatus @default(UNKNOWN)
|
||||
|
||||
patient Patient @relation(fields: [patientId], references: [id], onDelete: Cascade)
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
staff Staff? @relation(fields: [staffId], references: [id])
|
||||
procedures AppointmentProcedure[]
|
||||
claims Claim[]
|
||||
|
||||
@@index([patientId])
|
||||
@@index([date])
|
||||
}
|
||||
|
||||
model Staff {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
name String
|
||||
email String?
|
||||
role String // e.g., "Dentist", "Hygienist", "Assistant"
|
||||
phone String?
|
||||
createdAt DateTime @default(now())
|
||||
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
appointments Appointment[]
|
||||
claims Claim[] @relation("ClaimStaff")
|
||||
}
|
||||
|
||||
model NpiProvider {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
npiNumber String
|
||||
providerName String
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([userId, npiNumber])
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
|
||||
enum ProcedureSource {
|
||||
COMBO
|
||||
MANUAL
|
||||
}
|
||||
|
||||
model AppointmentProcedure {
|
||||
id Int @id @default(autoincrement())
|
||||
appointmentId Int
|
||||
patientId Int
|
||||
|
||||
procedureCode String
|
||||
procedureLabel String?
|
||||
fee Decimal? @db.Decimal(10, 2)
|
||||
|
||||
category String?
|
||||
|
||||
toothNumber String?
|
||||
toothSurface String?
|
||||
oralCavityArea String?
|
||||
|
||||
source ProcedureSource @default(MANUAL)
|
||||
comboKey String?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
appointment Appointment @relation(fields: [appointmentId], references: [id], onDelete: Cascade)
|
||||
patient Patient @relation(fields: [patientId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([appointmentId])
|
||||
@@index([patientId])
|
||||
}
|
||||
|
||||
model Claim {
|
||||
id Int @id @default(autoincrement())
|
||||
patientId Int
|
||||
appointmentId Int
|
||||
userId Int
|
||||
staffId Int
|
||||
patientName String
|
||||
memberId String
|
||||
dateOfBirth DateTime @db.Date
|
||||
remarks String
|
||||
missingTeethStatus MissingTeethStatus @default(No_missing)
|
||||
missingTeeth Json? // { "T_14": "X", "T_G": "O", ... }
|
||||
serviceDate DateTime
|
||||
insuranceProvider String // e.g., "Delta MA"
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
status ClaimStatus @default(PENDING)
|
||||
claimNumber String?
|
||||
|
||||
patient Patient @relation(fields: [patientId], references: [id], onDelete: Cascade)
|
||||
appointment Appointment @relation(fields: [appointmentId], references: [id], onDelete: Cascade)
|
||||
user User? @relation(fields: [userId], references: [id])
|
||||
staff Staff? @relation("ClaimStaff", fields: [staffId], references: [id])
|
||||
|
||||
serviceLines ServiceLine[]
|
||||
claimFiles ClaimFile[]
|
||||
payment Payment?
|
||||
}
|
||||
|
||||
enum ClaimStatus {
|
||||
PENDING
|
||||
APPROVED
|
||||
CANCELLED
|
||||
REVIEW
|
||||
VOID
|
||||
}
|
||||
|
||||
enum MissingTeethStatus {
|
||||
No_missing
|
||||
endentulous
|
||||
Yes_missing
|
||||
}
|
||||
|
||||
model ServiceLine {
|
||||
id Int @id @default(autoincrement())
|
||||
claimId Int?
|
||||
paymentId Int?
|
||||
procedureCode String
|
||||
procedureDate DateTime @db.Date
|
||||
quad String?
|
||||
arch String?
|
||||
toothNumber String?
|
||||
toothSurface String?
|
||||
totalBilled Decimal @db.Decimal(10, 2)
|
||||
totalPaid Decimal @default(0.00) @db.Decimal(10, 2)
|
||||
totalAdjusted Decimal @default(0.00) @db.Decimal(10, 2)
|
||||
totalDue Decimal @default(0.00) @db.Decimal(10, 2)
|
||||
status ServiceLineStatus @default(UNPAID)
|
||||
|
||||
claim Claim? @relation(fields: [claimId], references: [id], onDelete: Cascade)
|
||||
payment Payment? @relation(fields: [paymentId], references: [id], onDelete: Cascade)
|
||||
|
||||
serviceLineTransactions ServiceLineTransaction[]
|
||||
}
|
||||
|
||||
enum ServiceLineStatus {
|
||||
PENDING
|
||||
PARTIALLY_PAID
|
||||
PAID
|
||||
UNPAID
|
||||
ADJUSTED
|
||||
OVERPAID
|
||||
DENIED
|
||||
}
|
||||
|
||||
model ClaimFile {
|
||||
id Int @id @default(autoincrement())
|
||||
claimId Int
|
||||
filename String
|
||||
mimeType String
|
||||
|
||||
claim Claim @relation(fields: [claimId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
|
||||
model InsuranceCredential {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
siteKey String
|
||||
username String
|
||||
password String
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([userId, siteKey])
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
model PdfGroup {
|
||||
id Int @id @default(autoincrement())
|
||||
title String
|
||||
titleKey PdfTitleKey @default(OTHER)
|
||||
createdAt DateTime @default(now())
|
||||
patientId Int
|
||||
patient Patient @relation(fields: [patientId], references: [id], onDelete: Cascade)
|
||||
pdfs PdfFile[]
|
||||
|
||||
@@index([patientId])
|
||||
@@index([titleKey])
|
||||
}
|
||||
|
||||
model PdfFile {
|
||||
id Int @id @default(autoincrement())
|
||||
filename String
|
||||
pdfData Bytes
|
||||
uploadedAt DateTime @default(now())
|
||||
groupId Int
|
||||
group PdfGroup @relation(fields: [groupId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([groupId])
|
||||
}
|
||||
|
||||
enum PdfTitleKey {
|
||||
INSURANCE_CLAIM
|
||||
INSURANCE_CLAIM_PREAUTH
|
||||
ELIGIBILITY_STATUS
|
||||
CLAIM_STATUS
|
||||
OTHER
|
||||
}
|
||||
|
||||
model Payment {
|
||||
id Int @id @default(autoincrement())
|
||||
claimId Int? @unique
|
||||
patientId Int
|
||||
userId Int
|
||||
updatedById Int?
|
||||
totalBilled Decimal @db.Decimal(10, 2)
|
||||
totalPaid Decimal @default(0.00) @db.Decimal(10, 2)
|
||||
totalAdjusted Decimal @default(0.00) @db.Decimal(10, 2)
|
||||
totalDue Decimal @db.Decimal(10, 2)
|
||||
status PaymentStatus @default(PENDING)
|
||||
notes String?
|
||||
icn String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
claim Claim? @relation(fields: [claimId], references: [id], onDelete: Cascade)
|
||||
patient Patient @relation(fields: [patientId], references: [id], onDelete: Cascade)
|
||||
updatedBy User? @relation("PaymentUpdatedBy", fields: [updatedById], references: [id])
|
||||
serviceLineTransactions ServiceLineTransaction[]
|
||||
serviceLines ServiceLine[]
|
||||
|
||||
@@index([claimId])
|
||||
@@index([patientId])
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
||||
model ServiceLineTransaction {
|
||||
id Int @id @default(autoincrement())
|
||||
paymentId Int
|
||||
serviceLineId Int
|
||||
transactionId String?
|
||||
paidAmount Decimal @db.Decimal(10, 2)
|
||||
adjustedAmount Decimal @default(0.00) @db.Decimal(10, 2)
|
||||
method PaymentMethod
|
||||
receivedDate DateTime
|
||||
payerName String?
|
||||
notes String?
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
payment Payment @relation(fields: [paymentId], references: [id], onDelete: Cascade)
|
||||
serviceLine ServiceLine @relation(fields: [serviceLineId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([paymentId])
|
||||
@@index([serviceLineId])
|
||||
}
|
||||
|
||||
enum PaymentStatus {
|
||||
PENDING
|
||||
PARTIALLY_PAID
|
||||
PAID
|
||||
OVERPAID
|
||||
DENIED
|
||||
VOID
|
||||
}
|
||||
|
||||
enum PaymentMethod {
|
||||
EFT
|
||||
CHECK
|
||||
CASH
|
||||
CARD
|
||||
OTHER
|
||||
}
|
||||
|
||||
// Database management page
|
||||
model DatabaseBackup {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId])
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
||||
model BackupDestination {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
path String
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
}
|
||||
|
||||
model Notification {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
type NotificationTypes
|
||||
message String
|
||||
createdAt DateTime @default(now())
|
||||
read Boolean @default(false)
|
||||
|
||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([userId])
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
||||
enum NotificationTypes {
|
||||
BACKUP
|
||||
CLAIM
|
||||
PAYMENT
|
||||
ETC
|
||||
}
|
||||
|
||||
model CloudFolder {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
name String
|
||||
parentId Int?
|
||||
parent CloudFolder? @relation("FolderChildren", fields: [parentId], references: [id], onDelete: Cascade)
|
||||
children CloudFolder[] @relation("FolderChildren")
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
files CloudFile[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([userId, parentId, name]) // prevents sibling folder name duplicates
|
||||
@@index([parentId])
|
||||
}
|
||||
|
||||
model CloudFile {
|
||||
id Int @id @default(autoincrement())
|
||||
userId Int
|
||||
name String
|
||||
mimeType String?
|
||||
fileSize BigInt @db.BigInt
|
||||
folderId Int? // optional: null => root
|
||||
isComplete Boolean @default(false) // upload completed?
|
||||
totalChunks Int? // optional: expected number of chunks
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
folder CloudFolder? @relation(fields: [folderId], references: [id], onDelete: SetNull)
|
||||
|
||||
chunks CloudFileChunk[]
|
||||
|
||||
@@index([folderId])
|
||||
}
|
||||
|
||||
model CloudFileChunk {
|
||||
id Int @id @default(autoincrement())
|
||||
fileId Int
|
||||
seq Int
|
||||
data Bytes
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
file CloudFile @relation(fields: [fileId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@unique([fileId, seq])
|
||||
@@index([fileId, seq])
|
||||
}
|
||||
|
||||
// patient-connection-
|
||||
enum CommunicationChannel {
|
||||
sms
|
||||
voice
|
||||
}
|
||||
|
||||
enum CommunicationDirection {
|
||||
outbound
|
||||
inbound
|
||||
}
|
||||
|
||||
enum CommunicationStatus {
|
||||
queued
|
||||
sent
|
||||
delivered
|
||||
failed
|
||||
completed
|
||||
busy
|
||||
no_answer
|
||||
}
|
||||
|
||||
model Communication {
|
||||
id Int @id @default(autoincrement())
|
||||
patientId Int
|
||||
userId Int?
|
||||
|
||||
channel CommunicationChannel
|
||||
direction CommunicationDirection
|
||||
status CommunicationStatus
|
||||
|
||||
body String?
|
||||
callDuration Int?
|
||||
twilioSid String?
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
|
||||
// Relations
|
||||
patient Patient @relation(fields: [patientId], references: [id])
|
||||
user User? @relation(fields: [userId], references: [id])
|
||||
|
||||
@@map("communications")
|
||||
}
|
||||
|
||||
model PatientDocument {
|
||||
id Int @id @default(autoincrement())
|
||||
patientId Int
|
||||
filename String
|
||||
originalName String
|
||||
mimeType String
|
||||
fileSize BigInt
|
||||
filePath String
|
||||
uploadedAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
patient Patient @relation(fields: [patientId], references: [id], onDelete: Cascade)
|
||||
|
||||
@@index([patientId])
|
||||
@@index([uploadedAt])
|
||||
}
|
||||
93
packages/db/prisma/seed.ts
Executable file
93
packages/db/prisma/seed.ts
Executable file
@@ -0,0 +1,93 @@
|
||||
import { PrismaClient } from "../generated/prisma";
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
function formatTime(date: Date): string {
|
||||
return date.toTimeString().slice(0, 5); // "HH:MM"
|
||||
}
|
||||
|
||||
async function main() {
|
||||
// Create multiple users
|
||||
const users = await prisma.user.createMany({
|
||||
data: [
|
||||
{ username: "admin2", password: "123456" },
|
||||
{ username: "bob", password: "123456" },
|
||||
],
|
||||
});
|
||||
|
||||
const createdUsers = await prisma.user.findMany();
|
||||
|
||||
// Creatin staff
|
||||
await prisma.staff.createMany({
|
||||
data: [
|
||||
{ name: "Dr. Kai Gao", role: "Doctor" },
|
||||
{ name: "Dr. Jane Smith", role: "Doctor" },
|
||||
],
|
||||
});
|
||||
|
||||
const staffMembers = await prisma.staff.findMany();
|
||||
|
||||
// Create multiple patients
|
||||
const patients = await prisma.patient.createMany({
|
||||
data: [
|
||||
{
|
||||
firstName: "Emily",
|
||||
lastName: "Clark",
|
||||
dateOfBirth: new Date("1985-06-15"),
|
||||
gender: "female",
|
||||
phone: "555-0001",
|
||||
email: "emily@example.com",
|
||||
address: "101 Apple Rd",
|
||||
city: "Newtown",
|
||||
zipCode: "10001",
|
||||
userId: createdUsers[0].id,
|
||||
},
|
||||
{
|
||||
firstName: "Michael",
|
||||
lastName: "Brown",
|
||||
dateOfBirth: new Date("1979-09-10"),
|
||||
gender: "male",
|
||||
phone: "555-0002",
|
||||
email: "michael@example.com",
|
||||
address: "202 Banana Ave",
|
||||
city: "Oldtown",
|
||||
zipCode: "10002",
|
||||
userId: createdUsers[1].id,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const createdPatients = await prisma.patient.findMany();
|
||||
|
||||
// Create multiple appointments
|
||||
await prisma.appointment.createMany({
|
||||
data: [
|
||||
{
|
||||
patientId: createdPatients[0].id,
|
||||
userId: createdUsers[0].id,
|
||||
title: "Initial Consultation",
|
||||
date: new Date("2025-06-01"),
|
||||
startTime: formatTime(new Date("2025-06-01T10:00:00")),
|
||||
endTime: formatTime(new Date("2025-06-01T10:30:00")),
|
||||
type: "consultation",
|
||||
},
|
||||
{
|
||||
patientId: createdPatients[1].id,
|
||||
userId: createdUsers[1].id,
|
||||
title: "Follow-up",
|
||||
date: new Date("2025-06-02"),
|
||||
startTime: formatTime(new Date("2025-06-01T10:00:00")),
|
||||
endTime: formatTime(new Date("2025-06-01T10:30:00")),
|
||||
type: "checkup",
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
main()
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(async () => {
|
||||
await prisma.$disconnect();
|
||||
});
|
||||
Reference in New Issue
Block a user