Files
Tracker/Code/Tools/Samples/generators/docx_letter_to_client.py
T
2026-02-21 21:55:42 +00:00

103 lines
2.8 KiB
Python

"""Generate DOCX: Letter TO client from Jingtian & Gongcheng."""
from pathlib import Path
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
def generate(
output_path: Path,
firm: dict,
client: dict,
body: str,
closing: str,
ref_number: str,
date: str,
re_line: str,
):
"""Generate a formal letter from the firm to a client."""
doc = Document()
style = doc.styles["Normal"]
font = style.font
font.name = "Times New Roman"
font.size = Pt(11)
# Firm letterhead
header = doc.add_paragraph()
header.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = header.add_run(firm["name"])
run.bold = True
run.font.size = Pt(14)
run.font.color.rgb = RGBColor(0, 51, 102)
subheader = doc.add_paragraph()
subheader.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = subheader.add_run(firm.get("chinese_name", ""))
run.font.size = Pt(12)
run.font.color.rgb = RGBColor(0, 51, 102)
addr = doc.add_paragraph()
addr.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = addr.add_run(firm["address"])
run.font.size = Pt(9)
run.font.color.rgb = RGBColor(100, 100, 100)
# Divider line
doc.add_paragraph("_" * 72).runs[0].font.color.rgb = RGBColor(180, 180, 180)
# Reference and date
ref_para = doc.add_paragraph()
ref_para.add_run(f"Our Ref: {ref_number}").font.size = Pt(10)
date_para = doc.add_paragraph()
date_para.add_run(f"Date: {date}").font.size = Pt(10)
doc.add_paragraph() # spacer
# Recipient
recipient = doc.add_paragraph()
recipient.add_run(f"{client['contact_person']}").font.size = Pt(11)
recipient.add_run("\n")
recipient.add_run(f"{client['name']}").font.size = Pt(11)
recipient.add_run("\n")
recipient.add_run(client["address"]).font.size = Pt(11)
doc.add_paragraph()
# RE line
re_para = doc.add_paragraph()
run = re_para.add_run(f"RE: {re_line}")
run.bold = True
run.underline = True
doc.add_paragraph()
# Body paragraphs — strip any closing already in body text
body_clean = body
for strip_phrase in [
"Yours sincerely,",
"Yours faithfully,",
"Kind regards,",
"Best regards,",
]:
if strip_phrase in body_clean:
body_clean = body_clean[: body_clean.index(strip_phrase)].rstrip()
for para_text in body_clean.split("\n\n"):
if para_text.strip():
doc.add_paragraph(para_text.strip())
doc.add_paragraph()
# Signature block
doc.add_paragraph("Yours faithfully,")
doc.add_paragraph()
sig = doc.add_paragraph()
run = sig.add_run(firm["attorney"]["name"])
run.bold = True
doc.add_paragraph("Partner")
doc.add_paragraph(firm["name"])
doc.save(str(output_path))