151 lines
5.2 KiB
Python
151 lines
5.2 KiB
Python
import zipfile
|
||
from pathlib import Path
|
||
|
||
import pytest
|
||
from docx import Document
|
||
|
||
from review_agent.application_form_fill.schemas import MergedField, TemplateSpec
|
||
from review_agent.application_form_fill.services.word_fill import create_word_export, fill_template
|
||
from review_agent.models import (
|
||
ApplicationFormFillArtifact,
|
||
ApplicationFormFillBatch,
|
||
Conversation,
|
||
ExportedSummaryFile,
|
||
FileSummaryBatch,
|
||
)
|
||
|
||
|
||
pytestmark = pytest.mark.django_db
|
||
|
||
|
||
def _spec():
|
||
return TemplateSpec(
|
||
code="registration_certificate",
|
||
name="注册证格式",
|
||
source_file="template.docx",
|
||
output_label="注册证格式",
|
||
applies_when={"registration_type": ["首次注册"]},
|
||
file_format="docx",
|
||
fields=[
|
||
{"key": "product_name", "label": "产品名称", "target": {"type": "table_row", "row_label": "产品名称"}},
|
||
{"key": "intended_use", "label": "预期用途", "target": {"type": "table_row", "row_label": "预期用途"}},
|
||
],
|
||
)
|
||
|
||
|
||
def _template(path):
|
||
document = Document()
|
||
table = document.add_table(rows=2, cols=2)
|
||
table.rows[0].cells[0].text = "产品名称"
|
||
table.rows[1].cells[0].text = "预期用途"
|
||
document.save(path)
|
||
|
||
|
||
def test_word_fill_writes_table_rows(tmp_path):
|
||
template_path = tmp_path / "template.docx"
|
||
output_path = tmp_path / "filled.docx"
|
||
_template(template_path)
|
||
|
||
fill_template(
|
||
template_path,
|
||
output_path,
|
||
_spec(),
|
||
{
|
||
"product_name": MergedField("product_name", "产品名称", "甲胎蛋白检测试剂盒", "说明书.txt", "证据", 0.8),
|
||
"intended_use": MergedField("intended_use", "预期用途", "用于体外检测", "说明书.txt", "证据", 0.8),
|
||
},
|
||
)
|
||
|
||
document = Document(output_path)
|
||
assert document.tables[0].rows[0].cells[1].text == "甲胎蛋白检测试剂盒"
|
||
assert document.tables[0].rows[1].cells[1].text == "用于体外检测"
|
||
|
||
|
||
def test_word_fill_highlights_conflict_in_docx_xml(tmp_path):
|
||
template_path = tmp_path / "template.docx"
|
||
output_path = tmp_path / "filled.docx"
|
||
_template(template_path)
|
||
|
||
fill_template(
|
||
template_path,
|
||
output_path,
|
||
_spec(),
|
||
{
|
||
"product_name": MergedField(
|
||
"product_name",
|
||
"产品名称",
|
||
"甲胎蛋白检测试剂盒",
|
||
"说明书.txt",
|
||
"证据",
|
||
0.8,
|
||
has_conflict=True,
|
||
)
|
||
},
|
||
conflicts=[{"field_key": "product_name"}],
|
||
)
|
||
|
||
with zipfile.ZipFile(output_path) as package:
|
||
document_xml = package.read("word/document.xml").decode("utf-8")
|
||
assert 'w:fill="FFFF00"' in document_xml
|
||
assert 'w:color w:val="FF0000"' in document_xml
|
||
|
||
|
||
def test_create_word_export_records_artifact_and_export(settings, tmp_path, django_user_model):
|
||
settings.MEDIA_ROOT = tmp_path
|
||
user = django_user_model.objects.create_user(username="owner", password="pass")
|
||
conversation = Conversation.objects.create(user=user, title="会话")
|
||
summary = FileSummaryBatch.objects.create(conversation=conversation, user=user, batch_no="FS-WORD")
|
||
batch = ApplicationFormFillBatch.objects.create(
|
||
conversation=conversation,
|
||
user=user,
|
||
source_summary_batch=summary,
|
||
batch_no="AFF-WORD",
|
||
product_name="甲胎蛋白检测试剂盒",
|
||
work_dir=str(tmp_path / "aff" / "AFF-WORD"),
|
||
)
|
||
template_path = tmp_path / "template.docx"
|
||
_template(template_path)
|
||
|
||
exported = create_word_export(
|
||
batch,
|
||
_spec(),
|
||
template_path,
|
||
{"product_name": MergedField("product_name", "产品名称", "甲胎蛋白检测试剂盒", "说明书.txt", "证据", 0.8)},
|
||
)
|
||
|
||
assert exported.export_type == ExportedSummaryFile.ExportType.WORD
|
||
assert exported.workflow_type == "application_form_fill"
|
||
assert exported.workflow_batch_id == batch.pk
|
||
assert ApplicationFormFillArtifact.objects.filter(
|
||
batch=batch,
|
||
artifact_type=ApplicationFormFillArtifact.ArtifactType.FILLED_TEMPLATE,
|
||
).exists()
|
||
|
||
|
||
def test_create_word_export_sanitizes_product_name_newlines(settings, tmp_path, django_user_model):
|
||
settings.MEDIA_ROOT = tmp_path
|
||
user = django_user_model.objects.create_user(username="owner", password="pass")
|
||
conversation = Conversation.objects.create(user=user, title="会话")
|
||
summary = FileSummaryBatch.objects.create(conversation=conversation, user=user, batch_no="FS-WORD-NL")
|
||
batch = ApplicationFormFillBatch.objects.create(
|
||
conversation=conversation,
|
||
user=user,
|
||
source_summary_batch=summary,
|
||
batch_no="AFF-WORD-NL",
|
||
product_name="原体核酸检测试剂盒(荧\n光PCR法)",
|
||
work_dir=str(tmp_path / "aff" / "AFF-WORD-NL"),
|
||
)
|
||
template_path = tmp_path / "template.docx"
|
||
_template(template_path)
|
||
|
||
exported = create_word_export(
|
||
batch,
|
||
_spec(),
|
||
template_path,
|
||
{"product_name": MergedField("product_name", "产品名称", "原体核酸检测试剂盒", "说明书.txt", "证据", 0.8)},
|
||
)
|
||
|
||
assert "\n" not in exported.file_name
|
||
assert "\r" not in exported.file_name
|
||
assert Path(exported.storage_path).exists()
|