step 9 and cleanup
Build and Push Docker Image / build (push) Successful in 1m4s

This commit is contained in:
jason
2026-04-22 09:27:01 -05:00
parent c8c86c9ca4
commit e0dfac2d48
18 changed files with 1521 additions and 85 deletions
@@ -0,0 +1,61 @@
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);
}
}