From 3e04a8fc16797026b358a08d30cae88d56a70c2f Mon Sep 17 00:00:00 2001 From: justin Date: Sun, 3 May 2026 02:04:18 -0500 Subject: [PATCH] Add zero-revenue 499-A filing at $179 New service slug fcc-499a-zero for carriers with no telecom revenue: - $179 instead of $499 (no revenue analysis needed) - Minimal intake: entity, officer, filer ID, filing type only - Skips revenue schedules (blocks 3-4), USF calculations (block 5), traffic study upload, and revenue workbook generation - Fills blocks 1-2 and 6 only, all revenue lines left as zero Compliance checker: shows both options (mutually exclusive checkboxes) Order page: maps form_499a_zero to fcc-499a-zero slug Handler: detects slug and skips revenue pipeline DC Agent shown when either 499-A variant is checked Co-Authored-By: Claude Opus 4.6 (1M context) --- api/src/routes/compliance-orders.ts | 23 ++++++- scripts/workers/services/__init__.py | 2 + scripts/workers/services/form_499a.py | 68 +++++++++++-------- site/public/order/fcc-compliance/index.html | 7 ++ .../pages/tools/fcc-compliance-check.astro | 35 ++++++++-- 5 files changed, 98 insertions(+), 37 deletions(-) diff --git a/api/src/routes/compliance-orders.ts b/api/src/routes/compliance-orders.ts index bf9c9dc..dc7a086 100644 --- a/api/src/routes/compliance-orders.ts +++ b/api/src/routes/compliance-orders.ts @@ -32,6 +32,12 @@ const COMPLIANCE_SERVICES: Record< erpnext_item: "FCC-499A", discountable: true, }, + "fcc-499a-zero": { + name: "FCC Form 499-A Filing (Zero Revenue)", + price_cents: 17900, + erpnext_item: "FCC-499A-ZERO", + discountable: true, + }, "fcc-499a-499q": { name: "FCC Form 499-A + 499-Q Bundle", price_cents: 59900, @@ -284,6 +290,17 @@ const REQUIRED_FIELDS: Record = { ], validators: ["lnpa_sums_100", "de_minimis_calc", "trs_base_nonnegative"], }, + // Zero-revenue 499-A: minimal intake — no revenue schedules, no traffic study + "fcc-499a-zero": { + required: [ + "entity_structure", + "officer_1_name", "officer_1_title", + "officer_1_street", "officer_1_city", "officer_1_state", "officer_1_zip", + "filer_id_499", + "filing_type", + ], + soft: ["ceo_name", "trade_names"], + }, "fcc-499a-499q": { required: [ "line_105_primary", "line_105_categories", @@ -340,7 +357,7 @@ const REQUIRED_FIELDS: Record = { // 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", + "rmd-filing", "cpni-certification", "fcc-499a", "fcc-499a-zero", "fcc-499a-499q", "fcc-499-initial", "stir-shaken", "bdc-filing", "bdc-broadband", "bdc-voice", "calea-ssi", "fcc-63-11-notification", "fcc-full-compliance", ]); @@ -393,7 +410,7 @@ function resolveOrderFeeCents( // 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 (["fcc-499a", "fcc-499a-zero", "fcc-499a-499q"].includes(slug)) { if (waive_deminimis) { // Waive → full price, overrides any de minimis discount perYearPrice = service.price_cents; @@ -738,7 +755,7 @@ router.post("/api/v1/compliance-orders", async (req, res) => { .map((y: unknown) => Number(y)) : null; if (myf && myf.length > 0) { - if (!["fcc-499a", "fcc-499a-499q"].includes(service_slug)) { + if (!["fcc-499a", "fcc-499a-zero", "fcc-499a-499q"].includes(service_slug)) { res.status(400).json({ error: "multi_year_filings only supported for fcc-499a / fcc-499a-499q.", }); diff --git a/scripts/workers/services/__init__.py b/scripts/workers/services/__init__.py index f9a417a..6ed94cc 100644 --- a/scripts/workers/services/__init__.py +++ b/scripts/workers/services/__init__.py @@ -61,6 +61,7 @@ SERVICE_HANDLERS: dict[str, type] = { "rmd-filing": RMDFilingHandler, "cpni-certification": CPNIFilingHandler, "fcc-499a": Form499AHandler, + "fcc-499a-zero": Form499AHandler, # same handler, zero_revenue flag set from slug "fcc-499a-499q": Form499ABundleHandler, "stir-shaken": StirShakenHandler, # BDC triple — same handler, mode auto-resolved from slug @@ -96,6 +97,7 @@ FCC_SERVICE_SLUGS: frozenset[str] = frozenset({ "rmd-filing", "cpni-certification", "fcc-499a", + "fcc-499a-zero", "fcc-499a-499q", "stir-shaken", "bdc-filing", diff --git a/scripts/workers/services/form_499a.py b/scripts/workers/services/form_499a.py index 78b3fa8..8bb9b97 100644 --- a/scripts/workers/services/form_499a.py +++ b/scripts/workers/services/form_499a.py @@ -419,27 +419,29 @@ class Form499AHandler(BaseServiceHandler): except Exception as exc: logger.warning("499-A checklist PDF conversion failed: %s", exc) - try: - from scripts.document_gen.templates.form_499a_revenue_workbook_generator import ( - generate_499a_revenue_workbook, - ) - workbook_path = os.path.join( - work_dir, f"fcc_499a_revenue_workbook_{order_number}_{date_str}.xlsx", - ) - traffic_study = self._load_traffic_study(entity.get("id")) - wb_result = generate_499a_revenue_workbook( - entity_name=entity.get("legal_name", ""), - filer_id_499=entity.get("filer_id_499", ""), - frn=entity.get("frn", ""), - reporting_year=int(entity.get("last_filing_year") or 0) - or (datetime.utcnow().year - 1), - traffic_study=traffic_study, - output_path=workbook_path, - ) - if wb_result: - generated.append(wb_result) - except Exception as exc: - logger.warning("499-A revenue workbook generation failed: %s", exc) + # Skip revenue workbook for zero-revenue filings + if order_data.get("service_slug") != "fcc-499a-zero": + try: + from scripts.document_gen.templates.form_499a_revenue_workbook_generator import ( + generate_499a_revenue_workbook, + ) + workbook_path = os.path.join( + work_dir, f"fcc_499a_revenue_workbook_{order_number}_{date_str}.xlsx", + ) + traffic_study = self._load_traffic_study(entity.get("id")) + wb_result = generate_499a_revenue_workbook( + entity_name=entity.get("legal_name", ""), + filer_id_499=entity.get("filer_id_499", ""), + frn=entity.get("frn", ""), + reporting_year=int(entity.get("last_filing_year") or 0) + or (datetime.utcnow().year - 1), + traffic_study=traffic_study, + output_path=workbook_path, + ) + if wb_result: + generated.append(wb_result) + except Exception as exc: + logger.warning("499-A revenue workbook generation failed: %s", exc) return generated @@ -529,14 +531,24 @@ class Form499AHandler(BaseServiceHandler): await page.click('text="Form 499-A"') await human_delay() - revenue_lines = self._build_revenue_lines(entity, intake_data) + is_zero_revenue = order_data.get("service_slug") == "fcc-499a-zero" - await self._phase_block_1(page, entity, intake_data) - await self._phase_block_2(page, entity, intake_data) - await self._phase_blocks_3_4(page, entity, intake_data, revenue_lines) - await self._phase_block_5(page, entity, intake_data, revenue_lines) - await self._phase_block_6(page, entity, intake_data) - await self._phase_submit_traffic_study(page, entity, work_dir) + if is_zero_revenue: + # Zero-revenue filing: skip revenue schedules and traffic study + logger.info("Zero-revenue 499-A — skipping blocks 3-5 and traffic study") + revenue_lines = {} + await self._phase_block_1(page, entity, intake_data) + await self._phase_block_2(page, entity, intake_data) + # Blocks 3-4 (revenue) and 5 (USF) left as zero + await self._phase_block_6(page, entity, intake_data) + else: + revenue_lines = self._build_revenue_lines(entity, intake_data) + await self._phase_block_1(page, entity, intake_data) + await self._phase_block_2(page, entity, intake_data) + await self._phase_blocks_3_4(page, entity, intake_data, revenue_lines) + await self._phase_block_5(page, entity, intake_data, revenue_lines) + await self._phase_block_6(page, entity, intake_data) + await self._phase_submit_traffic_study(page, entity, work_dir) await human_delay(1.5, 3.0) await page.click('button:has-text("Review")') diff --git a/site/public/order/fcc-compliance/index.html b/site/public/order/fcc-compliance/index.html index a78ac98..961a8e1 100644 --- a/site/public/order/fcc-compliance/index.html +++ b/site/public/order/fcc-compliance/index.html @@ -144,6 +144,7 @@ window._existingOCN = ""; var CHECK_TO_SLUG = { cpni:"cpni-certification", cpni_certification:"cpni-certification", "499a":"fcc-499a", form_499a:"fcc-499a", + form_499a_zero:"fcc-499a-zero", "499a-zero":"fcc-499a-zero", "499q":"fcc-499a-499q", form_499q:"fcc-499a-499q", rmd:"rmd-filing", rmd_filing:"rmd-filing", stir:"stir-shaken", stir_shaken:"stir-shaken", @@ -159,6 +160,7 @@ var CHECK_TO_SLUG = { var SLUG_META = { "cpni-certification": {label:"CPNI Annual Certification", price:14900, desc:"47 CFR § 64.2009 annual CPNI cert filed to FCC ECFS", order:"/order/cpni-certification"}, "fcc-499a": {label:"FCC Form 499-A Filing", price:49900, desc:"Annual USF contribution filing at USAC E-File", order:"/order/fcc-499a"}, + "fcc-499a-zero": {label:"FCC Form 499-A (Zero Revenue)", price:17900, desc:"For carriers with no telecom revenue", order:"/order/fcc-499a"}, "fcc-499a-499q": {label:"FCC 499-A + 499-Q Bundle", price:59900, desc:"Annual + quarterly USF projections", order:"/order/fcc-499a-499q"}, "rmd-filing": {label:"RMD Registration / Recertification", price:21900, gov_fee:10000, gov_fee_label:"FCC RMD filing fee", desc:"Robocall Mitigation Database filing + $100 FCC filing fee", order:"/order/rmd-filing"}, "stir-shaken": {label:"STIR/SHAKEN Implementation", price:49900, desc:"STIR/SHAKEN certificate + attestation setup", order:"/order/stir-shaken"}, @@ -180,6 +182,8 @@ var frn=params.get("frn")||""; var slugs=[]; var seen={}; rawKeys.forEach(function(k){var s=CHECK_TO_SLUG[k]||k; if(SLUG_META[s]&&!seen[s]){slugs.push(s);seen[s]=1}}); if(slugs.indexOf("fcc-499a")>=0&&slugs.indexOf("fcc-499a-499q")>=0) slugs.splice(slugs.indexOf("fcc-499a"),1); +// Zero-revenue and full 499-A are mutually exclusive +if(slugs.indexOf("fcc-499a")>=0&&slugs.indexOf("fcc-499a-zero")>=0) slugs.splice(slugs.indexOf("fcc-499a-zero"),1); var listEl=document.getElementById("pw-svc-list"); var entityBar=document.getElementById("pw-entity-bar"); @@ -253,6 +257,9 @@ function renderServices() { // Deduplicate 499a/499a-499q if(s==="fcc-499a"&&e.target.checked&&selectedSlugs.indexOf("fcc-499a-499q")>=0) selectedSlugs=selectedSlugs.filter(function(x){return x!=="fcc-499a-499q"}); if(s==="fcc-499a-499q"&&e.target.checked&&selectedSlugs.indexOf("fcc-499a")>=0) selectedSlugs=selectedSlugs.filter(function(x){return x!=="fcc-499a"}); + // Zero-revenue ↔ full 499-A mutual exclusion + if(s==="fcc-499a"&&e.target.checked) selectedSlugs=selectedSlugs.filter(function(x){return x!=="fcc-499a-zero"}); + if(s==="fcc-499a-zero"&&e.target.checked) selectedSlugs=selectedSlugs.filter(function(x){return x!=="fcc-499a"&&x!=="fcc-499a-499q"}); // STIR/SHAKEN requires OCN — auto-add if not already present if(s==="stir-shaken"&&e.target.checked&&selectedSlugs.indexOf("ocn-registration")<0&&!window._hasExistingOCN) { selectedSlugs.push("ocn-registration"); diff --git a/site/src/pages/tools/fcc-compliance-check.astro b/site/src/pages/tools/fcc-compliance-check.astro index 3cda22b..be0d2fb 100644 --- a/site/src/pages/tools/fcc-compliance-check.astro +++ b/site/src/pages/tools/fcc-compliance-check.astro @@ -777,7 +777,8 @@ import Base from "../../layouts/Base.astro"; services.push({ id: "stir_shaken", name: "STIR/SHAKEN Implementation", desc: "", price: 499 }); break; case "form_499a": - services.push({ id: "form_499a", name: "Form 499-A Filing", desc: "", price: 499 }); + services.push({ id: "form_499a", name: "Form 499-A Filing", desc: "with revenue", price: 499 }); + services.push({ id: "form_499a_zero", name: "Form 499-A (Zero Revenue)", desc: "no telecom revenue", price: 179, altOf: "form_499a" }); if (s === "red") { services.push({ id: "dc_agent", name: "D.C. Registered Agent", desc: "", price: 99, priceLabel: "$99/yr" }); } @@ -813,10 +814,11 @@ import Base from "../../layouts/Base.astro"; html += `
`; for (const svc of services) { - const checked = svc.price > 0 && svc.id !== "stir_shaken" ? "checked" : ""; + // altOf items start unchecked (they're alternatives to the main item) + const checked = svc.price > 0 && svc.id !== "stir_shaken" && !svc.altOf ? "checked" : ""; const priceLabel = svc.priceLabel || (svc.price > 0 ? `$${svc.price}` : svc.desc || "included"); - html += `