/** * 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 = { "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 = 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, dottedKey: string): unknown { return dottedKey.split(".").reduce( (acc, part) => { if (acc && typeof acc === "object" && !Array.isArray(acc)) { return (acc as Record)[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, 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): 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).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, entity: Record, orderId: number, ): Promise<{ errors: string[]; warnings: string[]; calculations: Record; }> { const errors: string[] = []; const warnings: string[] = []; const calculations: Record = {}; 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) || {}; // Flatten revenue.{line_xxx} into {line_xxx: n} const flat: Record = {}; 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).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, 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; 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; 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[] = []; 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; 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) || {}; const src: Record = { ...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 | 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 = {}; 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;