From ef3e6cbffe24168993936e7c529a8e9b0b27db31 Mon Sep 17 00:00:00 2001 From: rikuke <33894149+rikuke@users.noreply.github.com> Date: Wed, 25 Sep 2024 09:07:25 +0300 Subject: [PATCH] feat: store ahjo validation errors to ahjoStatus (#3342) --- ...4_ahjostatus_validation_error_from_ahjo.py | 17 +++++ backend/benefit/applications/models.py | 5 ++ .../applications/services/ahjo_client.py | 3 + .../applications/tests/test_ahjo_requests.py | 69 ++++++++++++++++--- 4 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 backend/benefit/applications/migrations/0084_ahjostatus_validation_error_from_ahjo.py diff --git a/backend/benefit/applications/migrations/0084_ahjostatus_validation_error_from_ahjo.py b/backend/benefit/applications/migrations/0084_ahjostatus_validation_error_from_ahjo.py new file mode 100644 index 0000000000..272f1a92ad --- /dev/null +++ b/backend/benefit/applications/migrations/0084_ahjostatus_validation_error_from_ahjo.py @@ -0,0 +1,17 @@ +# Generated by Django 4.2.11 on 2024-09-20 11:26 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("applications", "0083_ahjostatus_ahjo_request_id"), + ] + + operations = [ + migrations.AddField( + model_name="ahjostatus", + name="validation_error_from_ahjo", + field=models.JSONField(blank=True, null=True), + ), + ] diff --git a/backend/benefit/applications/models.py b/backend/benefit/applications/models.py index 35024be88f..7c0b643d7a 100755 --- a/backend/benefit/applications/models.py +++ b/backend/benefit/applications/models.py @@ -1179,6 +1179,11 @@ class AhjoStatus(TimeStampedModel): blank=True, ) + validation_error_from_ahjo = JSONField( + null=True, + blank=True, + ) + def __str__(self): return self.status diff --git a/backend/benefit/applications/services/ahjo_client.py b/backend/benefit/applications/services/ahjo_client.py index a1fc149666..1e265aca2c 100644 --- a/backend/benefit/applications/services/ahjo_client.py +++ b/backend/benefit/applications/services/ahjo_client.py @@ -290,5 +290,8 @@ def handle_http_error(self, e: requests.exceptions.HTTPError) -> Tuple[None, dic if error_json: error_message += f" Error message: {error_json}" + status = self._request.application.ahjo_status.latest() + status.validation_error_from_ahjo = error_json + status.save() LOGGER.error(error_message) diff --git a/backend/benefit/applications/tests/test_ahjo_requests.py b/backend/benefit/applications/tests/test_ahjo_requests.py index 4755647894..b08c27051b 100644 --- a/backend/benefit/applications/tests/test_ahjo_requests.py +++ b/backend/benefit/applications/tests/test_ahjo_requests.py @@ -6,7 +6,8 @@ import requests_mock from django.urls import reverse -from applications.enums import AhjoRequestType +from applications.enums import AhjoRequestType, AhjoStatus as AhjoStatusEnum +from applications.models import AhjoStatus from applications.services.ahjo_authentication import AhjoToken, InvalidTokenException from applications.services.ahjo_client import ( AhjoAddRecordsRequest, @@ -164,15 +165,50 @@ def test_ahjo_requests( @pytest.mark.parametrize( - "ahjo_request_class, request_type, request_method", + "ahjo_request_class, request_type, request_method, previous_status", [ - (AhjoOpenCaseRequest, AhjoRequestType.OPEN_CASE, "POST"), - (AhjoDecisionProposalRequest, AhjoRequestType.SEND_DECISION_PROPOSAL, "POST"), - (AhjoUpdateRecordsRequest, AhjoRequestType.UPDATE_APPLICATION, "PUT"), - (AhjoDeleteCaseRequest, AhjoRequestType.DELETE_APPLICATION, "DELETE"), - (AhjoAddRecordsRequest, AhjoRequestType.ADD_RECORDS, "POST"), - (AhjoSubscribeDecisionRequest, AhjoRequestType.SUBSCRIBE_TO_DECISIONS, "POST"), - (AhjoDecisionDetailsRequest, AhjoRequestType.GET_DECISION_DETAILS, "GET"), + ( + AhjoOpenCaseRequest, + AhjoRequestType.OPEN_CASE, + "POST", + AhjoStatusEnum.SUBMITTED_BUT_NOT_SENT_TO_AHJO, + ), + ( + AhjoDecisionProposalRequest, + AhjoRequestType.SEND_DECISION_PROPOSAL, + "POST", + AhjoStatusEnum.CASE_OPENED, + ), + ( + AhjoUpdateRecordsRequest, + AhjoRequestType.UPDATE_APPLICATION, + "PUT", + AhjoStatusEnum.DECISION_PROPOSAL_SENT, + ), + ( + AhjoDeleteCaseRequest, + AhjoRequestType.DELETE_APPLICATION, + "DELETE", + AhjoStatusEnum.CASE_OPENED, + ), + ( + AhjoAddRecordsRequest, + AhjoRequestType.ADD_RECORDS, + "POST", + AhjoStatusEnum.CASE_OPENED, + ), + ( + AhjoSubscribeDecisionRequest, + AhjoRequestType.SUBSCRIBE_TO_DECISIONS, + "POST", + AhjoStatusEnum.DECISION_PROPOSAL_ACCEPTED, + ), + ( + AhjoDecisionDetailsRequest, + AhjoRequestType.GET_DECISION_DETAILS, + "GET", + AhjoStatusEnum.DETAILS_RECEIVED_FROM_AHJO, + ), ], ) @patch("applications.services.ahjo_client.LOGGER") @@ -184,10 +220,13 @@ def test_requests_exceptions( dummy_token, request_type, request_method, + previous_status, ): application = decided_application ahjo_request_without_ad_username = ahjo_request_class(application) + AhjoStatus.objects.create(application=application, status=previous_status) + if isinstance(ahjo_request_without_ad_username, AhjoDeleteCaseRequest): with pytest.raises(MissingHandlerIdError): ahjo_request_without_ad_username.api_url() @@ -210,13 +249,25 @@ def test_requests_exceptions( client = AhjoApiClient(dummy_token, configured_request) with requests_mock.Mocker() as m: + # an example of a real validation error response from ahjo + validation_error = [ + {"message": "/Title: does not match the regex pattern [a-zA-Z0-9åäöÅÄÖ]+"}, + { + "message": "/Records/0/SecurityReasons/0: does not match the regex pattern [a-zA-Z0-9åäöÅÄÖ]+" + }, + ] m.register_uri( configured_request.request_method, configured_request.api_url(), status_code=400, + json=validation_error, ) client.send_request_to_ahjo() mock_logger.error.assert_called() + assert ( + application.ahjo_status.latest().validation_error_from_ahjo + == validation_error + ) exception = requests.exceptions.RequestException with requests_mock.Mocker() as m: