def test_merged_datasets_retrieve(self): """Test retrieving a specific merged dataset""" merged_dataset = self._create_merged_dataset(geo=True) merged_xform = MergedXForm.objects.get(pk=merged_dataset['id']) # make submission to form b form_b = merged_xform.xforms.all()[1] xml = '<data id="b"><fruit>mango</fruit></data>' instance = Instance(xform=form_b, xml=xml) instance.save() form_b.refresh_from_db() form_b.last_submission_time = instance.date_created form_b.save() view = MergedXFormViewSet.as_view({'get': 'retrieve'}) request = self.factory.get('/') # status_code is 404 when the pk doesn't exist response = view(request, pk=(1000 * merged_dataset['id'])) self.assertEqual(response.status_code, 404) # status_code is 404 when: pk exists, user is not authenticated response = view(request, pk=merged_dataset['id']) self.assertEqual(response.status_code, 404) # status_code is 200 when: pk exists, user is authenticated request = self.factory.get('/', **self.extra) response = view(request, pk=merged_dataset['id']) self.assertEqual(response.status_code, 200) # data has expected fields self.assertIn('id', response.data) self.assertIn('title', response.data) self.assertIn('xforms', response.data) self.assertEqual(response.data['num_of_submissions'], 1) self.assertEqual(response.data['last_submission_time'], form_b.last_submission_time.isoformat()) # merged dataset should be available at api/forms/[pk] endpoint request = self.factory.get('/', **self.extra) view = XFormViewSet.as_view({'get': 'retrieve'}) response = view(request, pk=merged_dataset['id']) self.assertEqual(response.status_code, 200) self.assertEqual(merged_dataset['id'], response.data['formid']) self.assertIn('is_merged_dataset', response.data) self.assertTrue(response.data['is_merged_dataset']) self.assertTrue(response.data['instances_with_geopoints']) self.assertEqual(response.data['num_of_submissions'], 1) self.assertEqual(response.data['last_submission_time'], form_b.last_submission_time.isoformat())
def _get_instance( request: 'rest_framework.request.Request', xml: str, new_uuid: str, status: str, xform: XForm, defer_counting: bool = False, ) -> Instance: """ `defer_counting=False` will set a Python-only attribute of the same name on the *new* `Instance` if one is created. This will prevent `update_xform_submission_count()` from doing anything, which avoids locking any rows in `logger_xform` or `main_userprofile`. """ # check if its an edit submission old_uuid = get_deprecated_uuid_from_xml(xml) instances = Instance.objects.filter(uuid=old_uuid) if instances: # edits instance = instances[0] check_edit_submission_permissions(request, xform, instance) InstanceHistory.objects.create(xml=instance.xml, xform_instance=instance, uuid=old_uuid) instance.xml = xml instance._populate_xml_hash() instance.uuid = new_uuid instance.save() else: submitted_by = (request.user if request and request.user.is_authenticated else None) # new submission # Avoid `Instance.objects.create()` so that we can set a Python-only # attribute, `defer_counting`, before saving instance = Instance() instance.xml = xml instance.user = submitted_by instance.status = status instance.xform = xform if defer_counting: # Only set the attribute if requested, i.e. don't bother ever # setting it to `False` instance.defer_counting = True instance.save() return instance
def _get_instance(xml, new_uuid, submitted_by, status, xform, defer_counting=False): ''' `defer_counting=False` will set a Python-only attribute of the same name on the *new* `Instance` if one is created. This will prevent `update_xform_submission_count()` from doing anything, which avoids locking any rows in `logger_xform` or `main_userprofile`. ''' # check if its an edit submission old_uuid = get_deprecated_uuid_from_xml(xml) instances = Instance.objects.filter(uuid=old_uuid) if instances: # edits check_edit_submission_permissions(submitted_by, xform) instance = instances[0] InstanceHistory.objects.create(xml=instance.xml, xform_instance=instance, uuid=old_uuid) instance.xml = xml instance._populate_xml_hash() instance.uuid = new_uuid instance.save() else: # new submission # Avoid `Instance.objects.create()` so that we can set a Python-only # attribute, `defer_counting`, before saving instance = Instance() instance.xml = xml instance.user = submitted_by instance.status = status instance.xform = xform if defer_counting: # Only set the attribute if requested, i.e. don't bother ever # setting it to `False` instance.defer_counting = True instance.save() return instance
def _get_instance(xml, new_uuid, submitted_by, status, xform, defer_counting=False): ''' `defer_counting=False` will set a Python-only attribute of the same name on the *new* `Instance` if one is created. This will prevent `update_xform_submission_count()` from doing anything, which avoids locking any rows in `logger_xform` or `main_userprofile`. ''' # check if its an edit submission old_uuid = get_deprecated_uuid_from_xml(xml) instances = Instance.objects.filter(uuid=old_uuid) if instances: # edits check_edit_submission_permissions(submitted_by, xform) instance = instances[0] InstanceHistory.objects.create( xml=instance.xml, xform_instance=instance, uuid=old_uuid) instance.xml = xml instance._populate_xml_hash() instance.uuid = new_uuid instance.save() else: # new submission # Avoid `Instance.objects.create()` so that we can set a Python-only # attribute, `defer_counting`, before saving instance = Instance() instance.xml = xml instance.user = submitted_by instance.status = status instance.xform = xform if defer_counting: # Only set the attribute if requested, i.e. don't bother ever # setting it to `False` instance.defer_counting = True instance.save() return instance
def test_merged_datasets_deleted_parent_retrieve(self): """Test retrieving a specific merged dataset when the parent is deleted """ merged_dataset = self._create_merged_dataset(geo=True) merged_xform = MergedXForm.objects.get(pk=merged_dataset['id']) # make submission to form b form_b = merged_xform.xforms.all()[1] xml = '<data id="b"><fruit>mango</fruit></data>' instance = Instance(xform=form_b, xml=xml) instance.save() form_b.refresh_from_db() form_b.last_submission_time = instance.date_created form_b.save() view = MergedXFormViewSet.as_view({'get': 'retrieve'}) # status_code is 200 when: pk exists, user is authenticated request = self.factory.get('/', **self.extra) response = view(request, pk=merged_dataset['id']) self.assertEqual(response.status_code, 200) # delete parents [parent.delete() for parent in merged_xform.xforms.all()] merged_xform.refresh_from_db() # merged dataset should be available at api/forms/[pk] endpoint request = self.factory.get('/', **self.extra) view = XFormViewSet.as_view({'get': 'retrieve'}) response = view(request, pk=merged_dataset['id']) self.assertEqual(response.status_code, 200) self.assertEqual(merged_dataset['id'], response.data['formid']) self.assertTrue(response.data['is_merged_dataset']) self.assertTrue(response.data['instances_with_geopoints']) # deleted parents, 0 submissions self.assertEqual(response.data['num_of_submissions'], 0)
def test_merged_datasets_data(self): """Test retrieving data of a merged dataset""" merged_dataset = self._create_merged_dataset() request = self.factory.get('/', **self.extra) view = MergedXFormViewSet.as_view({'get': 'data'}) merged_xform = MergedXForm.objects.get(pk=merged_dataset['id']) detail_view = MergedXFormViewSet.as_view({ 'get': 'retrieve', }) xform_detail_view = XFormViewSet.as_view({ 'get': 'retrieve', }) response = view(request, pk=merged_dataset['id']) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data), 0) # check num_of_submissions response = detail_view(request, pk=merged_dataset['id']) self.assertEqual(response.status_code, 200) self.assertEqual(response.data['num_of_submissions'], 0) # make submission to form a form_a = merged_xform.xforms.all()[0] xml = '<data id="a"><fruit>orange</fruit></data>' Instance(xform=form_a, xml=xml).save() response = view(request, pk=merged_dataset['id']) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data), 1) fruit = [d['fruit'] for d in response.data] expected_fruit = ['orange'] self.assertEqual(fruit, expected_fruit) # check num_of_submissions response = detail_view(request, pk=merged_dataset['id']) self.assertEqual(response.status_code, 200) self.assertEqual(response.data['num_of_submissions'], 1) # make submission to form b form_b = merged_xform.xforms.all()[1] xml = '<data id="b"><fruit>mango</fruit></data>' last_submission = Instance(xform=form_b, xml=xml) last_submission.save() response = view(request, pk=merged_dataset['id']) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data), 2) fruit = [d['fruit'] for d in response.data] expected_fruit = ['orange', 'mango'] self.assertEqual(fruit, expected_fruit) # check num_of_submissions /merged-datasets/[pk] response = detail_view(request, pk=merged_dataset['id']) self.assertEqual(response.status_code, 200) self.assertEqual(response.data['num_of_submissions'], 2) # check last_submission_time self.assertEqual(response.data['last_submission_time'], last_submission.date_created.isoformat()) # check num_of_submissions /forms/[pk] response = xform_detail_view(request, pk=merged_dataset['id']) self.assertEqual(response.status_code, 200) self.assertEqual(response.data['num_of_submissions'], 2) # check last_submission_time self.assertEqual(response.data['last_submission_time'], last_submission.date_created.isoformat())