new-site/api/src/routes/compliance-orders.ts
justin 86205c309c Replace USAC email instructions with confirmation button + add API endpoint
- Intake email now has "I've completed the delegation →" button
  instead of "reply to this email"
- Button links to order success page with action=usac_delegation
- New API: POST /api/v1/compliance-orders/:id/usac-delegation
  Records confirmation timestamp in intake_data and logs it
- Removed "reply to this email" from intake email

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 21:20:22 -05:00

1500 lines
56 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Compliance Orders — CRUD for compliance service orders.
*
* POST /api/v1/compliance-orders
* Create a new compliance order (pending_payment).
* Returns { order_number, service_slug, ... } for checkout redirect.
*
* GET /api/v1/compliance-orders/:order_number
* Get order status (used by success page to confirm payment).
*/
import { Router } from "express";
import { pool } from "../db.js";
import { randomBytes } from "crypto";
const router = Router();
// ── Service catalog (prices in cents) ──────────────────────────────────────
const COMPLIANCE_SERVICES: Record<
string,
{ name: string; price_cents: number; gov_fee_cents?: number; gov_fee_label?: string; erpnext_item: string; discountable: boolean }
> = {
"fcc-compliance-checkup": {
name: "FCC Carrier Compliance Checkup",
price_cents: 79900,
erpnext_item: "FCC-COMPLIANCE-CHECKUP",
discountable: true,
},
"fcc-499a": {
name: "FCC Form 499-A Filing",
price_cents: 49900,
erpnext_item: "FCC-499A",
discountable: true,
},
"fcc-499a-499q": {
name: "FCC Form 499-A + 499-Q Bundle",
price_cents: 59900,
erpnext_item: "FCC-499A-499Q",
discountable: true,
},
"fcc-full-compliance": {
name: "FCC Full Compliance Bundle",
price_cents: 149900,
erpnext_item: "FCC-FULL-COMPLIANCE",
discountable: true,
},
"cpni-certification": {
name: "CPNI Annual Certification",
price_cents: 14900,
erpnext_item: "CPNI-CERT",
discountable: true,
},
"rmd-filing": {
name: "RMD Registration / Recertification",
price_cents: 21900,
gov_fee_cents: 10000,
gov_fee_label: "FCC RMD filing fee",
erpnext_item: "RMD-FILING",
discountable: true,
},
"stir-shaken": {
name: "STIR/SHAKEN Implementation Assistance",
price_cents: 49900,
erpnext_item: "STIR-SHAKEN",
discountable: true,
},
"dc-agent": {
name: "D.C. Registered Agent (Annual)",
price_cents: 9900,
erpnext_item: "DC-AGENT",
discountable: false,
},
// BDC filings — the FCC retired Form 477 in Dec 2022 and folded voice
// subscription data into BDC. Broadband-only and voice-only SKUs let
// carriers pay for just what they need; bdc-filing remains as a bundle.
"bdc-broadband": {
name: "BDC Broadband Deployment Filing",
price_cents: 19900,
erpnext_item: "BDC-BROADBAND",
discountable: true,
},
"bdc-voice": {
name: "BDC Voice Subscription Filing (formerly Form 477 Voice)",
price_cents: 14900,
erpnext_item: "BDC-VOICE",
discountable: true,
},
"bdc-filing": {
name: "BDC Filing (Broadband + Voice)",
price_cents: 29900,
erpnext_item: "BDC-FILING",
discountable: true,
},
// New-carrier entry point — register in CORES + obtain FRN
"cores-frn-registration": {
name: "CORES / FRN Registration",
price_cents: 9900,
erpnext_item: "CORES-FRN",
discountable: true,
},
// 499-A New Filer Registration (distinct from the annual revenue filing)
"fcc-499-initial": {
name: "Form 499 Initial Registration",
price_cents: 29900,
erpnext_item: "FCC-499-INITIAL",
discountable: true,
},
// CALEA System Security & Integrity plan (47 USC 229)
"calea-ssi": {
name: "CALEA SSI Plan",
price_cents: 29900,
erpnext_item: "CALEA-SSI",
discountable: true,
},
// 47 CFR § 63.11 Foreign Carrier Affiliation Notification
"fcc-63-11-notification": {
name: "Foreign Carrier Affiliation Notification (47 CFR § 63.11)",
price_cents: 34900,
erpnext_item: "FCC-63-11",
discountable: true,
},
// One-click onboarding for a brand-new carrier (composes 5 filings)
"new-carrier-bundle": {
name: "New Carrier Onboarding Bundle (FRN + 499 Initial + RMD + CPNI + CALEA)",
price_cents: 179900,
erpnext_item: "NEW-CARRIER-BUNDLE",
discountable: true,
},
// NECA OCN registration — required for VoIP/IPES carriers that need
// their own Operating Company Number for STIR/SHAKEN signing, LRN
// assignments, or direct numbering authority. NECA charges $550
// standard / $675 expedited; we pass through + margin for prep work.
"ocn-registration": {
name: "NECA OCN + Sponsoring CLEC Agreement",
price_cents: 265000,
erpnext_item: "OCN-REGISTRATION",
discountable: false,
},
"fcc-499a-discontinuance": {
name: "Form 499-A Discontinuance Filing",
price_cents: 29900,
erpnext_item: "499A-DISCONTINUANCE",
discountable: false,
},
// Standalone CDR Traffic Study — customers who want the classified
// study (unlocks the current reporting year) without buying the
// full 499-A filing service. Either slug unlocks the study via the
// cdr_study_access_grants paywall hook.
"cdr-analysis": {
name: "CDR Traffic Study (Annual)",
price_cents: 49900,
erpnext_item: "CDR-ANALYSIS",
discountable: true,
},
// CDR storage / processing tiers. Annual subscription; renew alongside
// the filing. Each tier is additive — customer picks the smallest tier
// that covers their worst of (storage bytes, classified rows).
"cdr-storage-tier1": {
name: "CDR Storage Tier 1 (50 GB / 50M calls)",
price_cents: 9900,
erpnext_item: "CDR-STORAGE-TIER1",
discountable: false,
},
"cdr-storage-tier2": {
name: "CDR Storage Tier 2 (250 GB / 250M calls)",
price_cents: 29900,
erpnext_item: "CDR-STORAGE-TIER2",
discountable: false,
},
"cdr-storage-tier3": {
name: "CDR Storage Tier 3 (1 TB / 1B calls)",
price_cents: 79900,
erpnext_item: "CDR-STORAGE-TIER3",
discountable: false,
},
// ── Foreign qualification (Certificate of Authority) ─────────────────
// Per-state fees are added on top of these flat service fees at order
// time (state fee + NWRA RA wholesale, looked up from jurisdictions +
// state_filing_fees). Handler fans out one filing per selected state.
//
// Pricing model:
// - `foreign-qualification-single`: flat service fee ($149) + state
// fee + optional NWRA RA. One state per order.
// - `foreign-qualification-multi`: discounted per-state service fee
// ($99) + state fees + RAs. For FCC carriers filing across their
// operating territory.
"foreign-qualification-single": {
name: "Foreign Qualification (One State)",
price_cents: 14900,
erpnext_item: "FOREIGN-QUAL-SINGLE",
discountable: true,
},
"foreign-qualification-multi": {
name: "Foreign Qualification (Multi-State)",
price_cents: 9900, // per-state service fee
erpnext_item: "FOREIGN-QUAL-MULTI",
discountable: true,
},
// State PUC/PSC Registration — $399 per-state service fee + state
// filing fees. Bond procurement coordinated separately.
"state-puc": {
name: "State PUC/PSC Registration",
price_cents: 39900, // per-state service fee
erpnext_item: "STATE-PUC",
discountable: true,
},
};
// ── Intake validation map ─────────────────────────────────────────────
//
// Required fields must be present in the submitted `intake_data` before
// Stripe Checkout is allowed to run. Soft fields trigger a warning but
// don't block payment — the handler degrades gracefully (e.g. blank
// signature line on a cert letter).
//
// Keys dot-nested where intake_data nests objects:
// "officer.name" → intake_data.officer.name
//
// Each handler's "what it actually needs" was audited against the
// handler file; stay in sync with those reads. Missing entries for a
// slug mean no enforcement — for discoverability, aim to keep this
// complete.
// FieldSpec shape:
// required — dotted-path keys that must be non-empty on intake_data
// soft — dotted-path keys that warn when empty but do not block
// conditional — rule objects evaluated at validate-time. Each rule has:
// when — predicate (see evalPredicate below)
// require — extra keys that become required when `when` is true
// reject — string error when `when` is true (hard block)
// validators — names of cross-field validators to run (see runCrossFieldValidators)
type ConditionalRule = {
when: string;
require?: string[];
reject?: string;
};
type FieldSpec = {
required: string[];
soft: string[];
conditional?: ConditionalRule[];
validators?: string[];
};
const REQUIRED_FIELDS: Record<string, FieldSpec> = {
"fcc-compliance-checkup": { required: [], soft: ["frn"] },
"rmd-filing": { required: ["frn", "carrier_category"], soft: ["stir_shaken_status", "analytics_systems"] },
"cpni-certification": { required: ["frn"], soft: ["officer.name", "officer.title", "complaints_count"] },
// ── 499-A family: the full audit-driven spec ───────────────────────────
"fcc-499a": {
required: [
"line_105_primary",
"line_105_categories",
"entity_structure",
"officer_1_name", "officer_1_title",
"officer_1_street", "officer_1_city", "officer_1_state", "officer_1_zip",
"jurisdictions_served",
"total_revenue_cents",
"interstate_pct", "international_pct",
"filer_id_499",
"safe_harbor_election.method",
"lnpa_region_allocations",
"filing_type",
],
soft: ["ceo_name", "trade_names", "itsp_regulatory_fee_email"],
conditional: [
{ when: "first_telecom_service_pre_1999!=true",
require: ["first_telecom_service_year", "first_telecom_service_month"] },
{ when: "officer_count_claimed>=2",
require: ["officer_2_name","officer_2_title",
"officer_2_street","officer_2_city","officer_2_state","officer_2_zip"] },
{ when: "officer_count_claimed>=3",
require: ["officer_3_name","officer_3_title",
"officer_3_street","officer_3_city","officer_3_state","officer_3_zip"] },
{ when: "affiliated_filer_name.truthy",
require: ["affiliated_filer_ein"] },
{ when: "exempt_usf|exempt_trs|exempt_nanpa|exempt_lnp|exempt_itsp",
require: ["exemption_explanation"] },
{ when: "safe_harbor_election.method=traffic_study",
require: ["traffic_study_minio_path"] },
{ when: "line_105_primary=voip_non_interconnected AND safe_harbor_election.method=safe_harbor",
reject: "Non-interconnected VoIP has no safe harbor. Select traffic study or actual data." },
{ when: "revenue.line_303.any>0",
require: ["reseller_certifications"] },
],
validators: ["lnpa_sums_100", "de_minimis_calc", "trs_base_nonnegative"],
},
"fcc-499a-499q": {
required: [
"line_105_primary", "line_105_categories",
"total_revenue_cents", "interstate_pct", "international_pct",
"filer_id_499", "safe_harbor_election.method",
],
soft: ["ceo_name", "ceo_title"],
conditional: [
{ when: "line_105_primary=voip_non_interconnected AND safe_harbor_election.method=safe_harbor",
reject: "Non-interconnected VoIP has no safe harbor. Select traffic study or actual data." },
],
validators: ["de_minimis_calc"],
},
"fcc-499-initial": {
required: [
"line_105_primary", "entity_structure",
"officer_1_name", "officer_1_title",
"officer_1_street", "officer_1_city", "officer_1_state", "officer_1_zip",
"jurisdictions_served",
"contact_name", "contact_email",
],
soft: ["ceo_name", "ein"],
conditional: [
{ when: "officer_count_claimed>=2",
require: ["officer_2_name","officer_2_title"] },
],
},
"stir-shaken": { required: ["frn"], soft: ["target_stir_shaken_status", "sti_ca_vendor"] },
"bdc-filing": { required: ["frn"], soft: ["availability_rows", "voice_subscribers"] },
"bdc-broadband": { required: ["frn", "availability_rows"], soft: [] },
"bdc-voice": { required: ["frn", "voice_subscribers"], soft: [] },
"cores-frn-registration": { required: ["legal_name", "officer.name", "officer.email", "password_recovery_email"], soft: ["ein", "address.street", "address.city"] },
"calea-ssi": { required: ["calea_ssi.law_enforcement_contact.name", "calea_ssi.law_enforcement_contact.phone", "calea_ssi.law_enforcement_contact.email_24h"], soft: ["calea_ssi.cpni_protection_officer.name", "calea_ssi.network_infrastructure_summary"] },
"fcc-63-11-notification": { required: ["foreign_carrier.foreign_carrier_legal_name", "foreign_carrier.country", "foreign_carrier.ownership_pct", "foreign_carrier.affected_routes", "foreign_carrier.affiliation_date"], soft: ["foreign_carrier.notification_type"] },
"ocn-registration": { required: ["service_category", "operating_states"], soft: ["expedited"] },
"dc-agent": { required: [], soft: [] },
"cdr-analysis": { required: ["reporting_year"], soft: ["reporting_period"] },
"fcc-full-compliance": {
required: [
"frn", "filer_id_499",
"line_105_primary", "line_105_categories",
"total_revenue_cents", "interstate_pct", "international_pct",
"safe_harbor_election.method",
],
soft: ["ceo_name", "ceo_title"],
validators: ["lnpa_sums_100", "de_minimis_calc", "trs_base_nonnegative"],
},
"new-carrier-bundle": { required: ["legal_name", "officer.name", "officer.email", "password_recovery_email", "line_105_primary"], soft: ["ein", "contact_phone"] },
// Foreign qualification — the target_states array is the critical input.
"foreign-qualification-single": { required: ["legal_name", "home_state_code", "entity_type", "target_states"], soft: ["ein"] },
"foreign-qualification-multi": { required: ["legal_name", "home_state_code", "entity_type", "target_states"], soft: ["ein"] },
};
// Entity-level requirements (e.g. "must have an FRN on file before this
// service can run"). Checked against the linked telecom_entity.
const REQUIRES_ENTITY_FRN: ReadonlySet<string> = new Set([
"rmd-filing", "cpni-certification", "fcc-499a", "fcc-499a-499q",
"fcc-499-initial", "stir-shaken", "bdc-filing", "bdc-broadband",
"bdc-voice", "calea-ssi", "fcc-63-11-notification", "fcc-full-compliance",
]);
function digField(source: Record<string, unknown>, dottedKey: string): unknown {
return dottedKey.split(".").reduce<unknown>(
(acc, part) => {
if (acc && typeof acc === "object" && !Array.isArray(acc)) {
return (acc as Record<string, unknown>)[part];
}
return undefined;
},
source,
);
}
function isEmpty(value: unknown): boolean {
if (value === undefined || value === null) return true;
if (typeof value === "string") return value.trim() === "";
if (Array.isArray(value)) return value.length === 0;
if (typeof value === "object") return Object.keys(value as object).length === 0;
return false;
}
/**
* Resolve the per-order service fee. Most orders use the catalog's
* price_cents directly. The exception: for 499-A filings from a
* de minimis, VoIP-interconnected-only carrier, the price drops to
* $299 — these filings are simpler (no USF contribution math, single
* category, safe harbor eligible) so our work is lower.
*
* Qualification criteria (all must be true):
* - slug is fcc-499a | fcc-499a-499q
* - intake_data.is_deminimis === true (self-declared or from Appendix A)
* - line_105_primary === 'voip_interconnected'
* - line_105_categories has exactly one entry (voip_interconnected)
*
* If any criteria fail, the catalog price applies.
*/
function resolveOrderFeeCents(
slug: string,
service: { price_cents: number },
intake: Record<string, unknown>,
waive_deminimis: boolean,
multi_year_filings: number[] | null,
): { fee_cents: number; pricing_note?: string; multi_year_discount_pct?: number } {
const DEMINIMIS_VOIP_ONLY_PRICE = 29900;
const MULTI_YEAR_DISCOUNT_PCT = 15;
// Compute the baseline per-year price for this order.
let perYearPrice = service.price_cents;
let baselineNote: string | undefined;
if (["fcc-499a", "fcc-499a-499q"].includes(slug)) {
if (waive_deminimis) {
// Waive → full price, overrides any de minimis discount
perYearPrice = service.price_cents;
} else {
const isDemin = intake.is_deminimis === true;
const primary = (intake.line_105_primary as string) || "";
const cats = Array.isArray(intake.line_105_categories)
? (intake.line_105_categories as Array<{ id: string }>)
: [];
const voipOnly =
primary === "voip_interconnected" &&
cats.length === 1 &&
cats[0]?.id === "voip_interconnected";
if (isDemin && voipOnly) {
perYearPrice = DEMINIMIS_VOIP_ONLY_PRICE;
baselineNote =
"De minimis + VoIP-interconnected-only pricing: $299/year instead of " +
"$499 (simpler filing — single category, no USF contribution " +
"calculation, safe harbor eligible).";
}
}
}
// If multi_year_filings has 2+ years, charge (N × perYearPrice × 0.85).
const yearCount = Array.isArray(multi_year_filings) ? multi_year_filings.length : 0;
if (yearCount >= 2) {
const gross = perYearPrice * yearCount;
const discount = Math.round(gross * (MULTI_YEAR_DISCOUNT_PCT / 100));
const fee = gross - discount;
const note =
(baselineNote ? baselineNote + " " : "") +
`Multi-year discount: ${yearCount} years at $${(perYearPrice/100).toFixed(2)}/year ` +
`less ${MULTI_YEAR_DISCOUNT_PCT}% = $${(fee/100).toFixed(2)} total.`;
return { fee_cents: fee, pricing_note: note, multi_year_discount_pct: MULTI_YEAR_DISCOUNT_PCT };
}
// OCN registration: if client has existing tandem agreement, charge only $650
// (OCN application fee) instead of $2,650 (OCN + sponsoring CLEC).
if (slug === "ocn-registration" && intake.has_existing_tandem === true) {
return {
fee_cents: 65000,
pricing_note: "Client has existing tandem/interconnection agreement — OCN application only ($650).",
};
}
return { fee_cents: perYearPrice, pricing_note: baselineNote };
}
/**
* Evaluate a conditional `when` predicate against the merged data source
* (intake_data entity columns).
*
* Syntax:
* key → truthy check on the key
* key.truthy → same as above (explicit)
* key=value → string equals (case-insensitive)
* key!=value → string not-equals
* key>=N → numeric >=
* key>N → numeric >
* key.any>N → numeric > for any element of an array of {value} OR for revenue_lines.* keys
* A AND B — both predicates true
* A|B|C → any of (OR, single pipe to avoid shell quoting issues)
*/
function evalPredicate(pred: string, src: Record<string, unknown>): boolean {
const s = pred.trim();
// AND combinator
if (s.includes(" AND ")) {
return s.split(" AND ").every((p) => evalPredicate(p.trim(), src));
}
// OR combinator (pipe)
if (s.includes("|") && !s.includes("=") && !s.includes(">")) {
return s.split("|").some((p) => evalPredicate(p.trim(), src));
}
// key.any>N — numeric "any element exceeds" against a dict-of-numbers
// keyspace OR a scalar number. `revenue.line_303.any>0` should fire
// whether `line_303` is a number (cents) OR a dict like
// {intra, inter, intl}.
const anyMatch = s.match(/^(.+)\.any([>])(-?\d+(?:\.\d+)?)$/);
if (anyMatch) {
const [, key, op, numStr] = anyMatch;
const num = Number(numStr);
const bag = digField(src, key);
if (bag === null || bag === undefined) return false;
// Scalar number: compare directly
if (typeof bag === "number") {
return op === ">" ? bag > num : false;
}
// String-numeric: parse and compare
if (typeof bag === "string") {
const n = Number(bag);
return !Number.isNaN(n) && (op === ">" ? n > num : false);
}
// Array / dict: any element exceeds
if (typeof bag === "object") {
return Object.values(bag as Record<string, unknown>).some((v) => {
const n = Number(v);
return !Number.isNaN(n) && (op === ">" ? n > num : false);
});
}
return false;
}
// key>=N, key>N
const numMatch = s.match(/^(.+?)(>=|>)(-?\d+(?:\.\d+)?)$/);
if (numMatch) {
const [, key, op, numStr] = numMatch;
const v = Number(digField(src, key.trim()));
const num = Number(numStr);
if (Number.isNaN(v)) return false;
return op === ">=" ? v >= num : v > num;
}
// key=value or key!=value
const eqMatch = s.match(/^(.+?)(!=|=)(.+)$/);
if (eqMatch) {
const [, key, op, val] = eqMatch;
const v = digField(src, key.trim());
const sv = v == null ? "" : String(v).trim().toLowerCase();
const tv = val.trim().toLowerCase();
return op === "=" ? sv === tv : sv !== tv;
}
// bare key: truthy check. isEmpty() doesn't recognize boolean false as
// empty (because for many of our fields a literal `false` string is a
// meaningful value). For THIS predicate we want classic JS truthiness:
// false / 0 / "" / null / undefined / [] / {} → not truthy.
const key = s.replace(/\.truthy$/, "");
const v = digField(src, key);
if (v === undefined || v === null) return false;
if (typeof v === "boolean") return v;
if (typeof v === "number") return v !== 0;
if (typeof v === "string") return v.trim() !== "";
if (Array.isArray(v)) return v.length > 0;
if (typeof v === "object") return Object.keys(v as object).length > 0;
return Boolean(v);
}
/**
* Run cross-field validators (LNPA sums, de minimis calc, TRS base sign).
* Returns { errors, warnings, calculations }. Errors block checkout.
*/
async function runCrossFieldValidators(
validators: string[],
src: Record<string, unknown>,
entity: Record<string, unknown>,
orderId: number,
): Promise<{
errors: string[];
warnings: string[];
calculations: Record<string, unknown>;
}> {
const errors: string[] = [];
const warnings: string[] = [];
const calculations: Record<string, unknown> = {};
for (const v of validators) {
if (v === "lnpa_sums_100") {
// Lines 503-510 columns (a) Block 3 and (b) Block 4 must each sum
// to exactly 100.00% (or 0 if no revenue in that block).
const rows = await pool.query(
`SELECT COALESCE(SUM(block_3_pct), 0) AS b3,
COALESCE(SUM(block_4_pct), 0) AS b4,
COUNT(*) AS n
FROM lnpa_region_allocations
WHERE telecom_entity_id = $1
AND reporting_year = $2`,
[entity.id, src.reporting_year ?? new Date().getUTCFullYear() - 1],
);
const r = rows.rows[0];
const b3 = Number(r.b3);
const b4 = Number(r.b4);
const n = Number(r.n);
calculations.lnpa_sums = { block_3_pct: b3, block_4_pct: b4, row_count: n };
if (n === 0) {
errors.push("LNPA region allocation (Lines 503-510) not set — required before filing.");
} else {
if (Math.abs(b3 - 100) > 0.01 && b3 !== 0) {
errors.push(`LNPA Block 3 (resale) column sums to ${b3.toFixed(2)}%, must be 100.00% or 0.`);
}
if (Math.abs(b4 - 100) > 0.01 && b4 !== 0) {
errors.push(`LNPA Block 4 (end-user) column sums to ${b4.toFixed(2)}%, must be 100.00% or 0.`);
}
}
}
if (v === "de_minimis_calc") {
try {
const { calculateDeMinimis } = await import("../lib/fcc_499_utils.js");
const formYear = Number(src.form_year ?? new Date().getUTCFullYear());
// Pull affiliates from telecom_entities linked by affiliated_filer_ein
const affEin = (entity.affiliated_filer_ein as string) || null;
const affRows = affEin
? await pool.query(
`SELECT total_revenue_cents, interstate_pct, international_pct
FROM telecom_entities
WHERE affiliated_filer_ein = $1 AND id <> $2`,
[affEin, entity.id],
)
: { rows: [] };
const worksheet = await calculateDeMinimis({
form_year: formYear,
filer_total_revenue_cents: Number(entity.total_revenue_cents) || 0,
filer_interstate_pct: Number(entity.interstate_pct) || 0,
filer_international_pct: Number(entity.international_pct) || 0,
affiliates: affRows.rows.map((a) => ({
total_revenue_cents: Number(a.total_revenue_cents) || 0,
interstate_pct: Number(a.interstate_pct) || 0,
international_pct: Number(a.international_pct) || 0,
})),
});
calculations.de_minimis = worksheet;
// Persist for the handler + admin review
await pool.query(
`UPDATE compliance_orders
SET deminimis_worksheet_json = $2::jsonb,
deminimis_estimated_contrib_cents = $3,
deminimis_result_is_exempt = $4
WHERE id = $1`,
[
orderId,
JSON.stringify(worksheet),
worksheet.line_11_estimated_contrib_cents,
worksheet.is_de_minimis,
],
);
// Warn if the filer's self-declared `is_deminimis` disagrees
if (
typeof entity.is_deminimis === "boolean" &&
entity.is_deminimis !== worksheet.is_de_minimis
) {
warnings.push(
`De minimis mismatch: you claimed ${
entity.is_deminimis ? "exempt" : "not exempt"
} but the Appendix A calculation shows ${
worksheet.is_de_minimis ? "exempt" : "not exempt"
} (estimated $${(worksheet.line_11_estimated_contrib_cents / 100).toFixed(2)}). Please confirm.`,
);
}
} catch (exc) {
warnings.push(`De minimis calculation failed: ${(exc as Error).message}`);
}
}
if (v === "trs_base_nonnegative") {
const { computeTrsContributionBase } = await import("../lib/fcc_499_utils.js");
const revLines = (src.revenue as Record<string, unknown>) || {};
// Flatten revenue.{line_xxx} into {line_xxx: n}
const flat: Record<string, number> = {};
for (const [k, val] of Object.entries(revLines)) {
if (typeof val === "number") flat[k] = val;
else if (val && typeof val === "object" && "cents" in (val as object)) {
flat[k] = Number((val as Record<string, unknown>).cents) || 0;
}
}
const trs = computeTrsContributionBase(flat);
calculations.trs_base = trs;
if (trs.line_512 < 0) {
errors.push(
`TRS contribution base (Line 512) computes to ${trs.line_512} cents — must be >= 0. ` +
`Check Line 511 (non-contributing resellers) vs sum of Lines 403-418.4.`,
);
}
if (trs.line_513 > trs.line_512) {
warnings.push(
`TRS uncollectible (Line 513) exceeds TRS base (Line 512). ` +
`Allowed in exceptional circumstances per 2026 instructions but flagged for review.`,
);
}
}
}
return { errors, warnings, calculations };
}
function generateOrderNumber(): string {
const hex = randomBytes(4).toString("hex").toUpperCase();
return `CO-${hex}`;
}
/**
* POST /api/v1/compliance-orders
*/
router.post("/api/v1/compliance-orders", async (req, res) => {
const {
service_slug,
customer_email,
customer_name,
customer_phone,
telecom_entity_id,
discount_code,
notes,
intake_data,
// Past-due + revision fields (migration 058)
filing_mode, // 'current' | 'past_due' | 'revised'
form_year_override, // 2015-2035; required when filing_mode != 'current'
revises_order_number, // prior order # when filing_mode = 'revised'
revised_reason, // 'registration' | 'revenue' | 'both'
// Waive de minimis exemption (migration 059) — filer qualifies as
// de minimis but elects to file as a regular contributor so they
// can get vendor-side USF waived on wholesale trunking.
waive_deminimis_exemption,
waive_deminimis_reason,
// Multi-year catch-up (migration 060) — array of reporting years.
// 2+ years gets the 15% multi-year discount.
multi_year_filings,
} = req.body ?? {};
if (!service_slug || !customer_email || !customer_name) {
res.status(400).json({
error: "service_slug, customer_email, and customer_name are required.",
});
return;
}
const service = COMPLIANCE_SERVICES[service_slug];
if (!service) {
res.status(400).json({
error: `Unknown service_slug: ${service_slug}. Valid options: ${Object.keys(COMPLIANCE_SERVICES).join(", ")}`,
});
return;
}
// Validate entity exists if provided
if (telecom_entity_id) {
const entity = await pool.query(
"SELECT id FROM telecom_entities WHERE id = $1",
[telecom_entity_id],
);
if (entity.rows.length === 0) {
res.status(400).json({ error: `Telecom entity ${telecom_entity_id} not found.` });
return;
}
}
// Validate multi_year_filings (if provided)
const myf: number[] | null = Array.isArray(multi_year_filings)
? multi_year_filings.filter((y: unknown) => Number.isFinite(Number(y)))
.map((y: unknown) => Number(y))
: null;
if (myf && myf.length > 0) {
if (!["fcc-499a", "fcc-499a-499q"].includes(service_slug)) {
res.status(400).json({
error: "multi_year_filings only supported for fcc-499a / fcc-499a-499q.",
});
return;
}
const unique = new Set(myf);
if (unique.size !== myf.length) {
res.status(400).json({ error: "multi_year_filings must not contain duplicates." });
return;
}
if (myf.length < 2) {
res.status(400).json({
error: "multi_year_filings must have 2 or more years (single-year orders should use form_year_override instead).",
});
return;
}
for (const y of myf) {
if (y < 2015 || y > 2035) {
res.status(400).json({ error: `multi_year_filings year out of range: ${y}` });
return;
}
}
}
// Resolve per-order fee (honors de minimis + VoIP-only discount for 499-A
// unless waived, plus 15% multi-year discount for 2+ reporting years).
const { fee_cents: resolved_fee_cents, pricing_note, multi_year_discount_pct } =
resolveOrderFeeCents(
service_slug, service, (intake_data || {}) as Record<string, unknown>,
waive_deminimis_exemption === true,
myf,
);
// Apply discount if provided
let discount_cents = 0;
if (discount_code) {
try {
const disc = await pool.query(
`SELECT discount_pct, discount_flat_cents, active
FROM discount_codes
WHERE code = $1 AND active = true`,
[discount_code.toUpperCase().trim()],
);
if (disc.rows.length > 0) {
const d = disc.rows[0] as Record<string, unknown>;
if ((d.discount_pct as number) > 0) {
discount_cents = Math.round(
(resolved_fee_cents * (d.discount_pct as number)) / 100,
);
} else if ((d.discount_flat_cents as number) > 0) {
discount_cents = d.discount_flat_cents as number;
}
}
} catch {
// discount_codes table may not exist — non-fatal
}
}
// Validate filing mode fields
const mode = filing_mode || "current";
if (!["current", "past_due", "revised"].includes(mode)) {
res.status(400).json({ error: "filing_mode must be current | past_due | revised" });
return;
}
if (mode === "past_due" && !form_year_override) {
res.status(400).json({ error: "form_year_override required for past_due filings" });
return;
}
if (mode === "revised") {
if (!revises_order_number) {
res.status(400).json({ error: "revises_order_number required for revised filings" });
return;
}
if (!revised_reason || !["registration", "revenue", "both"].includes(revised_reason)) {
res.status(400).json({ error: "revised_reason must be registration | revenue | both" });
return;
}
// Verify the prior order exists and belongs to the same entity
const prior = await pool.query(
`SELECT service_slug, telecom_entity_id, intake_data, form_year_override
FROM compliance_orders WHERE order_number = $1`,
[revises_order_number],
);
if (prior.rows.length === 0) {
res.status(400).json({ error: `Prior order ${revises_order_number} not found.` });
return;
}
const priorRow = prior.rows[0];
if (telecom_entity_id && priorRow.telecom_entity_id !== telecom_entity_id) {
res.status(400).json({
error: "Revised filing must use the same telecom_entity as the prior order.",
});
return;
}
}
const order_number = generateOrderNumber();
try {
const result = await pool.query(
`INSERT INTO compliance_orders (
order_number, service_slug, service_name, service_fee_cents,
gov_fee_cents, gov_fee_label,
telecom_entity_id, customer_email, customer_name, customer_phone,
discount_code, discount_cents, notes, intake_data,
filing_mode, form_year_override, revises_order_number, revised_reason,
waive_deminimis_exemption, waive_deminimis_reason,
multi_year_filings, multi_year_discount_pct
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22)
RETURNING *`,
[
order_number,
service_slug,
service.name,
resolved_fee_cents,
service.gov_fee_cents || 0,
service.gov_fee_label || null,
telecom_entity_id || null,
customer_email.toLowerCase().trim(),
customer_name.trim(),
customer_phone || null,
discount_code || null,
discount_cents,
notes || null,
intake_data ? JSON.stringify(intake_data) : "{}",
mode,
form_year_override || null,
revises_order_number || null,
revised_reason || null,
waive_deminimis_exemption === true,
waive_deminimis_reason || null,
myf && myf.length > 0 ? myf : null,
multi_year_discount_pct || null,
],
);
console.log(
`[compliance-orders] Created ${order_number}: ${service_slug} for ${customer_email}` +
(pricing_note ? ` [${pricing_note}]` : ""),
);
res.status(201).json({ ...result.rows[0], pricing_note: pricing_note || null });
} catch (err) {
console.error("[compliance-orders] Create error:", err);
res.status(500).json({ error: "Could not create compliance order." });
}
});
/**
* POST /api/v1/compliance-orders/batch
* Create multiple compliance orders linked by a shared batch_id.
* Applies 15% bundle discount when 2+ priced services are selected.
*/
router.post("/api/v1/compliance-orders/batch", async (req, res) => {
const {
services: rawServices,
customer_email,
customer_name,
customer_phone,
discount_code,
intake_data,
} = req.body ?? {};
if (!rawServices || !Array.isArray(rawServices) || rawServices.length === 0) {
res.status(400).json({ error: "services array is required." });
return;
}
if (!customer_email || !customer_name) {
res.status(400).json({ error: "customer_email and customer_name are required." });
return;
}
// Deduplicate and validate service slugs
let services = [...new Set(rawServices as string[])];
// If both 499a and 499a-499q selected, drop the standalone 499a
if (services.includes("fcc-499a") && services.includes("fcc-499a-499q")) {
services = services.filter(s => s !== "fcc-499a");
}
const invalid = services.filter(s => !COMPLIANCE_SERVICES[s]);
if (invalid.length > 0) {
res.status(400).json({
error: `Unknown service slugs: ${invalid.join(", ")}. Valid: ${Object.keys(COMPLIANCE_SERVICES).join(", ")}`,
});
return;
}
// At least one paid service required
const hasPaidService = services.some(s => COMPLIANCE_SERVICES[s].price_cents > 0);
if (!hasPaidService) {
res.status(400).json({ error: "At least one paid service is required." });
return;
}
// Split services into discountable vs non-discountable (e.g., RA services)
const discountableServices = services.filter(s => COMPLIANCE_SERVICES[s].discountable);
const nonDiscountableServices = services.filter(s => !COMPLIANCE_SERVICES[s].discountable);
const discountableTotal = discountableServices.reduce((sum, s) => sum + COMPLIANCE_SERVICES[s].price_cents, 0);
const nonDiscountableTotal = nonDiscountableServices.reduce((sum, s) => sum + COMPLIANCE_SERVICES[s].price_cents, 0);
// Government filing fees are passthrough — never discounted
const govFeeTotal = services.reduce((sum, s) => sum + (COMPLIANCE_SERVICES[s].gov_fee_cents || 0), 0);
const subtotal = discountableTotal + nonDiscountableTotal + govFeeTotal;
// Bundle discount applies only to discountable services
const bundleDiscountPct = discountableServices.filter(s => COMPLIANCE_SERVICES[s].price_cents > 0).length >= 2 ? 15 : 0;
const bundleDiscountCents = Math.round(discountableTotal * bundleDiscountPct / 100);
// Referral/promo code discount also applies only to discountable services
let promoDiscountCents = 0;
if (discount_code) {
try {
const disc = await pool.query(
`SELECT discount_pct, discount_flat_cents FROM discount_codes WHERE code = $1 AND active = true`,
[discount_code.toUpperCase().trim()],
);
if (disc.rows.length > 0) {
const d = disc.rows[0] as Record<string, unknown>;
const discountableAfterBundle = discountableTotal - bundleDiscountCents;
if ((d.discount_pct as number) > 0) {
promoDiscountCents = Math.round(discountableAfterBundle * (d.discount_pct as number) / 100);
} else if ((d.discount_flat_cents as number) > 0) {
promoDiscountCents = Math.min(d.discount_flat_cents as number, discountableAfterBundle);
}
}
} catch { /* discount_codes table may not exist */ }
}
const totalDiscountCents = bundleDiscountCents + promoDiscountCents;
const totalCents = subtotal - totalDiscountCents;
const batchId = `CB-${randomBytes(4).toString("hex").toUpperCase()}`;
try {
const orders: Record<string, unknown>[] = [];
let discountDistributed = 0;
const discountableCount = discountableServices.length;
let discountableIdx = 0;
for (const slug of services) {
const svc = COMPLIANCE_SERVICES[slug];
// Distribute discount proportionally — only across discountable services
// Last discountable service absorbs rounding remainder
let svcDiscount = 0;
if (svc.discountable && totalDiscountCents > 0) {
discountableIdx++;
if (discountableIdx === discountableCount) {
svcDiscount = totalDiscountCents - discountDistributed;
} else {
svcDiscount = Math.round(totalDiscountCents * svc.price_cents / (discountableTotal || 1));
}
discountDistributed += svcDiscount;
}
const orderNumber = generateOrderNumber();
const result = await pool.query(
`INSERT INTO compliance_orders (
order_number, batch_id, service_slug, service_name, service_fee_cents,
gov_fee_cents, gov_fee_label,
customer_email, customer_name, customer_phone,
discount_code, discount_cents, intake_data
) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13)
RETURNING *`,
[
orderNumber,
batchId,
slug,
svc.name,
svc.price_cents,
svc.gov_fee_cents || 0,
svc.gov_fee_label || null,
customer_email.toLowerCase().trim(),
customer_name.trim(),
customer_phone || null,
discount_code || null,
svcDiscount,
intake_data ? JSON.stringify(intake_data) : "{}",
],
);
orders.push(result.rows[0]);
}
console.log(
`[compliance-orders] Batch ${batchId}: ${services.length} orders for ${customer_email}$${(totalCents / 100).toFixed(2)}`,
);
res.status(201).json({
batch_id: batchId,
orders,
subtotal_cents: subtotal,
gov_fee_cents: govFeeTotal,
bundle_discount_pct: bundleDiscountPct,
bundle_discount_cents: bundleDiscountCents,
promo_discount_cents: promoDiscountCents,
total_discount_cents: totalDiscountCents,
total_cents: totalCents,
});
} catch (err) {
console.error("[compliance-orders] Batch create error:", err);
res.status(500).json({ error: "Could not create compliance orders." });
}
});
/**
* GET /api/v1/compliance-orders/:id
* Supports both single order lookup (CO-XXXXXXXX) and batch lookup (CB-XXXXXXXX).
*/
router.get("/api/v1/compliance-orders/:id", async (req, res) => {
const id = req.params.id;
try {
// Check if this is a batch ID (CB-) or single order (CO-)
if (id.startsWith("CB-")) {
const result = await pool.query(
`SELECT co.*,
te.legal_name as entity_name,
te.frn as entity_frn
FROM compliance_orders co
LEFT JOIN telecom_entities te ON te.id = co.telecom_entity_id
WHERE co.batch_id = $1
ORDER BY co.created_at`,
[id],
);
if (result.rows.length === 0) {
res.status(404).json({ error: "Batch not found." });
return;
}
const orders = result.rows;
const allPaid = orders.every((o: any) => o.payment_status === "paid");
res.json({
batch_id: id,
payment_status: allPaid ? "paid" : (orders[0] as any).payment_status,
orders,
order_number: id,
});
return;
}
// Single order lookup
const result = await pool.query(
`SELECT co.*,
te.legal_name as entity_name,
te.frn as entity_frn
FROM compliance_orders co
LEFT JOIN telecom_entities te ON te.id = co.telecom_entity_id
WHERE co.order_number = $1`,
[id],
);
if (result.rows.length === 0) {
res.status(404).json({ error: "Order not found." });
return;
}
res.json(result.rows[0]);
} catch (err) {
console.error("[compliance-orders] Get error:", err);
res.status(500).json({ error: "Could not fetch order." });
}
});
/**
* GET /api/v1/compliance-orders/:order_number/recommendations
*
* Returns the list of recommended remediation services produced by the
* FCC Compliance Checkup handler (see migration 047 — `recommended_slugs`
* column, populated by `_persist_recommendations` in
* `scripts/workers/services/fcc_compliance_checkup.py`).
*
* Response:
* {
* slugs: ["rmd-filing", "cpni-certification"],
* bundle_eligible: true,
* bundle_discount_pct: 15,
* individual_urls: [
* { slug, name, price_cents, checkout_url },
* ...
* ],
* bundle_url: "https://site/checkout/compliance-bundle?..."
* }
*
* Consumed by:
* - delivery_worker.py — builds the upsell block in the email
* - the compliance checkup PDF appendix (bundle_url is embedded there too)
* - the customer portal's /orders page (when it lists remediation CTAs)
*/
router.get(
"/api/v1/compliance-orders/:order_number/recommendations",
async (req, res) => {
const orderNumber = req.params.order_number;
try {
const orderResult = await pool.query(
`SELECT co.order_number, co.customer_email, co.customer_name,
co.telecom_entity_id, co.recommended_slugs
FROM compliance_orders co
WHERE co.order_number = $1`,
[orderNumber],
);
if (orderResult.rows.length === 0) {
res.status(404).json({ error: "Order not found." });
return;
}
const order = orderResult.rows[0] as {
order_number: string;
customer_email: string;
customer_name: string;
telecom_entity_id: number | null;
recommended_slugs: string[] | null;
};
const slugs = (order.recommended_slugs ?? []).filter(
(s) => s in COMPLIANCE_SERVICES,
);
// Common querystring: prefill the order form with the customer's
// email/name/entity so the checkout is one click.
const prefill = new URLSearchParams({
email: order.customer_email,
name: order.customer_name,
});
if (order.telecom_entity_id) {
prefill.set("entity", String(order.telecom_entity_id));
}
prefill.set("source", `checkup:${order.order_number}`);
const siteBase =
process.env.SITE_URL ||
(process.env.DOMAIN ? `https://${process.env.DOMAIN}` : "https://performancewest.net");
const individual_urls = slugs
.filter((s) => s !== "fcc-full-compliance")
.map((slug) => {
const svc = COMPLIANCE_SERVICES[slug];
return {
slug,
name: svc.name,
price_cents: svc.price_cents,
gov_fee_cents: svc.gov_fee_cents || 0,
gov_fee_label: svc.gov_fee_label || null,
checkout_url: `${siteBase}/order/${slug}?${prefill.toString()}`,
};
});
// Bundle URL hits the batch create endpoint, which already applies
// the 15% discount when 2+ discountable services are selected
// (compliance-orders.ts:237). We pass the slugs in querystring so
// the frontend can POST them.
const bundleSlugs = slugs.filter((s) => s !== "fcc-full-compliance");
const bundleParams = new URLSearchParams(prefill);
for (const s of bundleSlugs) {
bundleParams.append("service", s);
}
const bundle_eligible = bundleSlugs.length >= 2;
const bundle_url = bundle_eligible
? `${siteBase}/order/compliance-bundle?${bundleParams.toString()}`
: null;
res.json({
order_number: orderNumber,
slugs,
bundle_eligible,
bundle_discount_pct: bundle_eligible ? 15 : 0,
individual_urls,
bundle_url,
});
} catch (err) {
console.error("[compliance-orders] Recommendations error:", err);
res.status(500).json({ error: "Could not fetch recommendations." });
}
},
);
/**
* POST /api/v1/compliance-orders/:order_number/approve-and-file
*
* Admin-review approval endpoint. When the global auto-filing toggle in
* the ERPNext `Compliance Settings` DocType is OFF (the default), every
* FCC/USAC filing handler stages its packet for review instead of
* submitting. The admin email + ToDo each include a link to this
* endpoint; hitting it flips `custom_auto_filing_override = 1` on the
* linked Sales Order and re-dispatches the worker job so the handler
* re-runs and (this time) actually submits to the FCC.
*
* Idempotent: safe to call multiple times; the handler's own idempotency
* check prevents double-filing.
*
* Auth: requires a valid admin bearer token. During local development a
* fallback `APPROVE_FILE_TOKEN` env var is accepted.
*/
router.post(
"/api/v1/compliance-orders/:order_number/approve-and-file",
async (req, res) => {
const orderNumber = req.params.order_number;
// Token gate — cheap header check; the ERPNext side is authoritative.
const headerToken = (req.headers["authorization"] || "")
.toString()
.replace(/^Bearer\s+/i, "")
.trim();
const expected = process.env.APPROVE_FILE_TOKEN || "";
if (!expected || headerToken !== expected) {
res.status(401).json({ error: "Unauthorized" });
return;
}
try {
const { rows } = await pool.query(
`SELECT order_number, service_slug, erpnext_sales_order,
telecom_entity_id, payment_status
FROM compliance_orders
WHERE order_number = $1`,
[orderNumber],
);
if (rows.length === 0) {
res.status(404).json({ error: "Order not found." });
return;
}
const order = rows[0] as {
order_number: string;
service_slug: string;
erpnext_sales_order: string | null;
telecom_entity_id: number | null;
payment_status: string;
};
if (order.payment_status !== "paid") {
res.status(409).json({
error: `Cannot approve-and-file: payment_status is ${order.payment_status}.`,
});
return;
}
if (!order.erpnext_sales_order) {
res.status(409).json({
error: "Order has no linked ERPNext Sales Order.",
});
return;
}
// 1. Flip the per-order override on the Sales Order.
const { callMethod, updateResource } = await import(
"../erpnext-client.js"
);
await updateResource("Sales Order", order.erpnext_sales_order, {
custom_auto_filing_override: 1,
});
// 2. Re-dispatch the worker job for this order. The job_server.py
// ``process_compliance_service`` handler expects order_name +
// service_slug + order_number in the payload.
try {
await callMethod("frappe.client.insert", {
doc: {
doctype: "Integration Request",
integration_request_service: "Compliance Filing Rerun",
data: JSON.stringify({
action: "process_compliance_service",
payload: {
order_name: order.erpnext_sales_order,
order_number: order.order_number,
service_slug: order.service_slug,
},
}),
status: "Queued",
},
});
} catch (dispatchErr) {
// Non-fatal — the override is flipped; the worker will re-run the
// handler on the next scheduled poll or workflow transition.
console.warn(
"[compliance-orders] approve-and-file: dispatch warning (non-fatal):",
dispatchErr,
);
}
res.json({
success: true,
order_number: order.order_number,
sales_order: order.erpnext_sales_order,
message: "Auto-filing override set. The filing handler will re-run and submit to the FCC.",
});
} catch (err) {
console.error("[compliance-orders] approve-and-file error:", err);
res.status(500).json({ error: "Could not approve and file." });
}
},
);
/**
* POST /api/v1/compliance-orders/:order_number/validate
*
* Dry-run validator invoked by the intake wizard's Review step BEFORE
* handing the user off to Stripe Checkout. Returns:
* - 200: { ok: true, soft_warnings: [...] } — OK to proceed to checkout
* - 422: { ok: false, missing: [...], soft_warnings: [...] } — block checkout
*
* Also writes the result to compliance_orders.intake_data_validated +
* validation_errors so a subsequent checkout attempt short-circuits with
* the same error.
*/
router.post(
"/api/v1/compliance-orders/:order_number/validate",
async (req, res) => {
const orderNumber = req.params.order_number;
try {
const orderResult = await pool.query(
`SELECT co.*, te.*
FROM compliance_orders co
LEFT JOIN telecom_entities te ON te.id = co.telecom_entity_id
WHERE co.order_number = $1`,
[orderNumber],
);
if (orderResult.rows.length === 0) {
res.status(404).json({ error: "order not found" });
return;
}
const row = orderResult.rows[0] as Record<string, unknown>;
const slug = (row.service_slug as string) || "";
const spec = REQUIRED_FIELDS[slug];
if (!spec) {
await pool.query(
"UPDATE compliance_orders SET intake_data_validated=TRUE, validation_errors=NULL WHERE order_number=$1",
[orderNumber],
);
res.json({ ok: true, missing: [], soft_warnings: [], calculations: {} });
return;
}
// Merge intake_data with entity columns into one lookup source so
// predicates/validators can reference either (e.g., entity columns
// like officer_count_claimed, or intake_data paths like
// revenue.line_303).
const intake = (row.intake_data as Record<string, unknown>) || {};
const src: Record<string, unknown> = { ...row, ...intake };
// Flatten safe_harbor_election[primary].* so predicate rules can
// reference it as `safe_harbor_election.method` without knowing
// which category is primary.
const sheRaw = src.safe_harbor_election as Record<string, unknown> | undefined;
const primaryCat = (src.line_105_primary as string) || "";
if (sheRaw && primaryCat && sheRaw[primaryCat] && typeof sheRaw[primaryCat] === "object") {
src.safe_harbor_election = {
...(sheRaw as object),
...(sheRaw[primaryCat] as object), // method, pct, year, q at top level
};
}
const missing = spec.required.filter((k) => isEmpty(digField(src, k)));
const soft = spec.soft.filter((k) => isEmpty(digField(src, k)));
const rejections: string[] = [];
// ── Conditional rules ──────────────────────────────────────────
if (spec.conditional) {
for (const rule of spec.conditional) {
if (!evalPredicate(rule.when, src)) continue;
if (rule.reject) {
rejections.push(rule.reject);
continue;
}
for (const k of rule.require || []) {
if (isEmpty(digField(src, k))) missing.push(k);
}
}
}
// Entity-level FRN gate
if (REQUIRES_ENTITY_FRN.has(slug) && !row.frn) {
missing.push("telecom_entity.frn");
}
// ── Cross-field validators ─────────────────────────────────────
let xErrors: string[] = [];
let xWarnings: string[] = [];
let calculations: Record<string, unknown> = {};
if (spec.validators && spec.validators.length > 0) {
const xv = await runCrossFieldValidators(
spec.validators, src, row, Number(row.id),
);
xErrors = xv.errors;
xWarnings = xv.warnings;
calculations = xv.calculations;
}
const allErrors = [...rejections, ...xErrors];
const ok = missing.length === 0 && allErrors.length === 0;
const result = {
ok,
missing,
rejections: allErrors,
soft_warnings: [...soft, ...xWarnings],
calculations,
checked_at: new Date().toISOString(),
};
await pool.query(
`UPDATE compliance_orders
SET intake_data_validated = $2,
validation_errors = $3::jsonb
WHERE order_number = $1`,
[orderNumber, ok, JSON.stringify(result)],
);
if (!ok) {
res.status(422).json(result);
return;
}
res.json(result);
} catch (err) {
console.error("[compliance-orders] validate error:", err);
res.status(500).json({ error: "validation failed" });
}
},
);
/**
* POST /api/v1/compliance-orders/:id/usac-delegation
* Customer confirms they've completed USAC E-File delegation.
* Updates order status and notifies the team to begin filing.
*/
router.post("/api/v1/compliance-orders/:id/usac-delegation", async (req, res) => {
const id = req.params.id;
try {
// Support both batch ID (CB-) and order number (CO-)
const whereCol = id.startsWith("CB-") ? "batch_id" : "order_number";
const result = await pool.query(
`UPDATE compliance_orders
SET intake_data = jsonb_set(
COALESCE(intake_data, '{}'::jsonb),
'{usac_delegation_confirmed}',
to_jsonb(now()::text)
),
updated_at = NOW()
WHERE ${whereCol} = $1
AND service_slug IN ('fcc-499a', 'fcc-499a-499q')
RETURNING order_number, service_slug, customer_email`,
[id],
);
if (result.rows.length === 0) {
res.status(404).json({ error: "No 499-A order found for this ID." });
return;
}
console.log(`[compliance-orders] USAC delegation confirmed for ${id} (${result.rows.length} orders)`);
res.json({
success: true,
message: "Thank you! We've been notified that delegation is complete and will begin your filing within 1 business day.",
orders_updated: result.rows.length,
});
} catch (err) {
console.error("[compliance-orders] USAC delegation error:", err);
res.status(500).json({ error: "Could not record delegation confirmation." });
}
});
export { COMPLIANCE_SERVICES, REQUIRED_FIELDS };
export default router;