From c36c3ba25dd8fa5280eab7413472f5cf3fd1f04e Mon Sep 17 00:00:00 2001 From: sonnenteich Date: Thu, 3 Jul 2025 22:19:59 +0200 Subject: [PATCH 1/4] initial query --- app/api/tree.py | 26 ++++++++++++++++++++++++-- app/services/tree.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/app/api/tree.py b/app/api/tree.py index 0d5b84f..a3d0354 100755 --- a/app/api/tree.py +++ b/app/api/tree.py @@ -11,7 +11,8 @@ ) from ..dependencies import get_session from ..services.tree import ( - get_tree_by_id + get_tree_by_id, + get_tree_by_species ) from geoalchemy2.shape import to_shape @@ -72,4 +73,25 @@ async def fetch_tree_by_id( "registration_date": tree.registration_date.isoformat() if tree.registration_date else None, "type": tree.type, "geom": geojson_dict, - } \ No newline at end of file + } + +@route_street_tree.get( + '/species', + response_model=StreetTreeResponse, + tags=['Strassenbaeume'], + description='Retrieves street tree details based there species.' +) +async def get_tree_by_species( + tree_id: int, + session: AsyncSession = Depends(get_session) +) -> StreetTreeResponse: + + rows = await get_tree_by_species() + + if not row: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f'No matches found for tree_id {tree_id}' + ) + + return rows diff --git a/app/services/tree.py b/app/services/tree.py index 6bba84b..2fdf90a 100755 --- a/app/services/tree.py +++ b/app/services/tree.py @@ -10,3 +10,39 @@ async def get_tree_by_id(session: AsyncSession, tree_id: int): row = result.scalars().first() return row + +async def get_tree_by_species(session: AsyncSession): + stmt = text(''' + SELECT + tr.id, + tr.tree_number, + tr.street, + tr.species, + tr.type, + ROUND(ST_X(ST_Transform(tr.geom, 4326))::numeric, 6) AS lon, + ROUND(ST_Y(ST_Transform(tr.geom, 4326))::numeric, 6) AS lat, + CASE + WHEN tr.species ILIKE '%Tilia%' THEN 1 + WHEN tr.species ILIKE '%Acer%' THEN 2 + WHEN tr.species ILIKE '%Quercus%' THEN 3 + WHEN tr.species ILIKE '%Fagus%' THEN 4 + WHEN tr.species ILIKE '%Betula%' THEN 5 + WHEN tr.species ILIKE '%Carpinus%' THEN 6 + ELSE 0 + END AS species_index + FROM flensburg.street_tree_register tr + WHERE tr.type = 'bestand' + AND NOT EXISTS ( + SELECT 1 + FROM flensburg.street_tree_register gef + WHERE gef.type = 'gefaellt' + AND gef.tree_number = tr.tree_number + AND gef.street = tr.street + ) + ORDER BY tr.species + ''') + + result = await session.execute(stmt) + rows = result.mappings().all() + + return [dict(row) for row in rows] \ No newline at end of file From a5bd7b7ccf0238347b56bd4b3511ac3ef62d5327 Mon Sep 17 00:00:00 2001 From: sonnenteich Date: Thu, 3 Jul 2025 22:48:45 +0200 Subject: [PATCH 2/4] small fixes --- app/api/tree.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/app/api/tree.py b/app/api/tree.py index a3d0354..cce0c22 100755 --- a/app/api/tree.py +++ b/app/api/tree.py @@ -77,21 +77,22 @@ async def fetch_tree_by_id( @route_street_tree.get( '/species', - response_model=StreetTreeResponse, + response_model=List, tags=['Strassenbaeume'], description='Retrieves street tree details based there species.' ) async def get_tree_by_species( - tree_id: int, session: AsyncSession = Depends(get_session) -) -> StreetTreeResponse: +): - rows = await get_tree_by_species() + rows = await get_tree_by_species(session) + response = jsonable_encoder(rows) - if not row: + try: + return JSONResponse(content=response[0]) + except IndexError: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, - detail=f'No matches found for tree_id {tree_id}' + detail='Not found' ) - - return rows + \ No newline at end of file From ec3dac4c88145e04ff3b7ed5bdcac1d3445e0f55 Mon Sep 17 00:00:00 2001 From: sonnenteich Date: Fri, 4 Jul 2025 21:38:55 +0200 Subject: [PATCH 3/4] fixed missing imports --- app/api/tree.py | 8 +++++--- app/services/tree.py | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/api/tree.py b/app/api/tree.py index cce0c22..0575fdd 100755 --- a/app/api/tree.py +++ b/app/api/tree.py @@ -3,9 +3,13 @@ from typing import List, Dict, Any from fastapi import Depends, APIRouter, HTTPException, status +from fastapi.encoders import jsonable_encoder +from fastapi.responses import JSONResponse from geojson import Feature, FeatureCollection from sqlalchemy.ext.asyncio import AsyncSession + + from ..schemas.tree import ( StreetTreeResponse ) @@ -84,15 +88,13 @@ async def fetch_tree_by_id( async def get_tree_by_species( session: AsyncSession = Depends(get_session) ): - rows = await get_tree_by_species(session) response = jsonable_encoder(rows) try: - return JSONResponse(content=response[0]) + return JSONResponse(content=response) except IndexError: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail='Not found' ) - \ No newline at end of file diff --git a/app/services/tree.py b/app/services/tree.py index 2fdf90a..f8d2217 100755 --- a/app/services/tree.py +++ b/app/services/tree.py @@ -1,4 +1,5 @@ from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.sql import text from sqlmodel import select from app.models.tree import StreetTreeRegister @@ -45,4 +46,4 @@ async def get_tree_by_species(session: AsyncSession): result = await session.execute(stmt) rows = result.mappings().all() - return [dict(row) for row in rows] \ No newline at end of file + return [dict(row) for row in rows] From ea92747ed56300986bef652cc164604e7e4a8a49 Mon Sep 17 00:00:00 2001 From: sonnenteich Date: Fri, 4 Jul 2025 21:46:20 +0200 Subject: [PATCH 4/4] fixed methode name --- app/api/tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/tree.py b/app/api/tree.py index 0575fdd..54ea4b3 100755 --- a/app/api/tree.py +++ b/app/api/tree.py @@ -85,7 +85,7 @@ async def fetch_tree_by_id( tags=['Strassenbaeume'], description='Retrieves street tree details based there species.' ) -async def get_tree_by_species( +async def fetch_tree_by_species( session: AsyncSession = Depends(get_session) ): rows = await get_tree_by_species(session)