Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check if XForm is a MergedXForm and merge field choices if it is(a MergedXForm) #2011

Merged
merged 2 commits into from
Feb 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions onadata/apps/api/tests/viewsets/test_charts_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,48 @@
import mock

from django.utils import timezone
from django.core.cache import cache
from rest_framework.test import APIClient
from rest_framework.test import APIRequestFactory
from rest_framework.test import force_authenticate
from onadata.apps.api.viewsets.charts_viewset import ChartsViewSet
from onadata.apps.api.viewsets.merged_xform_viewset import MergedXFormViewSet
from onadata.apps.main.tests.test_base import TestBase
from onadata.apps.logger.models.instance import Instance
from django.db.utils import DataError
from onadata.libs.utils.timing import calculate_duration
from onadata.libs.utils.user_auth import get_user_default_project
from onadata.libs.renderers.renderers import DecimalJSONRenderer


def raise_data_error(a):
raise DataError


MD = """
| survey |
| | type | name | label |
| | select one fruits | fruits | Fruit |

| choices |
| | list name | name | label |
| | fruits | orange | Orange |
| | fruits | mango | Mango |
"""


MD2 = """
| survey |
| | type | name | label |
| | select one fruits | fruits | Fruit |

| choices |
| | list name | name | label |
| | fruits | apple | Apple |
| | fruits | cherries | Cherries |
"""


class TestChartsViewSet(TestBase):

def setUp(self):
Expand Down Expand Up @@ -47,6 +74,59 @@ def setUp(self):
os.path.dirname(__file__), '..', 'fixtures', 'forms',
'tutorial', 'instances', '3.xml'))

def test_correct_merged_dataset_data_for_charts(self):
"""Return correct data from the charts endpoint"""
view = MergedXFormViewSet.as_view({
'post': 'create',
})
# pylint: disable=attribute-defined-outside-init
self.project = get_user_default_project(self.user)
xform_a = self._publish_markdown(MD, self.user, id_string='a')
xform_b = self._publish_markdown(MD2, self.user, id_string='b')

data = {
'xforms': [
"http://testserver/api/v1/forms/%s" % xform_a.pk,
"http://testserver/api/v1/forms/%s" % xform_b.pk,
],
'name':
'Merged Dataset',
'project':
"http://testserver/api/v1/projects/%s" % self.project.pk,
}
# anonymous user
request = self.factory.post('/', data=data)
response = view(request)
self.assertEqual(response.status_code, 401)

request = self.factory.post('/', data=data)
force_authenticate(request, user=self.user)
response = view(request)
self.assertEqual(response.status_code, 201)

# make submission to form a
xml = '<data id="b"><fruits>orange mango</fruits></data>'
Instance(xform=xform_a, xml=xml).save()

# make submission to form b
xml = '<data id="b"><fruits>apple cherries</fruits></data>'
Instance(xform=xform_b, xml=xml).save()

data = {'field_xpath': 'fruits'}
request = self.factory.get('/charts', data=data)
force_authenticate(request, user=self.user)
response = self.view(
request,
pk=response.data['id']
)
self.assertEqual(response.status_code, 200)
# check that the data is correct
expected_data = [{'fruits': ['Apple', 'Cherries'], 'count': 1},
{'fruits': ['Orange', 'Mango'], 'count': 1}]
self.assertEqual(response.data['data'],
expected_data)
cache.clear()

def test_duration_field_on_metadata(self):
# the instance below has valid start and end times
instance = Instance.objects.all()[0]
Expand Down
30 changes: 25 additions & 5 deletions onadata/libs/utils/chart_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from rest_framework.exceptions import ParseError

from onadata.apps.logger.models.data_view import DataView
from onadata.apps.logger.models.merged_xform import MergedXForm
from onadata.apps.logger.models.xform import XForm
from onadata.libs.data.query import \
get_form_submissions_aggregated_by_select_one
Expand Down Expand Up @@ -435,6 +436,16 @@ def get_field_label(field, language_index=0):
return field_label


def _get_form_field_from_name_or_xpath(xform, name=None, xpath=None):
"""
Given a name or xpath, get xform field
"""
if name:
return get_field_from_field_name(name, xform)
elif xpath:
return get_field_from_field_xpath(xpath, xform)
Comment on lines +443 to +446
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if name:
return get_field_from_field_name(name, xform)
elif xpath:
return get_field_from_field_xpath(xpath, xform)
return get_field_from_field_xpath(name or xpath, xform)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this would work, because we need to call a different method when we have name from when we have xpath

Copy link
Contributor

@ivermac ivermac Feb 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aah...cool, my bad. I thought it was the same function.



def get_chart_data_for_field(field_name,
xform,
accepted_format,
Expand All @@ -446,9 +457,6 @@ def get_chart_data_for_field(field_name,
"""
data = {}

if field_name:
field = get_field_from_field_name(field_name, xform)

if group_by:
if len(group_by.split(',')) > 1:
group_by = [
Expand All @@ -458,10 +466,22 @@ def get_chart_data_for_field(field_name,
else:
group_by = get_field_from_field_xpath(group_by, xform)

if field_xpath:
field = get_field_from_field_xpath(field_xpath, xform)
field = _get_form_field_from_name_or_xpath(xform,
name=field_name,
xpath=field_xpath)

choices = get_field_choices(field, xform)
# check if xform is a MergedXForm and if it is, merge the field's choices
if xform.is_merged_dataset:
merged_xform = MergedXForm.objects.get(pk=xform.pk)
children = []
for xform in merged_xform.xforms.all():
form_field = _get_form_field_from_name_or_xpath(xform,
name=field_name,
xpath=field_xpath)
children += form_field.children
field.children = children
xform = merged_xform

try:
data = build_chart_data_for_field(
Expand Down