From d9c642bb319df286cee9162bb73396bba1ee2226 Mon Sep 17 00:00:00 2001 From: Bart van der Schoor Date: Fri, 12 Apr 2024 09:24:13 +0200 Subject: [PATCH] [#2260] Removed StatusTranslation model --- src/open_inwoner/cms/cases/views/status.py | 20 +++--- src/open_inwoner/openzaak/admin.py | 30 -------- src/open_inwoner/openzaak/api_models.py | 7 +- src/open_inwoner/openzaak/models.py | 19 ----- src/open_inwoner/openzaak/notifications.py | 8 ++- .../openzaak/resources/__init__.py | 0 .../openzaak/resources/import_resource.py | 33 --------- src/open_inwoner/openzaak/tests/factories.py | 9 --- .../openzaak/tests/test_notification_utils.py | 7 +- .../openzaak/tests/test_status_translation.py | 33 --------- src/open_inwoner/openzaak/utils.py | 22 +----- .../userfeed/hooks/case_status.py | 10 +-- src/open_inwoner/utils/glom.py | 13 ++++ src/open_inwoner/utils/tests/test_glom.py | 14 ++++ .../utils/tests/test_translate.py | 69 ------------------- 15 files changed, 50 insertions(+), 244 deletions(-) delete mode 100644 src/open_inwoner/openzaak/resources/__init__.py delete mode 100644 src/open_inwoner/openzaak/resources/import_resource.py delete mode 100644 src/open_inwoner/openzaak/tests/test_status_translation.py create mode 100644 src/open_inwoner/utils/glom.py create mode 100644 src/open_inwoner/utils/tests/test_glom.py delete mode 100644 src/open_inwoner/utils/tests/test_translate.py diff --git a/src/open_inwoner/cms/cases/views/status.py b/src/open_inwoner/cms/cases/views/status.py index 4978d0a552..759c61ebe0 100644 --- a/src/open_inwoner/cms/cases/views/status.py +++ b/src/open_inwoner/cms/cases/views/status.py @@ -37,7 +37,6 @@ ) from open_inwoner.openzaak.models import ( OpenZaakConfig, - StatusTranslation, ZaakTypeConfig, ZaakTypeInformatieObjectTypeConfig, ZaakTypeResultaatTypeConfig, @@ -45,8 +44,8 @@ ) from open_inwoner.openzaak.utils import get_role_name_display, is_info_object_visible from open_inwoner.userfeed import hooks +from open_inwoner.utils.glom import glom_multiple from open_inwoner.utils.time import has_new_elements -from open_inwoner.utils.translate import TranslationLookup from open_inwoner.utils.views import CommonPageMixin, LogMixin from ..forms import CaseContactForm, CaseUploadForm @@ -138,7 +137,6 @@ def get_context_data(self, **kwargs): self.log_access_case_detail(self.case) config = OpenZaakConfig.get_solo() - status_translate = StatusTranslation.objects.get_lookup() zaken_client = build_client_openzaak("zaak") @@ -193,7 +191,6 @@ def get_context_data(self, **kwargs): end_statustype_data = self.handle_end_statustype_data( status_types_mapping=status_types_mapping, end_statustype=self.handle_end_statustype(statuses, statustypen), - status_translate=status_translate, ) result_data = self.get_result_data( self.case, self.resulttype_config_mapping, zaken_client @@ -216,7 +213,7 @@ def get_context_data(self, **kwargs): ), "description": self.case.zaaktype.omschrijving, "statuses": self.get_statuses_data( - statuses, status_translate, self.statustype_config_mapping + statuses, self.statustype_config_mapping ), "end_statustype_data": end_statustype_data, "second_status_preview": second_status_preview, @@ -364,7 +361,6 @@ def handle_end_statustype_data( self, status_types_mapping: dict[str, StatusType], end_statustype: StatusType, - status_translate: StatusTranslation, ): """ Prepare data about end statustype for use in context/template @@ -372,9 +368,10 @@ def handle_end_statustype_data( end_statustype_data = None if not status_types_mapping.get(end_statustype.url): end_statustype_data = { - "label": status_translate( - (end_statustype.statustekst or end_statustype.omschrijving), - default=_("No data available"), + "label": ( + end_statustype.statustekst + or end_statustype.omschrijving + or _("No data available") ), "status_indicator": getattr( self.statustype_config_mapping.get(end_statustype.url), @@ -533,19 +530,18 @@ def get_result_data( def get_initiator_display(case: Zaak) -> str: if client := build_client_openzaak("zaak"): roles = client.fetch_case_roles(case.url, RolOmschrijving.initiator) - return ", ".join([get_role_name_display(r) for r in roles]) + return ", ".join(get_role_name_display(r) for r in roles) return "" @staticmethod def get_statuses_data( statuses: list[Status], - lookup: TranslationLookup, statustype_config_mapping: dict | None = None, ) -> list[dict]: return [ { "date": s.datum_status_gezet, - "label": lookup.from_glom_multiple( + "label": glom_multiple( s, ("statustype.statustekst", "statustype.omschrijving"), default=_("No data available"), diff --git a/src/open_inwoner/openzaak/admin.py b/src/open_inwoner/openzaak/admin.py index 73799865d9..f80a1aec70 100644 --- a/src/open_inwoner/openzaak/admin.py +++ b/src/open_inwoner/openzaak/admin.py @@ -5,8 +5,6 @@ from django.forms.models import BaseInlineFormSet from django.utils.translation import gettext_lazy as _, ngettext -from import_export.admin import ImportExportMixin -from import_export.formats import base_formats from solo.admin import SingletonModelAdmin from open_inwoner.ckeditor5.widgets import CKEditorWidget @@ -14,7 +12,6 @@ from .models import ( CatalogusConfig, OpenZaakConfig, - StatusTranslation, UserCaseInfoObjectNotification, UserCaseStatusNotification, ZaakTypeConfig, @@ -22,7 +19,6 @@ ZaakTypeResultaatTypeConfig, ZaakTypeStatusTypeConfig, ) -from .resources.import_resource import StatusTranslationImportResource @admin.register(OpenZaakConfig) @@ -449,29 +445,3 @@ class UserCaseInfoObjectNotificationAdmin(admin.ModelAdmin): def has_change_permission(self, request, obj=None): return False - - -@admin.register(StatusTranslation) -class StatusTranslationAdmin(ImportExportMixin, admin.ModelAdmin): - fields = [ - "status", - "translation", - ] - search_fields = [ - "status", - "translation", - ] - list_display = [ - "id", - "status", - "translation", - ] - list_editable = [ - "status", - "translation", - ] - ordering = ("status",) - - # import-export - resource_class = StatusTranslationImportResource - formats = [base_formats.XLSX, base_formats.CSV] diff --git a/src/open_inwoner/openzaak/api_models.py b/src/open_inwoner/openzaak/api_models.py index b4ecb20fb7..ea904ec82b 100644 --- a/src/open_inwoner/openzaak/api_models.py +++ b/src/open_inwoner/openzaak/api_models.py @@ -8,6 +8,8 @@ from zgw_consumers.api_models.base import Model, ZGWModel from zgw_consumers.api_models.constants import RolOmschrijving, RolTypes +from open_inwoner.utils.glom import glom_multiple + logger = logging.getLogger(__name__) @@ -69,9 +71,6 @@ def process_data(self) -> dict: """ Prepare data for template """ - from open_inwoner.openzaak.models import StatusTranslation - - status_translate = StatusTranslation.objects.get_lookup() return { "identification": self.identification, @@ -79,7 +78,7 @@ def process_data(self) -> dict: "start_date": self.startdatum, "end_date": getattr(self, "einddatum", None), "description": self.zaaktype.omschrijving, - "current_status": status_translate.from_glom_multiple( + "current_status": glom_multiple( self, ("status.statustype.statustekst", "status.statustype.omschrijving"), default="", diff --git a/src/open_inwoner/openzaak/models.py b/src/open_inwoner/openzaak/models.py index 450d9ab89c..5d3fefcd02 100644 --- a/src/open_inwoner/openzaak/models.py +++ b/src/open_inwoner/openzaak/models.py @@ -12,7 +12,6 @@ from zgw_consumers.constants import APITypes from open_inwoner.openzaak.managers import ( - StatusTranslationQuerySet, UserCaseInfoObjectNotificationManager, UserCaseStatusNotificationManager, ZaakTypeConfigQueryset, @@ -594,21 +593,3 @@ def has_received_similar_notes_within( return UserCaseInfoObjectNotification.objects.has_received_similar_notes_within( self.user, self.case_uuid, period, collision_key, not_record_id=self.id ) - - -class StatusTranslation(models.Model): - status = models.CharField( - verbose_name=_("Status tekst"), - max_length=255, - unique=True, - ) - translation = models.CharField( - verbose_name=_("Vertaling"), - max_length=255, - ) - - objects = StatusTranslationQuerySet.as_manager() - - class Meta: - verbose_name = _("Status vertaling") - verbose_name_plural = _("Status vertalingen") diff --git a/src/open_inwoner/openzaak/notifications.py b/src/open_inwoner/openzaak/notifications.py index 7f097f3c27..008e9988ad 100644 --- a/src/open_inwoner/openzaak/notifications.py +++ b/src/open_inwoner/openzaak/notifications.py @@ -3,6 +3,7 @@ from django.conf import settings from django.urls import reverse +from django.utils.translation import gettext as _ from mail_editor.helpers import find_template from zgw_consumers.api_models.constants import RolOmschrijving, RolTypes @@ -30,7 +31,6 @@ get_zaak_type_info_object_type_config, is_info_object_visible, is_zaak_visible, - translate_single_status, ) from open_inwoner.userfeed import hooks from open_inwoner.utils.logentry import system_action as log_system_action @@ -592,8 +592,10 @@ def send_case_update_email( } if status: status_type = status.statustype - context["status_description"] = translate_single_status( - status_type.statustekst or status_type.omschrijving + context["status_description"] = ( + status_type.statustekst + or status_type.omschrijving + or _("No data available") ) if extra_context: context.update(extra_context) diff --git a/src/open_inwoner/openzaak/resources/__init__.py b/src/open_inwoner/openzaak/resources/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/open_inwoner/openzaak/resources/import_resource.py b/src/open_inwoner/openzaak/resources/import_resource.py deleted file mode 100644 index 3e44b701d6..0000000000 --- a/src/open_inwoner/openzaak/resources/import_resource.py +++ /dev/null @@ -1,33 +0,0 @@ -from django.utils.translation import gettext_lazy as _ - -from import_export import fields, resources -from import_export.exceptions import ImportExportError - -from open_inwoner.openzaak.models import StatusTranslation - - -class StatusTranslationImportResource(resources.ModelResource): - def before_import(self, dataset, using_transactions, dry_run, **kwargs): - # Validate that file contains all the headers - missing_headers = set(self.get_diff_headers()) - set(dataset.headers) - if missing_headers: - missing_headers = ",\n".join(missing_headers) - raise ImportExportError(_(f"Missing required headers: {missing_headers}")) - - return super().before_import(dataset, using_transactions, dry_run, **kwargs) - - def get_or_init_instance(self, instance_loader, row): - # Replace newlines from excel - for key, value in row.items(): - if isinstance(value, str): - row[key] = value.replace("_x000D_", "\n") - - return super().get_or_init_instance(instance_loader, row) - - status = fields.Field(column_name="status", attribute="status") - translation = fields.Field(column_name="translation", attribute="translation") - - class Meta: - model = StatusTranslation - import_id_fields = ("status",) - fields = ("status", "translation") diff --git a/src/open_inwoner/openzaak/tests/factories.py b/src/open_inwoner/openzaak/tests/factories.py index c33846f35c..63eef20b32 100644 --- a/src/open_inwoner/openzaak/tests/factories.py +++ b/src/open_inwoner/openzaak/tests/factories.py @@ -11,7 +11,6 @@ from open_inwoner.openzaak.api_models import Notification, Rol from open_inwoner.openzaak.models import ( CatalogusConfig, - StatusTranslation, UserCaseInfoObjectNotification, UserCaseStatusNotification, ZaakTypeConfig, @@ -152,14 +151,6 @@ class Meta: model = Notification -class StatusTranslationFactory(factory.django.DjangoModelFactory): - status = factory.Faker("pystr", max_chars=50) - translation = factory.Faker("pystr", max_chars=80) - - class Meta: - model = StatusTranslation - - def generate_rol( type_: str, identification: dict, diff --git a/src/open_inwoner/openzaak/tests/test_notification_utils.py b/src/open_inwoner/openzaak/tests/test_notification_utils.py index 7084b63bd3..783a3530a8 100644 --- a/src/open_inwoner/openzaak/tests/test_notification_utils.py +++ b/src/open_inwoner/openzaak/tests/test_notification_utils.py @@ -18,7 +18,6 @@ from open_inwoner.openzaak.tests.factories import generate_rol from ..api_models import Status, StatusType, Zaak, ZaakType -from ..models import StatusTranslation from .test_notification_data import MockAPIData @@ -38,10 +37,6 @@ def test_send_case_update_email(self): case.status = status - StatusTranslation.objects.create( - status=status.statustype.omschrijving, translation="My Translated Status" - ) - case_url = reverse("cases:case_detail", kwargs={"object_id": str(case.uuid)}) # mock `_format_zaak_identificatie`, but then continue with result of actual call @@ -65,7 +60,7 @@ def test_send_case_update_email(self): body_html = email.alternatives[0][0] self.assertIn(case.identificatie, body_html) self.assertIn(case.zaaktype.omschrijving, body_html) - self.assertIn("My Translated Status", body_html) + self.assertIn(status.statustype.omschrijving, body_html) self.assertIn(case_url, body_html) self.assertIn(config.name, body_html) diff --git a/src/open_inwoner/openzaak/tests/test_status_translation.py b/src/open_inwoner/openzaak/tests/test_status_translation.py deleted file mode 100644 index 79718abeb6..0000000000 --- a/src/open_inwoner/openzaak/tests/test_status_translation.py +++ /dev/null @@ -1,33 +0,0 @@ -from django.test import TestCase - -from open_inwoner.openzaak.models import StatusTranslation -from open_inwoner.openzaak.tests.factories import StatusTranslationFactory -from open_inwoner.openzaak.utils import translate_single_status - - -class StatusTranslationModelTest(TestCase): - def test_lookup(self): - StatusTranslationFactory(status="foo", translation="FOO") - StatusTranslationFactory(status="bar", translation="BAR") - - lookup = StatusTranslation.objects.get_lookup() - - tests = [ - # input, expected - ("foo", "FOO"), - ("bar", "BAR"), - ("bazz", "bazz"), - ("", ""), - ] - for value, expected in tests: - with self.subTest(value=value, expected=expected): - actual = lookup(value) - self.assertEqual(expected, actual) - - # NOTE the TranslationLookup helper is further tested in its own file - # src/open_inwoner/utils/tests/test_translate.py - - def test_helper(self): - StatusTranslationFactory(status="foo", translation="FOO") - self.assertEqual("FOO", translate_single_status("foo")) - self.assertEqual("not_translated", translate_single_status("not_translated")) diff --git a/src/open_inwoner/openzaak/utils.py b/src/open_inwoner/openzaak/utils.py index 699e86bc6a..9c484572d5 100644 --- a/src/open_inwoner/openzaak/utils.py +++ b/src/open_inwoner/openzaak/utils.py @@ -1,18 +1,11 @@ import logging -from django.utils.translation import gettext as _ - from zgw_consumers.api_models.constants import RolTypes, VertrouwelijkheidsAanduidingen from open_inwoner.kvk.branches import get_kvk_branch_number from open_inwoner.openzaak.api_models import InformatieObject, Rol, Zaak, ZaakType -from .models import ( - OpenZaakConfig, - StatusTranslation, - ZaakTypeConfig, - ZaakTypeInformatieObjectTypeConfig, -) +from .models import OpenZaakConfig, ZaakTypeConfig, ZaakTypeInformatieObjectTypeConfig logger = logging.getLogger(__name__) @@ -133,19 +126,6 @@ def get_zaak_type_info_object_type_config( return None -def translate_single_status(status_text: str) -> str: - if not status_text: - return _("No data available") - - # in most cases try to cache with StatusTranslation.objects.get_lookup() - try: - return StatusTranslation.objects.values_list("translation", flat=True).get( - status=status_text - ) - except StatusTranslation.DoesNotExist: - return status_text - - def get_user_fetch_parameters(request) -> dict: """ Determine the parameters used to perform ZGW resource fetches diff --git a/src/open_inwoner/userfeed/hooks/case_status.py b/src/open_inwoner/userfeed/hooks/case_status.py index 1d60b6564d..b9e9278768 100644 --- a/src/open_inwoner/userfeed/hooks/case_status.py +++ b/src/open_inwoner/userfeed/hooks/case_status.py @@ -9,7 +9,6 @@ from open_inwoner.accounts.models import User from open_inwoner.openzaak.api_models import Status, Zaak from open_inwoner.openzaak.models import ZaakTypeStatusTypeConfig -from open_inwoner.openzaak.utils import translate_single_status from open_inwoner.userfeed.adapter import FeedItem from open_inwoner.userfeed.adapters import register_item_adapter from open_inwoner.userfeed.choices import FeedItemType @@ -23,8 +22,10 @@ def case_status_notification_received(user: User, case: Zaak, status: Status): "case_uuid": case.uuid, "case_identificatie": case.identificatie, "case_omschrijving": case.omschrijving, - "status_omschrijving": translate_single_status( - status.statustype.statustekst or status.statustype.omschrijving + "status_omschrijving": ( + status.statustype.statustekst + or status.statustype.omschrijving + or _("No data available") ), # new for actionable "catalogus_url": case.zaaktype.catalogus, @@ -90,8 +91,7 @@ def title(self) -> str: @property def message(self) -> str: - status_text = self.get_data("status_omschrijving") - status_text = translate_single_status(status_text) + status_text = self.get_data("status_omschrijving") or _("No data available") html = escape(self.base_message) status = format_html('{}', status_text) html = format_html(html, status=status) diff --git a/src/open_inwoner/utils/glom.py b/src/open_inwoner/utils/glom.py new file mode 100644 index 0000000000..e3c596edf5 --- /dev/null +++ b/src/open_inwoner/utils/glom.py @@ -0,0 +1,13 @@ +from glom import glom + + +def glom_multiple(obj, paths: tuple[str, ...], *, default=None): + if not len(paths) > 1: + raise ValueError("no paths provided") + + # note this isn't the same as using glom.Coalesce() because we also skip falsy values + for p in paths: + value = glom(obj, p, default=None) + if value: + return value + return default diff --git a/src/open_inwoner/utils/tests/test_glom.py b/src/open_inwoner/utils/tests/test_glom.py new file mode 100644 index 0000000000..013b43f439 --- /dev/null +++ b/src/open_inwoner/utils/tests/test_glom.py @@ -0,0 +1,14 @@ +from django.test import SimpleTestCase + +from open_inwoner.utils.glom import glom_multiple + + +class GlomTestCase(SimpleTestCase): + def test_glom_multiple(self): + obj = { + "aa": {"bb": 1}, + "cc": {"dd": 2}, + } + self.assertEquals(glom_multiple(obj, ("aa.bb", "cc.dd")), 1) + self.assertEquals(glom_multiple(obj, ("aa.xyz", "cc.dd")), 2) + self.assertEquals(glom_multiple(obj, ("aa.xyz", "cc.xyz"), default=999), 999) diff --git a/src/open_inwoner/utils/tests/test_translate.py b/src/open_inwoner/utils/tests/test_translate.py deleted file mode 100644 index ceb5871b3b..0000000000 --- a/src/open_inwoner/utils/tests/test_translate.py +++ /dev/null @@ -1,69 +0,0 @@ -from django.test import TestCase - -from open_inwoner.utils.translate import TranslationLookup - - -class TranslationLookupTest(TestCase): - def test_lookup(self): - values_list = [ - ("foo", "FOO"), - ("bar", "BAR"), - ] - lookup = TranslationLookup(values_list) - - tests = [ - # input, expected - ("foo", "FOO"), - ("bar", "BAR"), - ("bazz", "bazz"), - ("", ""), - ] - for value, expected in tests: - with self.subTest(value=value, expected=expected): - actual = lookup(value) - self.assertEqual(expected, actual) - - # extra - with self.subTest("normal key with default returns key"): - actual = lookup("bazz", default="buzz") - self.assertEqual("bazz", actual) - - with self.subTest("empty key with default return default"): - actual = lookup("", default="buzz") - self.assertEqual("buzz", actual) - - def test_lookup_from_glom(self): - values_list = [ - ("foo", "FOO"), - ("bar", "BAR"), - ] - lookup = TranslationLookup(values_list) - - data = { - "aaa": { - "fff": "foo", - "bbb": "bar", - "zzz": "bazz", - }, - } - - tests = [ - # input, expected - ("aaa.fff", "FOO"), - ("aaa.bbb", "BAR"), - ("aaa.zzz", "bazz"), - ("aaa.xxx", ""), - ("", ""), - ] - for value, expected in tests: - with self.subTest(value=value, expected=expected): - actual = lookup.from_glom(data, value) - self.assertEqual(expected, actual) - - with self.subTest("with default"): - actual = lookup.from_glom(data, "aaa.xxx", default="buzz") - self.assertEqual("buzz", actual) - - with self.subTest("with empty default"): - actual = lookup.from_glom(data, "aaa.xxx", default="") - self.assertEqual("", actual)