Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider every additional entities without clipping them with AOI #2017

Merged
merged 2 commits into from
Dec 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading