Files
SkyMoney/api/prisma/schema.prisma

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])
}