@@ -435,10 +435,8 @@ def generate_district_settings_message(subscription, test_time=None):
435435
436436
437437def queue_route_event_notifications (saved_route , updated_event_ids ):
438- # Apply a 150m buffer to the route geometry
439- saved_route .route .transform (3857 )
440- buffered_route = saved_route .route .buffer (150 )
441- buffered_route .transform (4326 )
438+ # Same 150m flattened-route buffer used when sending notifications
439+ buffered_route = merge_multilinestring (saved_route .route )
442440
443441 updated_interecting_events = Event .objects .filter (
444442 id__in = updated_event_ids ,
@@ -484,55 +482,43 @@ def update_event_area_relations():
484482 event .area .set (intersecting_areas )
485483
486484
487- def merge_multilinestring (multilinestring ):
488- # Flatten all coordinates from each LineString in the MultiLineString
485+ def flatten_route_linestring (multilinestring ):
486+ """ Flatten a MultiLineString into a single LineString (SRID unchanged)."""
489487 coords = []
490488 for line in multilinestring :
491489 coords .extend (line .coords )
492- ls = LineString (coords , srid = multilinestring .srid )
490+ return LineString (coords , srid = multilinestring .srid )
491+
492+
493+ def merge_multilinestring (multilinestring ):
494+ """Return a 150m buffer (SRID 4326) around the flattened route."""
495+ ls = flatten_route_linestring (multilinestring )
496+ if ls .empty :
497+ return ls
493498
494- # Apply a 150m buffer to the route geometry
495499 ls .transform (3857 )
496500 buffered_route = ls .buffer (150 )
497501 buffered_route .transform (4326 )
498502
499503 return buffered_route
500504
501505
502- def get_event_reference_point (event_location , route ):
503- # If event_location is a Point, return as is
504- if event_location .geom_type == 'Point' :
505- return event_location
506-
507- # If event_location is a LineString, get intersection with route
508- elif event_location .geom_type == 'LineString' :
509- intersection = event_location .intersection (route )
510- # If intersection is a Point, return it
511- if intersection .geom_type == 'Point' :
512- return intersection
513-
514- # If intersection is a MultiPoint or LineString, return centroid or first point
515- elif intersection .geom_type in ['MultiPoint' , 'LineString' ]:
516- return intersection .centroid
517-
518- # Fallback: return centroid
519- return event_location .centroid
520-
521-
522506def get_ordered_events (events , route ):
523- events = list (events )
524- event_distances = []
525- for event in events :
526- # Get reference point from buffered route
527- ref_point = get_event_reference_point (event .location , merge_multilinestring (route ))
528- distance = route .project (ref_point )
529- event_distances .append ((distance , event ))
507+ """Sort events by distance along the route (point location, else centroid)."""
508+ route_ls = flatten_route_linestring (route )
509+ if route_ls .empty :
510+ return list (events )
530511
531- # Sort events by distance along the route
532- event_distances .sort (key = lambda x : x [0 ])
533- ordered_events = [e for _ , e in event_distances ]
512+ def distance_along_route (event ):
513+ loc = event .location
514+ if loc .empty :
515+ return float ('inf' )
516+ point = loc if loc .geom_type == 'Point' else loc .centroid
517+ if point .empty :
518+ return float ('inf' )
519+ return route_ls .project (point )
534520
535- return ordered_events
521+ return sorted ( events , key = distance_along_route )
536522
537523
538524def send_queued_notifications ():
@@ -548,7 +534,12 @@ def send_queued_notifications():
548534 queued_notification_ids += queued_notifications .values_list ('id' , flat = True )
549535
550536 queued_event_ids = queued_notifications .values_list ('event_id' , flat = True )
551- events = active_events .filter (id__in = queued_event_ids ) # filter out inactive events
537+ buffered_route = merge_multilinestring (saved_route .route )
538+ # Active + still near the route (drops stale queue rows / geometry drift)
539+ events = active_events .filter (
540+ id__in = queued_event_ids ,
541+ location__intersects = buffered_route ,
542+ )
552543 ordered_events = get_ordered_events (events , saved_route .route )
553544
554545 if not ordered_events :
@@ -578,7 +569,7 @@ def send_queued_notifications():
578569 # image attachments
579570 attach_default_email_images (msg )
580571
581- file_names = get_unique_image_type_files_names (events )
572+ file_names = get_unique_image_type_files_names (ordered_events )
582573 for fn in file_names :
583574 attach_image_to_email (msg , fn .split ('.' )[0 ], fn ) # use file name (without extension) as cid
584575
0 commit comments