@@ -429,6 +429,7 @@ class Meta:
429429 "modified_by" ,
430430 "created_by" ,
431431 "budget_file_preview" ,
432+ "is_dref_imminent_v2" ,
432433 )
433434 exclude = (
434435 "cover_image" ,
@@ -1083,6 +1084,7 @@ def update(self, instance, validated_data):
10831084
10841085class DrefFinalReportSerializer (NestedUpdateMixin , NestedCreateMixin , ModelSerializer ):
10851086 MAX_NUMBER_OF_PHOTOS = 4
1087+ SUB_TOTAL_COST = 75000
10861088 national_society_actions = NationalSocietyActionSerializer (many = True , required = False )
10871089 needs_identified = IdentifiedNeedSerializer (many = True , required = False )
10881090 planned_interventions = PlannedInterventionSerializer (many = True , required = False )
@@ -1105,13 +1107,15 @@ class DrefFinalReportSerializer(NestedUpdateMixin, NestedCreateMixin, ModelSeria
11051107 modified_by_details = UserNameSerializer (source = "modified_by" , read_only = True )
11061108 disaster_type_details = DisasterTypeSerializer (source = "disaster_type" , read_only = True )
11071109 source_information = SourceInformationSerializer (many = True , required = False )
1110+ proposed_action = ProposedActionSerializer (many = True , required = False )
11081111
11091112 class Meta :
11101113 model = DrefFinalReport
11111114 read_only_fields = (
11121115 "modified_by" ,
11131116 "created_by" ,
11141117 "financial_report_preview" ,
1118+ "is_dref_imminent_v2" ,
11151119 )
11161120 exclude = (
11171121 "images" ,
@@ -1123,7 +1127,7 @@ class Meta:
11231127
11241128 def validate (self , data ):
11251129 dref = data .get ("dref" )
1126- # check if dref is published and operational_update associated with it is also published
1130+ # Check if dref is published and operational_update associated with it is also published
11271131 if not self .instance and dref :
11281132 if not dref .is_published :
11291133 raise serializers .ValidationError (gettext ("Can't create Final Report for not published dref %s." % dref .id ))
@@ -1141,6 +1145,68 @@ def validate(self, data):
11411145
11421146 if self .instance and self .instance .is_published :
11431147 raise serializers .ValidationError (gettext ("Can't update published final report %s." % self .instance .id ))
1148+
1149+ # NOTE: Validation for type DREF Imminent
1150+ if self .instance and self .instance .is_dref_imminent_v2 and data .get ("type_of_dref" ) == Dref .DrefType .IMMINENT :
1151+ sub_total_cost = data .get ("sub_total_cost" )
1152+ sub_total_expenditure_cost = data .get ("sub_total_expenditure_cost" )
1153+ surge_deployment_expenditure_cost = data .get ("surge_deployment_expenditure_cost" ) or 0
1154+ indirect_cost = data .get ("indirect_cost" )
1155+ indirect_expenditure_cost = data .get ("indirect_expenditure_cost" )
1156+ total_cost = data .get ("total_cost" )
1157+ total_expenditure_cost = data .get ("total_expenditure_cost" )
1158+ proposed_actions = data .get ("proposed_action" , [])
1159+
1160+ if not proposed_actions :
1161+ raise serializers .ValidationError (
1162+ {"proposed_action" : gettext ("Proposed Action is required for type DREF Imminent" )}
1163+ )
1164+ if not sub_total_cost :
1165+ raise serializers .ValidationError ({"sub_total_cost" : gettext ("Sub-total is required for Imminent DREF" )})
1166+ if not sub_total_expenditure_cost :
1167+ raise serializers .ValidationError (
1168+ {"sub_total_expenditure_cost" : gettext ("Sub-total Expenditure is required for Imminent DREF" )}
1169+ )
1170+ if sub_total_cost != self .SUB_TOTAL_COST :
1171+ raise serializers .ValidationError (
1172+ {"sub_total" : gettext ("Sub-total should be equal to %s for Imminent DREF" % self .SUB_TOTAL_COST )}
1173+ )
1174+ if not indirect_cost :
1175+ raise serializers .ValidationError ({"indirect_cost" : gettext ("Indirect Cost is required for Imminent DREF" )})
1176+ if not indirect_expenditure_cost :
1177+ raise serializers .ValidationError (
1178+ {"indirect_expenditure_cost" : gettext ("Indirect Expenditure is required for Imminent DREF" )}
1179+ )
1180+ if not total_cost :
1181+ raise serializers .ValidationError ({"total_cost" : gettext ("Total is required for Imminent DREF" )})
1182+ if not total_expenditure_cost :
1183+ raise serializers .ValidationError (
1184+ {"total_expenditure_cost" : gettext ("Total Expenditure is required for Imminent DREF" )}
1185+ )
1186+
1187+ total_proposed_budget : int = 0
1188+ total_proposed_expenditure : int = 0
1189+ for action in proposed_actions :
1190+ total_proposed_budget += action .get ("total_budget" , 0 )
1191+ total_proposed_expenditure += action .get ("total_expenditure" , 0 )
1192+ if total_proposed_budget != sub_total_cost :
1193+ raise serializers .ValidationError ({"sub_total_cost" : gettext ("Sub-total should be equal to proposed budget." )})
1194+ if total_proposed_expenditure != sub_total_expenditure_cost :
1195+ raise serializers .ValidationError (
1196+ {"sub_total_expenditure_cost" : gettext ("Sub-total Expenditure should be equal to proposed expenditure." )}
1197+ )
1198+ expected_total_expenditure_cost : int = (
1199+ sub_total_expenditure_cost + surge_deployment_expenditure_cost + indirect_expenditure_cost
1200+ )
1201+ if expected_total_expenditure_cost != total_expenditure_cost :
1202+ raise serializers .ValidationError (
1203+ {
1204+ "total_expenditure_cost" : gettext (
1205+ "Total Expenditure Cost should be equal to sum of Sub-total Expenditure, "
1206+ "Surge Deployment Expenditure and Indirect Expenditure Cost."
1207+ )
1208+ }
1209+ )
11441210 return data
11451211
11461212 def validate_photos (self , photos ):
@@ -1166,6 +1232,16 @@ def create(self, validated_data):
11661232 DrefOperationalUpdate .objects .filter (dref = dref , is_published = True ).order_by ("-operational_update_number" ).first ()
11671233 )
11681234 validated_data ["created_by" ] = self .context ["request" ].user
1235+ # NOTE: Checks and common fields for the new dref final reports of new dref imminents
1236+ if dref .type_of_dref == Dref .DrefType .IMMINENT and dref .is_dref_imminent_v2 :
1237+ validated_data ["is_dref_imminent_v2" ] = True
1238+ validated_data ["sub_total_cost" ] = dref .sub_total_cost
1239+ validated_data ["surge_deployment_cost" ] = dref .surge_deployment_cost
1240+ validated_data ["surge_deployment_expenditure_cost" ] = dref .surge_deployment_cost
1241+ validated_data ["indirect_cost" ] = dref .indirect_cost
1242+ validated_data ["indirect_expenditure_cost" ] = dref .indirect_cost
1243+ validated_data ["total_cost" ] = dref .total_cost
1244+
11691245 if dref_operational_update :
11701246 validated_data ["title" ] = dref_operational_update .title
11711247 validated_data ["title_prefix" ] = dref_operational_update .title_prefix
@@ -1274,11 +1350,6 @@ def create(self, validated_data):
12741350 if validated_data ["type_of_dref" ] == Dref .DrefType .LOAN :
12751351 raise serializers .ValidationError (gettext ("Can't create final report for dref type %s" % Dref .DrefType .LOAN ))
12761352
1277- # TODO: Remove me! After final report is implemented for drefs IMMINENT
1278- if validated_data ["type_of_dref" ] == Dref .DrefType .IMMINENT and dref .is_dref_imminent_v2 :
1279- raise serializers .ValidationError (
1280- gettext ("Can't create final report for newly created dref type %s" % Dref .DrefType .IMMINENT .label )
1281- )
12821353 dref_final_report = super ().create (validated_data )
12831354 # XXX: Copy files from DREF (Only nested serialized fields)
12841355 nested_serialized_file_fields = [
@@ -1299,6 +1370,8 @@ def create(self, validated_data):
12991370 dref_final_report .risk_security .add (* dref_operational_update .risk_security .all ())
13001371 dref_final_report .users .add (* dref_operational_update .users .all ())
13011372 dref_final_report .source_information .add (* dref_operational_update .source_information .all ())
1373+ if dref_final_report .is_dref_imminent_v2 :
1374+ dref_final_report .proposed_action .add (* dref .proposed_action .all ())
13021375 else :
13031376 validated_data ["title" ] = dref .title
13041377 validated_data ["title_prefix" ] = dref .title_prefix
@@ -1322,7 +1395,7 @@ def create(self, validated_data):
13221395 validated_data ["total_dref_allocation" ] = dref .total_cost
13231396 # NOTE:These field should be blank for final report
13241397 validated_data ["total_operation_timeframe" ] = None
1325- validated_data ["operation_end_date " ] = None
1398+ validated_data ["total_operation_timeframe_imminent " ] = dref . operation_timeframe_imminent
13261399 validated_data ["glide_code" ] = dref .glide_code
13271400 validated_data ["ifrc_appeal_manager_name" ] = dref .ifrc_appeal_manager_name
13281401 validated_data ["ifrc_appeal_manager_email" ] = dref .ifrc_appeal_manager_email
@@ -1336,6 +1409,13 @@ def create(self, validated_data):
13361409 validated_data ["national_society_contact_email" ] = dref .national_society_contact_email
13371410 validated_data ["national_society_contact_title" ] = dref .national_society_contact_title
13381411 validated_data ["national_society_contact_phone_number" ] = dref .national_society_contact_phone_number
1412+ validated_data ["national_society_integrity_contact_name" ] = dref .national_society_integrity_contact_name
1413+ validated_data ["national_society_integrity_contact_email" ] = dref .national_society_integrity_contact_email
1414+ validated_data ["national_society_integrity_contact_title" ] = dref .national_society_integrity_contact_title
1415+ validated_data ["national_society_integrity_contact_phone_number" ] = (
1416+ dref .national_society_integrity_contact_phone_number
1417+ )
1418+ validated_data ["national_society_hotline_phone_number" ] = dref .national_society_hotline_phone_number
13391419 validated_data ["media_contact_name" ] = dref .media_contact_name
13401420 validated_data ["media_contact_email" ] = dref .media_contact_email
13411421 validated_data ["media_contact_title" ] = dref .media_contact_title
@@ -1396,11 +1476,16 @@ def create(self, validated_data):
13961476 gettext ("Can't create final report for dref type %s" % Dref .DrefType .LOAN .label )
13971477 )
13981478
1399- # TODO: Remove me! After final report is implemented for drefs IMMINENT
1479+ # NOTE: Checks for the new dref final reports of new dref imminents
14001480 if validated_data ["type_of_dref" ] == Dref .DrefType .IMMINENT and dref .is_dref_imminent_v2 :
1401- raise serializers .ValidationError (
1402- gettext ("Can't create final report for newly created dref type %s" % Dref .DrefType .IMMINENT .label )
1403- )
1481+ validated_data ["is_dref_imminent_v2" ] = True
1482+ validated_data ["sub_total_cost" ] = dref .sub_total_cost
1483+ validated_data ["surge_deployment_cost" ] = dref .surge_deployment_cost
1484+ validated_data ["surge_deployment_expenditure_cost" ] = dref .surge_deployment_cost
1485+ validated_data ["indirect_cost" ] = dref .indirect_cost
1486+ validated_data ["indirect_expenditure_cost" ] = dref .indirect_cost
1487+ validated_data ["total_cost" ] = dref .total_cost
1488+
14041489 dref_final_report = super ().create (validated_data )
14051490 # XXX: Copy files from DREF (Only nested serialized fields)
14061491 nested_serialized_file_fields = [
@@ -1420,6 +1505,8 @@ def create(self, validated_data):
14201505 dref_final_report .users .add (* dref .users .all ())
14211506 dref_final_report .national_society_actions .add (* dref .national_society_actions .all ())
14221507 dref_final_report .source_information .add (* dref .source_information .all ())
1508+ if dref_final_report .type_of_dref == Dref .DrefType .IMMINENT and dref_final_report .is_dref_imminent_v2 :
1509+ dref_final_report .proposed_action .add (* dref .proposed_action .all ())
14231510 # also update is_final_report_created for dref
14241511 dref .is_final_report_created = True
14251512 dref .save (update_fields = ["is_final_report_created" ])
0 commit comments