In der Nutzerverwaltung kannst du jetzt pro Konto die Rolle, die AG-Zuordnung und die Freigaberollen bearbeiten. Die feste 3er-Freigabelogik bleibt Vorstand A / Vorstand B / Finanz-AG, aber jetzt legst du über die Nutzer fest, wer diese Schritte autorisieren darf. Zusätzlich gibt es unter Nutzer anlegen eine eigene Insel für die Freigabe-Schwelle, und diese Schwelle wird jetzt auch wirklich überall verwendet: in der Erfassungslogik, in den Budgetkarten, im CSV-Backup/-Import und im Audit-Restore. Die Hauptänderungen sitzen in dashboard-shell.tsx, budget-column.tsx, route.ts, schema.prisma und route.ts.
All checks were successful
CI / build-and-deploy (push) Successful in 1m22s

Den Zeitraum-Bereich habe ich dabei gleich mit aufgeräumt: die Auswahl des aktuellen Haushalts ist breiter und sauberer angeordnet, und die Desktop-Nutzerverwaltung ist jetzt wirklich links Anlegen + Schwelle und rechts die Nutzerliste. Seed und Backup/Restore kennen die neuen Felder ebenfalls in seed.ts, route.ts und route.ts.
This commit is contained in:
Jan
2026-04-12 20:09:46 +02:00
parent 92d96ffa27
commit b202fc6c26
20 changed files with 1018 additions and 365 deletions

View File

@@ -30,20 +30,21 @@ enum ExpenseRecurrence {
}
model User {
id String @id @default(cuid())
name String
username String @unique
email String? @unique
passwordHash String @map("password_hash")
role Role
approvalPreference ApprovalType? @map("approval_preference")
workingGroupId String? @map("working_group_id")
workingGroup WorkingGroup? @relation(fields: [workingGroupId], references: [id], onDelete: SetNull)
createdExpenses Expense[] @relation("ExpenseCreator")
approvals Approval[]
auditLogs AuditLog[]
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
id String @id @default(cuid())
name String
username String @unique
email String? @unique
passwordHash String @map("password_hash")
role Role
approvalPreference ApprovalType? @map("approval_preference")
approvalPermissions ApprovalType[] @default([]) @map("approval_permissions")
workingGroupId String? @map("working_group_id")
workingGroup WorkingGroup? @relation(fields: [workingGroupId], references: [id], onDelete: SetNull)
createdExpenses Expense[] @relation("ExpenseCreator")
approvals Approval[]
auditLogs AuditLog[]
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("users")
}
@@ -62,6 +63,15 @@ model AccountingPeriod {
@@map("accounting_periods")
}
model AppSettings {
id String @id @default("global")
approvalThreshold Decimal @default(50) @db.Decimal(10, 2) @map("approval_threshold")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@map("app_settings")
}
model WorkingGroup {
id String @id @default(cuid())
name String @unique
@@ -75,42 +85,42 @@ model WorkingGroup {
}
model Budget {
id String @id @default(cuid())
id String @id @default(cuid())
name String
totalBudget Decimal @db.Decimal(10, 2) @map("total_budget")
colorCode String @map("color_code")
workingGroupId String @map("working_group_id")
periodId String @map("period_id")
workingGroup WorkingGroup @relation(fields: [workingGroupId], references: [id], onDelete: Cascade)
totalBudget Decimal @db.Decimal(10, 2) @map("total_budget")
colorCode String @map("color_code")
workingGroupId String @map("working_group_id")
periodId String @map("period_id")
workingGroup WorkingGroup @relation(fields: [workingGroupId], references: [id], onDelete: Cascade)
period AccountingPeriod @relation(fields: [periodId], references: [id], onDelete: Restrict)
expenses Expense[]
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
@@unique([workingGroupId, periodId, name])
@@map("budgets")
}
model Expense {
id String @id @default(cuid())
id String @id @default(cuid())
title String
description String?
amount Decimal @db.Decimal(10, 2)
creatorId String @map("creator_id")
agId String @map("ag_id")
budgetId String @map("budget_id")
periodId String @map("period_id")
approvalStatus ApprovalStatus @default(PENDING) @map("approval_status")
amount Decimal @db.Decimal(10, 2)
creatorId String @map("creator_id")
agId String @map("ag_id")
budgetId String @map("budget_id")
periodId String @map("period_id")
approvalStatus ApprovalStatus @default(PENDING) @map("approval_status")
recurrence ExpenseRecurrence @default(NONE)
paidAt DateTime? @map("paid_at")
documentedAt DateTime? @map("documented_at")
proofUrl String? @map("proof_url")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
creator User @relation("ExpenseCreator", fields: [creatorId], references: [id], onDelete: Restrict)
workingGroup WorkingGroup @relation(fields: [agId], references: [id], onDelete: Cascade)
budget Budget @relation(fields: [budgetId], references: [id], onDelete: Restrict)
period AccountingPeriod @relation(fields: [periodId], references: [id], onDelete: Restrict)
paidAt DateTime? @map("paid_at")
documentedAt DateTime? @map("documented_at")
proofUrl String? @map("proof_url")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
creator User @relation("ExpenseCreator", fields: [creatorId], references: [id], onDelete: Restrict)
workingGroup WorkingGroup @relation(fields: [agId], references: [id], onDelete: Cascade)
budget Budget @relation(fields: [budgetId], references: [id], onDelete: Restrict)
period AccountingPeriod @relation(fields: [periodId], references: [id], onDelete: Restrict)
approvals Approval[]
@@map("expenses")