From 570ea8c830ffcba7c1a687dd7737d0762c558cdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20J=C3=A9z=C3=A9gou?= Date: Mon, 15 Jan 2024 16:09:14 +0100 Subject: [PATCH] Validation - Send notification to version author and validation requester on request change and validation --- .../core/api/referral_report_version.py | 58 +++++-- ...api_referralreportversion_requestchange.py | 128 +++++++++++++++- ...test_api_referralreportversion_validate.py | 143 ++++++++++++++++-- .../partaj/core/utils/mail_sender_args.py | 12 +- 4 files changed, 304 insertions(+), 37 deletions(-) diff --git a/src/backend/partaj/core/api/referral_report_version.py b/src/backend/partaj/core/api/referral_report_version.py index fef178fb31..f729bbbd8e 100644 --- a/src/backend/partaj/core/api/referral_report_version.py +++ b/src/backend/partaj/core/api/referral_report_version.py @@ -481,11 +481,26 @@ def request_change(self, request, pk): # All previous validations and request change by the same user has to be # inactivated / canceled - version.events.filter( + active_request_validation_query_set = version.events.filter( state=ReportEventState.ACTIVE, verb=ReportEventVerb.REQUEST_VALIDATION, metadata__receiver_role=sender_role, - ).update(state=ReportEventState.INACTIVE) + ) + + active_request_validation_event_authors = [ + active_event.user + for active_event in active_request_validation_query_set.all() + ] + + notified_users = list( + set(active_request_validation_event_authors + [version.created_by]) + ) + + # All previous validation requests has to be also + # inactivated / canceled + active_request_validation_query_set.update( + state=ReportEventState.INACTIVE + ) request_change_event = ReportEventFactory().create_request_change_event( sender=request.user, @@ -494,14 +509,16 @@ def request_change(self, request, pk): comment=comment, ) version.report.referral.save() - notification = Notification.objects.create( - notification_type=NotificationEvents.VERSION_REQUEST_CHANGE, - notifier=request.user, - notified=version.created_by, - preview=comment, - item_content_object=request_change_event, - ) - notification.notify(version.report.referral, version) + + for notified_user in notified_users: + notification = Notification.objects.create( + notification_type=NotificationEvents.VERSION_REQUEST_CHANGE, + notifier=request.user, + notified=notified_user, + preview=comment, + item_content_object=request_change_event, + ) + notification.notify(version.report.referral, version) except (IntegrityError, PermissionError, Exception) as error: for i in error.args: @@ -550,11 +567,24 @@ def validate(self, request, pk): metadata__sender_unit_name=request.user.unit_name, ).update(state=ReportEventState.INACTIVE) - version.events.filter( + active_request_validation_query_set = version.events.filter( state=ReportEventState.ACTIVE, verb=ReportEventVerb.REQUEST_VALIDATION, metadata__receiver_role=sender_role, - ).update(state=ReportEventState.INACTIVE) + ) + + active_request_validation_event_authors = [ + active_event.user + for active_event in active_request_validation_query_set.all() + ] + + notified_users = list( + set(active_request_validation_event_authors + [version.created_by]) + ) + + active_request_validation_query_set.update( + state=ReportEventState.INACTIVE + ) # Finally create the new validation event validate_version_event = ReportEventFactory().validate_version_event( @@ -565,11 +595,11 @@ def validate(self, request, pk): ) version.report.referral.save() - for assignee in version.report.referral.assignees.all(): + for notified_user in notified_users: notification = Notification.objects.create( notification_type=NotificationEvents.VERSION_VALIDATED, notifier=request.user, - notified=assignee, + notified=notified_user, preview=comment, item_content_object=validate_version_event, ) diff --git a/src/backend/tests/partaj/core/test_api_referralreportversion_requestchange.py b/src/backend/tests/partaj/core/test_api_referralreportversion_requestchange.py index 8be095af03..54a271153f 100644 --- a/src/backend/tests/partaj/core/test_api_referralreportversion_requestchange.py +++ b/src/backend/tests/partaj/core/test_api_referralreportversion_requestchange.py @@ -18,7 +18,7 @@ class ReferralReportRequestChangeApiTestCase(TestCase): """ # Request validation API TESTS - def test_referralreport_requestchange_behavior(self, mock_mailer_send): + def test_referralreport_requestchange_scenario_1(self, mock_mailer_send): """ Test - Request change can be done by unit granted users on last version @@ -171,7 +171,127 @@ def test_referralreport_requestchange_behavior(self, mock_mailer_send): ).count() self.assertEqual(active_validation_request_events, 2) - def test_referralreport_requestvalidation_state_and_mails(self, mock_mailer_send): + def test_referralreportversion_validate_scenario_2(self, mock_mailer_send): + """ + Test + - Referral doesn't change its state after request change + - Mails are sent to version author and request validation author + """ + + # Initialize requesters, unit members and referral + unit = factories.UnitFactory(name='unit_name') + unit_member_1 = factories.UserFactory(unit_name=unit.name) + + # Add unit members + unit.members.add(unit_member_1) + + # Add unit owner + unit_owner_1 = factories.UserFactory(unit_name=unit.name) + factories.UnitMembershipFactory( + role=models.UnitMembershipRole.OWNER, + unit=unit, + user=unit_owner_1 + ) + + # Add unit admin + unit_admin = factories.UserFactory(unit_name="admin_unit") + factories.UnitMembershipFactory( + role=models.UnitMembershipRole.ADMIN, + unit=unit, + user=unit_admin + ) + + requester_1 = factories.UserFactory(unit_name='tieps') + requester_2 = factories.UserFactory(unit_name='tieps') + + report = factories.ReferralReportFactory() + referral = mock_create_referral( + models.ReferralState.PROCESSING, + report, + unit + ) + + # Set requesters + referral.users.set([requester_1.id, requester_2.id]) + + created_referral = models.Referral.objects.get(id=referral.id) + created_referral.refresh_from_db() + + """ + Send a first version with the unit_member_1 and validate it by granted user + """ + first_attachment_file = BytesIO(b"attachment_file") + first_attachment_file.name = "the first attachment file name.doc" + unit_member_1_token = Token.objects.get_or_create(user=unit_member_1)[0] + unit_owner_token_1 = Token.objects.get_or_create(user=unit_owner_1)[0] + unit_admin_token_1 = Token.objects.get_or_create(user=unit_admin)[0] + + # Send first version + first_version_response = self.client.post( + "/api/referralreportversions/", + { + "report": str(created_referral.report.id), + "files": (first_attachment_file,), + }, + HTTP_AUTHORIZATION=f"Token {unit_member_1_token}", + ) + + version = models.ReferralReportVersion.objects.get( + id=first_version_response.json()['id']) + + self.assertEqual(first_version_response.status_code, 201) + + # Request validation from unit owner of unit member version + request_validation_response = self.client.post( + f"/api/referralreportversions/{first_version_response.json()['id']}/request_validation/", + { + "comment": "blabla admin_1", + "selected_options": [ + { + "role": "admin", + "unit_name": "admin_unit", + } + ] + }, + content_type="application/json", + HTTP_AUTHORIZATION=f"Token {unit_owner_token_1}", + ) + self.assertEqual(request_validation_response.status_code, 200) + + admin_validation_response = self.client.post( + f"/api/referralreportversions/{first_version_response.json()['id']}/request_change/", + {"comment": "blabla owner_1"}, + content_type="application/json", + HTTP_AUTHORIZATION=f"Token {unit_admin_token_1}", + ) + self.assertEqual(admin_validation_response.status_code, 200) + + mailer_send_args = [call[0] for call in mock_mailer_send.call_args_list] + + self.assertEquals(referral.state, models.ReferralState.PROCESSING) + self.assertTrue( + get_request_change( + notified_user=unit_member_1, + referral=referral, + validator=unit_admin, + unit_name=unit_admin.unit_name, + version=version + ) + in mailer_send_args + ) + + self.assertTrue( + get_request_change( + notified_user=unit_owner_1, + referral=referral, + validator=unit_admin, + unit_name=unit_admin.unit_name, + version=version + ) + in mailer_send_args + ) + + def test_referralreport_requestchange_scenario_3(self, mock_mailer_send): """ Test - Referral doesn't change its state after request change @@ -247,10 +367,10 @@ def test_referralreport_requestvalidation_state_and_mails(self, mock_mailer_send self.assertTrue( get_request_change( - requester=unit_member_1, + notified_user=unit_member_1, referral=referral, validator=unit_owner_1, - unit=referral.units.get(), + unit_name=unit_owner_1.unit_name, version=version ) in mailer_send_args diff --git a/src/backend/tests/partaj/core/test_api_referralreportversion_validate.py b/src/backend/tests/partaj/core/test_api_referralreportversion_validate.py index fac6ed76c1..8e1dc07510 100644 --- a/src/backend/tests/partaj/core/test_api_referralreportversion_validate.py +++ b/src/backend/tests/partaj/core/test_api_referralreportversion_validate.py @@ -14,18 +14,16 @@ @mock.patch("partaj.core.email.Mailer.send") class ReferralReportValidate(TestCase): """ - Test API routes related to ReferralReportVersion validation endpoints. + Test API routes related to ReferralReportVersion validate endpoints. """ - # Request validation API TESTS - def test_referralreport_requestvalidation_by_linked_unit_user(self, mock_mailer_send): + # VALIDATE API TESTS + def test_referralreportversion_validate_scenarii_1(self, mock_mailer_send): """ Test - Validation can be done by unit granted users on last version - - A second same change request on a version inactivate the previous request change event - - Can't request change on a draft, closed or answered referral - - Referral doesn't change its state after request change - - Mails are sent to assignees only + - A second same validate on a version inactivate the previous validate event + - Can't validate on a draft, closed or answered referral """ # Initialize requesters, unit members and referral @@ -155,7 +153,126 @@ def test_referralreport_requestvalidation_by_linked_unit_user(self, mock_mailer_ ).count() self.assertEqual(active_validation_request_events, 1) - def test_referralreport_requestvalidation_state_and_mails(self, mock_mailer_send): + def test_referralreportversion_validate_scenarii_2(self, mock_mailer_send): + """ + Test + - Referral doesn't change its state after validate + - Mails are sent to version author and request validation author + """ + + # Initialize requesters, unit members and referral + unit = factories.UnitFactory(name='unit_name') + unit_member_1 = factories.UserFactory(unit_name=unit.name) + + # Add unit members + unit.members.add(unit_member_1) + + # Add unit owner + unit_owner_1 = factories.UserFactory(unit_name=unit.name) + factories.UnitMembershipFactory( + role=models.UnitMembershipRole.OWNER, + unit=unit, + user=unit_owner_1 + ) + + # Add unit admin + unit_admin = factories.UserFactory(unit_name="admin_unit") + factories.UnitMembershipFactory( + role=models.UnitMembershipRole.ADMIN, + unit=unit, + user=unit_admin + ) + + requester_1 = factories.UserFactory(unit_name='tieps') + requester_2 = factories.UserFactory(unit_name='tieps') + + report = factories.ReferralReportFactory() + referral = mock_create_referral( + models.ReferralState.PROCESSING, + report, + unit + ) + + # Set requesters + referral.users.set([requester_1.id, requester_2.id]) + + created_referral = models.Referral.objects.get(id=referral.id) + created_referral.refresh_from_db() + + """ + Send a first version with the unit_member_1 and validate it by granted user + """ + first_attachment_file = BytesIO(b"attachment_file") + first_attachment_file.name = "the first attachment file name.doc" + unit_member_1_token = Token.objects.get_or_create(user=unit_member_1)[0] + unit_owner_token_1 = Token.objects.get_or_create(user=unit_owner_1)[0] + unit_admin_token_1 = Token.objects.get_or_create(user=unit_admin)[0] + + # Send first version + first_version_response = self.client.post( + "/api/referralreportversions/", + { + "report": str(created_referral.report.id), + "files": (first_attachment_file,), + }, + HTTP_AUTHORIZATION=f"Token {unit_member_1_token}", + ) + + version = models.ReferralReportVersion.objects.get(id=first_version_response.json()['id']) + + self.assertEqual(first_version_response.status_code, 201) + + # Request validation from unit owner of unit member version + request_validation_response = self.client.post( + f"/api/referralreportversions/{first_version_response.json()['id']}/request_validation/", + { + "comment": "blabla admin_1", + "selected_options": [ + { + "role": "admin", + "unit_name": "admin_unit", + } + ] + }, + content_type="application/json", + HTTP_AUTHORIZATION=f"Token {unit_owner_token_1}", + ) + self.assertEqual(request_validation_response.status_code, 200) + + admin_validation_response = self.client.post( + f"/api/referralreportversions/{first_version_response.json()['id']}/validate/", + {"comment": "blabla owner_1"}, + content_type="application/json", + HTTP_AUTHORIZATION=f"Token {unit_admin_token_1}", + ) + self.assertEqual(admin_validation_response.status_code, 200) + + mailer_send_args = [call[0] for call in mock_mailer_send.call_args_list] + + self.assertEquals(referral.state, models.ReferralState.PROCESSING) + self.assertTrue( + get_validate( + notified_user=unit_member_1, + referral=referral, + validator=unit_admin, + unit_name=unit_admin.unit_name, + version=version + ) + in mailer_send_args + ) + + self.assertTrue( + get_validate( + notified_user=unit_owner_1, + referral=referral, + validator=unit_admin, + unit_name=unit_admin.unit_name, + version=version + ) + in mailer_send_args + ) + + def test_referralreport_validate_state_and_mails(self, mock_mailer_send): """ Test - Referral doesn't change its state after request change @@ -215,25 +332,25 @@ def test_referralreport_requestvalidation_state_and_mails(self, mock_mailer_send self.assertEqual(first_version_response.status_code, 201) - # Request change with unit owner + # Validate with unit owner # AUTHORIZED: done by granted user even before a validation request - first_authorized_request_change = self.client.post( + first_authorized_validate = self.client.post( f"/api/referralreportversions/{first_version_response.json()['id']}/validate/", {"comment": "blabla owner_1"}, content_type="application/json", HTTP_AUTHORIZATION=f"Token {unit_owner_token_1}", ) - self.assertEqual(first_authorized_request_change.status_code, 200) + self.assertEqual(first_authorized_validate.status_code, 200) mailer_send_args = [call[0] for call in mock_mailer_send.call_args_list] self.assertEquals(referral.state, models.ReferralState.PROCESSING) self.assertTrue( get_validate( - requester=unit_member_1, + notified_user=unit_member_1, referral=referral, validator=unit_owner_1, - unit=referral.units.get(), + unit_name=unit_owner_1.unit_name, version=version ) in mailer_send_args diff --git a/src/backend/tests/partaj/core/utils/mail_sender_args.py b/src/backend/tests/partaj/core/utils/mail_sender_args.py index ceb76d0cc0..d0d2a36ad2 100644 --- a/src/backend/tests/partaj/core/utils/mail_sender_args.py +++ b/src/backend/tests/partaj/core/utils/mail_sender_args.py @@ -45,7 +45,7 @@ def get_request_validation(requester: User, referral: Referral, validator: User, },) -def get_request_change(requester: User, referral: Referral, validator: User, unit: Unit, version: ReferralReportVersion): +def get_request_change(notified_user: User, referral: Referral, validator: User, unit_name: str, version: ReferralReportVersion): return ({ "params": { "case_number": referral.id, @@ -53,7 +53,7 @@ def get_request_change(requester: User, referral: Referral, validator: User, uni "referral_users": referral.get_users_text_list(), "title": referral.title or referral.object, "topic": referral.topic.name, - "unit_name": unit.name, + "unit_name": unit_name, "version_number": version.version_number, "validator": validator.get_full_name(), }, @@ -61,11 +61,11 @@ def get_request_change(requester: User, referral: Referral, validator: User, uni "templateId": settings.SENDINBLUE[ "REFERRAL_VERSION_REQUEST_CHANGE" ], - "to": [{"email": requester.email}], + "to": [{"email": notified_user.email}], },) -def get_validate(requester: User, referral: Referral, validator: User, unit: Unit, version: ReferralReportVersion): +def get_validate(notified_user: User, referral: Referral, validator: User, unit_name: str, version: ReferralReportVersion): return ({ "params": { "case_number": referral.id, @@ -73,7 +73,7 @@ def get_validate(requester: User, referral: Referral, validator: User, unit: Uni "referral_users": referral.get_users_text_list(), "title": referral.title or referral.object, "topic": referral.topic.name, - "unit_name": unit.name, + "unit_name": unit_name, "version_number": version.version_number, "validator": validator.get_full_name(), }, @@ -81,7 +81,7 @@ def get_validate(requester: User, referral: Referral, validator: User, unit: Uni "templateId": settings.SENDINBLUE[ "REFERRAL_VERSION_VALIDATED" ], - "to": [{"email": requester.email}], + "to": [{"email": notified_user.email}], },)