Skip to content

Commit 384b715

Browse files
author
Bart van der Schoor
committed
[#1427] Implemented OpenZaak status translation
1 parent 3966c11 commit 384b715

File tree

16 files changed

+357
-12
lines changed

16 files changed

+357
-12
lines changed

src/open_inwoner/cms/cases/views/mixins.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
fetch_single_case_type,
2020
fetch_single_status_type,
2121
)
22-
from open_inwoner.openzaak.models import OpenZaakConfig
22+
from open_inwoner.openzaak.models import OpenZaakConfig, StatusTranslation
2323
from open_inwoner.openzaak.utils import format_zaak_identificatie, is_zaak_visible
2424
from open_inwoner.utils.mixins import PaginationMixin
2525
from open_inwoner.utils.views import LogMixin
@@ -141,6 +141,7 @@ def get_cases(self) -> List[Zaak]:
141141
def process_cases(self, cases: List[Zaak]) -> List[dict]:
142142
# Prepare data for frontend
143143
config = OpenZaakConfig.get_solo()
144+
status_translate = StatusTranslation.objects.get_lookup()
144145

145146
updated_cases = []
146147
for case in cases:
@@ -150,7 +151,7 @@ def process_cases(self, cases: List[Zaak]) -> List[dict]:
150151
"start_date": case.startdatum,
151152
"end_date": getattr(case, "einddatum", None),
152153
"description": case.zaaktype.omschrijving,
153-
"current_status": glom(
154+
"current_status": status_translate.from_glom(
154155
case, "status.statustype.omschrijving", default=""
155156
),
156157
}

src/open_inwoner/cms/cases/views/status.py

+19-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
create_klant,
2424
fetch_klant_for_bsn,
2525
)
26-
from open_inwoner.openzaak.api_models import Zaak
26+
from open_inwoner.openzaak.api_models import Status, Zaak
2727
from open_inwoner.openzaak.cases import (
2828
connect_case_with_document,
2929
fetch_case_information_objects,
@@ -41,6 +41,7 @@
4141
)
4242
from open_inwoner.openzaak.models import (
4343
OpenZaakConfig,
44+
StatusTranslation,
4445
ZaakTypeConfig,
4546
ZaakTypeInformatieObjectTypeConfig,
4647
)
@@ -49,6 +50,7 @@
4950
get_role_name_display,
5051
is_info_object_visible,
5152
)
53+
from open_inwoner.utils.translate import TranslationLookup
5254
from open_inwoner.utils.views import CommonPageMixin, LogMixin
5355

5456
from ..forms import CaseContactForm, CaseUploadForm
@@ -110,6 +112,7 @@ def get_context_data(self, **kwargs):
110112
if self.case:
111113
self.log_case_access(self.case.identificatie)
112114
config = OpenZaakConfig.get_solo()
115+
status_translate = StatusTranslation.objects.get_lookup()
113116

114117
documents = self.get_case_document_files(self.case)
115118

@@ -147,12 +150,12 @@ def get_context_data(self, **kwargs):
147150
self.case, "uiterlijke_einddatum_afdoening", None
148151
),
149152
"description": self.case.zaaktype.omschrijving,
150-
"current_status": glom(
153+
"current_status": status_translate.from_glom(
151154
self.case,
152155
"status.statustype.omschrijving",
153156
default=_("No data available"),
154157
),
155-
"statuses": statuses,
158+
"statuses": self.get_statuses_data(statuses, status_translate),
156159
"documents": documents,
157160
"allowed_file_extensions": sorted(config.allowed_file_extensions),
158161
}
@@ -221,6 +224,19 @@ def get_initiator_display(self, case: Zaak) -> str:
221224
return ""
222225
return ", ".join([get_role_name_display(r) for r in roles])
223226

227+
def get_statuses_data(
228+
self, statuses: List[Status], lookup: TranslationLookup
229+
) -> List[dict]:
230+
return [
231+
{
232+
"date": s.datum_status_gezet,
233+
"label": lookup.from_glom(
234+
s, "statustype.omschrijving", default=_("No data available")
235+
),
236+
}
237+
for s in statuses
238+
]
239+
224240
def get_case_document_files(self, case: Zaak) -> List[SimpleFile]:
225241
case_info_objects = fetch_case_information_objects(case.url)
226242

src/open_inwoner/openzaak/admin.py

+31-1
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
from django.contrib import admin, messages
22
from django.core.exceptions import ValidationError
3-
from django.db.models import BooleanField, Count, Exists, ExpressionWrapper, Q
3+
from django.db.models import BooleanField, Count, ExpressionWrapper, Q
44
from django.forms.models import BaseInlineFormSet
55
from django.utils.translation import gettext_lazy as _, ngettext
66

7+
from import_export.admin import ImportExportMixin
8+
from import_export.formats import base_formats
79
from solo.admin import SingletonModelAdmin
810

911
from .models import (
1012
CatalogusConfig,
1113
OpenZaakConfig,
14+
StatusTranslation,
1215
UserCaseInfoObjectNotification,
1316
UserCaseStatusNotification,
1417
ZaakTypeConfig,
1518
ZaakTypeInformatieObjectTypeConfig,
1619
)
20+
from .resources.import_resource import StatusTranslationImportResource
1721

1822

1923
@admin.register(OpenZaakConfig)
@@ -316,3 +320,29 @@ class UserCaseInfoObjectNotificationAdmin(admin.ModelAdmin):
316320

317321
def has_change_permission(self, request, obj=None):
318322
return False
323+
324+
325+
@admin.register(StatusTranslation)
326+
class StatusTranslationAdmin(ImportExportMixin, admin.ModelAdmin):
327+
fields = [
328+
"status",
329+
"translation",
330+
]
331+
search_fields = [
332+
"status",
333+
"translation",
334+
]
335+
list_display = [
336+
"id",
337+
"status",
338+
"translation",
339+
]
340+
list_editable = [
341+
"status",
342+
"translation",
343+
]
344+
ordering = ("status",)
345+
346+
# import-export
347+
resource_class = StatusTranslationImportResource
348+
formats = [base_formats.XLSX, base_formats.CSV]

src/open_inwoner/openzaak/managers.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
from django.db import IntegrityError, models, transaction
55

66
from open_inwoner.accounts.models import User
7-
from open_inwoner.openzaak.api_models import Zaak, ZaakType
7+
from open_inwoner.openzaak.api_models import ZaakType
8+
from open_inwoner.utils.translate import TranslationLookup
89

910
if TYPE_CHECKING:
1011
from open_inwoner.openzaak.models import (
@@ -148,3 +149,8 @@ def filter_questions_enabled_for_case_type(self, case_type: ZaakType):
148149
return self.none()
149150

150151
return self.filter_case_type(case_type).filter(questions_enabled=True)
152+
153+
154+
class StatusTranslationQuerySet(models.QuerySet):
155+
def get_lookup(self):
156+
return TranslationLookup(self.values_list("status", "translation"))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Generated by Django 3.2.20 on 2023-08-25 08:07
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
(
10+
"openzaak",
11+
"0020_rename_contact_moments_enabled_zaaktypeconfig_contact_form_enabled",
12+
),
13+
]
14+
15+
operations = [
16+
migrations.CreateModel(
17+
name="StatusTranslation",
18+
fields=[
19+
(
20+
"id",
21+
models.AutoField(
22+
auto_created=True,
23+
primary_key=True,
24+
serialize=False,
25+
verbose_name="ID",
26+
),
27+
),
28+
(
29+
"status",
30+
models.CharField(
31+
max_length=255, unique=True, verbose_name="Status tekst"
32+
),
33+
),
34+
(
35+
"translation",
36+
models.CharField(max_length=255, verbose_name="Vertaling"),
37+
),
38+
],
39+
options={
40+
"verbose_name": "Status vertaling",
41+
"verbose_name_plural": "Status vertalingen",
42+
},
43+
),
44+
]

src/open_inwoner/openzaak/models.py

+19
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from zgw_consumers.constants import APITypes
1111

1212
from open_inwoner.openzaak.managers import (
13+
StatusTranslationQuerySet,
1314
UserCaseInfoObjectNotificationManager,
1415
UserCaseStatusNotificationManager,
1516
ZaakTypeConfigQueryset,
@@ -346,3 +347,21 @@ class Meta:
346347
fields=["user", "case_uuid", "zaak_info_object_uuid"],
347348
)
348349
]
350+
351+
352+
class StatusTranslation(models.Model):
353+
status = models.CharField(
354+
verbose_name=_("Status tekst"),
355+
max_length=255,
356+
unique=True,
357+
)
358+
translation = models.CharField(
359+
verbose_name=_("Vertaling"),
360+
max_length=255,
361+
)
362+
363+
objects = StatusTranslationQuerySet.as_manager()
364+
365+
class Meta:
366+
verbose_name = _("Status vertaling")
367+
verbose_name_plural = _("Status vertalingen")

src/open_inwoner/openzaak/resources/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from django.utils.translation import ugettext_lazy as _
2+
3+
from import_export import fields, resources
4+
from import_export.exceptions import ImportExportError
5+
6+
from open_inwoner.openzaak.models import StatusTranslation
7+
8+
9+
class StatusTranslationImportResource(resources.ModelResource):
10+
def before_import(self, dataset, using_transactions, dry_run, **kwargs):
11+
# Validate that file contains all the headers
12+
missing_headers = set(self.get_diff_headers()) - set(dataset.headers)
13+
if missing_headers:
14+
missing_headers = ",\n".join(missing_headers)
15+
raise ImportExportError(_(f"Missing required headers: {missing_headers}"))
16+
17+
return super().before_import(dataset, using_transactions, dry_run, **kwargs)
18+
19+
def get_or_init_instance(self, instance_loader, row):
20+
# Replace newlines from excel
21+
for key, value in row.items():
22+
if isinstance(value, str):
23+
row[key] = value.replace("_x000D_", "\n")
24+
25+
return super().get_or_init_instance(instance_loader, row)
26+
27+
status = fields.Field(column_name="status", attribute="status")
28+
translation = fields.Field(column_name="translation", attribute="translation")
29+
30+
class Meta:
31+
model = StatusTranslation
32+
import_id_fields = ("status",)
33+
fields = ("status", "translation")

src/open_inwoner/openzaak/tests/factories.py

+9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from open_inwoner.openzaak.api_models import Notification, Rol, ZaakType
1212
from open_inwoner.openzaak.models import (
1313
CatalogusConfig,
14+
StatusTranslation,
1415
ZaakTypeConfig,
1516
ZaakTypeInformatieObjectTypeConfig,
1617
)
@@ -120,6 +121,14 @@ class Meta:
120121
model = Notification
121122

122123

124+
class StatusTranslationFactory(factory.django.DjangoModelFactory):
125+
status = factory.Faker("pystr", max_chars=50)
126+
translation = factory.Faker("pystr", max_chars=80)
127+
128+
class Meta:
129+
model = StatusTranslation
130+
131+
123132
def generate_rol(
124133
type_: str,
125134
identification: dict,

src/open_inwoner/openzaak/tests/test_case_detail.py

+31-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from open_inwoner.accounts.tests.factories import UserFactory
2525
from open_inwoner.cms.cases.views.status import SimpleFile
2626
from open_inwoner.openzaak.tests.factories import (
27+
StatusTranslationFactory,
2728
ZaakTypeConfigFactory,
2829
ZaakTypeInformatieObjectTypeConfigFactory,
2930
)
@@ -350,6 +351,8 @@ def _setUpMocks(self, m):
350351
)
351352

352353
def test_status_is_retrieved_when_user_logged_in_via_digid(self, m):
354+
self.maxDiff = None
355+
353356
self._setUpMocks(m)
354357
status_new_obj, status_finish_obj = factory(
355358
Status, [self.status_new, self.status_finish]
@@ -370,7 +373,16 @@ def test_status_is_retrieved_when_user_logged_in_via_digid(self, m):
370373
"end_date_legal": datetime.date(2022, 1, 5),
371374
"description": "Coffee zaaktype",
372375
"current_status": "Finish",
373-
"statuses": [status_new_obj, status_finish_obj],
376+
"statuses": [
377+
{
378+
"date": datetime.datetime(2021, 1, 12),
379+
"label": "Initial request",
380+
},
381+
{
382+
"date": datetime.datetime(2021, 3, 12),
383+
"label": "Finish",
384+
},
385+
],
374386
# only one visible information object
375387
"documents": [self.informatie_object_file],
376388
"initiator": "Foo Bar van der Bazz",
@@ -407,6 +419,24 @@ def test_page_reformats_zaak_identificatie(self, m):
407419

408420
spy_format.assert_called_once()
409421

422+
def test_page_translates_statuses(self, m):
423+
st1 = StatusTranslationFactory(
424+
status=self.status_type_new["omschrijving"],
425+
translation="Translated First Status Type",
426+
)
427+
st2 = StatusTranslationFactory(
428+
status=self.status_type_finish["omschrijving"],
429+
translation="Translated Second Status Type",
430+
)
431+
self._setUpMocks(m)
432+
response = self.app.get(
433+
self.case_detail_url, user=self.user, headers={"HX-Request": "true"}
434+
)
435+
self.assertNotContains(response, st1.status)
436+
self.assertNotContains(response, st2.status)
437+
self.assertContains(response, st1.translation)
438+
self.assertContains(response, st2.translation)
439+
410440
def test_when_accessing_case_detail_a_timelinelog_is_created(self, m):
411441
self._setUpMocks(m)
412442

0 commit comments

Comments
 (0)