From 3f0641ce22bf06ff7dc669039bc13a8e712c1f42 Mon Sep 17 00:00:00 2001 From: "mark.j0hnst0n" Date: Tue, 17 Dec 2024 16:16:19 +0000 Subject: [PATCH] error checking moved to check_and_route_emails and test for error added --- mail/libraries/data_processors.py | 14 ---- mail/libraries/routing_controller.py | 18 ++++- mail/tests/libraries/client.py | 1 - mail/tests/test_celery_task.py | 98 ++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 16 deletions(-) diff --git a/mail/libraries/data_processors.py b/mail/libraries/data_processors.py index 4e173e7a..9628aae3 100644 --- a/mail/libraries/data_processors.py +++ b/mail/libraries/data_processors.py @@ -20,8 +20,6 @@ from mail.models import LicenceData, Mail, UsageData from mail.serializers import LicenceDataMailSerializer, UpdateResponseSerializer, UsageDataMailSerializer -from mail.chief.licence_reply import LicenceReplyProcessor - class EdifactFileError(Exception): pass @@ -59,18 +57,6 @@ def serialize_email_message(dto: EmailMessageDto) -> Mail or None: logging.info("Successfully serialized email (subject: %s)", dto.subject) - if _mail.response_subject and "licenceReply" in _mail.response_subject: - processor = LicenceReplyProcessor.load_licence_reply_from_mail(_mail) - - if processor._current_rejected: - rejected_transaction_errors = processor._current_rejected.errors - for error in rejected_transaction_errors: - if "Duplicate transaction reference" in error.text: - run_number = LicenceData.objects.get(mail=_mail).hmrc_run_number - raise EdifactFileError( - f"Unable to process file due to the following error: {error.text}. It was sent in run number {run_number}" - ) - # if _mail.response_data and "Duplicate transaction reference" in _mail.response_data: # raise EdifactFileError( # f"Unable to process file due to error with mail {_mail.id} the edi file was {_mail.edi_filename}" diff --git a/mail/libraries/routing_controller.py b/mail/libraries/routing_controller.py index 5d4b1adf..3cf083f0 100644 --- a/mail/libraries/routing_controller.py +++ b/mail/libraries/routing_controller.py @@ -22,12 +22,16 @@ sort_dtos_by_date, ) from mail.libraries.mailbox_service import get_message_iterator -from mail.models import Mail +from mail.models import Mail, LicenceData from mail.servers import MailServer, smtp_send logger = logging.getLogger(__name__) +class EdifactFileError(Exception): + pass + + def get_spire_to_dit_mailserver() -> MailServer: """ Mailbox that receives emails sent from SPIRE @@ -221,9 +225,21 @@ def get_email_message_dtos(server: MailServer, number: Optional[int] = 3) -> Lis def check_and_notify_rejected_licences(mail): from mail.celery_tasks import notify_users_of_rejected_licences + from mail.chief.licence_reply import LicenceReplyProcessor if not settings.SEND_REJECTED_EMAIL: return if mail.response_data and ReplyStatusEnum.REJECTED in mail.response_data: notify_users_of_rejected_licences(str(mail.id), mail.response_subject) + + if mail.response_subject and "licenceReply" in mail.response_subject: + processor = LicenceReplyProcessor.load_licence_reply_from_mail(mail) + + if processor.file_errors: + for error in processor.file_errors: + if "Duplicate transaction reference" in error.text: + run_number = LicenceData.objects.get(mail=mail).hmrc_run_number + raise EdifactFileError( + f"Unable to process file due to the following error: {error.text}. It was sent in run number {run_number}" + ) diff --git a/mail/tests/libraries/client.py b/mail/tests/libraries/client.py index 6a4a1d0b..becdd8f3 100644 --- a/mail/tests/libraries/client.py +++ b/mail/tests/libraries/client.py @@ -1,5 +1,4 @@ import json -import logging from django.test import testcases from django.utils import timezone diff --git a/mail/tests/test_celery_task.py b/mail/tests/test_celery_task.py index d5590f63..cd584d66 100644 --- a/mail/tests/test_celery_task.py +++ b/mail/tests/test_celery_task.py @@ -227,3 +227,101 @@ def test_processing_of_licence_reply_with_rejected_licences( self.assertEqual(message["From"], emails_data[index]["sender"]) self.assertEqual(message["To"], emails_data[index]["recipients"]) self.assertEqual(message["Subject"], emails_data[index]["subject"]) + + @parameterized.expand( + [ + # SEND_REJECTED_EMAIL state, mail sender and recipients + ( + True, + [ + { + "sender": "lite-hmrc@gov.uk", + "recipients": "spire@example.com", + "subject": "ILBDOTI_live_CHIEF_licenceReply_78120_202403060300", + }, + { + "sender": "lite-hmrc@gov.uk", + "recipients": "ecju@gov.uk", + "subject": "Licence rejected by HMRC", + }, + ], + ) + ] + ) + @override_settings( + EMAIL_USER="lite-hmrc@gov.uk", + NOTIFY_USERS=["ecju@gov.uk"], + SPIRE_ADDRESS="spire@example.com", + ) + @mock.patch("mail.libraries.routing_controller.get_spire_to_dit_mailserver") + @mock.patch("mail.libraries.routing_controller.get_hmrc_to_dit_mailserver") + @mock.patch("mail.celery_tasks.smtp_send") + @mock.patch("mail.celery_tasks.cache") + @mock.patch("mail.libraries.routing_controller.get_email_message_dtos") + def test_processing_of_licence_reply_with_duplicate_transaction_error( + self, + send_rejected_email_flag, + emails_data, + email_dtos, + mock_cache, + mock_smtp_send, + mock_get_hmrc_to_dit_mailserver, + mock_get_spire_to_dit_mailserver, + ): + """ + Test processing of licence reply from HMRC with rejected licences. + If SEND_REJECTED_EMAIL=True then we send email notifications to users if any licences are rejected. + """ + obj = MagicMock() + mock_get_hmrc_to_dit_mailserver.return_value = obj + mock_get_spire_to_dit_mailserver.return_value = obj + mock_cache.add.return_value = True + + run_number = 78120 + mail = MailFactory( + extract_type=ExtractTypeEnum.LICENCE_DATA, + edi_filename=self.licence_data_file_name, + edi_data=self.licence_data_file_body.decode("utf-8"), + status=ReceptionStatusEnum.REPLY_PENDING, + ) + LicenceDataFactory(mail=mail, source_run_number=run_number, hmrc_run_number=run_number) + + licence_reply_filename = f"ILBDOTI_live_CHIEF_licenceReply_{run_number}_202403060300" + file_lines = "\n".join( + [ + f"1\\fileHeader\\CHIEF\\SPIRE\\licenceReply\\202111091457\\{run_number}", + "2\\fileError\\3057\\Duplicate transaction reference = 20240005721P - Input Line Number = 0\\2", + "3\\fileTrailer\\0\\0\\1", + ] + ) + + email_message_dto = EmailMessageDto( + run_number=f"{run_number}", + sender="test@example.com", + receiver="receiver@example.com", + date="Mon, 17 May 2021 14:20:18 +0100", + body="licence rejected", + subject=licence_reply_filename, + attachment=[licence_reply_filename, file_lines.encode("utf-8")], + raw_data="qwerty", + ) + email_dtos.return_value = [ + (email_message_dto, lambda x: x), + ] + + with override_settings(SEND_REJECTED_EMAIL=send_rejected_email_flag): + with pytest.raises(Exception) as excinfo: + check_and_route_emails() + + # mail.refresh_from_db() + # self.assertEqual(mail.status, ReceptionStatusEnum.REPLY_SENT) + + # assert mock_cache.add.call_count == len(emails_data) + # mock_smtp_send.call_count == len(emails_data) + + # for index, item in enumerate(mock_smtp_send.call_args_list): + # message = item.args[0] + # self.assertTrue(isinstance(message, MIMEMultipart)) + # self.assertEqual(message["From"], emails_data[index]["sender"]) + # self.assertEqual(message["To"], emails_data[index]["recipients"]) + # self.assertEqual(message["Subject"], emails_data[index]["subject"])