new-site/scripts/workers/services/form_499a_discontinuance.py
justin 5e74c1dcb9 Split discontinuance CTA into two options based on revenue
When user selects "cancel registration" in the compliance checker:
- Option 1: "499-A Discontinuance (incl. zero-revenue filing)" $299
  For carriers with no revenue — includes final zero-revenue 499-A
  + deactivation letter + CORES update
- Option 2: "499-A Filing + Discontinuance" $798 ($499+$299)
  For carriers with actual revenue — full 499-A filed separately
  + deactivation process

Standalone discontinuance ($299) is for carriers already current
on filings who just want to close out.

Handler detects whether zero-revenue filing is included vs
handled by a separate full 499-A order.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-03 03:39:52 -05:00

150 lines
7.3 KiB
Python

"""FCC Form 499-A Discontinuance Filing Handler.
For carriers who no longer provide telecommunications services and need
to close out their USAC 499-A filing obligations. Files a final 499-A
with zero revenue and requests discontinuance status from USAC.
This is typically for:
- Pure broadband resale ISPs who were incorrectly filing 499-A
- Carriers who have ceased operations
- Companies that were acquired and the FRN is being retired
"""
from __future__ import annotations
import logging
import os
from datetime import datetime
from .base_handler import BaseComplianceHandler
logger = logging.getLogger("workers.services.form_499a_discontinuance")
class Form499ADiscontinuanceHandler(BaseComplianceHandler):
SERVICE_SLUG = "fcc-499a-discontinuance"
SERVICE_NAME = "Form 499-A Discontinuance Filing"
async def process(self, order_data: dict) -> dict | None:
order_number = order_data.get("order_number", "")
entity = order_data.get("entity", {})
intake_data = order_data.get("intake_data", {})
filer_id = intake_data.get("filer_id_499") or entity.get("filer_id_499", "")
frn = intake_data.get("frn") or entity.get("frn", "")
legal_name = entity.get("legal_name") or intake_data.get("entity_name", "")
logger.info(
"Form499ADiscontinuanceHandler: %s for %s (FRN: %s, Filer ID: %s)",
order_number, legal_name, frn, filer_id,
)
discontinuance_reason = intake_data.get("discontinuance_reason", "Ceased providing telecommunications services")
last_service_date = intake_data.get("last_service_date", "")
# If ordered as standalone discontinuance ($299), includes a zero-revenue
# final filing. If ordered with a full 499-A ($499+$299), the 499-A handler
# files the revenue report separately — we just handle the deactivation.
includes_zero_filing = not intake_data.get("has_separate_499a", False)
# Per FCC 499-A Instructions: discontinuance requires TWO steps:
# 1. File the final 499-A (may have actual revenue from the portion
# of the year the company operated — NOT required to be zero)
# 2. Submit a deactivation letter to USAC within 30 days of ceasing service
#
# Line 603: check TRS/LNP/NANPA exemption boxes, write
# "Not in business as of filing date" on the explanation line
self._create_admin_todo(
order_number,
f"FILE 499-A DISCONTINUANCE for {legal_name}\n\n"
f"FRN: {frn}\n"
f"Filer ID: {filer_id}\n"
f"Reason: {discontinuance_reason}\n"
f"Last service date: {last_service_date or 'Not specified'}\n\n"
f"STEP 1 — File Final 499-A {'(ZERO REVENUE — included in this order)' if includes_zero_filing else '(filed separately via full 499-A order)'}:\n"
f" Log in to USAC E-File (https://forms.universalservice.org/)\n"
f" {'File a zero-revenue 499-A (all revenue lines $0).' if includes_zero_filing else 'The full 499-A with actual revenue is being filed under a separate order.'}\n"
f" On Line 603, check all exemption boxes (TRS, LNP, NANPA)\n"
f" and write 'Not in business as of {last_service_date or 'filing date'}'\n"
f" on the explanation line.\n\n"
f"STEP 2 — Submit USAC Deactivation Letter:\n"
f" Send letter to USAC (Form499@usac.org) with:\n"
f" - Company name: {legal_name}\n"
f" - Filer ID: {filer_id}\n"
f" - FRN: {frn}\n"
f" - Termination date: {last_service_date or 'TBD'}\n"
f" - Reason: {discontinuance_reason}\n"
f" - Successor entity: {intake_data.get('successor_entity', 'None')}\n"
f" Must be submitted within 30 days of ceasing service.\n"
f" Processing takes up to 60-90 days.\n\n"
f"STEP 3 — Update CORES:\n"
f" Update FCC CORES registration to reflect inactive status.\n\n"
f"STEP 4 — Related Filings:\n"
f" Confirm CPNI, RMD, and BDC filings are also discontinued.\n\n"
f"Client email: {entity.get('contact_email') or order_data.get('customer_email', '')}",
)
# Send confirmation to client
self._send_confirmation(
to=entity.get("contact_email") or order_data.get("customer_email", ""),
entity_name=legal_name,
order_number=order_number,
filer_id=filer_id,
)
return {"status": "submitted_for_processing"}
def _send_confirmation(
self, to: str, entity_name: str, order_number: str, filer_id: str,
) -> None:
if not to:
return
try:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
subject = f"Form 499-A Discontinuance Filed — {entity_name}"
html = f"""
<div style="font-family:Inter,sans-serif;max-width:600px;margin:0 auto;color:#1f2937">
<div style="background:#1e3a5f;padding:16px 24px;border-radius:8px 8px 0 0">
<h2 style="color:#fff;margin:0;font-size:16px">Form 499-A Discontinuance</h2>
</div>
<div style="padding:24px;border:1px solid #e5e7eb;border-top:none;border-radius:0 0 8px 8px">
<p>We've received your request to discontinue the FCC Form 499-A filing
obligation for <strong>{entity_name}</strong> (Filer ID: {filer_id}).</p>
<p>We will:</p>
<ol style="font-size:14px;color:#374151;padding-left:1.25rem">
<li>File your final Form 499-A reporting revenue for the period you were in service (this may be zero or actual revenue for a partial year)</li>
<li>Submit a deactivation letter to USAC requesting closure of your filer account</li>
<li>Update your FCC CORES registration to reflect inactive status</li>
<li>Confirm discontinuance of related obligations (CPNI, RMD, BDC)</li>
</ol>
<p>USAC processing takes 60-90 days. You'll receive a confirmation
email at each step. During this period, you won't receive new
invoices for USF contributions.</p>
<p style="font-size:13px;color:#6b7280;margin-top:1rem">
Order: {order_number}<br>
Questions? Reply to this email or contact
<a href="mailto:ops@performancewest.net">ops@performancewest.net</a>.
</p>
</div>
</div>
"""
msg = MIMEMultipart("alternative")
msg["From"] = os.environ.get("SMTP_FROM", "Performance West <noreply@performancewest.net>")
msg["To"] = to
msg["Subject"] = subject
msg.attach(MIMEText(html, "html"))
with smtplib.SMTP(
os.environ.get("SMTP_HOST", "co.carrierone.com"),
int(os.environ.get("SMTP_PORT", "587")),
timeout=30,
) as s:
s.starttls()
s.login(os.environ.get("SMTP_USER", ""), os.environ.get("SMTP_PASS", ""))
s.send_message(msg)
except Exception as exc:
logger.warning("Discontinuance confirmation email failed: %s", exc)