fix(auto-migrate): tenant_categories on-the-fly erstellung + migrate.js fail-fast
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 10m41s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 10m41s
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { prisma } from '@/lib/db'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { ensureTenantCategoriesTable } from '@/lib/auto-migrate'
|
||||
|
||||
function isMissingTable(err: any) {
|
||||
return err?.message?.includes('tenant_categories') || err?.code === 'P2021'
|
||||
}
|
||||
|
||||
async function getTenantId() {
|
||||
const user = await getSession()
|
||||
@@ -37,10 +42,25 @@ export async function GET() {
|
||||
})
|
||||
} catch (dbErr: any) {
|
||||
console.error('tenantCategory.findMany failed:', dbErr)
|
||||
if (dbErr?.message?.includes('tenant_categories') || dbErr?.code === 'P2021') {
|
||||
return NextResponse.json({ categories: [] })
|
||||
if (isMissingTable(dbErr)) {
|
||||
try {
|
||||
await ensureTenantCategoriesTable()
|
||||
categories = await (prisma as any).tenantCategory.findMany({
|
||||
where: { tenantId },
|
||||
include: {
|
||||
_count: {
|
||||
select: { symbols: true },
|
||||
},
|
||||
},
|
||||
orderBy: { sortOrder: 'asc' },
|
||||
})
|
||||
} catch (retryErr) {
|
||||
console.error('Retry after auto-migrate failed:', retryErr)
|
||||
return NextResponse.json({ categories: [] })
|
||||
}
|
||||
} else {
|
||||
throw dbErr
|
||||
}
|
||||
throw dbErr
|
||||
}
|
||||
|
||||
const result = categories.map((cat: any) => ({
|
||||
@@ -79,19 +99,23 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
|
||||
// Check for duplicate name within tenant
|
||||
let existing: any = null
|
||||
try {
|
||||
const existing = await (prisma as any).tenantCategory.findFirst({
|
||||
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 })
|
||||
}
|
||||
} 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 })
|
||||
if (isMissingTable(dbErr)) {
|
||||
await ensureTenantCategoriesTable()
|
||||
existing = await (prisma as any).tenantCategory.findFirst({
|
||||
where: { tenantId, name: { equals: name, mode: 'insensitive' } },
|
||||
})
|
||||
} else {
|
||||
throw dbErr
|
||||
}
|
||||
throw dbErr
|
||||
}
|
||||
if (existing) {
|
||||
return NextResponse.json({ error: 'Kategorie existiert bereits' }, { status: 409 })
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -105,9 +129,17 @@ export async function POST(req: NextRequest) {
|
||||
})
|
||||
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 })
|
||||
if (isMissingTable(dbErr)) {
|
||||
await ensureTenantCategoriesTable()
|
||||
const category = await (prisma as any).tenantCategory.create({
|
||||
data: {
|
||||
tenantId,
|
||||
name: name.trim(),
|
||||
sortOrder: sortOrder ?? 0,
|
||||
icon: icon || null,
|
||||
},
|
||||
})
|
||||
return NextResponse.json({ category }, { status: 201 })
|
||||
}
|
||||
throw dbErr
|
||||
}
|
||||
@@ -141,23 +173,31 @@ export async function PATCH(req: NextRequest) {
|
||||
|
||||
// If renaming, check for duplicates
|
||||
if (name) {
|
||||
let existing: any = null
|
||||
try {
|
||||
const existing = await (prisma as any).tenantCategory.findFirst({
|
||||
existing = await (prisma as any).tenantCategory.findFirst({
|
||||
where: {
|
||||
tenantId,
|
||||
name: { equals: name.trim(), mode: 'insensitive' },
|
||||
id: { not: id },
|
||||
},
|
||||
})
|
||||
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 })
|
||||
if (isMissingTable(dbErr)) {
|
||||
await ensureTenantCategoriesTable()
|
||||
existing = await (prisma as any).tenantCategory.findFirst({
|
||||
where: {
|
||||
tenantId,
|
||||
name: { equals: name.trim(), mode: 'insensitive' },
|
||||
id: { not: id },
|
||||
},
|
||||
})
|
||||
} else {
|
||||
throw dbErr
|
||||
}
|
||||
throw dbErr
|
||||
}
|
||||
if (existing) {
|
||||
return NextResponse.json({ error: 'Kategorie existiert bereits' }, { status: 409 })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,11 +211,18 @@ export async function PATCH(req: NextRequest) {
|
||||
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 })
|
||||
if (isMissingTable(dbErr)) {
|
||||
await ensureTenantCategoriesTable()
|
||||
const category = await (prisma as any).tenantCategory.updateMany({
|
||||
where: { id, tenantId },
|
||||
data,
|
||||
})
|
||||
if (category.count === 0) {
|
||||
return NextResponse.json({ error: 'Kategorie nicht gefunden' }, { status: 404 })
|
||||
}
|
||||
} else {
|
||||
throw dbErr
|
||||
}
|
||||
throw dbErr
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true })
|
||||
@@ -214,7 +261,6 @@ export async function DELETE(req: NextRequest) {
|
||||
)
|
||||
}
|
||||
} 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 {
|
||||
@@ -227,11 +273,14 @@ export async function DELETE(req: NextRequest) {
|
||||
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 })
|
||||
if (isMissingTable(dbErr)) {
|
||||
await ensureTenantCategoriesTable()
|
||||
await (prisma as any).tenantCategory.deleteMany({
|
||||
where: { id, tenantId },
|
||||
})
|
||||
} else {
|
||||
throw dbErr
|
||||
}
|
||||
throw dbErr
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true })
|
||||
|
||||
Reference in New Issue
Block a user