Skip to content

Commit

Permalink
Feat/get all sites (#26)
Browse files Browse the repository at this point in the history
* test(api): test all_geometries route

* feat(api): geojson instead of geobuf for sites

* feat(api): add all_sites_group_geometry route

To return the geometries of all sites groups

* test(api): refactor fixture

To add a new one: site_group_with_sites since not all sites_groups
have sites

* test(api): test get_sites_groups route

* feat(api): add possibility to filter

On id_base_site, base_site_name and id_sites_group

* test(api): add fixture to get group without site
  • Loading branch information
mvergez authored and amandine-sahl committed Oct 5, 2023
1 parent bb5767d commit 994935b
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 6 deletions.
22 changes: 21 additions & 1 deletion backend/gn_module_monitoring/routes/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@

from gn_module_monitoring.blueprint import blueprint
from gn_module_monitoring.monitoring.models import BibTypeSite, TMonitoringSites
from gn_module_monitoring.monitoring.schemas import BibTypeSiteSchema, MonitoringSitesSchema
from gn_module_monitoring.utils.routes import (
filter_params,
geojson_query,
get_limit_page,
get_sort,
paginate,
sort,
)
from gn_module_monitoring.monitoring.schemas import MonitoringSitesSchema,BibTypeSiteSchema


@blueprint.route("/sites/types", methods=["GET"])
Expand Down Expand Up @@ -60,6 +61,25 @@ def get_sites():
)


@blueprint.route("/sites/geometries", methods=["GET"])
def get_all_site_geometries():
params = MultiDict(request.args)
subquery = (
TMonitoringSites.query.with_entities(
TMonitoringSites.id_base_site,
TMonitoringSites.base_site_name,
TMonitoringSites.geom,
TMonitoringSites.id_sites_group,
)
.filter_by_params(params)
.subquery()
)

result = geojson_query(subquery)

return jsonify(result)


@blueprint.route("/sites/module/<string:module_code>", methods=["GET"])
def get_module_sites(module_code: str):
# TODO: load with site_categories.json API
Expand Down
30 changes: 27 additions & 3 deletions backend/gn_module_monitoring/routes/sites_groups.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
from flask import request
from flask import jsonify, request
from geonature.utils.env import db
from sqlalchemy import func
from werkzeug.datastructures import MultiDict

from gn_module_monitoring.blueprint import blueprint
from gn_module_monitoring.monitoring.models import TMonitoringSitesGroups
from gn_module_monitoring.monitoring.models import TMonitoringSites, TMonitoringSitesGroups
from gn_module_monitoring.monitoring.schemas import MonitoringSitesGroupsSchema
from gn_module_monitoring.utils.routes import (
filter_params,
geojson_query,
get_limit_page,
get_sort,
paginate,
sort,
)
from gn_module_monitoring.monitoring.schemas import MonitoringSitesGroupsSchema


@blueprint.route("/sites_groups", methods=["GET"])
Expand All @@ -29,3 +32,24 @@ def get_sites_groups():
limit=limit,
page=page,
)


@blueprint.route("/sites_groups/geometries", methods=["GET"])
def get_sites_group_geometries():
subquery = (
db.session.query(
TMonitoringSitesGroups.id_sites_group,
TMonitoringSitesGroups.sites_group_name,
func.st_convexHull(func.st_collect(TMonitoringSites.geom)),
)
.group_by(TMonitoringSitesGroups.id_sites_group, TMonitoringSitesGroups.sites_group_name)
.join(
TMonitoringSites,
TMonitoringSites.id_sites_group == TMonitoringSitesGroups.id_sites_group,
)
.subquery()
)

result = geojson_query(subquery)

return jsonify(result)
4 changes: 2 additions & 2 deletions backend/gn_module_monitoring/tests/fixtures/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


@pytest.fixture()
def sites(users, types_site, sites_groups):
def sites(users, types_site, site_group_with_sites):
user = users["user"]
geom_4326 = from_shape(Point(43, 24), srid=4326)
sites = {}
Expand All @@ -21,7 +21,7 @@ def sites(users, types_site, sites_groups):
geom=geom_4326,
id_nomenclature_type_site=types_site[key].id_nomenclature_type_site,
types_site=[types_site[key]],
id_sites_group=sites_groups["Site_Groupe"].id_sites_group,
id_sites_group=site_group_with_sites.id_sites_group,
)
with db.session.begin_nested():
db.session.add_all(sites.values())
Expand Down
10 changes: 10 additions & 0 deletions backend/gn_module_monitoring/tests/fixtures/sites_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,13 @@ def sites_groups():
db.session.add_all(groups.values())

return groups


@pytest.fixture
def site_group_with_sites(sites_groups):
return sites_groups["Site_Groupe"]


@pytest.fixture
def site_group_without_sites(sites_groups):
return sites_groups["Site_eolien"]
28 changes: 28 additions & 0 deletions backend/gn_module_monitoring/tests/test_routes/test_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,34 @@ def test_get_sites_id_base_site(self, sites):
assert len(r.json["items"]) == 1
assert r.json["items"][0]["id_base_site"] == id_base_site

def test_get_all_site_geometries(self, sites):
r = self.client.get(url_for("monitorings.get_all_site_geometries"))

json_resp = r.json
features = json_resp.get("features")
sites_values = list(sites.values())
assert r.content_type == "application/json"
assert json_resp.get("type") == "FeatureCollection"
assert len(features) >= len(sites_values)
for site in sites_values:
id_ = [
obj["properties"]
for obj in features
if obj["properties"]["base_site_name"] == site.base_site_name
][0]["id_base_site"]
assert id_ == site.id_base_site

def test_get_all_site_geometries_filter_site_group(self, sites, site_group_without_sites):
r = self.client.get(
url_for(
"monitorings.get_all_site_geometries",
id_sites_group=site_group_without_sites.id_sites_group,
)
)
json_resp = r.json
features = json_resp.get("features")
assert features is None

def test_get_module_sites(self):
module_code = "TEST"
r = self.client.get(url_for("monitorings.get_module_sites", module_code=module_code))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,18 @@ def test_serialize_sites_groups(self, sites_groups, sites):
).all()
schema = MonitoringSitesGroupsSchema()
assert [schema.dump(site) for site in groups]

def test_get_sites_groups_geometries(self, sites, site_group_with_sites):
r = self.client.get(url_for("monitorings.get_sites_group_geometries"))

json_resp = r.json
features = json_resp.get("features")
assert r.content_type == "application/json"
assert json_resp.get("type") == "FeatureCollection"
assert len(features) >= 1
id_ = [
obj["properties"]
for obj in features
if obj["properties"]["sites_group_name"] == site_group_with_sites.sites_group_name
][0]["id_sites_group"]
assert id_ == site_group_with_sites.id_sites_group
20 changes: 20 additions & 0 deletions backend/gn_module_monitoring/utils/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

from flask import Response
from flask.json import jsonify
from geonature.utils.env import DB
from marshmallow import Schema
from sqlalchemy import cast, func, text
from sqlalchemy.dialects.postgresql import JSON
from sqlalchemy.orm import Query
from werkzeug.datastructures import MultiDict

Expand Down Expand Up @@ -37,3 +40,20 @@ def sort(query: MonitoringQuery, sort: str, sort_dir: str) -> MonitoringQuery:
if sort_dir in ["desc", "asc"]:
query = query.sort(label=sort, direction=sort_dir)
return query


def geojson_query(subquery) -> bytes:
subquery_name = "q"
subquery = subquery.alias(subquery_name)
query = DB.session.query(
func.json_build_object(
text("'type'"),
text("'FeatureCollection'"),
text("'features'"),
func.json_agg(cast(func.st_asgeojson(subquery), JSON)),
)
)
result = query.first()
if len(result) > 0:
return result[0]
return b""

0 comments on commit 994935b

Please sign in to comment.