import json import re import subprocess from pathlib import Path OLD_APP = Path("/mnt/storage/sftp/mcelwain/repository/word-doc-generator") DRAFT_PROFILE = Path("diagnostics/legacy_word_doc_generator_profile_draft.json") OUT_PROFILE = Path("tools/doc_generator/content/document_types/legal_profile.json") TEMPLATES_OUT = Path("tools/doc_generator/content/templates/legacy") OLD_PUBLIC = OLD_APP / "public" def run_node_list_extractor(): js = f""" import {{ pathToFileURL }} from 'url'; const files = [ 'casePlaintiffInfo.js', 'opposingCounselInfo.js', 'judgeInfo.js', 'caseFilingAttorneyInfo.js', 'filingAttorneyInfo.js', 'debtCollectorInfo.js' ]; const base = {json.dumps(str(OLD_PUBLIC))}; const result = {{}}; for (const file of files) {{ try {{ const mod = await import(pathToFileURL(`${{base}}/${{file}}`).href); for (const [exportName, value] of Object.entries(mod)) {{ if (value && typeof value === 'object' && !Array.isArray(value)) {{ result[exportName] = Object.keys(value).sort(); }} }} }} catch (err) {{ // Some optional info files may not exist. }} }} console.log(JSON.stringify(result)); """ try: completed = subprocess.run( ["node", "--input-type=module", "-e", js], check=True, capture_output=True, text=True, ) return json.loads(completed.stdout) except Exception: return {} def nice_label(name): label = re.sub(r"([a-z])([A-Z])", r"\1 \2", name) label = label.replace("_", " ").replace("-", " ") label = re.sub(r"\bSsn\b", "SSN", label.title()) label = label.replace("Dob", "DOB") return label def apply_legal_field_metadata(field): name = field["name"] lower = name.lower() # Normalize generated labels. field["label"] = nice_label(name) # Autocomplete fields. if name == "casePlaintiff": field["type"] = "autocomplete" field["list"] = "plaintiffs" elif name == "caseOpposingCounsel": field["type"] = "autocomplete" field["list"] = "opposingCounsel" elif name == "caseDivisionJudge": field["type"] = "autocomplete" field["list"] = "judges" elif name == "caseFilingAttorney": field["type"] = "autocomplete" field["list"] = "filingAttorneys" elif re.fullmatch(r"debtCollector\d+Name", name): field["type"] = "autocomplete" field["list"] = "debtCollectors" elif lower.endswith("state") or name in {"caseState", "homeState", "client2homeState"}: field["type"] = "autocomplete" field["list"] = "states" elif name == "caseDesignation": field["type"] = "autocomplete" field["list"] = "caseDesignations" # Long text fields. if name in {"notes", "caseAppearanceInfo", "paymentOptions", "paymentOptions1", "paymentOptions2", "paymentOptions3", "paymentOptions4", "paymentOptions5"}: field["type"] = "textarea" return field def walk_sections(sections): for section in sections: section["collapsible"] = section.get("heading") not in { "Client Information", "Case Information", } section["defaultOpen"] = section.get("heading") in { "Client Information", "Case Information", } section["fields"] = [ apply_legal_field_metadata(field) for field in section.get("fields", []) ] for subsection in section.get("subsections", []): walk_sections([subsection]) def discover_templates(): templates = [] for path in sorted(TEMPLATES_OUT.rglob("*.docx")): rel = path.relative_to(Path("tools/doc_generator/content/templates")).as_posix() template_id = re.sub(r"[^a-zA-Z0-9]+", "_", path.stem).strip("_").lower() label = path.relative_to(TEMPLATES_OUT).as_posix() label = label.replace(".docx", "") label = label.replace("/", " / ") label = label.replace("_", " ") templates.append({ "id": template_id, "label": label, "template": rel, "outputFilename": f"{template_id}_{{caseNumber}}_{{timestamp_YYYY-MM-DD_HH-mm-ss}}.docx" }) return templates def main(): if not DRAFT_PROFILE.exists(): raise SystemExit(f"Missing {DRAFT_PROFILE}. Run review-old-word-doc-generator.py first.") draft = json.loads(DRAFT_PROFILE.read_text(encoding="utf-8")) lists_raw = run_node_list_extractor() lists = { "plaintiffs": lists_raw.get("casePlaintiffInfo", []), "opposingCounsel": lists_raw.get("caseOpposingCounselInfo", []) or lists_raw.get("opposingCounselInfo", []), "judges": lists_raw.get("judgeInfo", []), "filingAttorneys": lists_raw.get("caseFilingAttorneyInfo", []) or lists_raw.get("filingAttorneyInfo", []), "debtCollectors": lists_raw.get("debtCollectorInfo", []), "states": ["MO", "KS"], "caseDesignations": [ "Associate Circuit", "Circuit", "Limited Actions", "Small Claims" ] } sections = draft["sections"] walk_sections(sections) templates = discover_templates() profile = { "id": "legal_profile", "name": "Legal Profile", "description": "Consumer debt defense legal profile generated from the legacy word-doc-generator app.", "template": templates[0]["template"] if templates else "legacy/Canned-Emails.docx", "outputFilename": "legal_{caseNumber}_{timestamp_YYYY-MM-DD_HH-mm-ss}.docx", "lists": lists, "templates": templates, "sections": sections } OUT_PROFILE.parent.mkdir(parents=True, exist_ok=True) OUT_PROFILE.write_text(json.dumps(profile, indent=2), encoding="utf-8") print(f"Wrote {OUT_PROFILE}") print(f"Lists: {', '.join(f'{k}={len(v)}' for k, v in lists.items())}") print(f"Templates: {len(templates)}") if __name__ == "__main__": main()