First commit
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
"""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))
|
||||
Reference in New Issue
Block a user