diff --git a/onadata/apps/api/tests/viewsets/test_xform_viewset.py b/onadata/apps/api/tests/viewsets/test_xform_viewset.py index f17b249b29..b90e9f14f3 100644 --- a/onadata/apps/api/tests/viewsets/test_xform_viewset.py +++ b/onadata/apps/api/tests/viewsets/test_xform_viewset.py @@ -4987,6 +4987,38 @@ def test_form_publishing_floip(self): self.assertEqual(response.status_code, 201, response.data) self.assertEqual(xforms + 1, XForm.objects.count()) + def test_xlsx_import(self): + """Ensure XLSX imports work as expected and dates are formatted correctly""" + with HTTMock(enketo_mock): + xls_path = os.path.join( + settings.PROJECT_ROOT, + "apps", + "main", + "tests", + "fixtures", + "double_image_form.xlsx", + ) + self._publish_xls_form_to_project(xlsform_path=xls_path) + view = XFormViewSet.as_view({"post": "data_import"}) + xls_import = fixtures_path("double_image_field_form_data.xlsx") + post_data = {"xls_file": xls_import} + request = self.factory.post("/", data=post_data, **self.extra) + response = view(request, pk=self.xform.id) + + # check that date columns are formatted correctly + self.assertEqual( + self.xform.instances.values("json___submission_time")[::1], + [ + {"json___submission_time": "2023-02-03T10:27:41"}, + {"json___submission_time": "2023-02-03T10:27:42"}, + {"json___submission_time": "2023-03-13T08:42:57"}, + ], + ) + self.assertEqual(response.status_code, 200) + self.assertEqual(response.get("Cache-Control"), None) + self.assertEqual(response.data.get("additions"), 3) + self.assertEqual(response.data.get("updates"), 0) + def test_xls_import(self): with HTTMock(enketo_mock): xls_path = os.path.join( diff --git a/onadata/apps/api/viewsets/xform_viewset.py b/onadata/apps/api/viewsets/xform_viewset.py index 9ad28451dc..21b9dcf718 100644 --- a/onadata/apps/api/viewsets/xform_viewset.py +++ b/onadata/apps/api/viewsets/xform_viewset.py @@ -705,8 +705,9 @@ def data_import(self, request, *args, **kwargs): ) else: csv_file.seek(0) + file_name = getattr(csv_file, "name", xls_file and xls_file.name) upload_to = os.path.join( - request.user.username, "csv_imports", csv_file.name + request.user.username, "csv_imports", file_name ) file_name = default_storage.save(upload_to, csv_file) task = submit_csv_async.delay( diff --git a/onadata/apps/main/tests/fixtures/double_image_form.xlsx b/onadata/apps/main/tests/fixtures/double_image_form.xlsx new file mode 100644 index 0000000000..4a363ee979 Binary files /dev/null and b/onadata/apps/main/tests/fixtures/double_image_form.xlsx differ diff --git a/onadata/libs/tests/utils/fixtures/double_image_field_form_data.xlsx b/onadata/libs/tests/utils/fixtures/double_image_field_form_data.xlsx new file mode 100644 index 0000000000..5196d5dd56 Binary files /dev/null and b/onadata/libs/tests/utils/fixtures/double_image_field_form_data.xlsx differ diff --git a/onadata/libs/utils/csv_import.py b/onadata/libs/utils/csv_import.py index f75c3d5386..4ce7f19f4e 100644 --- a/onadata/libs/utils/csv_import.py +++ b/onadata/libs/utils/csv_import.py @@ -129,7 +129,7 @@ def dict_merge(part_a, part_b): if not isinstance(part_b, dict): return part_b result = deepcopy(part_a) - for (k, v) in iteritems(part_b): + for k, v in iteritems(part_b): if k in result and isinstance(result[k], dict): result[k] = dict_merge(result[k], v) else: @@ -628,16 +628,16 @@ def submission_xls_to_csv(xls_file): # noqa # convert excel dates(floats) to datetime for date_column_index in date_columns: try: - row_values[date_column_index] = ( - row_values[date_column_index].strftime("%Y-%m-%d").isoformat() - ) + row_values[date_column_index - 1] = row_values[ + date_column_index - 1 + ].isoformat() except (ValueError, TypeError): pass # convert excel boolean to true/false for boolean_column_index in boolean_columns: - row_values[boolean_column_index] = bool( - row_values[boolean_column_index] == EXCEL_TRUE + row_values[boolean_column_index - 1] = bool( + row_values[boolean_column_index - 1] == EXCEL_TRUE ) csv_writer.writerow(row_values)