import { type NextRequest } from "next/server"; import { prisma } from "@/lib/prisma"; import { ok, errorResponse, requireRole, ApiError } from "@/lib/api"; import { audit } from "@/lib/audit"; import { clientIp } from "@/lib/request"; /** * Admin-only: clear a QC failure so the step can be reworked. We roll the * op back to either `pending` (nothing produced yet — the failed unit was * the first attempt) or `partial` (some units had already been logged as * good before the fail) based on the cumulative `unitsCompleted` counter. * * The failed QCRecord is intentionally LEFT IN PLACE so reporting can still * count rework events — we just unblock the op. */ export async function POST(req: NextRequest, ctx: { params: Promise<{ id: string }> }) { try { const actor = await requireRole("admin"); const { id } = await ctx.params; const existing = await prisma.operation.findUnique({ where: { id }, select: { id: true, status: true, unitsCompleted: true }, }); if (!existing) throw new ApiError(404, "not_found", "Operation not found"); if (existing.status !== "qc_failed") { throw new ApiError( 409, "op_not_qc_failed", "Only steps in qc_failed state can be reset", ); } const nextStatus = existing.unitsCompleted > 0 ? "partial" : "pending"; const updated = await prisma.operation.update({ where: { id }, data: { status: nextStatus, // Claim was already cleared on the failing close; belt-and-braces // defensively zero it here in case something set it back somehow. claimedByUserId: null, claimedAt: null, completedAt: null, }, }); await audit({ actorId: actor.id, action: "qc_reset_op", entity: "Operation", entityId: id, before: { status: "qc_failed" }, after: { status: nextStatus, unitsCompleted: existing.unitsCompleted }, ipAddress: clientIp(req), }); return ok({ operation: updated }); } catch (err) { return errorResponse(err); } }