Skip to content

Commit 6023ad1

Browse files
committed
feat(eap): update revise workflow with locked feature
- Update admin panel - Add test for edge cases
1 parent 456fcc1 commit 6023ad1

6 files changed

Lines changed: 88 additions & 18 deletions

File tree

assets

eap/admin.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,13 @@ class SimplifiedEAPAdmin(admin.ModelAdmin):
8585
"eap_registration__country__name",
8686
"eap_registration__disaster_type__name",
8787
)
88-
list_display = ("simplifed_eap_application", "version", "is_locked")
88+
list_display = ("simplifed_eap_application", "eap_registration", "version", "is_locked")
8989
autocomplete_fields = (
9090
"eap_registration",
9191
"created_by",
9292
"modified_by",
9393
"admin2",
94+
"partners",
9495
)
9596
readonly_fields = (
9697
"cover_image",
@@ -159,6 +160,7 @@ def get_queryset(self, request):
159160
)
160161
.prefetch_related(
161162
"admin2",
163+
"partners",
162164
"partner_contacts",
163165
)
164166
)
@@ -176,12 +178,13 @@ class FullEAPAdmin(admin.ModelAdmin):
176178
"eap_registration__country__name",
177179
"eap_registration__disaster_type__name",
178180
)
179-
list_display = ("eap_registration",)
181+
list_display = ("full_eap_application", "eap_registration", "version", "is_locked")
180182
autocomplete_fields = (
181183
"eap_registration",
182184
"created_by",
183185
"modified_by",
184186
"admin2",
187+
"partners",
185188
)
186189
readonly_fields = (
187190
"partner_contacts",
@@ -244,6 +247,9 @@ def regenerate_diff_pdf_file(self, request, queryset):
244247

245248
regenerate_diff_pdf_file.short_description = "Regenerate EAP diff PDF files for selected Full EAPs"
246249

250+
def full_eap_application(self, obj):
251+
return f"{obj.eap_registration.national_society.society_name} - {obj.eap_registration.disaster_type.name}"
252+
247253
def get_queryset(self, request):
248254
return (
249255
super()
@@ -258,6 +264,7 @@ def get_queryset(self, request):
258264
)
259265
.prefetch_related(
260266
"admin2",
267+
"partners",
261268
"partner_contacts",
262269
"key_actors",
263270
"risk_analysis_source_of_information",

eap/models.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,7 +1275,7 @@ class Meta:
12751275
]
12761276

12771277
def __str__(self):
1278-
return f"Simplified EAP for {self.eap_registration}- version:{self.version}"
1278+
return f"{self.eap_registration} (VERSION {self.version})"
12791279

12801280
def generate_snapshot(self):
12811281
"""
@@ -1291,6 +1291,7 @@ def generate_snapshot(self):
12911291
overrides={
12921292
"parent_id": self.id,
12931293
"version": self.version + 1,
1294+
"is_locked": False,
12941295
"created_by_id": self.created_by_id,
12951296
"modified_by_id": self.modified_by_id,
12961297
"review_checklist_file": None,
@@ -1823,7 +1824,7 @@ class Meta:
18231824
]
18241825

18251826
def __str__(self):
1826-
return f"Full EAP for {self.eap_registration}- version:{self.version}"
1827+
return f"{self.eap_registration} (VERSION {self.version})"
18271828

18281829
def generate_snapshot(self):
18291830
"""
@@ -1838,6 +1839,7 @@ def generate_snapshot(self):
18381839
overrides={
18391840
"parent_id": self.id,
18401841
"version": self.version + 1,
1842+
"is_locked": False,
18411843
"created_by_id": self.created_by_id,
18421844
"modified_by_id": self.modified_by_id,
18431845
"review_checklist_file": None,

eap/serializers.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -918,14 +918,19 @@ def _validate_status(self, validated_data: dict[str, typing.Any]) -> dict[str, t
918918
EAPRegistration.Status.UNDER_REVIEW,
919919
):
920920
if self.instance.get_eap_type_enum == EAPType.SIMPLIFIED_EAP:
921-
# NOTE: Generating PDF asynchronously
921+
self.instance.latest_simplified_eap.is_locked = True
922+
self.instance.latest_simplified_eap.save(update_fields=["is_locked"])
923+
# NOTE: Generating export PDF asynchronously
922924
transaction.on_commit(
923925
lambda: generate_export_eap_pdf.delay(
924926
eap_registration_id=self.instance.id,
925927
version=self.instance.latest_simplified_eap.version,
926928
)
927929
)
928930
else:
931+
self.instance.latest_full_eap.is_locked = True
932+
self.instance.latest_full_eap.save(update_fields=["is_locked"])
933+
# NOTE: Generate export PDF asynchronously
929934
transaction.on_commit(
930935
lambda: generate_export_eap_pdf.delay(
931936
eap_registration_id=self.instance.id,
@@ -1010,6 +1015,10 @@ def _validate_status(self, validated_data: dict[str, typing.Any]) -> dict[str, t
10101015
},
10111016
)
10121017

1018+
# Lock the latest eap
1019+
self.instance.latest_simplified_eap.is_locked = True
1020+
self.instance.latest_simplified_eap.save(update_fields=["is_locked"])
1021+
10131022
# Generating PDFs asynchronously
10141023
transaction.on_commit(
10151024
lambda: group(
@@ -1035,6 +1044,10 @@ def _validate_status(self, validated_data: dict[str, typing.Any]) -> dict[str, t
10351044
},
10361045
)
10371046

1047+
# Lock the latest full eap
1048+
self.instance.latest_full_eap.is_locked = True
1049+
self.instance.latest_full_eap.save(update_fields=["is_locked"])
1050+
10381051
# Generating PDFs asynchronously
10391052
transaction.on_commit(
10401053
lambda: group(

eap/test_views.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,6 +1274,8 @@ def test_status_transition(self):
12741274
response = self.client.post(self.url, data, format="json")
12751275
self.assertEqual(response.status_code, 200, response.data)
12761276
self.assertEqual(response.data["status"], EAPStatus.UNDER_REVIEW)
1277+
simplified_eap.refresh_from_db()
1278+
self.assertTrue(simplified_eap.is_locked)
12771279

12781280
# NOTE: Check if the NS can update after changing to UNDER_REVIEW
12791281
# FAILS: As simplified EAP is in UNDER_REVIEW, cannot update
@@ -1283,6 +1285,7 @@ def test_status_transition(self):
12831285
"readiness_budget": 5000,
12841286
"pre_positioning_budget": 5000,
12851287
"early_action_budget": 5000,
1288+
"modified_at": datetime.now(),
12861289
}
12871290
url = f"/api/v2/simplified-eap/{simplified_eap.id}/"
12881291
response = self.client.patch(url, update_data, format="json")
@@ -1321,12 +1324,18 @@ def test_status_transition(self):
13211324
self.eap_registration.latest_simplified_eap.review_checklist_file,
13221325
)
13231326

1327+
# Fails, As User only can revise after NS_ADDRESSING_COMMENTS, cannot update directly as it's locked
1328+
update_data["modified_at"] = datetime.now()
1329+
response = self.client.patch(url, update_data, format="json")
1330+
self.assertEqual(response.status_code, 400, response.data)
1331+
13241332
# NOTE: NS revise which creates a snapshot of simplified eap
13251333
# updates the latest simplified eap with updated checklist file. So, there should be two snapshots of SimplifiedEAP now.
13261334
revise_url = f"/api/v2/simplified-eap/{simplified_eap.id}/revise/"
13271335
self.authenticate(self.country_admin)
13281336
response = self.client.post(revise_url)
1329-
self.assertEqual(response.status_code, 200)
1337+
self.assertEqual(response.status_code, 200, response.data)
1338+
self.assertFalse(response.data["is_locked"], response.data)
13301339

13311340
# NOTE: Check if snapshot is created or not
13321341
# First SimplifedEAP should be locked
@@ -1371,13 +1380,21 @@ def test_status_transition(self):
13711380
self.eap_registration.latest_simplified_eap.id,
13721381
second_snapshot.id,
13731382
)
1383+
# Second snapshot should not be locked.
1384+
self.assertFalse(second_snapshot.is_locked, "Latest snapshot shouldn't be locked."),
13741385

1375-
# NOTE: Cannot create another snapshot from locked snapshot
1386+
# NOTE: Cannot create revise as this eap has already been revised once.
13761387
revise_url = f"/api/v2/simplified-eap/{simplified_eap.id}/revise/"
13771388
self.authenticate(self.country_admin)
13781389
response = self.client.post(revise_url)
13791390
self.assertEqual(response.status_code, 400, response.data)
13801391

1392+
# NOTE: Cannot update in previous snapshot
1393+
url = f"/api/v2/simplified-eap/{simplified_eap.id}/"
1394+
update_data["modified_at"] = datetime.now()
1395+
response = self.client.patch(url, update_data, format="json")
1396+
self.assertEqual(response.status_code, 400, response.data)
1397+
13811398
# NOTE: Transition to UNDER_REVIEW
13821399
# NS_ADDRESSING_COMMENTS -> UNDER_REVIEW
13831400
data = {
@@ -1411,6 +1428,8 @@ def test_status_transition(self):
14111428
response = self.client.post(self.url, data, format="json")
14121429
self.assertEqual(response.status_code, 200, response.data)
14131430
self.assertEqual(response.data["status"], EAPStatus.UNDER_REVIEW)
1431+
second_snapshot.refresh_from_db()
1432+
self.assertTrue(second_snapshot.is_locked, "Should be locked after transition to UNDER_REVIEW.")
14141433

14151434
# AGAIN NOTE: Transition to NS_ADDRESSING_COMMENTS
14161435
# UNDER_REVIEW -> NS_ADDRESSING_COMMENTS
@@ -1433,10 +1452,16 @@ def test_status_transition(self):
14331452
self.assertEqual(response.status_code, 200, response.data)
14341453
self.assertEqual(response.data["status"], EAPStatus.NS_ADDRESSING_COMMENTS)
14351454

1455+
# Cannot update as it is in NS_ADDRESSING_COMMENTS, only revise is allowed
1456+
update_data["modified_at"] = datetime.now()
1457+
response = self.client.patch(url, update_data, format="json")
1458+
self.assertEqual(response.status_code, 400, response.data)
1459+
14361460
revise_url = f"/api/v2/simplified-eap/{second_snapshot.id}/revise/"
14371461
self.authenticate(self.country_admin)
14381462
response = self.client.post(revise_url)
1439-
self.assertEqual(response.status_code, 200)
1463+
self.assertEqual(response.status_code, 200, response.data)
1464+
self.assertFalse(response.data["is_locked"])
14401465

14411466
# Check if three snapshots are created now
14421467
self.eap_registration.refresh_from_db()
@@ -1482,12 +1507,18 @@ def test_status_transition(self):
14821507
third_snapshot.id,
14831508
)
14841509

1485-
# NOTE: Cannot create another snapshot from locked snapshot
1510+
# NOTE: Cannot create another snapshot as this eap has already been revised
14861511
revise_url = f"/api/v2/simplified-eap/{second_snapshot.id}/revise/"
14871512
self.authenticate(self.country_admin)
14881513
response = self.client.post(revise_url)
14891514
self.assertEqual(response.status_code, 400, response.data)
14901515

1516+
# NOTE: Cannot update the previous snapshot
1517+
url = f"/api/v2/simplified-eap/{second_snapshot.id}/"
1518+
update_data["modified_at"] = datetime.now()
1519+
response = self.client.patch(url, update_data, format="json")
1520+
self.assertEqual(response.status_code, 400, response.data)
1521+
14911522
# NOTE: Again Transition to UNDER_REVIEW
14921523
# NS_ADDRESSING_COMMENTS -> UNDER_REVIEW
14931524
data = {

eap/views.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -296,14 +296,23 @@ def revise(
296296
id: int,
297297
):
298298
simplified_eap_instance = self.get_object()
299-
if simplified_eap_instance.is_locked:
299+
if simplified_eap_instance.eap_registration.status != EAPStatus.NS_ADDRESSING_COMMENTS:
300300
return response.Response(
301-
{"detail": "This version is locked and cannot be revised again."},
301+
{"detail": f"Only EAPs with status {EAPStatus.NS_ADDRESSING_COMMENTS} can be revised."},
302302
status=status.HTTP_400_BAD_REQUEST,
303303
)
304-
if simplified_eap_instance.eap_registration.status != EAPStatus.NS_ADDRESSING_COMMENTS:
304+
305+
if simplified_eap_instance.is_locked is False:
305306
return response.Response(
306-
{"detail": f"Only EAPs with status {EAPStatus.NS_ADDRESSING_COMMENTS} can be revised."},
307+
{"detail": "EAP can only be revised when it is locked."},
308+
status=status.HTTP_400_BAD_REQUEST,
309+
)
310+
311+
# Check if new version of EAP can be created (i.e. if the current version is locked)
312+
eap_registration_instance = EAPRegistration.objects.filter(id=simplified_eap_instance.eap_registration_id).first()
313+
if eap_registration_instance and eap_registration_instance.latest_simplified_eap_id != simplified_eap_instance.id:
314+
return response.Response(
315+
{"detail": "A new version of the EAP has already been created. Please revise the latest version of the EAP."},
307316
status=status.HTTP_400_BAD_REQUEST,
308317
)
309318

@@ -409,15 +418,23 @@ def revise(
409418
id: int,
410419
):
411420
full_eap_instance = self.get_object()
412-
if full_eap_instance.is_locked:
421+
if full_eap_instance.eap_registration.status != EAPStatus.NS_ADDRESSING_COMMENTS:
413422
return response.Response(
414-
{"detail": "This version is locked and cannot be revised again."},
423+
{"detail": f"Only EAPs with status {EAPStatus.NS_ADDRESSING_COMMENTS} can be revised."},
415424
status=status.HTTP_400_BAD_REQUEST,
416425
)
417426

418-
if full_eap_instance.eap_registration.status != EAPStatus.NS_ADDRESSING_COMMENTS:
427+
if full_eap_instance.is_locked is False:
419428
return response.Response(
420-
{"detail": f"Only EAPs with status {EAPStatus.NS_ADDRESSING_COMMENTS} can be revised."},
429+
{"detail": "EAP can only be revised when it is locked."},
430+
status=status.HTTP_400_BAD_REQUEST,
431+
)
432+
433+
# Check if new version of EAP can be created (i.e. if the current version is locked)
434+
eap_registration_instance = EAPRegistration.objects.filter(id=full_eap_instance.eap_registration_id).first()
435+
if eap_registration_instance and eap_registration_instance.latest_full_eap_id != full_eap_instance.id:
436+
return response.Response(
437+
{"detail": "A new version of the EAP has already been created. Please revise the latest version of the EAP."},
421438
status=status.HTTP_400_BAD_REQUEST,
422439
)
423440

0 commit comments

Comments
 (0)