Skip to content

Commit 49b8ec1

Browse files
committed
Track granular form updates
Signed-off-by: Kipchirchir Sigei <[email protected]>
1 parent 730b37d commit 49b8ec1

File tree

6 files changed

+101
-35
lines changed

6 files changed

+101
-35
lines changed

onadata/apps/api/tests/viewsets/test_xform_viewset.py

+49-4
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@
6161
from onadata.apps.logger.xform_instance_parser import XLSFormError
6262
from onadata.apps.main.models import MetaData
6363
from onadata.apps.messaging.constants import (
64-
FORM_UPDATED, XFORM, PROJECT, FORM_DELETED, FORM_CREATED
64+
FORM_UPDATED, XFORM, PROJECT, FORM_DELETED, FORM_CREATED,
65+
FORM_RENAMED, FORM_ACTIVE
6566
)
6667
from onadata.apps.viewer.models import Export
6768
from onadata.apps.viewer.models.export import ExportTypeError
@@ -1385,7 +1386,7 @@ def test_publish_xlsform(self, mock_send_message):
13851386
self.assertTrue(mock_send_message.called)
13861387
mock_send_message.assert_called_with(
13871388
instance_id=xform.id,
1388-
target_id=xform.project.pk,
1389+
target_id=xform.pk,
13891390
target_type=XFORM,
13901391
user=request.user,
13911392
message_verb=FORM_CREATED
@@ -1823,7 +1824,8 @@ def test_publish_invalid_xls_form_no_choices(self):
18231824
)
18241825
self.assertEqual(response.data.get("text"), error_msg)
18251826

1826-
def test_partial_update(self):
1827+
@patch("onadata.apps.api.viewsets.xform_viewset.send_message")
1828+
def test_partial_update(self, mock_send_message):
18271829
with HTTMock(enketo_mock):
18281830
self._publish_xls_form_to_project()
18291831
view = XFormViewSet.as_view({"patch": "partial_update"})
@@ -1847,6 +1849,38 @@ def test_partial_update(self):
18471849
request = self.factory.patch("/", data=data, **self.extra)
18481850
response = view(request, pk=self.xform.id)
18491851
self.assertEqual(response.status_code, 200)
1852+
1853+
# send messages upon form update
1854+
self.assertTrue(mock_send_message.called)
1855+
1856+
# check calls to send_message triggered by patch request
1857+
mock_calls = mock_send_message.call_args_list
1858+
args, kwargs = mock_calls[0]
1859+
# test form rename message
1860+
message_kwargs = {
1861+
"instance_id": self.xform.id,
1862+
"target_id": self.xform.id,
1863+
"target_type": XFORM,
1864+
"user": self.xform.user,
1865+
"message_verb": FORM_RENAMED,
1866+
"custom_message": {
1867+
"old_title": "transportation_2011_07_25",
1868+
"new_title": "Hello & World!"
1869+
}
1870+
}
1871+
self.assertEqual(kwargs, message_kwargs)
1872+
1873+
# test form status message
1874+
args, kwargs = mock_calls[1]
1875+
message_kwargs = {
1876+
"instance_id": self.xform.id,
1877+
"target_id": self.xform.id,
1878+
"target_type": XFORM,
1879+
"user": self.xform.user,
1880+
"message_verb": FORM_ACTIVE,
1881+
}
1882+
self.assertEqual(kwargs, message_kwargs)
1883+
18501884
xform_old_hash = self.xform.hash
18511885
self.xform.refresh_from_db()
18521886
self.assertTrue(self.xform.downloadable)
@@ -3541,8 +3575,9 @@ def test_survey_preview_endpoint(self):
35413575
self.assertEqual(response.data.get("detail"), error_message)
35423576

35433577
@override_settings(CELERY_TASK_ALWAYS_EAGER=True)
3578+
@patch("onadata.apps.api.viewsets.xform_viewset.send_message")
35443579
@patch("onadata.apps.api.tasks.get_async_status")
3545-
def test_delete_xform_async(self, mock_get_status):
3580+
def test_delete_xform_async(self, mock_get_status, mock_send_msg):
35463581
with HTTMock(enketo_mock):
35473582
mock_get_status.return_value = {"job_status": "PENDING"}
35483583
self._publish_xls_form_to_project()
@@ -3571,6 +3606,16 @@ def test_delete_xform_async(self, mock_get_status):
35713606
self.assertEqual(response.status_code, 202)
35723607
self.assertEqual(response.data, {"job_status": "PENDING"})
35733608

3609+
# send message upon form deletion
3610+
self.assertTrue(mock_send_msg.called)
3611+
mock_send_msg.assert_called_with(
3612+
instance_id=self.xform.id,
3613+
target_id=self.xform.project.pk,
3614+
target_type=XFORM,
3615+
user=request.user,
3616+
message_verb=FORM_DELETED
3617+
)
3618+
35743619
xform = XForm.objects.get(pk=formid)
35753620

35763621
self.assertIsNotNone(xform.deleted_at)

onadata/apps/api/viewsets/project_viewset.py

+8-17
Original file line numberDiff line numberDiff line change
@@ -229,14 +229,6 @@ def share(self, request, *args, **kwargs):
229229
DEFAULT_FROM_EMAIL,
230230
(user.email,),
231231
)
232-
# send notification upon sharing project with multiple users
233-
send_message(
234-
instance_id=self.object.pk,
235-
target_id=self.object.pk,
236-
target_type=PROJECT,
237-
user=user,
238-
message_verb=message_verb
239-
)
240232
else:
241233
if email_msg:
242234
# send email if email_msg is present in payload
@@ -246,20 +238,19 @@ def share(self, request, *args, **kwargs):
246238
DEFAULT_FROM_EMAIL,
247239
(user.email,),
248240
)
249-
# send notification upon sharing project with single user
250-
send_message(
251-
instance_id=self.object.pk,
252-
target_id=self.object.pk,
253-
target_type=PROJECT,
254-
user=user,
255-
message_verb=message_verb,
256-
)
257-
258241
else:
259242
return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
260243

261244
# clear cache
262245
safe_delete(f"{PROJ_OWNER_CACHE}{self.object.pk}")
246+
# send message upon sharing/unsharing project with user
247+
send_message(
248+
instance_id=self.object.pk,
249+
target_id=self.object.pk,
250+
target_type=PROJECT,
251+
user=user,
252+
message_verb=message_verb,
253+
)
263254

264255
return Response(status=status.HTTP_204_NO_CONTENT)
265256

onadata/apps/api/viewsets/xform_viewset.py

+30-10
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,15 @@
5353
from onadata.apps.logger.models.xform_version import XFormVersion
5454
from onadata.apps.logger.xform_instance_parser import XLSFormError
5555
from onadata.apps.messaging.constants import (
56-
FORM_UPDATED, EXPORT_CREATED, XFORM,
57-
FORM_DELETED, FORM_CREATED, PROJECT
56+
FORM_UPDATED,
57+
EXPORT_CREATED,
58+
XFORM,
59+
FORM_DELETED,
60+
FORM_CREATED,
61+
PROJECT,
62+
FORM_ACTIVE,
63+
FORM_INACTIVE,
64+
FORM_RENAMED
5865
)
5966
from onadata.apps.messaging.serializers import send_message
6067
from onadata.apps.viewer.models.export import Export
@@ -85,7 +92,7 @@
8592
response_for_format,
8693
)
8794
from onadata.libs.utils.cache_tools import PROJ_OWNER_CACHE, safe_delete
88-
from onadata.libs.utils.common_tools import json_stream
95+
from onadata.libs.utils.common_tools import json_stream, str_to_bool
8996
from onadata.libs.utils.csv_import import (
9097
get_async_csv_submission_status,
9198
submission_xls_to_csv,
@@ -437,11 +444,7 @@ def create_async(self, request, *args, **kwargs):
437444
owner.id,
438445
{"name": fname, "path": xls_file_path},
439446
)
440-
resp.update(
441-
{
442-
"job_uuid": survey.task_id
443-
}
444-
)
447+
resp.update({"job_uuid": survey.task_id})
445448
resp_code = status.HTTP_202_ACCEPTED
446449

447450
# send form creation notification
@@ -848,14 +851,31 @@ def partial_update(self, request, *args, **kwargs):
848851

849852
try:
850853
# send notification for each form activity
851-
if request.POST.get("title") or request.POST.get("title"):
854+
if request.POST.get("title"):
852855
# send form update notification
853856
send_message(
854857
instance_id=self.object.pk,
855858
target_id=self.object.pk,
856859
target_type=XFORM,
857860
user=request.user or owner,
858-
message_verb=FORM_UPDATED,
861+
message_verb=FORM_RENAMED,
862+
custom_message={
863+
"old_title": self.object.title,
864+
"new_title": request.POST.get("title"),
865+
},
866+
)
867+
if request.POST.get("downloadable"):
868+
downloadable = request.POST.get("downloadable")
869+
message_verb = (
870+
FORM_ACTIVE if str_to_bool(downloadable) else FORM_INACTIVE
871+
)
872+
# send form status notification
873+
send_message(
874+
instance_id=self.object.pk,
875+
target_id=self.object.pk,
876+
target_type=XFORM,
877+
user=request.user or owner,
878+
message_verb=message_verb,
859879
)
860880
return super().partial_update(request, *args, **kwargs)
861881
except XLSFormError as e:

onadata/apps/messaging/constants.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
FORM_UPDATED = "form_updated"
3636
FORM_CREATED = "form_created"
3737
FORM_DELETED = "form_deleted"
38+
FORM_INACTIVE = "form_inactive"
39+
FORM_ACTIVE = "form_active"
40+
FORM_RENAMED = "form_renamed"
3841
EXPORT_CREATED = "export_created"
3942
EXPORT_DELETED = "export_deleted"
4043
PERMISSION_GRANTED = "permission_granted"
@@ -44,7 +47,7 @@
4447
SUBMISSION_DELETED, FORM_UPDATED, FORM_CREATED, FORM_DELETED,
4548
EXPORT_CREATED, EXPORT_DELETED, PROJECT_EDITED, PROJECT_SHARED,
4649
PROJECT_CREATED, USER_ADDED_TO_PROJECT, USER_REMOVED_FROM_PROJECT,
47-
PROJECT_DELETED
50+
PROJECT_DELETED, FORM_INACTIVE, FORM_ACTIVE
4851
]
4952
VERB_TOPIC_DICT = {
5053
SUBMISSION_CREATED: "submission/created",
@@ -54,6 +57,9 @@
5457
FORM_UPDATED: "form/updated",
5558
FORM_CREATED: "form/created",
5659
FORM_DELETED: "form/deleted",
60+
FORM_ACTIVE: "form/active",
61+
FORM_RENAMED: "form/renamed",
62+
FORM_INACTIVE: "form/inactive",
5763
EXPORT_CREATED: "export/created",
5864
EXPORT_DELETED: "export/deleted",
5965
PROJECT_CREATED: "project/created",

onadata/apps/messaging/serializers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from django.utils.translation import gettext as _
1818
from rest_framework import exceptions, serializers
1919

20-
from onadata.apps.logger.models import Instance
2120
from onadata.apps.messaging.constants import MESSAGE, MESSAGE_VERBS
2221
from onadata.apps.messaging.utils import TargetDoesNotExist, get_target
2322

@@ -146,6 +145,7 @@ def create(self, validated_data):
146145
return instance
147146

148147

148+
# pylint: disable=too-many-arguments
149149
def send_message(
150150
instance_id: Union[list, int],
151151
target_id: int,

onadata/apps/messaging/tests/test_utils.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
Tests messaging app utils
33
"""
44
import json
5+
from mock import patch
6+
57
from django.http.request import HttpRequest
68
from django.test.utils import override_settings
7-
from unittest.mock import patch
9+
810

911
from onadata.apps.main.tests.test_base import TestBase
1012
from onadata.apps.messaging.serializers import send_message
@@ -39,6 +41,9 @@ def is_valid():
3941

4042
@patch('onadata.apps.messaging.serializers.MessageSerializer')
4143
def test_custom_message(self, message_serializer_mock):
44+
"""
45+
Test custom_message passed into send_message function
46+
"""
4247
def is_valid():
4348
return True
4449
message_serializer_mock.is_valid.side_effect = is_valid
@@ -73,4 +78,3 @@ def is_valid():
7378
message_serializer_mock.called_with(
7479
data=data, context={"request": request}
7580
)
76-

0 commit comments

Comments
 (0)