1111from django .contrib import messages
1212from django .db .models import Q
1313from django .core .exceptions import ValidationError
14+ from api .logger import logger
1415
1516from api .models import (
1617 Country ,
1718 District ,
1819 DisasterType ,
1920)
2021
21- from .widgets import EnumArrayWidget
2222from .models import (
2323 Project ,
2424 ProjectImport ,
@@ -170,24 +170,32 @@ def _parse_integer(integer):
170170 # Enum options
171171 operation_types = {label .lower (): value for value , label in OperationTypes .choices }
172172 programme_types = {label .lower (): value for value , label in ProgrammeTypes .choices }
173- sectors = {t .title .lower (): t .id for t in Sector .objects .all ()}
174- sector_tags = {t .title .lower (): t .id for t in SectorTag .objects .all ()}
175173 statuses = {label .lower (): value for value , label in Statuses .choices }
176174
175+ # Not enums, but maybe could be used later to avoid multiple queries for id-s: FIXME
176+ # sectors = {t.title.lower(): t.id for t in Sector.objects.all()}
177+ # sector_tags = {t.title.lower(): t.id for t in SectorTag.objects.all()}
178+ # disaster_types ?
179+
177180 c = self .Columns
181+
178182 # Extract from import csv file
179183 for row_number , row in enumerate (reader , start = 2 ):
180184 district_names = [
181185 d .strip () for d in row [c .DISTRICT ].split (',' )
182- if d .lower () not in ['countrywide' , '' ]
183- ]
186+ ] if row [c .DISTRICT ].lower () not in ['countrywide' , '' ] else []
184187 reporting_ns_name = row [c .REPORTING_NS ].strip ()
185188 country_name = row [c .COUNTRY ].strip ()
186189 disaster_type_name = row [c .DISASTER_TYPE ].strip ()
190+ sector_name = row [c .PRIMARY_SECTOR ].strip ()
191+ tag_names = [
192+ d .strip () for d in row [c .TAGS ].split (',' )
193+ ]
187194
188195 reporting_ns = Country .objects .filter (
189196 Q (name__iexact = reporting_ns_name ) | Q (society_name__iexact = reporting_ns_name )
190197 ).first ()
198+ project_sector = Sector .objects .filter (title = sector_name ).first ()
191199 disaster_type = DisasterType .objects .filter (name__iexact = disaster_type_name ).first ()
192200
193201 row_errors = {}
@@ -219,6 +227,18 @@ def _parse_integer(integer):
219227 # A validation error will be raised. This is just a custom message
220228 row_errors ['project_districts' ] = ['Given districts/regions are not available.' ]
221229
230+ project_sectortags = []
231+ if tag_names :
232+ project_sectortags = list (SectorTag .objects .filter (
233+ reduce (lambda acc , item : acc | item ,
234+ [Q (title = title ) for title in tag_names ],
235+ )
236+ ).all ())
237+ # Check if all tag_names is available in db
238+ if len (project_sectortags ) != len (tag_names ):
239+ # A validation error will be raised. This is just a custom message
240+ row_errors ['project_sectortags' ] = [f'Given tags: "{ tag_names } " are not all available.' ]
241+
222242 if reporting_ns is None :
223243 row_errors ['reporting_ns' ] = [f'Given country "{ reporting_ns_name } " is not available.' ]
224244 if disaster_type is None :
@@ -234,10 +254,7 @@ def _parse_integer(integer):
234254 # Enum fields
235255 operation_type = operation_types .get (_key_clean (row [c .OPERATION_TYPE ])),
236256 programme_type = programme_types .get (_key_clean (row [c .PROGRAMME_TYPE ])),
237- primary_sector = sectors .get (_key_clean (row [c .PRIMARY_SECTOR ])),
238- secondary_sectors = [
239- sector_tags .get (_key_clean (tag )) for tag in row [c .TAGS ].split (',' ) if _key_clean (tag ) in sector_tags
240- ],
257+ primary_sector = project_sector ,
241258 status = statuses .get (_key_clean (row [c .STATUS ])),
242259
243260 name = row [c .PROJECT_NAME ],
@@ -258,7 +275,7 @@ def _parse_integer(integer):
258275 try :
259276 project .full_clean ()
260277 if len (row_errors ) == 0 :
261- projects .append ([project , project_districts ])
278+ projects .append ([project , project_districts , project_sectortags ])
262279 else :
263280 errors .append (_get_error_message (row_number , row_errors ))
264281 except ValidationError as e :
@@ -270,8 +287,9 @@ def _parse_integer(integer):
270287
271288 Project .objects .bulk_create ([p [0 ] for p in projects ])
272289 # Set M2M Now
273- for project , project_districts in projects :
290+ for project , project_districts , project_sectortags in projects :
274291 project .project_districts .set (project_districts )
292+ project .secondary_sectors .set (project_sectortags )
275293 # Return projects for ProjectImport
276294 return [p [0 ] for p in projects ]
277295
@@ -288,7 +306,7 @@ def handle_bulk_upload(self, request):
288306 projects = self ._handle_bulk_upload (request .user , file , delimiter , quotechar )
289307 project_import .projects_created .add (* projects )
290308 project_import .message = f'Successfully added <b>{ len (projects )} </b> project(s) using <b>{ file } </b>.'
291- project_import .status = ProjectImport .SUCCESS
309+ project_import .status = ProjectImport .ProjImpStatus . SUCCESS
292310 # Also show error in Admin Panel
293311 messages .add_message (request , messages .INFO , mark_safe (project_import .message ))
294312 except Exception as e :
@@ -301,5 +319,5 @@ def handle_bulk_upload(self, request):
301319 "<pre>NOTE: Make sure to use correct <b>file delimiter</b> and <b>string delimiter!</b></pre>"
302320 )
303321 messages .add_message (request , messages .ERROR , mark_safe (project_import .message ))
304- project_import .status = ProjectImport .FAILURE
322+ project_import .status = ProjectImport .ProjImpStatus . FAILURE
305323 project_import .save ()
0 commit comments