@@ -202,6 +202,9 @@ def validate_code_postal(self, obj):
202202
203203 def validate_telephone (self , obj ):
204204 # weird invisible char
205+ if not obj :
206+ return obj
207+
205208 obj = obj .replace (" " , "" )
206209 obj = obj .replace (" " , "" )
207210 return obj
@@ -235,81 +238,85 @@ def validate(self, obj):
235238 if "accessibilite" not in obj :
236239 raise serializers .ValidationError ("Veuillez fournir les données d'accessibilité." )
237240
238- if self .instance :
239- # if we are updating an ERP, only accessibility, asp_id and import_email are editable
240- self .instance .import_email = obj .get ("import_email" )
241- self .instance .asp_id = obj .get ("asp_id" )
242- accessibilite = Accessibilite (** obj ["accessibilite" ])
243- accessibilite .full_clean ()
244-
245- sources_data_list = []
246- sources_data = obj .get ("sources" ) or []
247- for source_data in sources_data :
248- external_source = ExternalSource (** source_data )
249- external_source .full_clean (exclude = ("erp" ,))
250- sources_data_list .append (model_to_dict (external_source ))
251-
252- return (
253- model_to_dict (self .instance )
254- | {"accessibilite" : model_to_dict (accessibilite )}
255- | {"sources" : sources_data_list }
256- )
257-
258- if not obj .get ("voie" ) and not obj .get ("lieu_dit" ):
259- raise serializers .ValidationError ("Veuillez entrer une voie OU un lieu-dit" )
260-
261- for i in range (3 ):
262- try :
263- address = get_address_query_to_geocode (obj )
264- locdata = geocoder .geocode (address , postcode = obj ["code_postal" ])
265- if not locdata :
266- raise RuntimeError
267- self ._geom = locdata ["geom" ]
268- obj ["voie" ] = locdata ["voie" ]
269- obj ["lieu_dit" ] = locdata ["lieu_dit" ]
270- obj ["code_postal" ] = locdata ["code_postal" ]
271- obj ["commune" ] = locdata ["commune" ]
272- obj ["code_insee" ] = locdata ["code_insee" ]
273- obj ["geoloc_provider" ] = locdata ["provider" ]
274- obj ["numero" ] = locdata ["numero" ]
275- obj ["ban_id" ] = locdata .get ("ban_id" )
276- obj .pop ("latitude" , None )
277- obj .pop ("longitude" , None )
278- break
279- except (RuntimeError , KeyError ):
280- if i < 2 :
281- continue
282-
283- if obj .get ("latitude" ) is not None and obj .get ("longitude" ) is not None :
284- self ._geom = Point ((obj ["longitude" ], obj ["latitude" ]), srid = 4326 )
285- obj .pop ("latitude" )
286- obj .pop ("longitude" )
241+ if not self .partial :
242+ if self .instance :
243+ # if we are updating an ERP, only accessibility, asp_id and import_email are editable
244+ self .instance .import_email = obj .get ("import_email" )
245+ self .instance .asp_id = obj .get ("asp_id" )
246+ accessibilite = Accessibilite (** obj ["accessibilite" ])
247+ accessibilite .full_clean ()
248+
249+ sources_data_list = []
250+ sources_data = obj .get ("sources" ) or []
251+ for source_data in sources_data :
252+ external_source = ExternalSource (** source_data )
253+ external_source .full_clean (exclude = ("erp" ,))
254+ sources_data_list .append (model_to_dict (external_source ))
255+
256+ return (
257+ model_to_dict (self .instance )
258+ | {"accessibilite" : model_to_dict (accessibilite )}
259+ | {"sources" : sources_data_list }
260+ )
261+
262+ if not obj .get ("voie" ) and not obj .get ("lieu_dit" ):
263+ raise serializers .ValidationError ("Veuillez entrer une voie OU un lieu-dit" )
264+
265+ for i in range (3 ):
266+ try :
267+ address = get_address_query_to_geocode (obj )
268+ locdata = geocoder .geocode (address , postcode = obj ["code_postal" ])
269+ if not locdata :
270+ raise RuntimeError
271+ self ._geom = locdata ["geom" ]
272+ obj ["voie" ] = locdata ["voie" ]
273+ obj ["lieu_dit" ] = locdata ["lieu_dit" ]
274+ obj ["code_postal" ] = locdata ["code_postal" ]
275+ obj ["commune" ] = locdata ["commune" ]
276+ obj ["code_insee" ] = locdata ["code_insee" ]
277+ obj ["geoloc_provider" ] = locdata ["provider" ]
278+ obj ["numero" ] = locdata ["numero" ]
279+ obj ["ban_id" ] = locdata .get ("ban_id" )
280+ obj .pop ("latitude" , None )
281+ obj .pop ("longitude" , None )
287282 break
283+ except (RuntimeError , KeyError ):
284+ if i < 2 :
285+ continue
286+
287+ if obj .get ("latitude" ) is not None and obj .get ("longitude" ) is not None :
288+ self ._geom = Point ((obj ["longitude" ], obj ["latitude" ]), srid = 4326 )
289+ obj .pop ("latitude" )
290+ obj .pop ("longitude" )
291+ break
292+
293+ raise serializers .ValidationError (f"Adresse non localisable: { address } " )
288294
289- raise serializers .ValidationError (f"Adresse non localisable: { address } " )
295+ obj ["commune_ext" ] = Commune .objects .filter (
296+ nom__iexact = obj ["commune" ], code_postaux__contains = [obj ["code_postal" ]]
297+ ).first ()
290298
291- obj ["commune_ext" ] = Commune .objects .filter (
292- nom__iexact = obj ["commune" ], code_postaux__contains = [obj ["code_postal" ]]
293- ).first ()
299+ self ._ensure_no_duplicate (obj )
294300
295- self ._ensure_no_duplicate (obj )
301+ erp_data = obj .copy ()
302+ erp_data .pop ("accessibilite" )
303+ erp_data .pop ("sources" )
296304
297- erp_data = obj .copy ()
298- erp_data .pop ("accessibilite" )
299- erp_data .pop ("sources" )
305+ Erp (** erp_data ).full_clean (exclude = ("source_id" , "asp_id" , "user" , "metadata" , "search_vector" ))
300306
301- Erp ( ** erp_data ). full_clean ( exclude = ( "source_id" , "asp_id" , "user" , "metadata" , "search_vector" ))
302- Accessibilite (** obj ["accessibilite" ]).full_clean ()
307+ if "accessibilite" in obj :
308+ Accessibilite (** obj ["accessibilite" ]).full_clean ()
303309
304310 sources_data = obj .get ("sources" ) or []
305311 for source_data in sources_data :
306312 ExternalSource (** source_data ).full_clean (exclude = ("erp" ,))
307313
308314 return obj
309315
310- def update (self , instance , validated_data , partial = True ):
311- # If enrich_only, it won't update any access info already there
316+ def update (self , instance , validated_data ):
312317 enrich_only = self .context .get ("enrich_only" ) or False
318+ raw_data = self .initial_data
319+
313320 # if we are updating an ERP, only accessibility, asp_id and import_email are editable
314321 if validated_data .get ("import_email" ):
315322 instance .import_email = validated_data ["import_email" ]
@@ -320,15 +327,20 @@ def update(self, instance, validated_data, partial=True):
320327 instance .save (update_fields = ["asp_id" ])
321328
322329 accessibilite = instance .accessibilite
323- for attr in ("id" , "erp" ):
324- validated_data ["accessibilite" ].pop (attr , False )
330+ acc_data = validated_data .get ("accessibilite" , {})
331+ raw_acc_data = raw_data .get ("accessibilite" , {})
332+
333+ for attr , new_value in acc_data .items ():
334+ if attr in ("id" , "erp" ):
335+ continue
325336
326- for attr in validated_data ["accessibilite" ]:
327337 if enrich_only and getattr (accessibilite , attr , None ) is not None :
328338 continue
329339
330- new_value = validated_data ["accessibilite" ][attr ]
331- if new_value not in (None , [], ()):
340+ if self .partial and attr in raw_acc_data and raw_acc_data [attr ] in (None , "" , [], ()):
341+ continue
342+
343+ if not enrich_only or new_value not in (None , [], ()):
332344 setattr (accessibilite , attr , new_value )
333345 self ._handle_children_reinit (accessibilite , attr )
334346
0 commit comments