healthcare: go live with wet-signature filings + 2-day ETA buffer

Adds explicit order timelines for the 5 CMS provider filings (nppes-update,
npi-reactivation, npi-revalidation, medicare-enrollment, provider-compliance-
bundle) and a +2 business-day buffer applied from the signature step onward,
giving us time to produce + mail the original ink signature while the plotter
station is brought online.

- Buffer only affects post-signature steps; pre-signature steps and all
  non-wet-signature services are unchanged (verified with date math).
- Single source of truth: order-timeline route (consumed by the order success
  page), so the buffer flows through to the customer-facing ETA.
- Remove WET_SIGNATURE_BUFFER_DAYS once the ink-signature station is in
  steady-state (see docs/plans/plotter-plan.md).

API tsc clean; buffer compiled into dist.
This commit is contained in:
justin 2026-06-07 02:56:41 -05:00
parent 0b06043437
commit 41df4d9553

View file

@ -98,6 +98,45 @@ const SERVICE_TIMELINES: Record<string, TimelineStep[]> = {
{ name: "BOC-3 Update", description: "Updating process agent filing", business_days: 8, status: "pending" },
{ name: "Complete", description: "All filings updated under your new entity", business_days: 10, status: "pending" },
],
// ── Healthcare / CMS provider filings ────────────────────────────────────
// These submit a signed form to CMS; the WET_SIGNATURE_BUFFER is applied to
// the post-signature steps (see the buffer logic below).
"nppes-update": [
{ name: "Order Received", description: "Payment confirmed, order in queue", business_days: 0, status: "completed" },
{ name: "Document Preparation", description: "Preparing your NPI update for filing", business_days: 1, status: "pending" },
{ name: "Signature Required", description: "Review and sign the certification", business_days: 1, status: "pending" },
{ name: "Filed with CMS", description: "Your signed update is submitted to CMS", business_days: 2, status: "pending" },
{ name: "CMS Confirmation", description: "CMS processes the update (typically 1-2 weeks)", business_days: 10, status: "pending" },
],
"npi-reactivation": [
{ name: "Order Received", description: "Payment confirmed, order in queue", business_days: 0, status: "completed" },
{ name: "Document Preparation", description: "Preparing your NPI reactivation", business_days: 1, status: "pending" },
{ name: "Signature Required", description: "Review and sign the certification", business_days: 1, status: "pending" },
{ name: "Filed with CMS", description: "Your signed reactivation is submitted to CMS", business_days: 2, status: "pending" },
{ name: "CMS Confirmation", description: "CMS processes the reactivation (typically 1-2 weeks)", business_days: 10, status: "pending" },
],
"npi-revalidation": [
{ name: "Order Received", description: "Payment confirmed, order in queue", business_days: 0, status: "completed" },
{ name: "Document Preparation", description: "Preparing your Medicare revalidation", business_days: 1, status: "pending" },
{ name: "Signature Required", description: "Review and sign the certification", business_days: 1, status: "pending" },
{ name: "Filed with CMS", description: "Your signed revalidation is submitted to CMS", business_days: 2, status: "pending" },
{ name: "CMS Confirmation", description: "CMS/MAC processes the revalidation", business_days: 15, status: "pending" },
],
"medicare-enrollment": [
{ name: "Order Received", description: "Payment confirmed, order in queue", business_days: 0, status: "completed" },
{ name: "Document Preparation", description: "Preparing your Medicare enrollment", business_days: 1, status: "pending" },
{ name: "Signature Required", description: "Review and sign the certification", business_days: 1, status: "pending" },
{ name: "Filed with CMS", description: "Your signed enrollment is submitted to CMS", business_days: 2, status: "pending" },
{ name: "CMS Confirmation", description: "CMS/MAC processes the enrollment", business_days: 15, status: "pending" },
],
"provider-compliance-bundle": [
{ name: "Order Received", description: "Payment confirmed, order in queue", business_days: 0, status: "completed" },
{ name: "Document Preparation", description: "Preparing your provider compliance filings", business_days: 1, status: "pending" },
{ name: "Signature Required", description: "Review and sign the certification(s)", business_days: 1, status: "pending" },
{ name: "Filed with CMS", description: "Your signed filings are submitted to CMS", business_days: 2, status: "pending" },
{ name: "Screening Complete", description: "OIG/SAM screening completed (no action needed from you)", business_days: 2, status: "pending" },
{ name: "CMS Confirmation", description: "CMS/MAC processes your filings", business_days: 15, status: "pending" },
],
};
// Default timeline for services without a specific definition
@ -107,6 +146,23 @@ const DEFAULT_TIMELINE: TimelineStep[] = [
{ name: "Complete", description: "Filing completed and delivered", business_days: 5, status: "pending" },
];
// Services whose Standard path requires an ORIGINAL ink signature on a mailed
// CMS form (verified against the forms: CMS-855I/B/O "original signatures" and
// CMS-10114 "original and signed in ink"). While the ink-signature station is
// being brought online we add a buffer to these services' ETAs so we always
// have time to produce + mail the signed original. Remove the buffer once the
// plotter station is calibrated and in steady-state.
// See docs/state-healthcare-compliance-opportunities.md (wet-signature check)
// and docs/plans/plotter-plan.md.
const WET_SIGNATURE_BUFFER_DAYS = 2;
const WET_SIGNATURE_SLUGS = new Set<string>([
"nppes-update",
"npi-reactivation",
"npi-revalidation",
"medicare-enrollment",
"provider-compliance-bundle",
]);
router.get("/api/v1/order-timeline/:order_id", async (req: Request, res: Response) => {
try {
const orderId = req.params.order_id;
@ -136,10 +192,22 @@ router.get("/api/v1/order-timeline/:order_id", async (req: Request, res: Respons
const timelines = orders.map((order) => {
const slug = order.service_slug as string;
const startDate = new Date(order.created_at as string);
const steps = (SERVICE_TIMELINES[slug] || DEFAULT_TIMELINE).map((step) => ({
...step,
estimated_date: addBusinessDays(startDate, step.business_days).toISOString().split("T")[0],
}));
// Wet-signature services get a buffer on every step from the signature
// onward, so we always have time to produce + mail the original ink form.
const isWetSig = WET_SIGNATURE_SLUGS.has(slug);
let pastSignature = false;
const steps = (SERVICE_TIMELINES[slug] || DEFAULT_TIMELINE).map((step) => {
if (isWetSig && /signature/i.test(step.name)) {
pastSignature = true;
}
const buffer = isWetSig && pastSignature ? WET_SIGNATURE_BUFFER_DAYS : 0;
return {
...step,
estimated_date: addBusinessDays(startDate, step.business_days + buffer)
.toISOString()
.split("T")[0],
};
});
return {
order_number: order.order_number,