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>
123 lines
4.8 KiB
Python
123 lines
4.8 KiB
Python
"""Do-Not-Call (DNC) Compliance Review handler (LLM-based).
|
|
|
|
Reviews an organization's telemarketing practices and Do-Not-Call compliance
|
|
under the Telephone Consumer Protection Act (TCPA), TSR, FCC rules, and
|
|
state DNC registries.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
from .base_handler import BaseServiceHandler
|
|
|
|
SERVICE_SYSTEM_PROMPT = """You are a compliance analyst at Performance West Inc.
|
|
generating a Do-Not-Call (DNC) Compliance Review report.
|
|
|
|
RULES:
|
|
- Write in professional, clear business English
|
|
- Reference TCPA (47 U.S.C. § 227), FCC rules (47 CFR § 64.1200), and
|
|
FTC Telemarketing Sales Rule (16 CFR Part 310)
|
|
- Reference applicable state DNC laws and registries
|
|
- Never provide legal advice — use "we recommend" not "you must"
|
|
- For each finding: what was found, regulation, risk level, remediation
|
|
- Consider: national DNC registry, internal DNC lists, EBR exemptions,
|
|
prior express consent, autodialer/prerecorded message rules, caller ID requirements
|
|
- Note TCPA statutory damages ($500-$1,500 per violation) as risk context
|
|
"""
|
|
|
|
SECTIONS = [
|
|
{
|
|
"name": "executive_summary",
|
|
"prompt": (
|
|
"Write a 200-word executive summary of the DNC compliance review. "
|
|
"Include scope, calling volume metrics if available, overall "
|
|
"compliance posture, and critical findings."
|
|
),
|
|
},
|
|
{
|
|
"name": "regulatory_landscape",
|
|
"prompt": (
|
|
"Summarize the applicable DNC regulatory framework for this "
|
|
"organization. Cover: TCPA, FCC rules, FTC TSR, state DNC "
|
|
"registries applicable to their calling patterns, and recent "
|
|
"enforcement actions and FCC declaratory rulings that affect "
|
|
"their operations."
|
|
),
|
|
},
|
|
{
|
|
"name": "dnc_list_management",
|
|
"prompt": (
|
|
"Audit DNC list management practices. Assess: national DNC "
|
|
"registry scrubbing frequency (must be every 31 days), state "
|
|
"DNC registry subscriptions, internal DNC list maintenance, "
|
|
"DNC request processing timeline (must honor within reasonable "
|
|
"time), entity-specific vs. seller-specific DNC, and EBR "
|
|
"exemption tracking."
|
|
),
|
|
},
|
|
{
|
|
"name": "consent_and_calling_practices",
|
|
"prompt": (
|
|
"Review consent management for telemarketing. Assess: prior "
|
|
"express written consent for autodialed/prerecorded calls, "
|
|
"consent revocation processes, consent record retention, "
|
|
"calling time restrictions (8am-9pm), caller ID transmission, "
|
|
"and abandoned call rates (max 3% per campaign per 30 days)."
|
|
),
|
|
},
|
|
{
|
|
"name": "technology_compliance",
|
|
"prompt": (
|
|
"Evaluate technology and systems compliance. Assess: autodialer "
|
|
"definition under current TCPA interpretation, predictive dialer "
|
|
"settings, prerecorded message opt-out mechanisms (press 2 to "
|
|
"opt-out), interactive voice response compliance, and call "
|
|
"recording consent (two-party consent states)."
|
|
),
|
|
},
|
|
{
|
|
"name": "remediation_plan",
|
|
"prompt": (
|
|
"Provide a prioritized remediation plan. For each finding: "
|
|
"reference, risk level (note TCPA statutory damages exposure), "
|
|
"recommended action, responsible party, and timeline. Address "
|
|
"both immediate risk reduction and long-term program improvements."
|
|
),
|
|
},
|
|
]
|
|
|
|
|
|
class DNCReviewHandler(BaseServiceHandler):
|
|
SERVICE_SLUG = "dnc-compliance"
|
|
SERVICE_NAME = "Do-Not-Call Compliance Review"
|
|
TEMPLATE_NAME = "dnc_review_template.docx"
|
|
REQUIRES_LLM = True
|
|
|
|
async def process(self, order_data: dict) -> list[str]:
|
|
work_dir = self._make_work_dir()
|
|
order_number = order_data["name"]
|
|
context = self._extract_order_context(order_data)
|
|
|
|
template_path = self._get_template_path()
|
|
docx_filename = self._output_filename(order_number, "docx")
|
|
docx_path = os.path.join(work_dir, docx_filename)
|
|
|
|
variables = {
|
|
"order_number": order_number,
|
|
"customer_name": order_data.get("customer_name", ""),
|
|
"date": __import__("datetime").datetime.now().strftime("%B %d, %Y"),
|
|
"service_name": self.SERVICE_NAME,
|
|
"company_size": order_data.get("custom_company_size", "N/A"),
|
|
"industry": order_data.get("custom_industry", "N/A"),
|
|
"state": order_data.get("custom_state", "N/A"),
|
|
}
|
|
self._fill_template(template_path, variables, docx_path)
|
|
|
|
sections = await self._generate_sections(
|
|
SERVICE_SYSTEM_PROMPT, SECTIONS, context
|
|
)
|
|
self._add_sections_to_doc(docx_path, sections)
|
|
|
|
pdf_path = self._convert_to_pdf(docx_path)
|
|
return [docx_path, pdf_path]
|