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

@@ -1,5 +1,6 @@
import { NextResponse } from "next/server";
import { getAppSettings, toApprovalThresholdNumber } from "@/lib/app-settings";
import { toCsvCell } from "@/lib/backup-csv";
import { canManageUsers } from "@/lib/domain";
import prisma from "@/lib/prisma";
@@ -26,6 +27,8 @@ const CSV_HEADERS = [
"email",
"role",
"approvalPreference",
"approvalPermissions",
"approvalThreshold",
"title",
"description",
"amount",
@@ -65,7 +68,8 @@ export async function GET() {
return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG duerfen CSV-Backups herunterladen." }, { status: 403 });
}
const [users, accountingPeriods, workingGroups, auditLogs] = await Promise.all([
const [appSettings, users, accountingPeriods, workingGroups, auditLogs] = await Promise.all([
getAppSettings(),
prisma.user.findMany({
include: {
workingGroup: {
@@ -96,7 +100,8 @@ export async function GET() {
username: true,
email: true,
role: true,
approvalPreference: true
approvalPreference: true,
approvalPermissions: true
},
orderBy: {
username: "asc"
@@ -157,6 +162,13 @@ export async function GET() {
const rows: CsvRow[] = [];
rows.push({
recordType: "settings",
id: appSettings.id,
approvalThreshold: toApprovalThresholdNumber(appSettings.approvalThreshold).toFixed(2),
createdAt: appSettings.createdAt.toISOString()
} as CsvRow);
for (const user of users) {
rows.push({
recordType: "user",
@@ -179,6 +191,8 @@ export async function GET() {
email: user.email,
role: user.role,
approvalPreference: user.approvalPreference ?? "",
approvalPermissions: user.approvalPermissions.join("|"),
approvalThreshold: "",
title: "",
description: "",
amount: "",
@@ -228,6 +242,8 @@ export async function GET() {
email: "",
role: "",
approvalPreference: "",
approvalPermissions: "",
approvalThreshold: "",
title: "",
description: "",
amount: "",
@@ -277,6 +293,8 @@ export async function GET() {
email: "",
role: "",
approvalPreference: "",
approvalPermissions: "",
approvalThreshold: "",
title: "",
description: "",
amount: "",
@@ -325,6 +343,8 @@ export async function GET() {
email: "",
role: "",
approvalPreference: "",
approvalPermissions: "",
approvalThreshold: "",
title: "",
description: "",
amount: "",
@@ -373,6 +393,8 @@ export async function GET() {
email: "",
role: "",
approvalPreference: "",
approvalPermissions: "",
approvalThreshold: "",
title: expense.title,
description: expense.description ?? "",
amount: Number(expense.amount).toFixed(2),
@@ -421,6 +443,8 @@ export async function GET() {
email: "",
role: "",
approvalPreference: "",
approvalPermissions: "",
approvalThreshold: "",
title: expense.title,
description: "",
amount: Number(expense.amount).toFixed(2),
@@ -473,6 +497,8 @@ export async function GET() {
email: "",
role: "",
approvalPreference: "",
approvalPermissions: "",
approvalThreshold: "",
title: "",
description: "",
amount: "",