Skip to content

Commit

Permalink
feat: Hl 1498 talpa errors (#3620)
Browse files Browse the repository at this point in the history
* fix: update instalments to accepted after decision

* fix: instalment initial status to WAITING

* chore: rename setting_response_handler.py

* chore: refactor decision details response handling

* fix: failing test for initial instalment status

* fix: decision datetime should be convert to a date

* fix: copy/paste error message
  • Loading branch information
rikuke authored Dec 4, 2024
1 parent 452d526 commit 47307a6
Show file tree
Hide file tree
Showing 12 changed files with 303 additions and 116 deletions.
12 changes: 11 additions & 1 deletion backend/benefit/applications/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,13 +276,23 @@ class AhjoDecisionUpdateType(models.TextChoices):
UPDATED = "Updated", _("Updated")


@dataclass
@dataclass(frozen=True, order=True)
class AhjoDecisionDetails:
decision_maker_name: str
decision_maker_title: str
section_of_the_law: str
decision_date: datetime

def __post_init__(self):
if not self.decision_maker_name.strip():
raise ValueError("Decision maker name cannot be empty")
if not self.decision_maker_title.strip():
raise ValueError("Decision maker title cannot be empty")
if not self.section_of_the_law.strip():
raise ValueError("Section of the law cannot be empty")
if not isinstance(self.decision_date, datetime):
raise TypeError("decision_date must be a datetime object")


DEFAULT_AHJO_CALLBACK_ERROR_MESSAGE = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
import logging
import time
from datetime import datetime
from typing import Dict, List, Union
from typing import List, Union

from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.core.management.base import BaseCommand
from django.db.models import QuerySet

from applications.enums import (
AhjoRequestType,
AhjoStatus as AhjoStatusEnum,
ApplicationBatchStatus,
ApplicationStatus,
)
from applications.models import AhjoStatus, Application
from applications.enums import AhjoRequestType
from applications.models import Application
from applications.services.ahjo.exceptions import DecisionProposalAlreadyAcceptedError
from applications.services.ahjo.response_handler import (
AhjoDecisionDetailsResponseHandler,
)
from applications.services.ahjo_application_service import AhjoApplicationsService
from applications.services.ahjo_authentication import (
AhjoToken,
AhjoTokenExpiredException,
)
from applications.services.ahjo_decision_service import (
parse_details_from_decision_response,
)
from applications.services.ahjo_integration import (
delete_application_in_ahjo,
get_decision_details_from_ahjo,
Expand Down Expand Up @@ -221,28 +216,6 @@ def _print_results(
)
)

def _handle_details_request_success(
self, application: Application, response_dict: Dict
) -> str:
"""Extract the details from the dict and update the application batch with them and also
with the p2p settings from ahjo_settings table"""

details = parse_details_from_decision_response(response_dict)

batch_status_to_update = ApplicationBatchStatus.DECIDED_ACCEPTED
if application.status == ApplicationStatus.REJECTED:
batch_status_to_update = ApplicationBatchStatus.DECIDED_REJECTED

batch = application.batch
batch.update_batch_after_details_request(batch_status_to_update, details)

AhjoStatus.objects.create(
application=application, status=AhjoStatusEnum.DETAILS_RECEIVED_FROM_AHJO
)

return f"Successfully received and updated decision details \
for application {application.id} and batch {batch.id} from Ahjo"

def _handle_application_request_success(
self,
application: Application,
Expand All @@ -268,7 +241,8 @@ def _handle_successful_request(
request_type: AhjoRequestType,
) -> None:
if request_type == AhjoRequestType.GET_DECISION_DETAILS:
success_text = self._handle_details_request_success(
response_handler = AhjoDecisionDetailsResponseHandler()
success_text = response_handler.handle_details_request_success(
application, response_content[0]
)
else:
Expand Down
2 changes: 1 addition & 1 deletion backend/benefit/applications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ def update_batch_after_details_request(
self.decision_maker_name = details.decision_maker_name
self.decision_maker_title = details.decision_maker_title
self.section_of_the_law = details.section_of_the_law
self.decision_date = details.decision_date
self.decision_date = details.decision_date.date()

p2p_settings = AhjoSetting.objects.get(name="p2p_settings")
self.p2p_checker_name = p2p_settings.data["acceptor_name"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from applications.enums import AhjoRequestType
from applications.services.ahjo.enums import AhjoSettingName
from applications.services.ahjo.setting_response_handler import AhjoResponseHandler
from applications.services.ahjo.response_handler import AhjoResponseHandler
from applications.services.ahjo_authentication import AhjoToken
from applications.services.ahjo_client import (
AhjoApiClient,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
import logging
import re
from datetime import datetime
from typing import Dict, List, Union

from django.conf import settings
from django.core.exceptions import ValidationError

from applications.models import AhjoSetting
from applications.enums import (
AhjoDecisionDetails,
AhjoStatus as AhjoStatusEnum,
ApplicationBatchStatus,
ApplicationStatus,
)
from applications.models import AhjoSetting, AhjoStatus, Application
from applications.services.ahjo.enums import AhjoSettingName
from applications.services.ahjo.exceptions import (
AhjoDecisionDetailsParsingError,
AhjoDecisionError,
)
from calculator.enums import InstalmentStatus
from calculator.models import Instalment

LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -150,3 +165,81 @@ def filter_signers(data: Dict) -> List[Dict[str, str]]:
for item in data["agentList"]:
result.append({"ID": item["ID"], "Name": item["Name"]})
return result


class AhjoDecisionDetailsResponseHandler:
def handle_details_request_success(
self, application: Application, response_dict: Dict
) -> str:
"""
Extract the details from the dict and update the application batchwith the data.
and data from the the p2p settings from ahjo_settings table"""

details = self._parse_details_from_decision_response(response_dict)

batch_status_to_update = ApplicationBatchStatus.DECIDED_ACCEPTED
if application.status == ApplicationStatus.REJECTED:
batch_status_to_update = ApplicationBatchStatus.DECIDED_REJECTED

batch = application.batch
batch.update_batch_after_details_request(batch_status_to_update, details)

if (
settings.PAYMENT_INSTALMENTS_ENABLED
and application.status == ApplicationStatus.ACCEPTED
):
self._update_instalments_as_accepted(application)

AhjoStatus.objects.create(
application=application, status=AhjoStatusEnum.DETAILS_RECEIVED_FROM_AHJO
)

return f"Successfully received and updated decision details \
for application {application.id} and batch {batch.id} from Ahjo"

def _update_instalments_as_accepted(self, application: Application):
calculation = application.calculation
instalments = Instalment.objects.filter(
calculation=calculation, status=InstalmentStatus.WAITING
)
if instalments.exists():
instalments.update(status=InstalmentStatus.ACCEPTED)

def _parse_details_from_decision_response(
self, decision_data: Dict
) -> AhjoDecisionDetails:
"""Extract the decision details from the given decision data"""
try:
html_content = decision_data["Content"]
decision_maker_name = self._parse_decision_maker_from_html(html_content)
decision_maker_title = decision_data["Organization"]["Name"]
section_of_the_law = decision_data["Section"]
decision_date_str = decision_data["DateDecision"]
decision_date = datetime.strptime(decision_date_str, "%Y-%m-%dT%H:%M:%S.%f")

return AhjoDecisionDetails(
decision_maker_name=decision_maker_name,
decision_maker_title=decision_maker_title,
section_of_the_law=f"{section_of_the_law} §",
decision_date=decision_date,
)
except KeyError as e:
raise AhjoDecisionDetailsParsingError(
f"Error in parsing decision details: {e}"
)
except ValueError as e:
raise AhjoDecisionDetailsParsingError(
f"Error in parsing decision details date: {e}"
)

def _parse_decision_maker_from_html(self, html_content: str) -> str:
"""Parse the decision maker from the given html string"""
match = re.search(
r'<div class="Puheenjohtajanimi">([^<]+)</div>', html_content, re.I
)
if match:
return match.group(1)
else:
raise AhjoDecisionError(
"Decision maker not found in the decision content html", html_content
)
48 changes: 3 additions & 45 deletions backend/benefit/applications/services/ahjo_decision_service.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
import re
from datetime import datetime
from string import Template
from typing import Dict, List
from typing import List

from django.conf import settings

from applications.enums import AhjoDecisionDetails, DecisionType
from applications.enums import DecisionType
from applications.models import (
AhjoDecisionText,
Application,
DecisionProposalTemplateSection,
)
from applications.services.ahjo.exceptions import (
AhjoDecisionDetailsParsingError,
AhjoDecisionError,
)
from applications.services.ahjo.exceptions import AhjoDecisionError
from applications.tests.factories import (
AcceptedDecisionProposalFactory,
DeniedDecisionProposalFactory,
Expand Down Expand Up @@ -107,40 +102,3 @@ def _generate_decision_text_string(
return replace_decision_template_placeholders(
decision_string, decision_type, application
)


def parse_details_from_decision_response(decision_data: Dict) -> AhjoDecisionDetails:
"""Extract the decision details from the given decision data"""
try:
html_content = decision_data["Content"]
decision_maker_name = parse_decision_maker_from_html(html_content)
decision_maker_title = decision_data["Organization"]["Name"]
section_of_the_law = decision_data["Section"]
decision_date_str = decision_data["DateDecision"]
decision_date = datetime.strptime(decision_date_str, "%Y-%m-%dT%H:%M:%S.%f")

return AhjoDecisionDetails(
decision_maker_name=decision_maker_name,
decision_maker_title=decision_maker_title,
section_of_the_law=f"{section_of_the_law} §",
decision_date=decision_date,
)
except KeyError as e:
raise AhjoDecisionDetailsParsingError(f"Error in parsing decision details: {e}")
except ValueError as e:
raise AhjoDecisionDetailsParsingError(
f"Error in parsing decision details date: {e}"
)


def parse_decision_maker_from_html(html_content: str) -> str:
"""Parse the decision maker from the given html string"""
match = re.search(
r'<div class="Puheenjohtajanimi">([^<]+)</div>', html_content, re.I
)
if match:
return match.group(1)
else:
raise AhjoDecisionError(
"Decision maker not found in the decision content html", html_content
)
Loading

0 comments on commit 47307a6

Please sign in to comment.