Category: - Add categoryColumn to NormalizerConfig and NormalizedRow - Map 'Category' column for Discover CC profile - Write category to Transaction on upload Budget rules: - Add BudgetRule model (userId, budgetId, pattern) - API: GET/POST /api/budget-rules, DELETE /api/budget-rules/:id - Apply rules during upload (first case-insensitive match wins) - Budgets page fetches and passes rules per budget - BudgetCard 'Rules' menu item opens BudgetRulesDialog for add/delete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
129 lines
3.3 KiB
Plaintext
129 lines
3.3 KiB
Plaintext
generator client {
|
|
provider = "prisma-client"
|
|
output = "../src/generated/prisma"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "postgresql"
|
|
}
|
|
|
|
model User {
|
|
id String @id @default(cuid())
|
|
email String @unique
|
|
passwordHash String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
accounts Account[]
|
|
budgets Budget[]
|
|
budgetRules BudgetRule[]
|
|
}
|
|
|
|
enum AccountType {
|
|
BANK
|
|
CREDIT_CARD
|
|
}
|
|
|
|
model Account {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
name String
|
|
institution String?
|
|
type AccountType
|
|
currency String @default("USD")
|
|
currentBalanceCents Int @default(0)
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
transactions Transaction[]
|
|
uploads CsvUpload[]
|
|
|
|
@@index([userId])
|
|
}
|
|
|
|
enum TransactionType {
|
|
DEBIT
|
|
CREDIT
|
|
}
|
|
|
|
model Transaction {
|
|
id String @id @default(cuid())
|
|
accountId String
|
|
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
|
|
uploadId String?
|
|
upload CsvUpload? @relation(fields: [uploadId], references: [id])
|
|
budgetId String?
|
|
budget Budget? @relation(fields: [budgetId], references: [id], onDelete: SetNull)
|
|
date DateTime
|
|
description String
|
|
amountCents Int
|
|
type TransactionType
|
|
category String?
|
|
notes String?
|
|
dedupeHash String
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@unique([dedupeHash])
|
|
@@index([accountId, date])
|
|
@@index([date])
|
|
@@index([budgetId])
|
|
}
|
|
|
|
model Budget {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
name String
|
|
limitCents Int?
|
|
color String?
|
|
isActive Boolean @default(true)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
transactions Transaction[]
|
|
rules BudgetRule[]
|
|
|
|
@@index([userId])
|
|
}
|
|
|
|
model BudgetRule {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
budgetId String
|
|
budget Budget @relation(fields: [budgetId], references: [id], onDelete: Cascade)
|
|
pattern String
|
|
createdAt DateTime @default(now())
|
|
|
|
@@index([userId])
|
|
@@index([budgetId])
|
|
}
|
|
|
|
model CsvUpload {
|
|
id String @id @default(cuid())
|
|
accountId String
|
|
account Account @relation(fields: [accountId], references: [id])
|
|
fileName String
|
|
rowCount Int
|
|
importedCount Int
|
|
skippedCount Int
|
|
status String
|
|
errorMessage String?
|
|
uploadedAt DateTime @default(now())
|
|
transactions Transaction[]
|
|
|
|
@@index([accountId])
|
|
}
|
|
|
|
model BalanceSnapshot {
|
|
id String @id @default(cuid())
|
|
accountId String
|
|
year Int
|
|
month Int
|
|
balanceCents Int
|
|
computedAt DateTime @default(now())
|
|
|
|
@@unique([accountId, year, month])
|
|
@@index([year, month])
|
|
}
|