diff --git a/onadata/libs/tests/utils/fixtures/csv_import_multiple_split_group_repeat.csv b/onadata/libs/tests/utils/fixtures/csv_import_multiple_split_group_repeat.csv new file mode 100644 index 0000000000..a97a56c2a9 --- /dev/null +++ b/onadata/libs/tests/utils/fixtures/csv_import_multiple_split_group_repeat.csv @@ -0,0 +1,2 @@ +name,age,grp1/grp2/browser_use[1]/grp3/grp4/grp5/year,grp1/grp2/browser_use[1]/grp3/grp4/grp5/browsers/firefox,grp1/grp2/browser_use[1]/grp3/grp4/grp5/browsers/chrome,grp1/grp2/browser_use[1]/grp3/grp4/grp5/browsers/ie,grp1/grp2/browser_use[1]/grp3/grp4/grp5/browsers/safari,grp1/grp2/browser_use[2]/grp3/grp4/grp5/year,grp1/grp2/browser_use[2]/grp3/grp4/grp5/browsers/firefox,grp1/grp2/browser_use[2]/grp3/grp4/grp5/browsers/chrome,grp1/grp2/browser_use[2]/grp3/grp4/grp5/browsers/ie,grp1/grp2/browser_use[2]/grp3/grp4/grp5/browsers/safari,meta/instanceID +Vic,30,2010,True,False,False,True,2011,True,True,False,False,uuid:13f5c2a8-0ba2-44e2-bd0a-9c6fa3991484 diff --git a/onadata/libs/tests/utils/fixtures/csv_import_multiple_wo_split_group_repeat.csv b/onadata/libs/tests/utils/fixtures/csv_import_multiple_wo_split_group_repeat.csv new file mode 100644 index 0000000000..8e3f030c29 --- /dev/null +++ b/onadata/libs/tests/utils/fixtures/csv_import_multiple_wo_split_group_repeat.csv @@ -0,0 +1,2 @@ +name,age,grp1/grp2/browser_use[1]/grp3/grp4/grp5/year,grp1/grp2/browser_use[1]/grp3/grp4/grp5/browsers,grp1/grp2/browser_use[2]/grp3/grp4/grp5/year,grp1/grp2/browser_use[2]/grp3/grp4/grp5/browsers,meta/instanceID +Vic,30,2010,firefox safari,2011,firefox chrome,uuid:13f5c2a8-0ba2-44e2-bd0a-9c6fa3991484 diff --git a/onadata/libs/tests/utils/test_csv_import.py b/onadata/libs/tests/utils/test_csv_import.py index 461b46bafa..d19a546d53 100644 --- a/onadata/libs/tests/utils/test_csv_import.py +++ b/onadata/libs/tests/utils/test_csv_import.py @@ -599,3 +599,107 @@ def test_get_columns_by_type(self): self.assertTrue( submission.json["section_B/year_established"].startswith("1890") ) + + def test_select_multiples_grouped_repeating_w_split(self): + """Select multiple choices within group within repeat with split""" + md_xform = """ + | survey | | | | + | | type | name | label | + | | text | name | Name | + | | integer | age | Age | + | | begin group | grp1 | Group 1 | + | | begin group | grp2 | Group 2 | + | | begin repeat | browser_use | Browser Use | + | | begin group | grp3 | Group 3 | + | | begin group | grp4 | Group 4 | + | | begin group | grp5 | Group 5 | + | | integer | year | Year | + | | select_multiple browsers | browsers | Browsers | + | | end group | | | + | | end group | | | + | | end group | | | + | | end repeat | | | + | | end group | | | + | | end group | | | + | choices | | | | + | | list_name | name | label | + | | browsers | firefox | Firefox | + | | browsers | chrome | Chrome | + | | browsers | ie | Internet Explorer | + | | browsers | safari | Safari |""" + xform = self._publish_markdown(md_xform, self.user, id_string="nested_split") + + with open( + os.path.join( + self.fixtures_dir, "csv_import_multiple_split_group_repeat.csv" + ), + "rb", + ) as csv_file: + csv_import.submit_csv(self.user.username, xform, csv_file) + self.assertEqual(Instance.objects.count(), 1) + submission = Instance.objects.first() + self.assertEqual( + submission.json["grp1/grp2/browser_use"], + [ + { + "grp1/grp2/browser_use/grp3/grp4/grp5/year": 2010, + "grp1/grp2/browser_use/grp3/grp4/grp5/browsers": "firefox safari", + }, + { + "grp1/grp2/browser_use/grp3/grp4/grp5/year": 2011, + "grp1/grp2/browser_use/grp3/grp4/grp5/browsers": "firefox chrome", + }, + ], + ) + + def test_select_multiples_grouped_repeating_wo_split(self): + """Select multiple choices within group within repeat without split""" + md_xform = """ + | survey | | | | + | | type | name | label | + | | text | name | Name | + | | integer | age | Age | + | | begin group | grp1 | Group 1 | + | | begin group | grp2 | Group 2 | + | | begin repeat | browser_use | Browser Use | + | | begin group | grp3 | Group 3 | + | | begin group | grp4 | Group 4 | + | | begin group | grp5 | Group 5 | + | | integer | year | Year | + | | select_multiple browsers | browsers | Browsers | + | | end group | | | + | | end group | | | + | | end group | | | + | | end repeat | | | + | | end group | | | + | | end group | | | + | choices | | | | + | | list_name | name | label | + | | browsers | firefox | Firefox | + | | browsers | chrome | Chrome | + | | browsers | ie | Internet Explorer | + | | browsers | safari | Safari |""" + xform = self._publish_markdown(md_xform, self.user, id_string="nested_split") + + with open( + os.path.join( + self.fixtures_dir, "csv_import_multiple_wo_split_group_repeat.csv" + ), + "rb", + ) as csv_file: + csv_import.submit_csv(self.user.username, xform, csv_file) + self.assertEqual(Instance.objects.count(), 1) + submission = Instance.objects.first() + self.assertEqual( + submission.json["grp1/grp2/browser_use"], + [ + { + "grp1/grp2/browser_use/grp3/grp4/grp5/year": 2010, + "grp1/grp2/browser_use/grp3/grp4/grp5/browsers": "firefox safari", + }, + { + "grp1/grp2/browser_use/grp3/grp4/grp5/year": 2011, + "grp1/grp2/browser_use/grp3/grp4/grp5/browsers": "firefox chrome", + }, + ], + ) diff --git a/onadata/libs/tests/utils/test_export_builder.py b/onadata/libs/tests/utils/test_export_builder.py index f5c2d7ec8f..ec1fe751ae 100644 --- a/onadata/libs/tests/utils/test_export_builder.py +++ b/onadata/libs/tests/utils/test_export_builder.py @@ -1172,7 +1172,7 @@ def test_zipped_sav_export_with_duplicate_column_name(self): rows = list(reader) # Check that columns are present - self.assertIn("Sport", _str_if_bytes(rows[0])) + self.assertIn("Sport", [_str_if_bytes(item) for item in rows[0]]) # Check for sport in first 5 characters # because rows contains 'sport@d4b6' self.assertIn("sport", list(map(_str_if_bytes, [x[0:5] for x in rows[0]]))) diff --git a/onadata/libs/utils/csv_import.py b/onadata/libs/utils/csv_import.py index 4ce7f19f4e..fdd807646d 100644 --- a/onadata/libs/utils/csv_import.py +++ b/onadata/libs/utils/csv_import.py @@ -287,7 +287,7 @@ def flatten_split_select_multiples( for key, value in row.items(): if key in select_multiples and isinstance(value, dict): picked_choices = [ - k for k, v in value.items() if v in ["1", "TRUE"] or v == k + k for k, v in value.items() if v.upper() in ["1", "TRUE"] or v == k ] new_value = " ".join(picked_choices) row.update({key: new_value}) @@ -295,6 +295,18 @@ def flatten_split_select_multiples( # Handle cases where select_multiples are within a group new_value = flatten_split_select_multiples(value, select_multiples) row.update({key: new_value}) + elif isinstance(value, list): + # Handle case where we have repeat questions + new_value = [] + + for repeat_question in value: + flattened_question = flatten_split_select_multiples( + repeat_question, select_multiples + ) + new_value.append(flattened_question) + + row.update({key: new_value}) + return row