Skip to content

Commit

Permalink
expose the ZGW import/export functionality through the admin page
Browse files Browse the repository at this point in the history
  • Loading branch information
swrichards committed Aug 15, 2024
1 parent fc677ee commit d44a38c
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 10 deletions.
17 changes: 13 additions & 4 deletions src/open_inwoner/openzaak/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.forms import Form, ModelForm, Textarea
from django.forms.models import BaseInlineFormSet
from django.http import HttpResponseRedirect, StreamingHttpResponse
from django.template.defaultfilters import filesizeformat
from django.template.response import TemplateResponse
from django.urls import path, reverse
from django.utils.translation import gettext_lazy as _, ngettext
Expand Down Expand Up @@ -82,14 +83,16 @@ class OpenZaakConfigAdmin(SingletonModelAdmin):


class ImportZGWDumpForm(Form):
MAX_UPLOAD_SIZE = 1024**2 * 25 # 25MB
zgw_export_file = LimitedUploadFileField(
label=_("ZGW export bestand"),
help_text=_(
"Upload your file previously generated by the export function. Max size is 25MB"
"Upload a file generated by the export function on the 'Catalogus Config' administration page. The maximum size of this file is %(file_size)s"
% {"file_size": filesizeformat(MAX_UPLOAD_SIZE)}
),
allow_empty_file=False,
required=True,
max_upload_size=1024**2 * 25,
max_upload_size=MAX_UPLOAD_SIZE,
min_upload_size=1,
allowed_mime_types=["application/json", "text/plain"],
)
Expand Down Expand Up @@ -159,7 +162,7 @@ def process_file_view(self, request):
storage.save(target_file_name, uploaded_file)

try:
import_result = CatalogusConfigImport.from_django_storage_jsonl(
import_result = CatalogusConfigImport.import_from_jsonl_file_in_django_storage(
target_file_name,
storage,
)
Expand All @@ -180,8 +183,14 @@ def process_file_view(self, request):
except Exception as e:
logger.exception("Unable to process ZGW import")
self.message_user(
request, f"Error processing file: {str(e)}", messages.ERROR
request,
_(
"We were unable to process your upload. Please regenerate the file and try again."
),
messages.ERROR,
)
finally:
storage.delete(target_file_name)
else:
self.message_user(
request, _("No file was uploaded"), messages.WARNING
Expand Down
70 changes: 64 additions & 6 deletions src/open_inwoner/openzaak/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from django_webtest import WebTest
from maykin_2fa.test import disable_admin_mfa
from privates.storages import PrivateMediaFileSystemStorage
from privates.test import temp_private_root
from webtest import Upload

from open_inwoner.accounts.tests.factories import UserFactory
Expand Down Expand Up @@ -124,6 +125,8 @@ def test_both_can_be_disabled(self):


@disable_admin_mfa()
@temp_private_root()
@freezegun.freeze_time("2024-08-14 17:50:01")
@override_settings(CELERY_TASK_ALWAYS_EAGER=True)
class TestCatalogusConfigExportAdmin(WebTest):
csrf_checks = False
Expand All @@ -138,7 +141,7 @@ def setUp(self):
service=self.service,
)

def test_export_action_returns_json_response(self):
def test_export_action_returns_correct_export(self):
response = self.app.post(
reverse(
"admin:openzaak_catalogusconfig_changelist",
Expand Down Expand Up @@ -168,12 +171,56 @@ def test_export_action_returns_json_response(self):
},
},
],
msg="Response should be valid JSONL matching the input object",
)
self.assertFalse(
PrivateMediaFileSystemStorage().exists(
"zgw_import_dump_2024-08-14-17-50-01.jsonl"
),
msg="File should always deleted regardless of success or failure",
)

@mock.patch(
"open_inwoner.openzaak.import_export.CatalogusConfigImport.import_from_jsonl_file_in_django_storage"
)
def test_import_flow_reports_success(self, m) -> None:
form = self.app.get(
reverse(
"admin:upload_zgw_import_file",
),
user=self.user,
).form
form["zgw_export_file"] = Upload("dump.json", b"foobar", "application/json")

response = form.submit().follow()

self.assertEqual(m.call_count, 1)
self.assertEqual(m.call_args[0][0], "zgw_import_dump_2024-08-14-17-50-01.jsonl")
self.assertTrue(isinstance(m.call_args[0][1], PrivateMediaFileSystemStorage))

messages = [str(msg) for msg in response.context["messages"]]
self.assertEqual(
messages,
["Successfully processed 1 items"],
)
self.assertFalse(
PrivateMediaFileSystemStorage().exists(
"zgw_import_dump_2024-08-14-17-50-01.jsonl"
),
msg="File should always deleted regardless of success or failure",
)
self.assertEqual(
response.request.path,
reverse(
"admin:openzaak_catalogusconfig_changelist",
),
)

@mock.patch(
"open_inwoner.openzaak.import_export.ZGWImportExportService.import_catalogus_config"
"open_inwoner.openzaak.import_export.CatalogusConfigImport.import_from_jsonl_file_in_django_storage"
)
def test_actual_import_flow(self, m) -> None:
def test_import_flow_errors_reports_failure_to_user(self, m) -> None:
m.side_effect = Exception("something went wrong")
form = self.app.get(
reverse(
"admin:upload_zgw_import_file",
Expand All @@ -182,8 +229,7 @@ def test_actual_import_flow(self, m) -> None:
).form
form["zgw_export_file"] = Upload("dump.json", b"foobar", "application/json")

with freezegun.freeze_time("2024-08-14 17:50:01"):
response = form.submit().follow()
response = form.submit()

self.assertEqual(m.call_count, 1)
self.assertEqual(m.call_args[0][0], "zgw_import_dump_2024-08-14-17-50-01.jsonl")
Expand All @@ -193,6 +239,18 @@ def test_actual_import_flow(self, m) -> None:
self.assertEqual(
messages,
[
'Your import has been successfully received and is being processed in the background. You can <a href="/admin/celery_monitor/taskstate/?name=open_inwoner.openzaak.tasks.process_zgw_import_file">monitor the task\'s progress here</a>. Note that it may take a few seconds for your task to appear, you might have to refresh the page a few times.'
"We were unable to process your upload. Please regenerate the file and try again."
],
)
self.assertFalse(
PrivateMediaFileSystemStorage().exists(
"zgw_import_dump_2024-08-14-17-50-01.jsonl"
),
msg="File should always deleted regardless of success or failure",
)
self.assertEqual(
response.request.path,
reverse(
"admin:upload_zgw_import_file",
),
)

0 comments on commit d44a38c

Please sign in to comment.