Skip to content

Commit 703936d

Browse files
committed
feat(dref): add translation completion check
1 parent 3c7741c commit 703936d

File tree

4 files changed

+73
-12
lines changed

4 files changed

+73
-12
lines changed

dref/serializers.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ class MiniDrefSerializer(serializers.ModelSerializer):
205205
unpublished_final_report_count = serializers.SerializerMethodField()
206206
operational_update_details = serializers.SerializerMethodField()
207207
final_report_details = serializers.SerializerMethodField()
208+
original_language = serializers.CharField(read_only=True)
208209

209210
class Meta:
210211
model = Dref
@@ -235,6 +236,7 @@ class Meta:
235236
"status",
236237
"status_display",
237238
"date_of_approval",
239+
"original_language",
238240
]
239241

240242
@extend_schema_field(MiniOperationalUpdateActiveSerializer(many=True))
@@ -1543,6 +1545,7 @@ class CompletedDrefOperationsSerializer(serializers.ModelSerializer):
15431545
status_display = serializers.CharField(source="get_status_display", read_only=True)
15441546
application_type = serializers.SerializerMethodField()
15451547
application_type_display = serializers.SerializerMethodField()
1548+
original_language = serializers.CharField(read_only=True)
15461549

15471550
class Meta:
15481551
model = DrefFinalReport
@@ -1560,6 +1563,7 @@ class Meta:
15601563
"dref",
15611564
"status",
15621565
"status_display",
1566+
"original_language",
15631567
)
15641568

15651569
def get_application_type(self, obj) -> str:

dref/test_views.py

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
from datetime import datetime, timedelta
33
from unittest import mock
4+
from unittest.mock import patch
45

56
from django.conf import settings
67
from django.contrib.auth import get_user_model
@@ -1028,10 +1029,16 @@ def test_update_and_finalize_dref(self):
10281029

10291030
# Finalize DREF
10301031
finalize_url = f"/api/v2/dref/{dref.id}/finalize/"
1031-
response = self.client.post(finalize_url)
1032-
self.assert_200(response)
1033-
self.assertEqual(response.data["status"], Dref.Status.FINALIZED)
1034-
self.assertEqual(response.data["translation_module_original_language"], "en")
1032+
# Finalize without translation
1033+
with patch("dref.views.is_translation_complete", return_value=False):
1034+
response = self.client.post(finalize_url)
1035+
self.assert_400(response)
1036+
# Finalize with translation complete
1037+
with patch("dref.views.is_translation_complete", return_value=True):
1038+
response = self.client.post(finalize_url)
1039+
self.assert_200(response)
1040+
self.assertEqual(response.data["status"], Dref.Status.FINALIZED)
1041+
self.assertEqual(response.data["translation_module_original_language"], "en")
10351042

10361043
# Update in English
10371044
finalized_dref_id = response.data["id"]
@@ -1169,10 +1176,16 @@ def test_dref_operational_update_finalize(self):
11691176

11701177
# Finalize Operational Update
11711178
finalize_url = f"/api/v2/dref-op-update/{op_update.id}/finalize/"
1172-
response = self.client.post(finalize_url)
1173-
self.assert_200(response)
1174-
self.assertEqual(response.data["status"], Dref.Status.FINALIZED)
1175-
self.assertEqual(response.data["translation_module_original_language"], "en")
1179+
# Finalize without translation
1180+
with patch("dref.views.is_translation_complete", return_value=False):
1181+
response = self.client.post(finalize_url)
1182+
self.assert_400(response)
1183+
# Finalize with translation complete
1184+
with patch("dref.views.is_translation_complete", return_value=True):
1185+
response = self.client.post(finalize_url)
1186+
self.assert_200(response)
1187+
self.assertEqual(response.data["status"], Dref.Status.FINALIZED)
1188+
self.assertEqual(response.data["translation_module_original_language"], "en")
11761189
# Update in English
11771190
finalized_op_update_id = response.data["id"]
11781191
url = f"/api/v2/dref-op-update/{finalized_op_update_id}/"
@@ -2200,10 +2213,16 @@ def test_dref_final_report_finalize(self):
22002213

22012214
# Finalize final-report
22022215
finalize_url = f"/api/v2/dref-final-report/{final_report.id}/finalize/"
2203-
response = self.client.post(finalize_url)
2204-
self.assert_200(response)
2205-
self.assertEqual(response.data["status"], Dref.Status.FINALIZED)
2206-
self.assertEqual(response.data["translation_module_original_language"], "en")
2216+
# Finalize without translation
2217+
with patch("dref.views.is_translation_complete", return_value=False):
2218+
response = self.client.post(finalize_url)
2219+
self.assert_400(response)
2220+
# Finalize with translation complete
2221+
with patch("dref.views.is_translation_complete", return_value=True):
2222+
response = self.client.post(finalize_url)
2223+
self.assert_200(response)
2224+
self.assertEqual(response.data["status"], Dref.Status.FINALIZED)
2225+
self.assertEqual(response.data["translation_module_original_language"], "en")
22072226
# Update in English
22082227
finalized_final_report_id = response.data["id"]
22092228
data_en = {"title": "Updated title in English", "modified_at": datetime.now()}

dref/utils.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from django.conf import settings
22
from django.contrib.postgres.aggregates import ArrayAgg
33
from django.db import models
4+
from django.utils import translation
5+
from modeltranslation.translator import translator
46

57
from dref.models import Dref, DrefFinalReport, DrefOperationalUpdate
68

@@ -53,3 +55,29 @@ def get_dref_users():
5355
)
5456
)
5557
return dref_users_list
58+
59+
60+
def is_translation_complete(instance, target_lang="en"):
61+
"""
62+
Check all translatable fields of a instance have been
63+
translated to the target language.
64+
"""
65+
original_lang = getattr(instance, "translation_module_original_language", None)
66+
if not original_lang:
67+
return False
68+
try:
69+
opts = translator.get_options_for_model(type(instance))
70+
except Exception:
71+
return True
72+
for field in getattr(opts, "fields", []):
73+
with translation.override(original_lang):
74+
original_value = getattr(instance, field, None)
75+
76+
with translation.override(target_lang):
77+
translated_value = getattr(instance, field, None)
78+
if not original_value:
79+
continue
80+
if not translated_value:
81+
return False
82+
83+
return True

dref/views.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
DrefShareUserSerializer,
4242
MiniDrefSerializer,
4343
)
44+
from dref.utils import is_translation_complete
4445
from main.permissions import DenyGuestUserPermission, UseBySuperAdminOnly
4546

4647

@@ -108,6 +109,10 @@ def finalize(self, request, pk=None, version=None):
108109
dref = self.get_object()
109110
if dref.status in [Dref.Status.FINALIZED, Dref.Status.APPROVED]:
110111
raise serializers.ValidationError(gettext("Cannot be finalized because it is already %s") % dref.get_status_display())
112+
113+
if not is_translation_complete(dref):
114+
raise serializers.ValidationError("Cannot be finalized because translation is not completed")
115+
111116
if dref.translation_module_original_language != "en":
112117
dref.translation_module_original_language = "en"
113118
dref.status = Dref.Status.FINALIZED
@@ -198,6 +203,8 @@ def finalize(self, request, pk=None, version=None):
198203
raise serializers.ValidationError(
199204
gettext("Cannot be finalized because it is already %s") % operational_update.get_status_display()
200205
)
206+
if not is_translation_complete(operational_update):
207+
raise serializers.ValidationError("Cannot be finalized because translation is not completed")
201208
if operational_update.translation_module_original_language != "en":
202209
operational_update.translation_module_original_language = "en"
203210
operational_update.status = Dref.Status.FINALIZED
@@ -258,6 +265,9 @@ def finalize(self, request, pk=None, version=None):
258265
raise serializers.ValidationError(
259266
gettext("Cannot be finalized because it is already %s") % field_report.get_status_display()
260267
)
268+
if not is_translation_complete(field_report):
269+
raise serializers.ValidationError("Cannot be finalized because translation is not completed")
270+
261271
if field_report.translation_module_original_language != "en":
262272
field_report.translation_module_original_language = "en"
263273
field_report.status = Dref.Status.FINALIZED

0 commit comments

Comments
 (0)