Files
Aseret_Bank/backend/prisma/schema.prisma
2026-02-09 21:51:31 -08:00

1006 lines
22 KiB
Plaintext

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// Core Entities
model User {
id String @id @default(uuid())
email String @unique
passwordHash String
firstName String?
lastName String?
phone String?
role UserRole @default(CUSTOMER)
isActive Boolean @default(true)
emailVerified Boolean @default(false)
lastLogin DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
customer Customer?
employee Employee?
sessions Session[]
auditLogs AuditLog[]
@@index([email])
@@index([role])
@@index([isActive])
@@index([createdAt])
}
enum UserRole {
CUSTOMER
LOAN_OFFICER
UNDERWRITER
SERVICING
ADMIN
FINANCIAL_OPERATIONS
COMPLIANCE
}
model Session {
id String @id @default(uuid())
userId String
token String @unique
refreshToken String? @unique
expiresAt DateTime
ipAddress String?
userAgent String?
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([token])
}
model Customer {
id String @id @default(uuid())
userId String? @unique
customerType CustomerType
firstName String?
lastName String?
businessName String?
taxId String? @unique
dateOfBirth DateTime?
email String
phone String?
address Json?
kycStatus KYCStatus @default(PENDING)
kycCompletedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
user User? @relation(fields: [userId], references: [id], onDelete: Cascade)
accounts Account[]
applications Application[]
interactions Interaction[]
creditProfiles CreditProfile[]
@@index([email])
@@index([customerType])
@@index([kycStatus])
}
enum CustomerType {
INDIVIDUAL
BUSINESS
}
enum KYCStatus {
PENDING
IN_PROGRESS
VERIFIED
REJECTED
}
model Account {
id String @id @default(uuid())
customerId String
accountNumber String @unique
accountType AccountType
status AccountStatus @default(ACTIVE)
balance Decimal @default(0) @db.Decimal(15, 2)
currency String @default("USD")
openedAt DateTime @default(now())
closedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
loans Loan[]
transactions Transaction[]
@@index([customerId])
@@index([accountNumber])
@@index([accountType])
@@index([status])
@@index([openedAt])
}
enum AccountType {
CHECKING
SAVINGS
LOAN
ESCROW
}
enum AccountStatus {
ACTIVE
INACTIVE
CLOSED
FROZEN
}
model Loan {
id String @id @default(uuid())
accountId String
applicationId String? @unique
loanNumber String @unique
productType LoanProductType
status LoanStatus @default(PENDING)
principalAmount Decimal @db.Decimal(15, 2)
interestRate Decimal @db.Decimal(5, 4)
termMonths Int
paymentFrequency PaymentFrequency @default(MONTHLY)
originationDate DateTime?
firstPaymentDate DateTime?
maturityDate DateTime?
currentBalance Decimal @default(0) @db.Decimal(15, 2)
totalPaid Decimal @default(0) @db.Decimal(15, 2)
nextPaymentDate DateTime?
nextPaymentAmount Decimal? @db.Decimal(15, 2)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
application Application? @relation(fields: [applicationId], references: [id])
transactions Transaction[]
paymentSchedule PaymentSchedule[]
escrowAccounts EscrowAccount[]
delinquencies Delinquency[]
workouts Workout[]
collateral Collateral[]
riskScores RiskScore[]
valuations Valuation[]
tokens Token[]
participations Participation[]
@@index([accountId])
@@index([loanNumber])
@@index([status])
@@index([productType])
@@index([originationDate])
@@index([maturityDate])
@@index([nextPaymentDate])
}
enum LoanProductType {
CONSUMER_PERSONAL
CONSUMER_SECURED
CONSUMER_UNSECURED
COMMERCIAL_WORKING_CAPITAL
COMMERCIAL_BRIDGE
COMMERCIAL_EQUIPMENT
RECEIVABLES_FINANCING
EQUIPMENT_FINANCING
}
enum LoanStatus {
PENDING
UNDERWRITING
APPROVED
FUNDED
SERVICING
DELINQUENT
DEFAULTED
PAID_OFF
CHARGED_OFF
CANCELLED
}
enum PaymentFrequency {
WEEKLY
BIWEEKLY
MONTHLY
QUARTERLY
ANNUALLY
}
model Transaction {
id String @id @default(uuid())
accountId String
loanId String?
transactionType TransactionType
amount Decimal @db.Decimal(15, 2)
balance Decimal @db.Decimal(15, 2)
description String?
referenceNumber String?
status TransactionStatus @default(PENDING)
postedAt DateTime?
createdAt DateTime @default(now())
// Relations
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
loan Loan? @relation(fields: [loanId], references: [id])
@@index([accountId])
@@index([loanId])
@@index([transactionType])
@@index([status])
@@index([createdAt])
@@index([postedAt])
@@index([referenceNumber])
@@index([accountId, createdAt])
}
enum TransactionType {
DEPOSIT
WITHDRAWAL
PAYMENT
INTEREST
FEE
REFUND
ADJUSTMENT
TRANSFER
}
enum TransactionStatus {
PENDING
PROCESSING
COMPLETED
FAILED
CANCELLED
}
model Application {
id String @id @default(uuid())
customerId String
applicationType LoanProductType
requestedAmount Decimal @db.Decimal(15, 2)
purpose String?
status ApplicationStatus @default(DRAFT)
submittedAt DateTime?
decisionDate DateTime?
decision ApplicationDecision?
decisionReason String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
loan Loan?
workflows Workflow[]
creditPulls CreditPull[]
documents Document[]
complianceTokens ComplianceToken[]
@@index([customerId])
@@index([status])
@@index([applicationType])
@@index([submittedAt])
@@index([decisionDate])
@@index([status, submittedAt])
}
enum ApplicationStatus {
DRAFT
SUBMITTED
UNDER_REVIEW
APPROVED
DENIED
WITHDRAWN
EXPIRED
}
enum ApplicationDecision {
APPROVED
DENIED
REFERRED
COUNTEROFFER
}
model Workflow {
id String @id @default(uuid())
applicationId String
workflowType WorkflowType
status WorkflowStatus @default(PENDING)
currentStep Int @default(0)
startedAt DateTime @default(now())
completedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)
tasks Task[]
@@index([applicationId])
@@index([status])
}
enum WorkflowType {
ORIGINATION
UNDERWRITING
APPROVAL
DOCUMENTATION
FUNDING
}
enum WorkflowStatus {
PENDING
IN_PROGRESS
COMPLETED
CANCELLED
FAILED
}
model Task {
id String @id @default(uuid())
workflowId String
title String
description String?
status TaskStatus @default(PENDING)
assignedTo String?
dueDate DateTime?
completedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
workflow Workflow @relation(fields: [workflowId], references: [id], onDelete: Cascade)
@@index([workflowId])
@@index([assignedTo])
@@index([status])
}
enum TaskStatus {
PENDING
IN_PROGRESS
COMPLETED
CANCELLED
}
model Document {
id String @id @default(uuid())
applicationId String?
loanId String?
documentType DocumentType
fileName String
filePath String
fileSize Int
mimeType String
uploadedBy String
status DocumentStatus @default(PENDING)
verifiedAt DateTime?
createdAt DateTime @default(now())
// Relations
application Application? @relation(fields: [applicationId], references: [id], onDelete: Cascade)
@@index([applicationId])
@@index([loanId])
@@index([documentType])
}
enum DocumentType {
IDENTIFICATION
INCOME_VERIFICATION
BANK_STATEMENT
TAX_RETURN
BUSINESS_LICENSE
FINANCIAL_STATEMENT
COLLATERAL_DOCUMENT
LOAN_AGREEMENT
DISCLOSURE
OTHER
}
enum DocumentStatus {
PENDING
VERIFIED
REJECTED
EXPIRED
}
// Servicing Entities
model EscrowAccount {
id String @id @default(uuid())
loanId String
escrowType EscrowType
balance Decimal @default(0) @db.Decimal(15, 2)
monthlyPayment Decimal @db.Decimal(15, 2)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
loan Loan @relation(fields: [loanId], references: [id], onDelete: Cascade)
disbursements EscrowDisbursement[]
@@index([loanId])
}
enum EscrowType {
TAXES
INSURANCE
PMI
OTHER
}
model EscrowDisbursement {
id String @id @default(uuid())
escrowAccountId String
amount Decimal @db.Decimal(15, 2)
payee String
description String?
disbursedAt DateTime @default(now())
status DisbursementStatus @default(PENDING)
// Relations
escrowAccount EscrowAccount @relation(fields: [escrowAccountId], references: [id], onDelete: Cascade)
@@index([escrowAccountId])
}
enum DisbursementStatus {
PENDING
PROCESSED
FAILED
}
model Delinquency {
id String @id @default(uuid())
loanId String
daysPastDue Int
status DelinquencyStatus
firstDelinquentDate DateTime
resolvedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
loan Loan @relation(fields: [loanId], references: [id], onDelete: Cascade)
collections Collection[]
@@index([loanId])
@@index([status])
}
enum DelinquencyStatus {
CURRENT
DELINQUENT_30
DELINQUENT_60
DELINQUENT_90
DELINQUENT_120_PLUS
RESOLVED
}
model Collection {
id String @id @default(uuid())
delinquencyId String
actionType CollectionActionType
notes String?
nextActionDate DateTime?
createdAt DateTime @default(now())
// Relations
delinquency Delinquency @relation(fields: [delinquencyId], references: [id], onDelete: Cascade)
@@index([delinquencyId])
}
enum CollectionActionType {
CALL
EMAIL
LETTER
PAYMENT_PLAN
FORBEARANCE
CHARGE_OFF
}
model Workout {
id String @id @default(uuid())
loanId String
workoutType WorkoutType
status WorkoutStatus @default(PENDING)
terms Json?
effectiveDate DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
loan Loan @relation(fields: [loanId], references: [id], onDelete: Cascade)
@@index([loanId])
@@index([status])
}
enum WorkoutType {
MODIFICATION
FORBEARANCE
SHORT_SALE
DEED_IN_LIEU
}
enum WorkoutStatus {
PENDING
APPROVED
ACTIVE
COMPLETED
REJECTED
}
model Collateral {
id String @id @default(uuid())
loanId String
collateralType CollateralType
description String
value Decimal @db.Decimal(15, 2)
location String?
lienPosition Int?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
loan Loan @relation(fields: [loanId], references: [id], onDelete: Cascade)
tokens CollateralToken[]
@@index([loanId])
}
enum CollateralType {
REAL_ESTATE
VEHICLE
EQUIPMENT
INVENTORY
RECEIVABLES
OTHER
}
model PaymentSchedule {
id String @id @default(uuid())
loanId String
paymentNumber Int
dueDate DateTime
principal Decimal @db.Decimal(15, 2)
interest Decimal @db.Decimal(15, 2)
total Decimal @db.Decimal(15, 2)
status PaymentStatus @default(PENDING)
paidAt DateTime?
createdAt DateTime @default(now())
// Relations
loan Loan @relation(fields: [loanId], references: [id], onDelete: Cascade)
@@index([loanId])
@@index([dueDate])
@@index([status])
}
enum PaymentStatus {
PENDING
PAID
PARTIAL
MISSED
SKIPPED
}
// Compliance Entities
model RegulatoryReport {
id String @id @default(uuid())
reportType ReportType
reportingPeriod DateTime
status ReportStatus @default(DRAFT)
submittedAt DateTime?
data Json
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([reportType])
@@index([reportingPeriod])
}
enum ReportType {
DFPI_ANNUAL
HMDA
MORTGAGE_CALL_REPORT
STATE_SPECIFIC
}
enum ReportStatus {
DRAFT
SUBMITTED
ACCEPTED
REJECTED
}
model Disclosure {
id String @id @default(uuid())
applicationId String?
loanId String?
disclosureType DisclosureType
content Json
deliveredAt DateTime?
acknowledgedAt DateTime?
createdAt DateTime @default(now())
@@index([applicationId])
@@index([loanId])
@@index([disclosureType])
}
enum DisclosureType {
LOAN_ESTIMATE
CLOSING_DISCLOSURE
TILA
RESPA
STATE_SPECIFIC
}
model ComplianceCheck {
id String @id @default(uuid())
entityType String
entityId String
checkType String
passed Boolean
details Json?
createdAt DateTime @default(now())
@@index([entityType, entityId])
}
model AuditLog {
id String @id @default(uuid())
userId String?
action String
entityType String?
entityId String?
changes Json?
ipAddress String?
userAgent String?
createdAt DateTime @default(now())
// Relations
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
@@index([userId])
@@index([entityType, entityId])
@@index([createdAt])
}
model AdverseAction {
id String @id @default(uuid())
applicationId String
reason String
noticeSentAt DateTime?
createdAt DateTime @default(now())
@@index([applicationId])
}
// Risk Entities
model RiskScore {
id String @id @default(uuid())
loanId String
scoreType ScoreType
score Decimal @db.Decimal(5, 2)
factors Json?
calculatedAt DateTime @default(now())
// Relations
loan Loan @relation(fields: [loanId], references: [id], onDelete: Cascade)
@@index([loanId])
@@index([scoreType])
}
enum ScoreType {
CREDIT
DEFAULT_RISK
PREPAYMENT_RISK
FRAUD
}
model CreditPull {
id String @id @default(uuid())
applicationId String
bureau CreditBureau
creditScore Int?
reportData Json?
pulledAt DateTime @default(now())
// Relations
application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)
@@index([applicationId])
@@index([bureau])
}
enum CreditBureau {
EXPERIAN
EQUIFAX
TRANSUNION
}
model Valuation {
id String @id @default(uuid())
loanId String
valuationType ValuationType
value Decimal @db.Decimal(15, 2)
source String
effectiveDate DateTime
createdAt DateTime @default(now())
// Relations
loan Loan @relation(fields: [loanId], references: [id], onDelete: Cascade)
@@index([loanId])
}
enum ValuationType {
AVM
APPRAISAL
MANUAL
}
// Funds Entities
model Fund {
id String @id @default(uuid())
fundName String @unique
fundType FundType
balance Decimal @default(0) @db.Decimal(15, 2)
status FundStatus @default(ACTIVE)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
participations Participation[]
@@index([fundType])
}
enum FundType {
WAREHOUSE_LINE
INVESTOR_FUND
OPERATING
}
enum FundStatus {
ACTIVE
INACTIVE
CLOSED
}
model Participation {
id String @id @default(uuid())
loanId String
fundId String?
participationType ParticipationType
percentage Decimal @db.Decimal(5, 4)
amount Decimal @db.Decimal(15, 2)
status ParticipationStatus @default(ACTIVE)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
loan Loan @relation(fields: [loanId], references: [id], onDelete: Cascade)
fund Fund? @relation(fields: [fundId], references: [id])
tokens ParticipationToken[]
@@index([loanId])
@@index([fundId])
}
enum ParticipationType {
SYNDICATION
PARTICIPATION
ASSIGNMENT
}
enum ParticipationStatus {
PENDING
ACTIVE
SOLD
TERMINATED
}
// Tokenization Entities
model Token {
id String @id @default(uuid())
loanId String?
tokenType TokenType
tokenAddress String? @unique
tokenId String?
blockchain String
metadata Json?
createdAt DateTime @default(now())
// Relations
loan Loan? @relation(fields: [loanId], references: [id], onDelete: Cascade)
transactions TokenTransaction[]
holders TokenHolder[]
@@index([loanId])
@@index([tokenAddress])
@@index([tokenType])
}
enum TokenType {
LOAN_RECORD
PARTICIPATION
COLLATERAL
RECEIVABLE
COMPLIANCE
PAYMENT
}
model TokenTransaction {
id String @id @default(uuid())
tokenId String
txHash String @unique
fromAddress String?
toAddress String?
amount Decimal? @db.Decimal(15, 2)
status TransactionStatus @default(PENDING)
blockNumber BigInt?
confirmedAt DateTime?
createdAt DateTime @default(now())
// Relations
token Token @relation(fields: [tokenId], references: [id], onDelete: Cascade)
@@index([tokenId])
@@index([txHash])
}
model TokenHolder {
id String @id @default(uuid())
tokenId String
address String
balance Decimal @db.Decimal(15, 2)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
token Token @relation(fields: [tokenId], references: [id], onDelete: Cascade)
@@index([tokenId])
@@index([address])
}
model SmartContract {
id String @id @default(uuid())
contractName String
contractAddress String @unique
blockchain String
abi Json
version String
deployedAt DateTime @default(now())
@@index([contractAddress])
}
model CollateralToken {
id String @id @default(uuid())
collateralId String
tokenAddress String @unique
blockchain String
createdAt DateTime @default(now())
// Relations
collateral Collateral @relation(fields: [collateralId], references: [id], onDelete: Cascade)
@@index([collateralId])
@@index([tokenAddress])
}
model ParticipationToken {
id String @id @default(uuid())
participationId String
tokenAddress String @unique
blockchain String
createdAt DateTime @default(now())
// Relations
participation Participation @relation(fields: [participationId], references: [id], onDelete: Cascade)
@@index([participationId])
@@index([tokenAddress])
}
model ReceivableToken {
id String @id @default(uuid())
receivableId String
tokenAddress String @unique
blockchain String
createdAt DateTime @default(now())
@@index([receivableId])
@@index([tokenAddress])
}
model ComplianceToken {
id String @id @default(uuid())
applicationId String
eventType String
tokenAddress String @unique
blockchain String
data Json?
createdAt DateTime @default(now())
// Relations
application Application @relation(fields: [applicationId], references: [id], onDelete: Cascade)
@@index([applicationId])
@@index([tokenAddress])
}
// Additional entities
model Employee {
id String @id @default(uuid())
userId String @unique
employeeId String @unique
department String?
title String?
hireDate DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relations
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([employeeId])
}
model Interaction {
id String @id @default(uuid())
customerId String
interactionType InteractionType
subject String?
notes String?
createdBy String
createdAt DateTime @default(now())
// Relations
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
@@index([customerId])
@@index([createdAt])
}
enum InteractionType {
CALL
EMAIL
MEETING
NOTE
DOCUMENT
}
model CreditProfile {
id String @id @default(uuid())
customerId String
creditScore Int?
creditBureau CreditBureau?
reportData Json?
lastUpdated DateTime @default(now())
createdAt DateTime @default(now())
// Relations
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
@@index([customerId])
}