new-site/scripts/workers/services/fcc_full_compliance.py
justin f8cd37ac8c Initial commit — Performance West telecom compliance platform
Includes: API (Express/TypeScript), Astro site, Python workers,
document generators, FCC compliance tools, Canada CRTC formation,
Ansible infrastructure, and deployment scripts.

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

88 lines
3 KiB
Python

"""FCC Full Compliance Bundle.
Composes the four individual remediation handlers in sequence:
1. RMD Registration / Recertification
2. CPNI Annual Certification
3. STIR/SHAKEN Implementation Assistance (which itself runs the RMD
flow with the updated posture, plus opens the STI-CA ToDo)
4. FCC Form 499-A + 499-Q Bundle
Each sub-handler is idempotent (see
``scripts/workers/services/telecom/filing_state.py``), so running this
bundle when some filings are already current only produces net-new
submissions.
"""
from __future__ import annotations
import logging
from .base_handler import BaseServiceHandler
from .rmd_filing import RMDFilingHandler
from .cpni_certification import CPNIFilingHandler
from .stir_shaken import StirShakenHandler
from .form_499a import Form499ABundleHandler
logger = logging.getLogger(__name__)
class FullComplianceHandler(BaseServiceHandler):
SERVICE_SLUG = "fcc-full-compliance"
SERVICE_NAME = "FCC Full Compliance Bundle"
REQUIRES_LLM = False
# In run order. Each sub-handler returns its own generated files; we
# concatenate them.
SUB_HANDLERS = (
RMDFilingHandler,
CPNIFilingHandler,
StirShakenHandler,
Form499ABundleHandler,
)
async def process(self, order_data: dict) -> list[str]:
generated: list[str] = []
order_number = order_data.get("name", "")
for cls in self.SUB_HANDLERS:
sub = cls()
try:
files = await sub.process(order_data)
if files:
generated.extend(files)
logger.info(
"FullComplianceHandler: %s produced %d file(s) for %s",
cls.__name__, len(files or []), order_number,
)
except Exception as exc:
logger.exception(
"FullComplianceHandler: %s failed for %s: %s",
cls.__name__, order_number, exc,
)
# Record the failure on an admin ToDo but keep going —
# a failure in one sub-handler should not block the rest.
self._record_sub_failure(order_number, cls.__name__, exc)
return generated
def _record_sub_failure(
self, order_number: str, sub_name: str, exc: Exception
) -> None:
try:
from scripts.workers.erpnext_client import ERPNextClient
ERPNextClient().create_resource(
"ToDo",
{
"description": (
f"[{self.SERVICE_SLUG}] {order_number}\n\n"
f"Sub-handler {sub_name} failed: {exc}. The other sub-handlers "
f"ran to completion; this one needs manual follow-up."
),
"priority": "High",
"role": "Accounting Advisor",
},
)
except Exception as erp_exc:
logger.error("Could not create sub-failure ToDo: %s", erp_exc)