Files
gutscheintracker/app/api/households/route.ts
T

81 lines
4.0 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { getDb } from "@/lib/db";
import { getViewer } from "@/lib/viewer";
function forbidden() {
return NextResponse.json({ error: "forbidden" }, { status: 403 });
}
/** Alle Haushalte mit Mitgliederzahl (nur Server-Admin). */
export async function GET() {
const viewer = await getViewer();
if (!viewer || viewer.role !== "admin") return forbidden();
const db = getDb();
const households = await db.household.findMany({
orderBy: { name: "asc" },
include: { _count: { select: { members: true, vouchers: true } }, members: { include: { user: true } } },
});
return NextResponse.json(
households.map((h) => ({
id: h.id,
name: h.name,
createdAt: h.createdAt,
mitgliederAnzahl: h._count.members,
gutscheineAnzahl: h._count.vouchers,
mitglieder: h.members.map((m) => ({ userId: m.userId, name: m.user.name, email: m.user.email, rolle: m.role })),
}))
);
}
/** Haushalt anlegen, optional mit erstem Haushalts-Admin (muss unzugeordnet sein). */
export async function POST(req: NextRequest) {
const viewer = await getViewer();
if (!viewer || viewer.role !== "admin") return forbidden();
const body = await req.json().catch(() => ({}));
const name = typeof body.name === "string" ? body.name.trim() : "";
if (!name || name.length > 100) return NextResponse.json({ errors: ["name"] }, { status: 400 });
const db = getDb();
if (await db.household.findUnique({ where: { name } })) {
return NextResponse.json({ errors: ["name"], message: "Haushalt existiert bereits." }, { status: 409 });
}
const household = await db.household.create({ data: { name } });
if (body.adminUserId !== undefined && body.adminUserId !== null) {
const adminId = Number(body.adminUserId);
if (!Number.isInteger(adminId)) {
await db.household.delete({ where: { id: household.id } });
return NextResponse.json({ errors: ["adminUserId"] }, { status: 400 });
}
const candidate = await db.user.findUnique({ where: { id: adminId }, include: { membership: true } });
if (!candidate || candidate.membership) {
await db.household.delete({ where: { id: household.id } });
return NextResponse.json({ errors: ["adminUserId"], message: "Nutzer existiert nicht oder hat bereits einen Haushalt." }, { status: 400 });
}
await db.householdMember.create({ data: { householdId: household.id, userId: adminId, role: "admin" } });
}
return NextResponse.json({ ok: true, id: household.id }, { status: 201 });
}
/** Haushalt samt Bestand auflösen (nur Server-Admin). Private Daten bleiben erhalten. */
export async function DELETE(req: NextRequest) {
const viewer = await getViewer();
if (!viewer || viewer.role !== "admin") return forbidden();
const id = Number(req.nextUrl.searchParams.get("id"));
if (!Number.isInteger(id)) return NextResponse.json({ error: "not found" }, { status: 404 });
const db = getDb();
const household = await db.household.findUnique({ where: { id } });
if (!household) return NextResponse.json({ error: "not found" }, { status: 404 });
const voucherIds = (await db.voucher.findMany({ where: { householdId: id }, select: { id: true } })).map((v) => v.id);
const contactIds = (await db.contact.findMany({ where: { householdId: id }, select: { id: true } })).map((c) => c.id);
await db.$transaction([
db.notificationLog.deleteMany({ where: { rule: { voucher: { id: { in: voucherIds } } } } }),
db.reminderRule.deleteMany({ where: { voucherId: { in: voucherIds } } }),
db.voucherContact.deleteMany({ where: { OR: [{ voucherId: { in: voucherIds } }, { contactId: { in: contactIds } }] } }),
db.voucher.deleteMany({ where: { id: { in: voucherIds } } }),
db.contact.deleteMany({ where: { id: { in: contactIds } } }),
db.invite.deleteMany({ where: { householdId: id } }),
db.householdMember.deleteMany({ where: { householdId: id } }),
db.household.delete({ where: { id } }),
]);
return NextResponse.json({ ok: true });
}