1
0
forked from erp-dev/erp
Files
erpnew/printing/test_docx_pagination.py

110 lines
3.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import re
import zipfile
from pathlib import Path
from django.conf import settings
from django.test import SimpleTestCase
class DocxPaginationTest(SimpleTestCase):
def _read_document_xml(self, docx_path: str) -> str:
with zipfile.ZipFile(docx_path, "r") as zf:
return zf.read("word/document.xml").decode("utf-8", errors="replace")
def _extract_pages_text(self, docx_path: str) -> list[str]:
"""
Extract per-page plain text by walking body elements and splitting on page breaks.
Important: we extract w:t texts, so assertions won't be broken by XML tag boundaries.
"""
import xml.etree.ElementTree as ET
xml = self._read_document_xml(docx_path)
ns = {"w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"}
root = ET.fromstring(xml)
body = root.find("w:body", ns)
if body is None:
return []
pages: list[list[str]] = [[]]
def has_page_break(el) -> bool:
for br in el.findall(".//w:br", ns):
if br.attrib.get(f"{{{ns['w']}}}type") == "page":
return True
return False
def collect_text(el) -> str:
ts = [(t.text or "") for t in el.findall(".//w:t", ns)]
return "".join(ts)
for child in list(body):
text = collect_text(child)
if text:
pages[-1].append(text)
if has_page_break(child):
pages.append([])
return ["".join(p) for p in pages if "".join(p).strip()]
def test_render_pages_per_page_totals(self):
template = str(Path(settings.BASE_DIR) / "print-template.docx")
out = str(Path(settings.BASE_DIR) / ".tmp_docx" / "rendered-pages-test.docx")
Path(out).parent.mkdir(parents=True, exist_ok=True)
from printing.docx_template import render_docx_template_pages
prefix = "打印-销售单8*9."
# Page 1: two non-empty qty cells => 匹数=2, 总数量=111.11
page1 = {
f"{prefix}当前页码": "1",
f"{prefix}总页数": "2",
f"{prefix}匹数": "2",
f"{prefix}总数量": "111.11",
# Put a couple of quantities too (indices exist 1..72)
f"{prefix}销售数量1": "11.11",
f"{prefix}销售数量2": "100",
# Fill one product line (index 1 exists for product fields)
f"{prefix}产品名称1": "P1-产品",
f"{prefix}幅宽1": "150cm",
f"{prefix}规格1": "规格A",
f"{prefix}单位1": "",
}
# Page 2: one non-empty qty cell => 匹数=1, 总数量=222.22
page2 = {
f"{prefix}当前页码": "2",
f"{prefix}总页数": "2",
f"{prefix}匹数": "1",
f"{prefix}总数量": "222.22",
f"{prefix}销售数量1": "222.22",
f"{prefix}产品名称1": "P2-产品",
f"{prefix}幅宽1": "160cm",
f"{prefix}规格1": "规格B",
f"{prefix}单位1": "",
}
render_docx_template_pages(
template_path=template,
output_path=out,
pages_contexts=[page1, page2],
clear_unresolved=True,
)
pages_text = self._extract_pages_text(out)
self.assertGreaterEqual(len(pages_text), 2, msg="未生成两页文本(可能分页符缺失)")
p1, p2 = pages_text[0], pages_text[1]
self.assertIn("P1-产品", p1)
self.assertIn("111.11", p1)
self.assertIn("P2-产品", p2)
self.assertIn("222.22", p2)
# No raw placeholders should remain (check on plain text concatenation)
all_text = "".join(pages_text)
self.assertIsNone(re.search(r"#\{.{1,300}?\}", all_text, flags=re.S))
self.assertIsNone(re.search(r"(?<!#)\{[^{}\r\n]{1,200}\}", all_text))