diff --git a/src/backend/app/projects/project_crud.py b/src/backend/app/projects/project_crud.py index 1fd881df86..4fb5f84c6c 100644 --- a/src/backend/app/projects/project_crud.py +++ b/src/backend/app/projects/project_crud.py @@ -453,8 +453,8 @@ def update_multi_polygon_project_boundary( result = db.execute(query) data = result.fetchone() - db_project.outline = data[0] - db_project.centroid = (wkt.loads(data[0])).centroid.wkt + update_project_location_info(db_project, data[0]) + db.commit() db.refresh(db_project) log.debug("COMPLETE: creating project boundary, based on task boundaries") @@ -898,8 +898,7 @@ def remove_z_dimension(coord): else: outline = shape(features[0]["geometry"]) - db_project.outline = outline.wkt - db_project.centroid = outline.centroid.wkt + update_project_location_info(db_project, outline.wkt) db.commit() db.refresh(db_project) @@ -1011,8 +1010,7 @@ def update_project_with_zip( outline_shape = get_outline_from_geojson_file_in_zip( zip, outline_filename, f"Could not generate Shape from {outline_filename}" ) - db_project.outline = outline_shape.wkt - db_project.centroid = outline_shape.centroid.wkt + update_project_location_info(db_project, outline_shape.wkt) # get all task outlines from file project_tasks_feature_collection = get_json_from_zip( @@ -1894,6 +1892,7 @@ def convert_to_project_summary(db_project: db_models.DbProject): None, ) # default_project_info = project_schemas.ProjectInfo + summary.location_str = db_project.location_str summary.title = default_project_info.name summary.description = default_project_info.short_description @@ -2669,3 +2668,46 @@ def generate_appuser_files_for_janakpur( update_background_task_status_in_database( db, background_task_id, 4 ) # 4 is COMPLETED + + +def get_address_from_lat_lon(latitude, longitude): + """Get address using Nominatim, using lat,lon.""" + base_url = "https://nominatim.openstreetmap.org/reverse" + + params = { + "format": "json", + "lat": latitude, + "lon": longitude, + "zoom": 18, + } + headers = {"Accept-Language": "en"} # Set the language to English + + response = requests.get(base_url, params=params, headers=headers) + data = response.json() + address = data["address"]["country"] + + if response.status_code == 200: + if "city" in data["address"]: + city = data["address"]["city"] + address = f"{city}" + "," + address + return address + else: + return "Address not found." + + +def update_project_location_info( + db_project: sqlalchemy.orm.declarative_base, project_boundary: str +): + """Update project boundary, centroid, address. + + Args: + db_project(sqlalchemy.orm.declarative_base): The project database record. + project_boundary(str): WKT string geometry. + """ + db_project.outline = project_boundary + centroid = (wkt.loads(project_boundary)).centroid.wkt + db_project.centroid = centroid + geometry = wkt.loads(centroid) + longitude, latitude = geometry.x, geometry.y + address = get_address_from_lat_lon(latitude, longitude) + db_project.location_str = address if address is not None else "" diff --git a/src/backend/tests/test_projects_routes.py b/src/backend/tests/test_projects_routes.py index 03a7119365..1351621f2c 100644 --- a/src/backend/tests/test_projects_routes.py +++ b/src/backend/tests/test_projects_routes.py @@ -8,7 +8,8 @@ from fastapi import FastAPI from geoalchemy2.elements import WKBElement from loguru import logger as log -from shapely import Polygon +from shapely import Polygon, wkb +from shapely.geometry import shape from app.central.central_crud import create_odk_project from app.db import db_models @@ -139,6 +140,18 @@ def test_generate_appuser_files(db, project): db, project_id, boundary_geojson, 500 ) assert boundary_created is True + # Check updated locations + db_project = project_crud.get_project_by_id(db, project_id) + # Outline + project_outline = db_project.outline.data.tobytes() + file_outline = shape(boundary_geojson) + assert wkb.loads(project_outline).wkt == file_outline.wkt + # Centroid + project_centroid = wkb.loads(db_project.centroid.data.tobytes()).wkt + file_centroid = file_outline.centroid.wkt + assert project_centroid == file_centroid + # Location string + assert db_project.location_str == "Zurich,Switzerland" # Load data extracts data_extracts_file = f"{test_data_path}/building_footprint.zip"