103 lines
2.8 KiB
Python
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))
|