diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000..3f53646 --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,18 @@ +name: Docker Image CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Build the Docker image + run: docker build . --file Dockerfile --tag my-image-name:$(date +%s) diff --git a/README.md b/README.md index de432ac..cfd9488 100644 --- a/README.md +++ b/README.md @@ -53,3 +53,19 @@ In addition to the packages specified in the table above, the following packages - `bazelisk` / `bazel` See [Dockerfile](Dockerfile) for the full details of installed packages. + +## Legal document generator module + +This repository includes a simple example module located in `legal_module/` that demonstrates how to generate Traditional Chinese legal filings using the `python-docx` package. The module exposes a `create_filing` function that accepts case information and outputs a formatted Word document. When `docx2pdf` is available the file can also be exported to PDF. Generated documents use **2.5 cm margins**, **1.5 line spacing**, and include an optional **附件** section for supporting materials. + +Example usage: + +```bash +python3 -m legal_module.example +``` + +This requires the optional dependencies **python-docx** and **docx2pdf** for PDF export. Install them with: + +```bash +pip install python-docx docx2pdf +``` diff --git a/legal_module/__init__.py b/legal_module/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/legal_module/example.py b/legal_module/example.py new file mode 100644 index 0000000..2339e53 --- /dev/null +++ b/legal_module/example.py @@ -0,0 +1,21 @@ +from .filing import create_filing + +sample_case = { + 'case_number': '臺北地方法院114年度訴字第1234號', + 'parties': '原告:李灃祐 被告:新鑫公司', + 'court': '臺灣臺北地方法院', + 'claims': '請求確認本票債權不存在,並請求返還不當得利新台幣1,000,000元。', + 'facts': '原告與被告簽署車輛分期契約,惟車輛自始未交付,卻遭告提出票據裁定……', + 'laws': ['民法第184條', '票據法第17條', '最高法院111年度台上字第3208號判決'], + 'evidence': [ + {'id': '乙1', 'summary': 'LINE對話紀錄,顯示告知車輛尚未交付'}, + {'id': '乙2', 'summary': '川立公司匯款憑證,顯示資金流向'} + ], + 'attachments': [ + {'id': '附件一', 'description': '車輛分期契約影本'}, + ] +} + +if __name__ == '__main__': + create_filing(sample_case, '法律文書_起訴狀.docx', pdf_path='法律文書_起訴狀.pdf') + print('Documents generated: 法律文書_起訴狀.docx, 法律文書_起訴狀.pdf') diff --git a/legal_module/filing.py b/legal_module/filing.py new file mode 100644 index 0000000..8870b0d --- /dev/null +++ b/legal_module/filing.py @@ -0,0 +1,116 @@ +from typing import Any, Dict, Optional +from pathlib import Path +import tempfile + +try: + from docx import Document + from docx.shared import Pt, Cm +except ImportError: # pragma: no cover - docx may not be installed + Document = None + Pt = None + +class LegalDocumentGenerator: + """Generate legal filings in Traditional Chinese.""" + + def __init__(self, case_info: Dict[str, Any]): + self.case_info = case_info + if Document is None: + raise RuntimeError( + "python-docx is required to generate documents. Please install it via 'pip install python-docx'." + ) + self.doc = Document() + style = self.doc.styles["Normal"] + font = style.font + font.name = "標楷體" + font.size = Pt(16) + style.paragraph_format.line_spacing = Pt(24) # 1.5 line spacing + + for section in self.doc.sections: + section.top_margin = Cm(2.5) + section.bottom_margin = Cm(2.5) + section.left_margin = Cm(2.5) + section.right_margin = Cm(2.5) + + def build(self) -> None: + self.doc.add_heading(self.case_info.get('title', '起訴狀'), level=1) + self._add_basic_info() + self._add_claims() + self._add_facts() + self._add_laws() + self._add_evidence() + self._add_attachments() + + def save(self, filepath: str) -> None: + self.doc.save(filepath) + + def save_pdf(self, filepath: str) -> None: + """Save the generated document as a PDF using docx2pdf if available.""" + try: + from docx2pdf import convert + except ImportError as exc: # pragma: no cover - optional dependency + raise RuntimeError( + "docx2pdf is required for PDF export. Install it via 'pip install docx2pdf'." + ) from exc + + with tempfile.TemporaryDirectory() as tmpdir: + docx_path = Path(tmpdir) / "temp.docx" + self.doc.save(docx_path) + convert(str(docx_path), filepath) + + # Internal helpers + def _add_basic_info(self) -> None: + self.doc.add_paragraph(f"案號:{self.case_info.get('case_number', '')}") + self.doc.add_paragraph(f"當事人:{self.case_info.get('parties', '')}") + self.doc.add_paragraph(f"法院:{self.case_info.get('court', '')}") + + def _add_claims(self) -> None: + self.doc.add_paragraph("壹、訴之聲明") + self.doc.add_paragraph(self.case_info.get('claims', '')) + + def _add_facts(self) -> None: + self.doc.add_paragraph("貳、事實與理由") + self.doc.add_paragraph(self.case_info.get('facts', '')) + + def _add_laws(self) -> None: + self.doc.add_paragraph("參、法律依據") + for law in self.case_info.get('laws', []): + self.doc.add_paragraph(f"• {law}") + + def _add_evidence(self) -> None: + self.doc.add_paragraph("肆、證據目錄") + for ev in self.case_info.get('evidence', []): + self.doc.add_paragraph(f"【{ev['id']}】{ev['summary']}") + + def _add_attachments(self) -> None: + attachments = self.case_info.get("attachments") + if not attachments: + return + self.doc.add_paragraph("伍、附件") + for att in attachments: + desc = att.get("description", "") + att_id = att.get("id", "") + self.doc.add_paragraph(f"【{att_id}】{desc}") + + +def create_filing( + case_info: Dict[str, Any], + output_path: str, + pdf_path: Optional[str] = None, +) -> None: + """Helper function to quickly generate a filing document. + + Parameters + ---------- + case_info : Dict[str, Any] + Information about the case. + output_path : str + Location to write the DOCX file. + pdf_path : Optional[str] + If provided, also export the document to this PDF path. + """ + generator = LegalDocumentGenerator(case_info) + generator.build() + generator.save(output_path) + if pdf_path: + generator.save_pdf(pdf_path) + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2e9298f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +python-docx +docx2pdf