import { NextRequest, NextResponse } from "next/server"; import { prisma } from "@/lib/db"; import { requireApiAuthWithOrg, handleApiError } from "@/lib/api-auth"; type Ctx = { params: Promise<{ id: string }> }; export async function POST(request: NextRequest, ctx: Ctx) { try { const session = await requireApiAuthWithOrg(); const orgId = session.user.orgId!; const { id: sourceId } = await ctx.params; const body = await request.json().catch(() => ({})); const { targetPersonId } = body; if (!targetPersonId) { return NextResponse.json({ error: "targetPersonId is required" }, { status: 400 }); } if (sourceId === targetPersonId) { return NextResponse.json({ error: "Cannot merge a person into themselves" }, { status: 400 }); } const [source, target] = await Promise.all([ prisma.person.findUnique({ where: { id: sourceId } }), prisma.person.findUnique({ where: { id: targetPersonId } }), ]); if (!source || source.organizationId !== orgId) { return NextResponse.json({ error: "Source person not found" }, { status: 404 }); } if (!target || target.organizationId !== orgId) { return NextResponse.json({ error: "Target person not found" }, { status: 404 }); } // 1. Move all cards from source to target await prisma.responseCard.updateMany({ where: { personId: sourceId }, data: { personId: targetPersonId }, }); // 2. Merge fieldData: target values take priority, fill gaps from source const mergedFieldData = { ...((source.fieldData as object) ?? {}), ...((target.fieldData as object) ?? {}), }; // 3. Update target's core fields if target's are null but source's are not const updates: Record = { fieldData: Object.keys(mergedFieldData).length > 0 ? mergedFieldData : null, }; if (!target.email && source.email) updates.email = source.email; if (!target.cellPhone && source.cellPhone) updates.cellPhone = source.cellPhone; const targetPerson = await prisma.person.update({ where: { id: targetPersonId }, data: updates, include: { _count: { select: { cards: true } } }, }); // 4. Mark source as merged await prisma.person.update({ where: { id: sourceId }, data: { mergedIntoId: targetPersonId }, }); return NextResponse.json({ success: true, targetPerson }); } catch (error) { return handleApiError(error); } }