@@ -25,13 +25,21 @@ class ProjectAreaImportResult:
2525 fetched : int
2626 matched : int
2727 updated : int
28+ created : int
29+ skipped : int
2830 unmatched_locations : tuple [str , ...]
2931
3032
3133def _normalize_name (value : str ) -> str :
3234 return value .strip ().lower ()
3335
3436
37+ def _geoms_equal (geom1 : str , geom2 : str ) -> bool :
38+ from shapely import wkt
39+
40+ return wkt .loads (geom1 ).equals (wkt .loads (geom2 ))
41+
42+
3543def _geojson_to_multipolygon_wkt (geometry : dict [str , Any ]) -> str :
3644 geom = shape (geometry )
3745 if isinstance (geom , Polygon ):
@@ -77,13 +85,16 @@ def _fetch_project_area_features(
7785
7886def import_project_area_boundaries (
7987 layer_url : str = PROJECT_AREA_LAYER_URL ,
88+ group_type : str = "Geographic Area" ,
8089) -> ProjectAreaImportResult :
8190 with httpx .Client (timeout = 60.0 ) as client :
8291 features = _fetch_project_area_features (client , layer_url )
8392
8493 unmatched_locations : list [str ] = []
8594 matched = 0
8695 updated = 0
96+ created = 0
97+ skipped = 0
8798
8899 with session_ctx () as session :
89100 for feature in features :
@@ -94,30 +105,53 @@ def import_project_area_boundaries(
94105 if not location_name or geometry is None :
95106 continue
96107
108+ normalized_name = _normalize_name (location_name )
97109 groups = session .scalars (
98110 select (Group ).where (
99- func .lower (func .trim (Group .name )) == _normalize_name (location_name )
111+ func .lower (func .trim (Group .name )) == normalized_name ,
112+ Group .group_type == group_type ,
100113 )
101114 ).all ()
102115
103- if not groups :
104- unmatched_locations .append (location_name )
105- continue
106-
107- matched += len (groups )
108116 project_area = WKTElement (
109117 _geojson_to_multipolygon_wkt (geometry ),
110118 srid = 4326 ,
111119 )
120+
121+ if not groups :
122+ new_group = Group (
123+ name = location_name ,
124+ group_type = group_type ,
125+ project_area = project_area ,
126+ )
127+ session .add (new_group )
128+ created += 1
129+ matched += 1
130+ continue
131+
132+ matched += len (groups )
112133 for group in groups :
113- group .project_area = project_area
114- updated += 1
134+ old_wkt = None
135+ if group .project_area is not None :
136+ from shapely import wkb
137+
138+ old_wkt = wkb .loads (bytes (group .project_area .data )).wkt
139+
140+ new_wkt = project_area .desc
141+
142+ if old_wkt is None or not _geoms_equal (old_wkt , new_wkt ):
143+ group .project_area = project_area
144+ updated += 1
145+ else :
146+ skipped += 1
115147
116148 session .commit ()
117149
118150 return ProjectAreaImportResult (
119151 fetched = len (features ),
120152 matched = matched ,
121153 updated = updated ,
154+ created = created ,
155+ skipped = skipped ,
122156 unmatched_locations = tuple (sorted (set (unmatched_locations ))),
123157 )
0 commit comments