Skip to content

Commit b7fb516

Browse files
committed
fix(dref): Handle auto creation of instance for M2M fields
1 parent 8d99e16 commit b7fb516

File tree

2 files changed

+270
-21
lines changed

2 files changed

+270
-21
lines changed

dref/serializers.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,24 @@
4242

4343

4444
class RiskSecuritySerializer(ModelSerializer):
45+
id = serializers.IntegerField(required=False)
46+
4547
class Meta:
4648
model = RiskSecurity
4749
fields = "__all__"
4850

4951

5052
class SourceInformationSerializer(ModelSerializer):
53+
id = serializers.IntegerField(required=False)
54+
5155
class Meta:
5256
model = SourceInformation
5357
fields = "__all__"
5458

5559

5660
class PlannedInterventionIndicatorsSerializer(ModelSerializer):
61+
id = serializers.IntegerField(required=False)
62+
5763
class Meta:
5864
model = PlannedInterventionIndicators
5965
fields = "__all__"
@@ -274,8 +280,13 @@ def get_unpublished_final_report_count(self, obj) -> int:
274280
return DrefFinalReport.objects.filter(dref_id=obj.id, is_published=False).count()
275281

276282

277-
class PlannedInterventionSerializer(ModelSerializer):
283+
class PlannedInterventionSerializer(
284+
NestedCreateMixin,
285+
NestedUpdateMixin,
286+
ModelSerializer,
287+
):
278288
# budget_file_details = DrefFileSerializer(source="budget_file", read_only=True)
289+
id = serializers.IntegerField(required=False)
279290
image_url = serializers.SerializerMethodField()
280291
indicators = PlannedInterventionIndicatorsSerializer(many=True, required=False)
281292
title_display = serializers.CharField(source="get_title_display", read_only=True)
@@ -284,20 +295,6 @@ class Meta:
284295
model = PlannedIntervention
285296
fields = "__all__"
286297

287-
def create(self, validated_data):
288-
indicators = validated_data.pop("indicators", [])
289-
intervention = super().create(validated_data)
290-
for indicator in indicators:
291-
ind_object = PlannedInterventionIndicators.objects.create(**indicator)
292-
intervention.indicators.add(ind_object)
293-
return intervention
294-
295-
def update(self, instance, validated_data):
296-
# TODO: implement this
297-
# indicators = validated_data.pop("indicators", [])
298-
intervention = super().update(instance, validated_data)
299-
return intervention
300-
301298
def get_image_url(self, plannedintervention) -> str:
302299
title = plannedintervention.title
303300
if title and self.context and "request" in self.context:
@@ -307,6 +304,7 @@ def get_image_url(self, plannedintervention) -> str:
307304

308305

309306
class NationalSocietyActionSerializer(ModelSerializer):
307+
id = serializers.IntegerField(required=False)
310308
image_url = serializers.SerializerMethodField()
311309
title_display = serializers.CharField(source="get_title_display", read_only=True)
312310

@@ -329,6 +327,7 @@ def get_image_url(self, nationalsocietyactions) -> str:
329327

330328

331329
class IdentifiedNeedSerializer(ModelSerializer):
330+
id = serializers.IntegerField(required=False)
332331
image_url = serializers.SerializerMethodField()
333332
title_display = serializers.CharField(source="get_title_display", read_only=True)
334333

dref/test_views.py

Lines changed: 256 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,23 @@ def test_post_dref_creation(self, send_notification):
180180
"originator_email": "[email protected]",
181181
"national_society": national_society.id,
182182
"disaster_type": disaster_type.id,
183-
"needs_identified": [{"title": "shelter_housing_and_settlements", "description": "hey"}],
183+
# NOTE: Test Many to Many fields
184+
"risk_security": [
185+
{"risk": "Test Risk 1", "mitigation_measure": "Test Mitigation Measure"},
186+
{"risk": "Test Risk 2", "mitigation_measure": "Test Mitigation Measure 1"},
187+
],
188+
"source_information": [
189+
{"source_name": "Test Source 1", "link": "http://test.com"},
190+
{"source_name": "Test Source 2", "link": "http://test.com"},
191+
],
192+
"needs_identified": [
193+
{"title": "shelter_housing_and_settlements", "description": "Shelter"},
194+
{"title": "health", "description": "Health"},
195+
],
196+
"national_society_actions": [
197+
{"title": "coordination", "description": "Coordination"},
198+
{"title": "shelter_housing_and_settlements", "description": "Shelter"},
199+
],
184200
"planned_interventions": [
185201
{
186202
"title": "shelter_housing_and_settlements",
@@ -190,25 +206,34 @@ def test_post_dref_creation(self, send_notification):
190206
"female": 2255,
191207
"indicators": [
192208
{
193-
"title": "test_title",
209+
"title": "test_title_1",
194210
"actual": 21232,
195211
"target": 44444,
196-
}
212+
},
213+
{
214+
"title": "test_title_2",
215+
"actual": 21232,
216+
"target": 44444,
217+
},
197218
],
198219
},
199220
{
200-
"id": 2,
201221
"title": "health",
202222
"description": "matrix reloaded",
203223
"budget": 451111111,
204224
"male": 12222,
205225
"female": 2255,
206226
"indicators": [
207227
{
208-
"title": "test_title",
228+
"title": "test_title_2",
209229
"actual": 21232,
210230
"target": 44444,
211-
}
231+
},
232+
{
233+
"title": "test_title_2",
234+
"actual": 21232,
235+
"target": 44444,
236+
},
212237
],
213238
},
214239
],
@@ -228,6 +253,231 @@ def test_post_dref_creation(self, send_notification):
228253
self.assertTrue(send_notification.assert_called)
229254
self.assertEqual(email_data["title"], instance.title)
230255

256+
# Testing Nested objects creation and update
257+
# Update the created dref
258+
data = {
259+
"modified_at": datetime.now(),
260+
**data,
261+
"risk_security": [
262+
{"id": response.data["risk_security"][0]["id"], "risk": "Updated Test Risk 1", "mitigation_measure": "Test"},
263+
{
264+
"id": response.data["risk_security"][1]["id"],
265+
"risk": "Updated Test Risk 2",
266+
"mitigation_measure": "Test Mitigation Measure 2",
267+
},
268+
# New item to be added
269+
{"risk": "New Test Risk", "mitigation_measure": "New Test Mitigation Measure"},
270+
],
271+
"source_information": [
272+
{
273+
"id": response.data["source_information"][0]["id"],
274+
"source_name": "Updated Test Source 1",
275+
"link": "http://updated.com",
276+
},
277+
{
278+
"id": response.data["source_information"][1]["id"],
279+
"source_name": "Updated Test Source 2",
280+
"link": "http://updated.com",
281+
},
282+
# New item to be added
283+
{"source_name": "New Test Source", "link": "http://new.com"},
284+
],
285+
"needs_identified": [
286+
{
287+
"id": response.data["needs_identified"][0]["id"],
288+
"title": "shelter_housing_and_settlements",
289+
"description": "Updated Shelter",
290+
},
291+
{"id": response.data["needs_identified"][1]["id"], "title": "health", "description": "Updated Health"},
292+
# New item to be added
293+
{"title": "water_sanitation_and_hygiene", "description": "WASH"},
294+
],
295+
"national_society_actions": [
296+
{
297+
"id": response.data["national_society_actions"][0]["id"],
298+
"title": "coordination",
299+
"description": "Updated Coordination",
300+
},
301+
{
302+
"id": response.data["national_society_actions"][1]["id"],
303+
"title": "shelter_housing_and_settlements",
304+
"description": "Updated Shelter",
305+
},
306+
# New item to be added
307+
{"title": "health", "description": "Health"},
308+
],
309+
"planned_interventions": [
310+
{
311+
"id": response.data["planned_interventions"][0]["id"],
312+
"title": "shelter_housing_and_settlements",
313+
"description": "Updated matrix",
314+
"budget": 99999,
315+
"male": 12222,
316+
"female": 2255,
317+
"indicators": [
318+
{
319+
"id": response.data["planned_interventions"][0]["indicators"][0]["id"],
320+
"title": "updated_test_title_1",
321+
"actual": 11111,
322+
"target": 22222,
323+
},
324+
{
325+
"id": response.data["planned_interventions"][0]["indicators"][1]["id"],
326+
"title": "updated_test_title_2",
327+
"actual": 33333,
328+
"target": 44444,
329+
},
330+
# New item to be added
331+
{
332+
"title": "new_test_title_3",
333+
"actual": 55555,
334+
"target": 66666,
335+
},
336+
],
337+
},
338+
{
339+
"id": response.data["planned_interventions"][1]["id"],
340+
"title": "health",
341+
"description": "Updated matrix reloaded",
342+
"budget": 88888,
343+
"male": 12222,
344+
"female": 2255,
345+
"indicators": [
346+
{
347+
"id": response.data["planned_interventions"][1]["indicators"][0]["id"],
348+
"title": "updated_test_title_1",
349+
"actual": 11111,
350+
"target": 22222,
351+
},
352+
{
353+
"id": response.data["planned_interventions"][1]["indicators"][1]["id"],
354+
"title": "updated_test_title_2",
355+
"actual": 33333,
356+
"target": 44444,
357+
},
358+
# New item to be added
359+
{
360+
"title": "new_test_title_3",
361+
"actual": 55555,
362+
"target": 66666,
363+
},
364+
],
365+
},
366+
],
367+
}
368+
369+
# Update the created dref
370+
url = f"/api/v2/dref/{instance.id}/"
371+
response = self.client.patch(url, data, format="json")
372+
self.assert_200(response)
373+
374+
# Risk Security should have 3 items now
375+
self.assertEqual(len(response.data["risk_security"]), 3)
376+
self.assertEqual(
377+
{
378+
response.data["risk_security"][0]["id"],
379+
response.data["risk_security"][1]["id"],
380+
response.data["risk_security"][2]["risk"],
381+
},
382+
{
383+
data["risk_security"][0].get("id"),
384+
data["risk_security"][1].get("id"),
385+
data["risk_security"][2].get("risk"),
386+
},
387+
)
388+
389+
# Source of Information should have 3 items now
390+
self.assertEqual(len(response.data["source_information"]), 3)
391+
self.assertEqual(
392+
{
393+
response.data["source_information"][0]["id"],
394+
response.data["source_information"][0]["source_name"],
395+
response.data["source_information"][1]["id"],
396+
response.data["source_information"][1]["source_name"],
397+
response.data["source_information"][2]["source_name"],
398+
},
399+
{
400+
data["source_information"][0].get("id"),
401+
data["source_information"][0].get("source_name"),
402+
data["source_information"][1].get("id"),
403+
data["source_information"][1].get("source_name"),
404+
data["source_information"][2].get("source_name"),
405+
},
406+
)
407+
408+
# Needs Identified should have 3 items mock_now
409+
self.assertEqual(len(response.data["needs_identified"]), 3)
410+
self.assertEqual(
411+
{
412+
response.data["needs_identified"][0]["id"],
413+
response.data["needs_identified"][0]["title"],
414+
response.data["needs_identified"][1]["id"],
415+
response.data["needs_identified"][1]["title"],
416+
response.data["needs_identified"][2]["title"],
417+
},
418+
{
419+
data["needs_identified"][0].get("id"),
420+
data["needs_identified"][0].get("title"),
421+
data["needs_identified"][1].get("id"),
422+
data["needs_identified"][1].get("title"),
423+
data["needs_identified"][2].get("title"),
424+
},
425+
)
426+
427+
# National Society Actions should have 3 items mock_now
428+
self.assertEqual(len(response.data["national_society_actions"]), 3)
429+
self.assertEqual(
430+
{
431+
response.data["national_society_actions"][0]["id"],
432+
response.data["national_society_actions"][0]["title"],
433+
response.data["national_society_actions"][1]["id"],
434+
response.data["national_society_actions"][1]["title"],
435+
response.data["national_society_actions"][2]["title"],
436+
},
437+
{
438+
data["national_society_actions"][0].get("id"),
439+
data["national_society_actions"][0].get("title"),
440+
data["national_society_actions"][1].get("id"),
441+
data["national_society_actions"][1].get("title"),
442+
data["national_society_actions"][2].get("title"),
443+
},
444+
)
445+
446+
# Planned Interventions should have 2 items
447+
self.assertEqual(len(response.data["planned_interventions"]), 2)
448+
self.assertEqual(
449+
{
450+
response.data["planned_interventions"][0]["id"],
451+
response.data["planned_interventions"][0]["title"],
452+
response.data["planned_interventions"][1]["id"],
453+
response.data["planned_interventions"][1]["title"],
454+
},
455+
{
456+
data["planned_interventions"][0].get("id"),
457+
data["planned_interventions"][0].get("title"),
458+
data["planned_interventions"][1].get("id"),
459+
data["planned_interventions"][1].get("title"),
460+
},
461+
)
462+
463+
# Planned Intervention - Indicators should have 3 items now
464+
self.assertEqual(
465+
{
466+
response.data["planned_interventions"][0]["indicators"][0]["id"],
467+
response.data["planned_interventions"][0]["indicators"][0]["title"],
468+
response.data["planned_interventions"][0]["indicators"][1]["id"],
469+
response.data["planned_interventions"][0]["indicators"][1]["title"],
470+
response.data["planned_interventions"][0]["indicators"][2]["title"],
471+
},
472+
{
473+
data["planned_interventions"][0]["indicators"][0].get("id"),
474+
data["planned_interventions"][0]["indicators"][0].get("title"),
475+
data["planned_interventions"][0]["indicators"][1].get("id"),
476+
data["planned_interventions"][0]["indicators"][1].get("title"),
477+
data["planned_interventions"][0]["indicators"][2].get("title"),
478+
},
479+
)
480+
231481
def test_event_date_in_dref(self):
232482
"""
233483
Test for the event date based on type_of_onset

0 commit comments

Comments
 (0)