admin approve: block filing when intake incomplete (force override + warning)

Paul Wilson's UCR (CO-FE07212A) sat at fulfillment_status=ready_to_file with
intake_data_validated=false, so the Approve & File button would have dispatched
it for government submission with incomplete intake and no document to review.

Backend: /approve now refuses an order whose intake_data_validated is false
unless {force:true} is passed (409 code=intake_incomplete); the override is
recorded in order_audit_log. The fulfillment_status=ready_to_file requirement
is unchanged, so awaiting_intake orders (e.g. Mitchell's MCS-150s) still 409.

UI: the drawer shows an amber 'intake not complete' warning above the approve
button, and approving an intake-incomplete order triggers an explicit
override confirmation before sending force=true.
This commit is contained in:
justin 2026-06-16 00:33:22 -05:00
parent aa498fdfdf
commit d18de006d8
2 changed files with 39 additions and 8 deletions

View file

@ -289,7 +289,7 @@
? `<span class="small">${g.max_reminder_count} reminder(s)${g.last_reminded_at ? ", last " + fmtDay(g.last_reminded_at) : ", none sent"}</span>` : "";
const services = g.services.map((s) => {
const approve = s.ready_to_approve
? `<button data-approve="${esc(s.order_number)}" data-svc="${esc(s.service_name)}" class="btn btn-blue btn-sm">Approve &amp; file</button>` : "";
? `<button data-approve="${esc(s.order_number)}" data-svc="${esc(s.service_name)}" data-intake="${s.intake_data_validated ? 1 : 0}" class="btn btn-blue btn-sm">Approve &amp; file</button>` : "";
return `<div class="svc-row"><div class="svc-left">
<button data-detail="${esc(s.order_number)}" class="linkbtn">${esc(s.service_name)}</button>
<span class="small">${esc(s.order_number)}</span>
@ -314,16 +314,26 @@
</div>`;
}).join("");
document.querySelectorAll("[data-approve]").forEach((b) => b.addEventListener("click", () => approveOrder(b.getAttribute("data-approve"), b.getAttribute("data-svc"))));
document.querySelectorAll("[data-approve]").forEach((b) => b.addEventListener("click", () => approveOrder(b.getAttribute("data-approve"), b.getAttribute("data-svc"), b.getAttribute("data-intake") === "1")));
document.querySelectorAll("[data-rearm]").forEach((b) => b.addEventListener("click", () => rearmIntake(b.getAttribute("data-rearm"))));
document.querySelectorAll("[data-detail]").forEach((b) => b.addEventListener("click", () => openDetail(b.getAttribute("data-detail"))));
}
async function approveOrder(orderNumber, svc) {
async function approveOrder(orderNumber, svc, intakeOk) {
// Hard warn when intake isn't complete — the filing may be missing data or
// have no prepared document to review.
if (intakeOk === false) {
if (!confirm(`⚠️ Intake is NOT complete for "${svc}" (${orderNumber}).\n\n`
+ `The prepared filing may be missing required data, and there may be no `
+ `document to review. Filing now could submit an incomplete/incorrect `
+ `form to the government.\n\nProceed ANYWAY (override)?`)) return;
}
if (!confirm(`Approve "${svc}" (${orderNumber}) and dispatch it for government submission?\n\nThis cannot be undone.`)) return;
const body = JSON.stringify(intakeOk === false ? { force: true } : {});
try {
const r = await api("/api/v1/admin/compliance-orders/" + encodeURIComponent(orderNumber) + "/approve", { method: "POST", body: "{}" });
const r = await api("/api/v1/admin/compliance-orders/" + encodeURIComponent(orderNumber) + "/approve", { method: "POST", body });
alert(r.dispatched ? "Approved and dispatched to the worker." : "Approved, but worker dispatch did not confirm — check worker logs.");
$("drawer").classList.add("hidden");
refresh();
} catch (e) { alert("Approve failed: " + e.message); }
}
@ -360,13 +370,18 @@
row("ERPNext SO", esc(order.erpnext_sales_order || "—")) +
(order.batch_id ? row("Batch", esc(order.batch_id)) : "") +
row("Created", fmtDate(order.created_at)) +
(order.fulfillment_status === "ready_to_file" ? `<button id="drawer-approve" class="btn btn-blue wfull" style="margin-top:16px;">Approve &amp; file this order</button>` : "") +
(order.fulfillment_status === "ready_to_file"
? ((!order.intake_data_validated
? `<div style="margin-top:16px;padding:8px 12px;border:1px solid #fbbf24;background:#fffbeb;border-radius:6px;font-size:12px;color:#92400e;">⚠️ Intake is not complete — review documents before filing. Approving will require an override.</div>`
: "")
+ `<button id="drawer-approve" class="btn btn-blue wfull" style="margin-top:8px;">Approve &amp; file this order</button>`)
: "") +
((order.payment_status === "paid" && !order.intake_data_validated) ? `<button id="drawer-rearm" class="btn btn-amber wfull" style="margin-top:8px;">Re-arm intake reminder</button>` : "") +
`<div class="section-h">Intake data</div><pre>${esc(JSON.stringify(intake, null, 2))}</pre>` +
`<div class="section-h">Documents</div><div id="drawer-docs"><div class="muted" style="font-size:12px;">Loading documents…</div></div>` +
`<div class="section-h">Audit log</div>${auditHtml}`;
const da = $("drawer-approve");
if (da) da.addEventListener("click", () => approveOrder(order.order_number, order.service_name || order.service_slug));
if (da) da.addEventListener("click", () => approveOrder(order.order_number, order.service_name || order.service_slug, !!order.intake_data_validated));
const dr = $("drawer-rearm");
if (dr) dr.addEventListener("click", () => rearmIntake(order.order_number));
loadDocuments(order.order_number);