""" Generate the CRTC Registration Notification Letter as a DOCX file. This produces a formal letter addressed to the Secretary General of the CRTC notifying them that a new telecommunications service provider has been established under a BC corporation and wishes to register as a: - Voice, Data & Wireless Reseller (domestic) - Basic International Telecommunications Service (BITS) provider (if applicable) The letter follows the format specified at: https://crtc.gc.ca/eng/comm/telecom/registr4.htm Usage: from scripts.document_gen.templates.crtc_letter_generator import generate_crtc_letter pdf_path = generate_crtc_letter( entity_name="1234567 B.C. Ltd.", incorporation_number="1234567", registered_office="329 Howe St, Vancouver, BC V6C 3N2", services_description="Resale of voice, data, and wireless services...", geographic_coverage="BC and Worldwide", include_bits=True, regulatory_contact_name="Regulatory Director", regulatory_contact_email="regulatory@example.ca", regulatory_contact_phone="+16045551234", director_name="John Doe", output_path="/tmp/crtc_letter.docx", ) """ from __future__ import annotations import logging import os from datetime import datetime from pathlib import Path from typing import Optional LOG = logging.getLogger("document_gen.crtc_letter") try: from docx import Document from docx.shared import Pt, Inches, RGBColor from docx.enum.text import WD_ALIGN_PARAGRAPH except ImportError: LOG.warning("python-docx not installed — CRTC letter generation unavailable") Document = None def generate_crtc_letter( entity_name: str, incorporation_number: str, registered_office: str, services_description: str, geographic_coverage: str = "Canada-wide", include_bits: bool = True, regulatory_contact_name: str = "Regulatory Director", regulatory_contact_email: str = "", regulatory_contact_phone: str = "", director_name: str = "", ca_domain: str = "", output_path: str = "/tmp/crtc_notification_letter.docx", ) -> Optional[str]: """ Generate a CRTC Registration Notification Letter as a DOCX file. Returns the output file path on success, None on failure. """ if Document is None: LOG.error("python-docx not installed") return None doc = Document() # Page margins for section in doc.sections: section.top_margin = Inches(1) section.bottom_margin = Inches(1) section.left_margin = Inches(1.25) section.right_margin = Inches(1.25) # ── Sender block ────────────────────────────────────────── today = datetime.now().strftime("%B %d, %Y") sender = doc.add_paragraph() sender.alignment = WD_ALIGN_PARAGRAPH.LEFT sender_run = sender.add_run( f"{entity_name}\n" f"Incorporation No. {incorporation_number}\n" f"{registered_office}\n" ) sender_run.font.size = Pt(10) if regulatory_contact_phone: sender.add_run(f"Tel: {regulatory_contact_phone}\n").font.size = Pt(10) if regulatory_contact_email: sender.add_run(f"Email: {regulatory_contact_email}\n").font.size = Pt(10) if ca_domain: sender.add_run(f"Web: https://{ca_domain}\n").font.size = Pt(10) # Date date_para = doc.add_paragraph() date_para.alignment = WD_ALIGN_PARAGRAPH.LEFT date_run = date_para.add_run(today) date_run.font.size = Pt(10) # ── Addressee ───────────────────────────────────────────── doc.add_paragraph() addressee = doc.add_paragraph() addressee_run = addressee.add_run( "Secretary General\n" "Canadian Radio-television and\n" "Telecommunications Commission (CRTC)\n" "Ottawa, Ontario\n" "K1A 0N2" ) addressee_run.font.size = Pt(10) # ── Subject line ────────────────────────────────────────── doc.add_paragraph() subject = doc.add_paragraph() subject_run = subject.add_run( f"Re: Registration as a Telecommunications Service Provider — {entity_name}" ) subject_run.font.size = Pt(10) subject_run.bold = True # ── Body ────────────────────────────────────────────────── doc.add_paragraph() # Introduction intro = doc.add_paragraph() intro_run = intro.add_run( f"Dear Secretary General,\n\n" f"Pursuant to the Telecommunications Act, S.C. 1993, c. 38, and the " f"Canadian Radio-television and Telecommunications Commission's registration " f"requirements for telecommunications service providers, {entity_name} " f"(Incorporation No. {incorporation_number}) hereby notifies the Commission of its " f"intention to provide telecommunications services in Canada." ) intro_run.font.size = Pt(10) # Company information section doc.add_paragraph() info_heading = doc.add_paragraph() info_heading_run = info_heading.add_run("1. Company Information") info_heading_run.font.size = Pt(10) info_heading_run.bold = True info = doc.add_paragraph() info.style.font.size = Pt(10) info_text = ( f"Legal Name: {entity_name}\n" f"Incorporation Number: {incorporation_number}\n" f"Mailing Address: {registered_office}\n" f"Telephone: {regulatory_contact_phone}\n" f"Email: {regulatory_contact_email}\n" ) info.add_run(info_text).font.size = Pt(10) # Services section doc.add_paragraph() svc_heading = doc.add_paragraph() svc_heading_run = svc_heading.add_run("2. Description of Services") svc_heading_run.font.size = Pt(10) svc_heading_run.bold = True svc = doc.add_paragraph() svc.add_run( f"{entity_name} intends to operate as a reseller of voice, data, and wireless " f"telecommunications services. Specifically:\n\n" f"{services_description}\n\n" f"Geographic Coverage: {geographic_coverage}" ).font.size = Pt(10) # Registration type doc.add_paragraph() reg_heading = doc.add_paragraph() reg_heading_run = reg_heading.add_run("3. Registration Category") reg_heading_run.font.size = Pt(10) reg_heading_run.bold = True reg = doc.add_paragraph() reg_text = f"{entity_name} registers as a Voice, Data & Wireless Reseller." if include_bits: reg_text += ( f"\n\n{entity_name} also intends to provide Basic International " f"Telecommunications Services (BITS) and will file a separate notification " f"with the Commission pursuant to CRTC Telecom Decision 98-17." ) reg.add_run(reg_text).font.size = Pt(10) # Response Manager doc.add_paragraph() rm_heading = doc.add_paragraph() rm_heading_run = rm_heading.add_run("4. Response Manager for Regulatory Matters") rm_heading_run.font.size = Pt(10) rm_heading_run.bold = True rm = doc.add_paragraph() rm.add_run( f"Name: {regulatory_contact_name}\n" f"Title: Regulatory Director\n" f"Organization: {entity_name}\n" f"Address: {registered_office}\n" f"Telephone: {regulatory_contact_phone}\n" f"Email: {regulatory_contact_email}" ).font.size = Pt(10) # Compliance commitment doc.add_paragraph() compliance_heading = doc.add_paragraph() compliance_heading_run = compliance_heading.add_run("5. Compliance") compliance_heading_run.font.size = Pt(10) compliance_heading_run.bold = True compliance = doc.add_paragraph() compliance.add_run( f"{entity_name} confirms that it will comply with all applicable provisions of " f"the Telecommunications Act, CRTC regulations, and conditions of service, " f"including participation in the Commission for Complaints for " f"Telecom-Television Services (CCTS)." ).font.size = Pt(10) # Closing doc.add_paragraph() doc.add_paragraph() closing = doc.add_paragraph() closing.add_run("Respectfully submitted,").font.size = Pt(10) # Signature block (space for eSign) doc.add_paragraph() doc.add_paragraph() # Space for signature doc.add_paragraph() sig_line = doc.add_paragraph() sig_line.add_run("_" * 40).font.size = Pt(10) sig_name = doc.add_paragraph() sig_name_run = sig_name.add_run(director_name or regulatory_contact_name) sig_name_run.font.size = Pt(10) sig_name_run.bold = True sig_title = doc.add_paragraph() sig_title.add_run(f"Director, {entity_name}").font.size = Pt(10) sig_date = doc.add_paragraph() sig_date.add_run(f"Date: {today}").font.size = Pt(10) # Save output = Path(output_path) output.parent.mkdir(parents=True, exist_ok=True) doc.save(str(output)) LOG.info("CRTC letter generated: %s", output) return str(output)