Files
DentalManagementElogin/packages/db/prisma/schema.prisma
2025-11-25 00:08:30 +05:30

381 lines
10 KiB
Plaintext

// 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[]
claims Claim[]
insuranceCredentials InsuranceCredential[]
updatedPayments Payment[] @relation("PaymentUpdatedBy")
backups DatabaseBackup[]
notifications Notification[]
cloudFolders CloudFolder[]
cloudFiles CloudFile[]
}
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[]
claims Claim[]
groups PdfGroup[]
payment Payment[]
@@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?
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])
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 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)
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
oralCavityArea 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
}
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 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])
}