// 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" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) username String @unique password String patients Patient[] appointments Appointment[] claims Claim[] insuranceCredentials InsuranceCredential[] } 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 String @default("active") userId Int createdAt DateTime @default(now()) user User @relation(fields: [userId], references: [id]) appointments Appointment[] claims Claim[] groups PdfGroup[] @@index([insuranceId]) @@index([createdAt]) } 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? status String @default("scheduled") // "scheduled", "completed", "cancelled", "no-show" createdAt DateTime @default(now()) patient Patient @relation(fields: [patientId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id]) staff Staff? @relation(fields: [staffId], references: [id]) claims Claim[] @@index([patientId]) @@index([date]) } model Staff { id Int @id @default(autoincrement()) name String email String? role String // e.g., "Dentist", "Hygienist", "Assistant" phone String? createdAt DateTime @default(now()) appointments Appointment[] claims Claim[] @relation("ClaimStaff") } 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 serviceDate DateTime insuranceProvider String // e.g., "Delta MA" createdAt DateTime @default(now()) updatedAt DateTime @updatedAt status ClaimStatus @default(PENDING) 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[] payment Payment? } enum ClaimStatus { PENDING APPROVED CANCELLED REVIEW } model ServiceLine { id Int @id @default(autoincrement()) claimId Int procedureCode String procedureDate DateTime @db.Date oralCavityArea String? toothNumber String? toothSurface String? billedAmount Float claim Claim @relation(fields: [claimId], references: [id], onDelete: Cascade) servicePayments ServiceLinePayment[] } 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 // e.g., "June Claim Docs", "Eligibility Set A" category PdfCategory createdAt DateTime @default(now()) patientId Int patient Patient @relation(fields: [patientId], references: [id], onDelete: Cascade) pdfs PdfFile[] @@index([patientId]) @@index([category]) } 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 PdfCategory { CLAIM ELIGIBILITY OTHER } model Payment { id Int @id @default(autoincrement()) patientId Int userId Int claimId Int @unique totalBilled Decimal @db.Decimal(10, 2) totalPaid Decimal @default(0.00) @db.Decimal(10, 2) totalDue Decimal @db.Decimal(10, 2) status PaymentStatus @default(PENDING) receivedDate DateTime? paymentMethod PaymentMethod? notes String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt claim Claim @relation(fields: [claimId], references: [id], onDelete: Cascade) transactions PaymentTransaction[] servicePayments ServiceLinePayment[] @@index([claimId]) } model PaymentTransaction { id Int @id @default(autoincrement()) paymentId Int amount Decimal @db.Decimal(10, 2) method PaymentMethod transactionId String? receivedDate DateTime payerName String? notes String? createdAt DateTime @default(now()) payment Payment @relation(fields: [paymentId], references: [id], onDelete: Cascade) @@index([paymentId]) } model ServiceLinePayment { id Int @id @default(autoincrement()) paymentId Int serviceLineId Int paidAmount Decimal @db.Decimal(10, 2) adjustedAmount Decimal @default(0.00) @db.Decimal(10, 2) notes String? 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 } enum PaymentMethod { EFT CHECK CASH CARD OTHER }