From 12a1cc12e0c177dd27f69d3a3e9bc99969adf532 Mon Sep 17 00:00:00 2001 From: apiyo Date: Tue, 8 Aug 2023 10:28:35 +0300 Subject: [PATCH 1/6] Fix off-by-one error in xls_to_csv function --- onadata/libs/utils/csv_import.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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) From 1daac1143362a0a9bc070abffb3b5cb6a0a8058c Mon Sep 17 00:00:00 2001 From: apiyo Date: Tue, 8 Aug 2023 10:29:13 +0300 Subject: [PATCH 2/6] Ensure csvs converted from xls have the correct file_name --- onadata/apps/api/viewsets/xform_viewset.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/onadata/apps/api/viewsets/xform_viewset.py b/onadata/apps/api/viewsets/xform_viewset.py index 9ad28451dc..4b904d3869 100644 --- a/onadata/apps/api/viewsets/xform_viewset.py +++ b/onadata/apps/api/viewsets/xform_viewset.py @@ -685,6 +685,7 @@ def data_import(self, request, *args, **kwargs): else: if xls_file and xls_file.name.split(".")[-1] in XLS_EXTENSIONS: + xls_file_name = xls_file.name csv_file = submission_xls_to_csv(xls_file) overwrite = request.query_params.get("overwrite") overwrite = ( @@ -705,8 +706,12 @@ def data_import(self, request, *args, **kwargs): ) else: csv_file.seek(0) + if hasattr(csv_file, "name"): + file_name = csv_file.name + else: + file_name = 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( From 9b3ae09935ea59ed08913a187f2f93f9c965843e Mon Sep 17 00:00:00 2001 From: apiyo Date: Tue, 8 Aug 2023 10:38:25 +0300 Subject: [PATCH 3/6] Refactor: Fix error raised by linter --- onadata/apps/api/viewsets/xform_viewset.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/onadata/apps/api/viewsets/xform_viewset.py b/onadata/apps/api/viewsets/xform_viewset.py index 4b904d3869..21b9dcf718 100644 --- a/onadata/apps/api/viewsets/xform_viewset.py +++ b/onadata/apps/api/viewsets/xform_viewset.py @@ -685,7 +685,6 @@ def data_import(self, request, *args, **kwargs): else: if xls_file and xls_file.name.split(".")[-1] in XLS_EXTENSIONS: - xls_file_name = xls_file.name csv_file = submission_xls_to_csv(xls_file) overwrite = request.query_params.get("overwrite") overwrite = ( @@ -706,10 +705,7 @@ def data_import(self, request, *args, **kwargs): ) else: csv_file.seek(0) - if hasattr(csv_file, "name"): - file_name = csv_file.name - else: - file_name = xls_file_name + file_name = getattr(csv_file, "name", xls_file and xls_file.name) upload_to = os.path.join( request.user.username, "csv_imports", file_name ) From c7f9b6c1038984713902747d92061b4b0502229d Mon Sep 17 00:00:00 2001 From: apiyo Date: Tue, 8 Aug 2023 18:05:09 +0300 Subject: [PATCH 4/6] test: Add test case for xlsx import --- .../api/tests/viewsets/test_xform_viewset.py | 22 ++++++++++++++++++ .../tests/fixtures/double_image_form.xlsx | Bin 0 -> 6030 bytes .../double_image_field_form_data.xlsx | Bin 0 -> 5583 bytes 3 files changed, 22 insertions(+) create mode 100644 onadata/apps/main/tests/fixtures/double_image_form.xlsx create mode 100644 onadata/libs/tests/utils/fixtures/double_image_field_form_data.xlsx diff --git a/onadata/apps/api/tests/viewsets/test_xform_viewset.py b/onadata/apps/api/tests/viewsets/test_xform_viewset.py index f17b249b29..ea0abb6648 100644 --- a/onadata/apps/api/tests/viewsets/test_xform_viewset.py +++ b/onadata/apps/api/tests/viewsets/test_xform_viewset.py @@ -4987,6 +4987,28 @@ 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): + 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) + + 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/main/tests/fixtures/double_image_form.xlsx b/onadata/apps/main/tests/fixtures/double_image_form.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..4a363ee9791920eb1002adec23cb0716fe58d218 GIT binary patch literal 6030 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5196d5dd562c34132045f1fdb9647b3c82d49a2a GIT binary patch literal 5583 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 Wz(8ty000j1D}yZHzP}_s!2bbK+^nMj literal 0 HcmV?d00001 From a1b02a5c3e070d6793c53a547af032500cc52092 Mon Sep 17 00:00:00 2001 From: apiyo Date: Wed, 9 Aug 2023 10:52:37 +0300 Subject: [PATCH 5/6] test: Test that dates are formatted correctly for xls imports --- onadata/apps/api/tests/viewsets/test_xform_viewset.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/onadata/apps/api/tests/viewsets/test_xform_viewset.py b/onadata/apps/api/tests/viewsets/test_xform_viewset.py index ea0abb6648..e5824b44a3 100644 --- a/onadata/apps/api/tests/viewsets/test_xform_viewset.py +++ b/onadata/apps/api/tests/viewsets/test_xform_viewset.py @@ -5004,6 +5004,15 @@ def test_xlsx_import(self): 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) From f1825db683f0612816536419f99c3fadb9fa4c1f Mon Sep 17 00:00:00 2001 From: apiyo Date: Wed, 9 Aug 2023 10:59:08 +0300 Subject: [PATCH 6/6] docs: Add documentation for xlsx import testcase --- onadata/apps/api/tests/viewsets/test_xform_viewset.py | 1 + 1 file changed, 1 insertion(+) diff --git a/onadata/apps/api/tests/viewsets/test_xform_viewset.py b/onadata/apps/api/tests/viewsets/test_xform_viewset.py index e5824b44a3..b90e9f14f3 100644 --- a/onadata/apps/api/tests/viewsets/test_xform_viewset.py +++ b/onadata/apps/api/tests/viewsets/test_xform_viewset.py @@ -4988,6 +4988,7 @@ def test_form_publishing_floip(self): 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,