Skip to content

Commit

Permalink
feat: consider every additional entities without clipping them with A…
Browse files Browse the repository at this point in the history
…OI (#2017)
  • Loading branch information
Sujanadh authored Dec 25, 2024
1 parent ece3b43 commit 19419fe
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 29 deletions.
59 changes: 38 additions & 21 deletions src/backend/app/central/central_crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from asyncio import gather
from io import BytesIO, StringIO
from typing import Optional, Union
from uuid import uuid4

import geojson
from fastapi import HTTPException
Expand Down Expand Up @@ -499,50 +500,66 @@ async def convert_odk_submission_json_to_geojson(

async def feature_geojson_to_entity_dict(
feature: geojson.Feature,
additional_features: bool = False,
) -> central_schemas.EntityDict:
"""Convert a single GeoJSON to an Entity dict for upload."""
if not isinstance(feature, (dict, geojson.Feature)):
log.error(f"Feature not in correct format: {feature}")
raise ValueError(f"Feature not in correct format: {type(feature)}")

feature_id = feature.get("id")

geometry = feature.get("geometry", {})
if not geometry:
msg = "'geometry' data field is mandatory"
log.debug(msg)
raise ValueError(msg)

javarosa_geom = await geojson_to_javarosa_geom(geometry)
properties = {}
for key, value in feature.get("properties", {}).items():
if not central_schemas.is_valid_property_name(key):
log.warning(f"Invalid property name: {key},Excluding from properties.")
continue
# NOTE all properties MUST be string values for Entities, convert
properties.update({str(central_schemas.sanitize_key(key)): str(value)})

properties["status"] = "0"

task_id = properties.get("task_id")
entity_label = f"Task {task_id} Feature {feature_id}"

return {"label": entity_label, "data": {"geometry": javarosa_geom, **properties}}
raw_properties = feature.get("properties", {})
properties = {
central_schemas.sanitize_key(key): str(
value
) # NOTE all properties MUST be string values for Entities
for key, value in raw_properties.items()
if central_schemas.is_valid_property_name(key)
}
if additional_features:
entity_label = f"Additional Feature {uuid4()}"
else:
properties["status"] = "0"
task_id = properties.get("task_id", None)
feature_id = feature.get("id", None)
entity_label = f"Task {task_id} Feature {feature_id}"

return {
"label": entity_label,
"data": {"geometry": javarosa_geom, **properties},
}


async def task_geojson_dict_to_entity_values(
task_geojson_dict: dict[int, geojson.Feature],
task_geojson_dict: Union[dict[int, geojson.Feature], geojson.FeatureCollection],
additional_features: bool = False,
) -> list[central_schemas.EntityDict]:
"""Convert a dict of task GeoJSONs into data for ODK Entity upload."""
log.debug("Converting dict of task GeoJSONs to Entity upload format")

asyncio_tasks = []
for _, geojson_dict in task_geojson_dict.items():
# Extract the features list and pass each Feature through
features = geojson_dict.get("features", [])

if additional_features:
features = task_geojson_dict.get("features", [])
asyncio_tasks.extend(
[feature_geojson_to_entity_dict(feature) for feature in features if feature]
feature_geojson_to_entity_dict(feature, additional_features)
for feature in features
if feature
)
else:
for geojson_dict in task_geojson_dict.values():
features = geojson_dict.get("features", [])
asyncio_tasks.extend(
feature_geojson_to_entity_dict(feature)
for feature in features
if feature
)

return await gather(*asyncio_tasks)

Expand Down
10 changes: 2 additions & 8 deletions src/backend/app/projects/project_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
flatgeobuf_to_featcol,
merge_polygons,
parse_geojson_file_to_featcol,
split_geojson_by_task_areas,
)
from app.organisations import organisation_deps
from app.projects import project_crud, project_deps, project_schemas
Expand Down Expand Up @@ -813,20 +812,15 @@ async def add_additional_entity_list(
of the GeoJSON uploaded.
"""
project = project_user_dict.get("project")
project_id = project.id
project_odk_id = project.odkid
project_odk_creds = project.odk_credentials
# NOTE the Entity name is extracted from the filename (without extension)
entity_name = Path(geojson.filename).stem

# Parse geojson + divide by task
# (not technically required, but also appends properties in correct format)
# Parse geojson
featcol = parse_geojson_file_to_featcol(await geojson.read())
properties = list(featcol.get("features")[0].get("properties").keys())
feature_split_by_task = await split_geojson_by_task_areas(db, featcol, project_id)
entities_list = await central_crud.task_geojson_dict_to_entity_values(
feature_split_by_task
)
entities_list = await central_crud.task_geojson_dict_to_entity_values(featcol, True)
dataset_name = entity_name.replace(" ", "_")

await central_crud.create_entity_list(
Expand Down

0 comments on commit 19419fe

Please sign in to comment.