fix(categories): POST/PATCH/DELETE mit Fallback bei fehlendem Schema
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 11m44s

This commit is contained in:
Pepe Ziberi
2026-05-21 08:51:54 +02:00
parent 0d0d9a7257
commit 3722a04091

View File

@@ -79,23 +79,38 @@ export async function POST(req: NextRequest) {
} }
// Check for duplicate name within tenant // Check for duplicate name within tenant
const existing = await (prisma as any).tenantCategory.findFirst({ try {
where: { tenantId, name: { equals: name, mode: 'insensitive' } }, const existing = await (prisma as any).tenantCategory.findFirst({
}) where: { tenantId, name: { equals: name, mode: 'insensitive' } },
if (existing) { })
return NextResponse.json({ error: 'Kategorie existiert bereits' }, { status: 409 }) if (existing) {
return NextResponse.json({ error: 'Kategorie existiert bereits' }, { status: 409 })
}
} catch (dbErr: any) {
console.error('tenantCategory.findFirst failed:', dbErr)
if (dbErr?.message?.includes('tenant_categories') || dbErr?.code === 'P2021') {
return NextResponse.json({ error: 'Datenbank nicht bereit Migration läuft möglicherweise noch' }, { status: 503 })
}
throw dbErr
} }
const category = await (prisma as any).tenantCategory.create({ try {
data: { const category = await (prisma as any).tenantCategory.create({
tenantId, data: {
name: name.trim(), tenantId,
sortOrder: sortOrder ?? 0, name: name.trim(),
icon: icon || null, sortOrder: sortOrder ?? 0,
}, icon: icon || null,
}) },
})
return NextResponse.json({ category }, { status: 201 }) return NextResponse.json({ category }, { status: 201 })
} catch (dbErr: any) {
console.error('tenantCategory.create failed:', dbErr)
if (dbErr?.message?.includes('tenant_categories') || dbErr?.code === 'P2021') {
return NextResponse.json({ error: 'Datenbank nicht bereit Migration läuft möglicherweise noch' }, { status: 503 })
}
throw dbErr
}
} catch (error) { } catch (error) {
console.error('Error creating tenant category:', error) console.error('Error creating tenant category:', error)
return NextResponse.json({ error: 'Interner Fehler' }, { status: 500 }) return NextResponse.json({ error: 'Interner Fehler' }, { status: 500 })
@@ -126,25 +141,41 @@ export async function PATCH(req: NextRequest) {
// If renaming, check for duplicates // If renaming, check for duplicates
if (name) { if (name) {
const existing = await (prisma as any).tenantCategory.findFirst({ try {
where: { const existing = await (prisma as any).tenantCategory.findFirst({
tenantId, where: {
name: { equals: name.trim(), mode: 'insensitive' }, tenantId,
id: { not: id }, name: { equals: name.trim(), mode: 'insensitive' },
}, id: { not: id },
}) },
if (existing) { })
return NextResponse.json({ error: 'Kategorie existiert bereits' }, { status: 409 }) if (existing) {
return NextResponse.json({ error: 'Kategorie existiert bereits' }, { status: 409 })
}
} catch (dbErr: any) {
console.error('tenantCategory.findFirst failed:', dbErr)
if (dbErr?.message?.includes('tenant_categories') || dbErr?.code === 'P2021') {
return NextResponse.json({ error: 'Datenbank nicht bereit Migration läuft möglicherweise noch' }, { status: 503 })
}
throw dbErr
} }
} }
const category = await (prisma as any).tenantCategory.updateMany({ try {
where: { id, tenantId }, const category = await (prisma as any).tenantCategory.updateMany({
data, where: { id, tenantId },
}) data,
})
if (category.count === 0) { if (category.count === 0) {
return NextResponse.json({ error: 'Kategorie nicht gefunden' }, { status: 404 }) return NextResponse.json({ error: 'Kategorie nicht gefunden' }, { status: 404 })
}
} catch (dbErr: any) {
console.error('tenantCategory.updateMany failed:', dbErr)
if (dbErr?.message?.includes('tenant_categories') || dbErr?.code === 'P2021') {
return NextResponse.json({ error: 'Datenbank nicht bereit Migration läuft möglicherweise noch' }, { status: 503 })
}
throw dbErr
} }
return NextResponse.json({ success: true }) return NextResponse.json({ success: true })
@@ -172,19 +203,36 @@ export async function DELETE(req: NextRequest) {
if (!id) return NextResponse.json({ error: 'id erforderlich' }, { status: 400 }) if (!id) return NextResponse.json({ error: 'id erforderlich' }, { status: 400 })
// Check if category has symbols // Check if category has symbols
const symbolCount = await (prisma as any).tenantSymbol.count({ try {
where: { categoryId: id, tenantId }, const symbolCount = await (prisma as any).tenantSymbol.count({
}) where: { categoryId: id, tenantId },
if (symbolCount > 0) { })
return NextResponse.json( if (symbolCount > 0) {
{ error: `Kategorie enthält ${symbolCount} Symbol(e) — bitte zuerst verschieben oder löschen` }, return NextResponse.json(
{ status: 409 } { error: `Kategorie enthält ${symbolCount} Symbol(e) — bitte zuerst verschieben oder löschen` },
) { status: 409 }
)
}
} catch (dbErr: any) {
console.error('tenantSymbol.count failed:', dbErr)
if (dbErr?.message?.includes('tenant_symbols') || dbErr?.code === 'P2021') {
// Skip check if table doesn't exist
} else {
throw dbErr
}
} }
await (prisma as any).tenantCategory.deleteMany({ try {
where: { id, tenantId }, await (prisma as any).tenantCategory.deleteMany({
}) where: { id, tenantId },
})
} catch (dbErr: any) {
console.error('tenantCategory.deleteMany failed:', dbErr)
if (dbErr?.message?.includes('tenant_categories') || dbErr?.code === 'P2021') {
return NextResponse.json({ error: 'Datenbank nicht bereit Migration läuft möglicherweise noch' }, { status: 503 })
}
throw dbErr
}
return NextResponse.json({ success: true }) return NextResponse.json({ success: true })
} catch (error) { } catch (error) {