164 lines
5.2 KiB
Plaintext
164 lines
5.2 KiB
Plaintext
// prisma/schema.prisma
|
|
generator client {
|
|
provider = "prisma-client-js"
|
|
binaryTargets = ["native", "debian-openssl-3.0.x"]
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
enum IncomeFrequency {
|
|
weekly
|
|
biweekly
|
|
monthly
|
|
}
|
|
|
|
enum IncomeType {
|
|
regular
|
|
irregular
|
|
}
|
|
|
|
model User {
|
|
id String @id @default(uuid())
|
|
email String @unique
|
|
passwordHash String?
|
|
displayName String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
incomeFrequency IncomeFrequency @default(biweekly)
|
|
incomeType IncomeType @default(regular)
|
|
firstIncomeDate DateTime? // Track when user's first income was received for accurate pay period calculation
|
|
pendingScheduledIncome Boolean @default(false) // Flag set when user dismisses payday overlay, cleared when paycheck is entered
|
|
timezone String @default("America/New_York") // IANA timezone identifier for accurate date calculations
|
|
fixedExpensePercentage Int @default(40) // Irregular income: percent of new income to auto-fund fixed expenses
|
|
totalBudgetCents BigInt?
|
|
budgetPeriod String @default("monthly")
|
|
|
|
variableCategories VariableCategory[]
|
|
fixedPlans FixedPlan[]
|
|
incomes IncomeEvent[]
|
|
allocations Allocation[]
|
|
transactions Transaction[]
|
|
budgetSessions BudgetSession[]
|
|
}
|
|
|
|
model VariableCategory {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
name String
|
|
percent Int
|
|
priority Int @default(100)
|
|
isSavings Boolean @default(false)
|
|
balanceCents BigInt @default(0)
|
|
savingsTargetCents BigInt?
|
|
transactions Transaction[] @relation("TransactionCategory")
|
|
|
|
@@unique([userId, name])
|
|
@@index([userId, priority])
|
|
}
|
|
|
|
model FixedPlan {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
name String
|
|
cycleStart DateTime
|
|
dueOn DateTime
|
|
totalCents BigInt
|
|
fundedCents BigInt @default(0)
|
|
currentFundedCents BigInt @default(0)
|
|
priority Int @default(100)
|
|
fundingMode String @default("auto-on-deposit")
|
|
scheduleJson Json?
|
|
periodDays Int @default(30)
|
|
frequency String? // "one-time", "weekly", "biweekly", "monthly"
|
|
autoRollover Boolean @default(true)
|
|
lastRollover DateTime?
|
|
lastFundingDate DateTime?
|
|
lastFundedPayPeriod DateTime? // Track when plan was last funded in a pay period
|
|
needsFundingThisPeriod Boolean @default(true) // Simple flag to track funding needs
|
|
|
|
// Auto-payment fields
|
|
autoPayEnabled Boolean @default(false)
|
|
paymentSchedule Json? // { frequency: "monthly", dayOfMonth: 1, minFundingPercent: 100 }
|
|
nextPaymentDate DateTime?
|
|
lastAutoPayment DateTime?
|
|
maxRetryAttempts Int @default(3)
|
|
|
|
// Overdue tracking fields
|
|
isOverdue Boolean @default(false)
|
|
overdueAmount BigInt @default(0)
|
|
overdueSince DateTime?
|
|
|
|
transactions Transaction[] @relation("TransactionPlan")
|
|
|
|
@@unique([userId, name])
|
|
@@index([userId, dueOn])
|
|
@@index([userId, priority])
|
|
}
|
|
|
|
model IncomeEvent {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
postedAt DateTime
|
|
amountCents BigInt
|
|
note String?
|
|
isScheduledIncome Boolean @default(false) // True if this is a regular paycheck (vs bonus/extra income)
|
|
allocations Allocation[]
|
|
|
|
@@index([userId, postedAt])
|
|
}
|
|
|
|
model Allocation {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
createdAt DateTime @default(now())
|
|
kind String
|
|
toId String
|
|
amountCents BigInt
|
|
incomeId String?
|
|
income IncomeEvent? @relation(fields: [incomeId], references: [id])
|
|
}
|
|
|
|
model Transaction {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
occurredAt DateTime
|
|
kind String
|
|
categoryId String?
|
|
category VariableCategory? @relation("TransactionCategory", fields: [categoryId], references: [id], onDelete: SetNull)
|
|
planId String?
|
|
plan FixedPlan? @relation("TransactionPlan", fields: [planId], references: [id], onDelete: SetNull)
|
|
amountCents BigInt
|
|
note String?
|
|
receiptUrl String?
|
|
isAutoPayment Boolean @default(false)
|
|
isReconciled Boolean @default(false)
|
|
|
|
@@index([userId, occurredAt])
|
|
}
|
|
|
|
model BudgetSession {
|
|
id String @id @default(uuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
periodStart DateTime
|
|
periodEnd DateTime
|
|
totalBudgetCents BigInt
|
|
allocatedCents BigInt @default(0)
|
|
fundedCents BigInt @default(0)
|
|
availableCents BigInt @default(0)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@unique([userId, periodStart])
|
|
@@index([userId, periodStart])
|
|
}
|