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>
126 lines
5 KiB
Python
126 lines
5 KiB
Python
"""NECA OCN / Company Code registration handler.
|
|
|
|
Generates the NECA Company Code Request Form packet for a carrier and
|
|
creates an ERPNext admin ToDo for the Accounting Advisor to mail/fax/email
|
|
the packet to NECA along with the required fee. Once NECA assigns the
|
|
OCN (10 business days standard / 5 expedited), the admin records it on
|
|
the telecom_entity — subsequent compliance checkups and 499-A filings
|
|
read it from there.
|
|
|
|
Because NECA does not offer an API or self-service submission, this
|
|
handler is inherently human-in-the-loop — there is no Playwright flow
|
|
for this service. The auto-filing toggle is therefore not gated: the
|
|
handler only produces the packet + ToDo, never submits directly.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import os
|
|
from datetime import datetime
|
|
|
|
from .base_handler import BaseServiceHandler
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class OCNRegistrationHandler(BaseServiceHandler):
|
|
SERVICE_SLUG = "ocn-registration"
|
|
SERVICE_NAME = "NECA OCN / Company Code Registration"
|
|
REQUIRES_LLM = False
|
|
|
|
async def process(self, order_data: dict) -> list[str]:
|
|
work_dir = self._make_work_dir()
|
|
order_number = order_data["name"]
|
|
entity = order_data.get("entity", {})
|
|
intake = order_data.get("intake_data") or {}
|
|
|
|
generated: list[str] = []
|
|
|
|
# Service category defaults to IPES (VoIP) unless intake specifies.
|
|
category = (intake.get("service_category") or "IPES").upper()
|
|
expedited = bool(intake.get("expedited", False))
|
|
operating_states = intake.get("operating_states") or []
|
|
|
|
# Derive contact info from the entity; default requestor to PW.
|
|
from scripts.document_gen.templates.ocn_request_form_generator import (
|
|
generate_ocn_request_packet,
|
|
)
|
|
|
|
date_str = datetime.now().strftime("%Y%m%d")
|
|
packet_docx = os.path.join(
|
|
work_dir,
|
|
f"ocn_request_packet_{order_number}_{date_str}.docx",
|
|
)
|
|
result = generate_ocn_request_packet(
|
|
entity_name=entity.get("legal_name", ""),
|
|
legal_entity_full=entity.get("legal_name", ""),
|
|
company_contact_name=entity.get("contact_name", ""),
|
|
company_contact_voice=entity.get("contact_phone", ""),
|
|
company_contact_email=entity.get("contact_email", ""),
|
|
company_contact_address=", ".join(filter(None, [
|
|
entity.get("address_street", ""),
|
|
entity.get("address_city", ""),
|
|
f"{entity.get('address_state', '')} {entity.get('address_zip', '')}".strip(),
|
|
])),
|
|
service_category=category,
|
|
operating_states=operating_states,
|
|
expedited=expedited,
|
|
output_path=packet_docx,
|
|
)
|
|
if result:
|
|
generated.append(result)
|
|
try:
|
|
generated.append(self._convert_to_pdf(result))
|
|
except Exception as exc:
|
|
logger.warning("OCN packet PDF conversion failed: %s", exc)
|
|
|
|
self._create_admin_todo(
|
|
order_number=order_number,
|
|
entity=entity,
|
|
category=category,
|
|
expedited=expedited,
|
|
)
|
|
return generated
|
|
|
|
def _create_admin_todo(
|
|
self,
|
|
*,
|
|
order_number: str,
|
|
entity: dict,
|
|
category: str,
|
|
expedited: bool,
|
|
) -> None:
|
|
try:
|
|
from scripts.workers.erpnext_client import ERPNextClient
|
|
|
|
fee = "$675 (5 business days)" if expedited else "$550 (10 business days)"
|
|
description = (
|
|
f"[{self.SERVICE_SLUG}] {order_number}\n\n"
|
|
f"Submit NECA Company Code request on behalf of this client.\n\n"
|
|
f"Entity legal name: {entity.get('legal_name', '')}\n"
|
|
f"DBA: {entity.get('dba_name', '')}\n"
|
|
f"FRN: {entity.get('frn', 'N/A')}\n"
|
|
f"Service category: {category}\n"
|
|
f"Processing: {fee}\n\n"
|
|
f"Steps:\n"
|
|
f" 1. Gather supporting docs (Articles of Incorporation for all "
|
|
f"categories; interconnection agreements + customer invoices for "
|
|
f"IPES; state PUC cert for CLEC/ULEC).\n"
|
|
f" 2. Send the generated packet (in MinIO) + supporting docs + "
|
|
f"fee to NECA via fax 973-993-1063 or ccfees@neca.org.\n"
|
|
f" 3. Pay NECA fee via Relay virtual debit card (SID-0002).\n"
|
|
f" 4. On OCN assignment: update telecom_entities.ocn and "
|
|
f"telecom_entities.ocn_assigned_at on this carrier.\n"
|
|
f" 5. Email client with the assigned OCN."
|
|
)
|
|
ERPNextClient().create_resource(
|
|
"ToDo",
|
|
{
|
|
"description": description,
|
|
"priority": "High",
|
|
"role": "Accounting Advisor",
|
|
},
|
|
)
|
|
except Exception as exc:
|
|
logger.error("Could not create OCN admin ToDo: %s", exc)
|