Skip to content

Commit 4d1c604

Browse files
authored
Merge pull request #3032 from unicef/develop
Develop
2 parents e6e5cd8 + a629c44 commit 4d1c604

File tree

3 files changed

+84
-22
lines changed

3 files changed

+84
-22
lines changed

src/etools/applications/field_monitoring/data_collection/offline/synchronizer.py

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from django.urls import reverse
88

99
from etools_offline import OfflineCollect
10+
from sentry_sdk import capture_exception
1011
from simplejson import JSONDecodeError
1112

1213
from etools.applications.environment.helpers import tenant_switch_is_active
@@ -46,33 +47,39 @@ def initialize_blueprints(self) -> None:
4647

4748
for method in self.activity.methods:
4849
blueprint = get_blueprint_for_activity_and_method(self.activity, method)
49-
OfflineCollect().add(data={
50-
"is_active": True,
51-
"code": blueprint.code,
52-
"form_title": blueprint.title,
53-
"form_instructions": json.dumps(blueprint.to_dict(), indent=2),
54-
"accessible_by": self._get_data_collectors(),
55-
"api_response_url": urljoin(
56-
host,
57-
'{}?workspace={}'.format(
58-
reverse(
59-
'field_monitoring_data_collection:activities-offline',
60-
args=[self.activity.id, method.id]
61-
),
62-
connection.tenant.schema_name or ''
50+
try:
51+
OfflineCollect().add(data={
52+
"is_active": True,
53+
"code": blueprint.code,
54+
"form_title": blueprint.title,
55+
"form_instructions": json.dumps(blueprint.to_dict(), indent=2),
56+
"accessible_by": self._get_data_collectors(),
57+
"api_response_url": urljoin(
58+
host,
59+
'{}?workspace={}'.format(
60+
reverse(
61+
'field_monitoring_data_collection:activities-offline',
62+
args=[self.activity.id, method.id]
63+
),
64+
connection.tenant.schema_name or ''
65+
)
6366
)
64-
)
65-
})
67+
})
68+
except JSONDecodeError:
69+
capture_exception()
6670

6771
def update_data_collectors_list(self) -> None:
6872
if not self.enabled:
6973
return
7074

7175
for method in self.activity.methods:
72-
OfflineCollect().update(
73-
get_blueprint_code(self.activity, method),
74-
accessible_by=self._get_data_collectors()
75-
)
76+
try:
77+
OfflineCollect().update(
78+
get_blueprint_code(self.activity, method),
79+
accessible_by=self._get_data_collectors()
80+
)
81+
except JSONDecodeError:
82+
capture_exception()
7683

7784
def close_blueprints(self) -> None:
7885
if not self.enabled:
@@ -85,4 +92,4 @@ def close_blueprints(self) -> None:
8592
try:
8693
OfflineCollect().delete(code)
8794
except JSONDecodeError:
88-
pass
95+
capture_exception()

src/etools/applications/field_monitoring/data_collection/tests/test_offline.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from django.db import connection
33
from django.test import override_settings
44

5+
import simplejson
56
from mock import patch
67
from rest_framework import status
78

@@ -280,6 +281,60 @@ def test_tenant_switch_missing_but_api_not_configured(self, add_mock):
280281
self._test_update(self.fm_user, activity, {'status': 'assigned'})
281282
add_mock.assert_not_called()
282283

284+
@override_settings(ETOOLS_OFFLINE_API='http://example.com/b/api/remote/blueprint/', SENTRY_DSN='https://test.dns')
285+
@patch('sentry_sdk.api.Hub.current.capture_exception')
286+
@patch('etools.applications.field_monitoring.data_collection.offline.synchronizer.OfflineCollect.add')
287+
def test_add_offline_backend_unavailable(self, add_mock, capture_event_mock):
288+
def communication_failure(*args, **kwargs):
289+
return 502, simplejson.loads(
290+
'<html>\r\n<head><title>502 Bad Gateway</title></head>\r\n<body bgcolor="white">\r\n<center>'
291+
'<h1>502 Bad Gateway</h1></center>\r\n<hr><center>nginx/1.13.12</center>\r\n</body>\r\n</html>\r\n'
292+
)
293+
294+
add_mock.side_effect = communication_failure
295+
296+
activity = MonitoringActivityFactory(status='pre_assigned', partners=[PartnerFactory()])
297+
ActivityQuestionFactory(monitoring_activity=activity, is_enabled=True, question__methods=[MethodFactory()])
298+
299+
self._test_update(self.fm_user, activity, {'status': 'assigned'})
300+
capture_event_mock.assert_called()
301+
302+
@override_settings(ETOOLS_OFFLINE_API='http://example.com/b/api/remote/blueprint/', SENTRY_DSN='https://test.dns')
303+
@patch('sentry_sdk.api.Hub.current.capture_exception')
304+
@patch('etools.applications.field_monitoring.data_collection.offline.synchronizer.OfflineCollect.update')
305+
def test_update_offline_backend_unavailable(self, update_mock, capture_event_mock):
306+
def communication_failure(*args, **kwargs):
307+
return 502, simplejson.loads(
308+
'<html>\r\n<head><title>502 Bad Gateway</title></head>\r\n<body bgcolor="white">\r\n<center>'
309+
'<h1>502 Bad Gateway</h1></center>\r\n<hr><center>nginx/1.13.12</center>\r\n</body>\r\n</html>\r\n'
310+
)
311+
312+
update_mock.side_effect = communication_failure
313+
314+
activity = MonitoringActivityFactory(status='data_collection', partners=[PartnerFactory()])
315+
ActivityQuestionFactory(monitoring_activity=activity, is_enabled=True, question__methods=[MethodFactory()])
316+
317+
activity.team_members.remove(activity.team_members.first())
318+
capture_event_mock.assert_called()
319+
320+
@override_settings(ETOOLS_OFFLINE_API='http://example.com/b/api/remote/blueprint/', SENTRY_DSN='https://test.dns')
321+
@patch('sentry_sdk.api.Hub.current.capture_exception')
322+
@patch('etools.applications.field_monitoring.data_collection.offline.synchronizer.OfflineCollect.delete')
323+
def test_delete_offline_backend_unavailable(self, delete_mock, capture_event_mock):
324+
def communication_failure(*args, **kwargs):
325+
return 502, simplejson.loads(
326+
'<html>\r\n<head><title>502 Bad Gateway</title></head>\r\n<body bgcolor="white">\r\n<center>'
327+
'<h1>502 Bad Gateway</h1></center>\r\n<hr><center>nginx/1.13.12</center>\r\n</body>\r\n</html>\r\n'
328+
)
329+
330+
delete_mock.side_effect = communication_failure
331+
332+
activity = MonitoringActivityFactory(status='data_collection', partners=[PartnerFactory()])
333+
ActivityQuestionFactory(monitoring_activity=activity, is_enabled=True, question__methods=[MethodFactory()])
334+
335+
self._test_update(self.fm_user, activity, {'status': 'cancelled', 'cancel_reason': 'For testing purposes'})
336+
capture_event_mock.assert_called()
337+
283338

284339
class MonitoringActivityOfflineValuesTestCase(APIViewSetTestCase, BaseTenantTestCase):
285340
base_view = 'field_monitoring_data_collection:activities'

src/etools/applications/partners/serializers/interventions_v2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ class InterventionResultNestedSerializer(serializers.ModelSerializer):
329329
ll_results = LowerResultSerializer(many=True, read_only=True)
330330

331331
def get_ram_indicator_names(self, obj):
332-
return [i.name for i in obj.ram_indicators.all()]
332+
return [i.light_repr for i in obj.ram_indicators.all()]
333333

334334
class Meta:
335335
model = InterventionResultLink

0 commit comments

Comments
 (0)