| import { NextRequest, NextResponse } from "next/server"; |
| import { z } from "zod"; |
| import { |
| getCommitmentById, |
| upsertCommitment, |
| addCommitmentAuditEvent, |
| updateCommitmentStatus, |
| recordAcceptanceOutcome, |
| } from "@/lib/commitment/store"; |
|
|
| export const dynamic = "force-dynamic"; |
| export const maxDuration = 30; |
|
|
| const OutcomeSchema = z.object({ |
| id: z.string().min(1), |
| eventId: z.string().min(6), |
| accepted: z.boolean(), |
| revisionRequested: z.boolean().optional().default(false), |
| notes: z.string().max(2000).optional().default(""), |
| }); |
|
|
| export async function POST(request: NextRequest) { |
| try { |
| const body = await request.json().catch(() => ({})); |
| const parsed = OutcomeSchema.safeParse(body); |
| if (!parsed.success) { |
| return NextResponse.json( |
| { error: "Invalid request", details: parsed.error.flatten() }, |
| { status: 400 }, |
| ); |
| } |
|
|
| const { id, eventId, accepted, revisionRequested, notes } = parsed.data; |
|
|
| const existing = getCommitmentById(id); |
| if (!existing) { |
| return NextResponse.json({ error: `Commitment not found: ${id}` }, { status: 404 }); |
| } |
|
|
| const already = (existing.auditEvents || []).some( |
| (e) => e.event === "outcome" && (e.detail || "").includes(`eventId=${eventId}`), |
| ); |
|
|
| if (already) { |
| return NextResponse.json({ |
| success: true, |
| alreadyRecorded: true, |
| id, |
| timestamp: new Date().toISOString(), |
| }); |
| } |
|
|
| const acceptedWithoutRevision = accepted && !revisionRequested; |
|
|
| recordAcceptanceOutcome({ acceptedWithoutRevision }); |
|
|
| const detail = [ |
| `eventId=${eventId}`, |
| `accepted=${accepted}`, |
| `revisionRequested=${revisionRequested}`, |
| notes ? `notes=${notes}` : "", |
| ] |
| .filter(Boolean) |
| .join(" "); |
|
|
| try { |
| addCommitmentAuditEvent(id, "outcome", detail); |
| } catch (e) { |
| console.error("[commitments/outcome] audit error:", e); |
| } |
|
|
| |
| try { |
| if (accepted) { |
| updateCommitmentStatus(id, "completed", "Outcome recorded: accepted"); |
| } else if (revisionRequested) { |
| updateCommitmentStatus(id, "executing", "Outcome recorded: revision requested"); |
| } else { |
| updateCommitmentStatus(id, "escalated", "Outcome recorded: rejected"); |
| } |
| } catch (e) { |
| console.error("[commitments/outcome] status update error:", e); |
| } |
|
|
| |
| const updated = getCommitmentById(id); |
| if (updated) { |
| upsertCommitment(updated); |
| } |
|
|
| return NextResponse.json({ |
| success: true, |
| alreadyRecorded: false, |
| id, |
| acceptedWithoutRevision, |
| timestamp: new Date().toISOString(), |
| }); |
| } catch (e: any) { |
| console.error("[commitments/outcome] error:", e); |
| return NextResponse.json({ error: e.message }, { status: 500 }); |
| } |
| } |
|
|