Skip to content

Commit

Permalink
fix: Hl 1549 xml exception (#3607)
Browse files Browse the repository at this point in the history
* fix: always use fi language in secret XML

* fix: always use fi language in ahjo payload

* fix: raise error after xml validation fails

* fix: handle ampersand in decision XML

* chore: removed unused code
  • Loading branch information
rikuke authored Nov 28, 2024
1 parent 508bad1 commit c8884fb
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 25 deletions.
11 changes: 2 additions & 9 deletions backend/benefit/applications/services/ahjo_payload.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,8 @@ def truncate_from_end_of_string(string_to_truncate: str, limit: int):


def resolve_payload_language(application: Application) -> str:
"""Ahjo cannot at the moment handle en and sv language cases, so if the language is en or sv we use fi"""
if application.applicant_language in [
APPLICATION_LANGUAGE_CHOICES[1][0],
APPLICATION_LANGUAGE_CHOICES[2][0],
]:
language = APPLICATION_LANGUAGE_CHOICES[0][0]
else:
language = application.applicant_language
return language
"""Ahjo cannot at the moment handle en and sv language cases, so if always return fi"""
return APPLICATION_LANGUAGE_CHOICES[0][0]


def _prepare_top_level_dict(
Expand Down
21 changes: 13 additions & 8 deletions backend/benefit/applications/services/ahjo_xml_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import os
from dataclasses import dataclass
from datetime import date
from typing import List, Tuple
from typing import List, Tuple, Union

from django.conf import settings
from django.template.loader import render_to_string
Expand All @@ -13,7 +13,11 @@
from lxml.etree import XMLSchema, XMLSchemaParseError, XMLSyntaxError

from applications.enums import ApplicationStatus
from applications.models import AhjoDecisionText, Application
from applications.models import (
AhjoDecisionText,
Application,
APPLICATION_LANGUAGE_CHOICES,
)
from calculator.enums import RowType
from calculator.models import Calculation, CalculationRow

Expand Down Expand Up @@ -48,7 +52,9 @@ def load_xsd_as_string(self, xsd_path: str) -> str:
with open(xsd_path, "r") as file:
return file.read()

def validate_against_schema(self, xml_string: str, xsd_string: str) -> bool:
def validate_against_schema(
self, xml_string: str, xsd_string: str
) -> Union[bool, None]:
try:
# Parse the XML string
xml_doc = etree.fromstring(xml_string.encode("utf-8"))
Expand Down Expand Up @@ -76,7 +82,7 @@ def validate_against_schema(self, xml_string: str, xsd_string: str) -> bool:
LOGGER.error(
f"Decision proposal Validation Error for application {self.application.application_number}: {e}"
)
return False # Return False if the document is invalid
raise


class AhjoPublicXMLBuilder(AhjoXMLBuilder):
Expand All @@ -95,11 +101,9 @@ def sanitize_text_input(text: str) -> str:
for target, replacement in replacements.items():
text = text.replace(target, replacement)

text = text.replace("&", "&")
return text

def remove_non_breaking_spaces(self, text: str) -> str:
return text.replace("\u00A0", " ")

def generate_xml(self) -> AhjoXMLString:
xml_string = (
f"{XML_VERSION}<body>{self.ahjo_decision_text.decision_text}</body>"
Expand Down Expand Up @@ -215,7 +219,8 @@ def get_context_for_secret_xml(self) -> dict:
context = {
"application": self.application,
"benefit_type": _("Salary Benefit"),
"language": self.application.applicant_language,
# Ahjo only supports Finnish language
"language": APPLICATION_LANGUAGE_CHOICES[0][0],
"include_calculation_data": False,
}
if self.application.status == ApplicationStatus.ACCEPTED:
Expand Down
13 changes: 10 additions & 3 deletions backend/benefit/applications/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from applications.models import (
AhjoSetting,
Application,
APPLICATION_LANGUAGE_CHOICES,
ApplicationAlteration,
ApplicationBatch,
)
Expand Down Expand Up @@ -477,15 +478,18 @@ def denied_ahjo_decision_section():
def accepted_ahjo_decision_text(decided_application):
template = AcceptedDecisionProposalFactory()
replaced_decision_text = replace_decision_template_placeholders(
template.template_decision_text + template.template_justification_text,
f"""
<section id="paatos"><h1>Päätös</h1>{template.template_decision_text}</section>
<section id="paatoksenperustelut">
<h1>Päätöksen perustelut</h1>{template.template_justification_text}</section>""",
DecisionType.ACCEPTED,
decided_application,
)
return AhjoDecisionTextFactory(
decision_type=DecisionType.ACCEPTED,
application=decided_application,
decision_text=replaced_decision_text,
language=decided_application.applicant_language,
language=APPLICATION_LANGUAGE_CHOICES[0][0],
)


Expand Down Expand Up @@ -544,7 +548,10 @@ def generate_ahjo_case_id():
def application_with_ahjo_decision(application_with_ahjo_case_id, fake_decisionmakers):
template = AcceptedDecisionProposalFactory()
replaced_decision_text = replace_decision_template_placeholders(
template.template_decision_text + template.template_justification_text,
f"""
<section id="paatos"><h1>Päätös</h1>{template.template_decision_text}</section>
<section id="paatoksenperustelut">
<h1>Päätöksen perustelut</h1>{template.template_justification_text}</section>""",
DecisionType.ACCEPTED,
application_with_ahjo_case_id,
)
Expand Down
11 changes: 6 additions & 5 deletions backend/benefit/applications/tests/test_ahjo_xml_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytest

from applications.enums import ApplicationStatus
from applications.models import APPLICATION_LANGUAGE_CHOICES
from applications.services.ahjo_xml_builder import (
AhjoPublicXMLBuilder,
AhjoSecretXMLBuilder,
Expand Down Expand Up @@ -86,11 +87,10 @@ def total_eur_row(calculation, ordering: int = 8):


@pytest.mark.django_db
def test_generate_secret_xml_string(decided_application, secret_xml_builder):
application = decided_application
def test_generate_secret_xml_string(secret_xml_builder):
xml_content = secret_xml_builder.generate_xml()

wanted_language = application.applicant_language
wanted_language = APPLICATION_LANGUAGE_CHOICES[0][0]

# Check if the returned XML string contains the expected content
assert f'<main id="paatoksenliite" lang="{wanted_language}">' in xml_content
Expand Down Expand Up @@ -241,7 +241,7 @@ def test_get_context_for_secret_xml_for_rejected_application(
context = secret_xml_builder.get_context_for_secret_xml()

assert context["application"] == decided_application
assert context["language"] == decided_application.applicant_language
assert context["language"] == APPLICATION_LANGUAGE_CHOICES[0][0]
assert context["include_calculation_data"] is False
assert "calculation_periods" not in context
assert "total_amount_row" not in context
Expand All @@ -262,7 +262,7 @@ def test_get_context_for_secret_xml_with_single_period(
monthly_row_1.amount
)
assert context["calculation_periods"][0].total_amount == int(total_eur_row.amount)
assert context["language"] == decided_application.applicant_language
assert context["language"] == APPLICATION_LANGUAGE_CHOICES[0][0]
assert isinstance(context["total_amount_row"], CalculationRow)
assert context["total_amount_row"] == total_eur_row
assert context["total_amount_row"].amount == int(total_eur_row.amount)
Expand Down Expand Up @@ -333,6 +333,7 @@ def test_get_context_for_secret_xml_with_multiple_periods(
"&nbsp;\u200b\u00a0\u200bTest\u200b\u200b",
" Test",
), # Mixed invisible characters
("Test & Co", "Test &amp; Co"), # No changes expected
("No special characters", "No special characters"), # No changes expected
],
)
Expand Down

0 comments on commit c8884fb

Please sign in to comment.