Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 30 additions & 8 deletions app/api/routes/documents/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ def generate_document(
editing_service: Annotated[
DocumentEditingService, Depends(get_document_editing_service)
],
record_service: Annotated[
DocumentRecordGenerationService,
Depends(get_document_record_generation_service),
],
settings: Annotated[Settings, Depends(get_settings)],
assets: Annotated[
list[UploadFile] | None,
Expand All @@ -80,14 +84,32 @@ def generate_document(
temporary_directory / f"output.{command.format.value}"
)
try:
result = editing_service.generate(
command.template_id,
command.format,
destination_path,
values=command.values,
application_options=command.application_options,
assets=asset_paths,
)
record_keys = {
key
for rule in record_service.rules.get(command.template_id, ())
for key in (rule.source_key, *rule.record_keys)
}
if (
command.format is DocumentFormat.HWPX
and command.values
and set(command.values) <= record_keys
and not command.application_options
and not asset_paths
):
result = record_service.generate(
command.values,
destination_path,
template_id=command.template_id,
)
else:
result = editing_service.generate(
command.template_id,
command.format,
destination_path,
values=command.values,
application_options=command.application_options,
assets=asset_paths,
)
except DocumentEditingError as exc:
raise_editing_http_error(exc)
return mutation_file_response(
Expand Down
70 changes: 70 additions & 0 deletions tests/api/test_document_editing_endpoint.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import io
import json
import xml.etree.ElementTree as ET
import zipfile
from pathlib import Path

Expand Down Expand Up @@ -160,6 +161,75 @@ async def test_generate_hwpx_with_values_and_application_options() -> None:
assert "[v]" in section


@pytest.mark.asyncio
async def test_generate_hwpx_with_canonical_values() -> None:
payload = {
"template_id": "immigration_integrated_application_v34",
"format": "hwpx",
"values": {
"family_name": "NGUYEN",
"given_names": "VAN A",
"birth_year": "1995",
"birth_month": "03",
"birth_day": "15",
"passport_number": "P1234567",
},
}

async with AsyncClient(
transport=ASGITransport(app=app),
base_url="http://test",
) as client:
response = await client.post(
"/api/v1/documents/generate",
data={"payload": json.dumps(payload)},
)

assert response.status_code == 200, response.text
with zipfile.ZipFile(io.BytesIO(response.content)) as package:
root = ET.fromstring(package.read("Contents/section0.xml"))
hp = "{http://www.hancom.co.kr/hwpml/2011/paragraph}"
table = next(root.iter(f"{hp}tbl"))
cells = {}
for cell in table.iter(f"{hp}tc"):
address = cell.find(f"{hp}cellAddr")
if address is not None:
coordinates = (
int(address.attrib["rowAddr"]),
int(address.attrib["colAddr"]),
)
cells[coordinates] = "".join(
text.text or "" for text in cell.iter(f"{hp}t")
)
assert cells[(14, 3)] == "NGUYEN"
assert cells[(14, 19)] == "VAN A"
assert cells[(16, 5)] == "1995"
assert cells[(16, 15)] == "03"
assert cells[(16, 19)] == "15"
assert cells[(18, 3)] == "P1234567"


@pytest.mark.asyncio
async def test_generate_hwpx_rejects_unknown_value_key() -> None:
payload = {
"template_id": "immigration_integrated_application_v34",
"format": "hwpx",
"values": {"definitely_unknown_field": "x"},
}

async with AsyncClient(
transport=ASGITransport(app=app),
base_url="http://test",
) as client:
response = await client.post(
"/api/v1/documents/generate",
data={"payload": json.dumps(payload)},
)

assert response.status_code == 422
assert "fields were not found in the HWPX template" in response.json()["detail"]


@pytest.mark.asyncio
async def test_generate_hwp_with_signature(tmp_path: Path) -> None:
payload = {
Expand Down
Loading