over / src /app /api /commitments /outcome /route.ts
luguog's picture
Deploy mailbox-automation Next.js app
9646e24 verified
Raw
History Blame Contribute Delete
2.91 kB
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);
}
// Update the contract status based on outcome feedback.
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);
}
// Ensure latest contract is persisted
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 });
}
}