import { NextResponse } from 'next/server' import { z } from 'zod' import { db } from '@/lib/db' export const dynamic = 'force-dynamic' const createAnlageSchema = z.object({ name: z.string().min(1), category: z.string().optional().default('hardware'), purchaseDate: z.string().min(1), purchaseCostCents: z.number().int().positive(), usefulLifeYears: z.number().int().min(1).optional(), afaMethod: z.string().optional(), }) // GET /api/aos/anlagen — list asset register with AfA export async function GET() { try { const anlagen = await db.anlage.findMany({ orderBy: { purchaseDate: 'desc' } }) const stats = { total: anlagen.length, totalPurchaseCents: anlagen.reduce((s, a) => s + a.purchaseCostCents, 0), totalBookValueCents: anlagen.reduce((s, a) => s + a.bookValueCents, 0), totalAnnualAfaCents: anlagen.reduce((s, a) => s + a.annualAfaCents, 0), gwgCount: anlagen.filter((a) => a.isGWG).length, sammelpostenCount: anlagen.filter((a) => a.isSammelposten).length, activeCount: anlagen.filter((a) => a.status === 'active').length, } return NextResponse.json({ anlagen, stats }) } catch (err) { const msg = err instanceof Error ? err.message : 'internal server error' return NextResponse.json({ error: msg }, { status: 500 }) } } // POST /api/aos/anlagen — create an asset with AfA computation export async function POST(req: Request) { try { const parsed = createAnlageSchema.safeParse(await req.json()) if (!parsed.success) { return NextResponse.json({ error: 'validation failed', details: parsed.error.flatten() }, { status: 400 }) } const { name, category, purchaseDate, purchaseCostCents, usefulLifeYears, afaMethod } = parsed.data const cost = Math.round(purchaseCostCents) const years = usefulLifeYears ?? 3 // GWG (Geringwertiger Wirtschaftsgüter): ≤ €800 net → Sofortabschreibung (§ 6 Abs. 2 EStG) const isGWG = cost <= 80000 // €800.00 in cents // Sammelposten: €251-€1000 net → Sammelabschreibung über 5 Jahre (§ 6 Abs. 2a EStG) const isSammelposten = !isGWG && cost > 80000 && cost <= 100000 // Compute AfA let annualAfaCents = 0 let bookValueCents = cost if (isGWG) { // Sofortabschreibung: full cost in year 1 annualAfaCents = cost bookValueCents = 0 } else if (isSammelposten) { // Sammelabschreibung: 1/5 per year over 5 years annualAfaCents = Math.round(cost / 5) bookValueCents = cost - annualAfaCents // after year 1 } else { // Lineare AfA: cost / usefulLifeYears annualAfaCents = Math.round(cost / years) bookValueCents = cost - annualAfaCents // after year 1 } const count = await db.anlage.count() const number = `ANL-2026-${String(count + 1).padStart(4, '0')}` const anlage = await db.anlage.create({ data: { number, name: name.trim(), category: category || 'hardware', purchaseDate: new Date(purchaseDate), purchaseCostCents: cost, afaMethod: afaMethod ?? 'linear', usefulLifeYears: isGWG ? 1 : isSammelposten ? 5 : years, isGWG, isSammelposten, annualAfaCents, accumulatedAfaCents: annualAfaCents, // year 1 bookValueCents, }, }) await db.auditLog.create({ data: { actor: 'nora@nordlicht.digital', action: 'anlage.create', entity: 'Anlage', entityId: anlage.id, after: JSON.stringify({ number, name, cost, isGWG, annualAfaCents, bookValueCents }), hash: 'sha256:' + Math.random().toString(36).slice(2), }, }) return NextResponse.json({ anlage }) } catch (err) { const msg = err instanceof Error ? err.message : 'internal server error' return NextResponse.json({ error: msg }, { status: 500 }) } }