Add V1 selected area map overlay
GeoIntel CI / docs-smoke (push) Has been cancelled
GeoIntel CI / contract-smoke (push) Has been cancelled

This commit is contained in:
Codex
2026-06-17 00:21:01 +02:00
parent 97be9d9293
commit 47cd2c6c1e
12 changed files with 315 additions and 21 deletions
+5 -5
View File
@@ -8,7 +8,7 @@ from sqlalchemy.orm import Session
from app.db.session import get_db
from app.models import Area
from app.schemas.area import AreaCreate, AreaRead, AreaUpdate
from app.schemas.area import AreaCreate, AreaUpdate
from app.services.area_service import AreaService
from app.utils.response import envelope
@@ -23,13 +23,13 @@ def list_areas(
db: Session = Depends(get_db),
):
areas, total = AreaService.list_areas(db, project_id=project_id, limit=limit, offset=offset)
return envelope({"items": [AreaRead.model_validate(area).model_dump() for area in areas], "total": total, "limit": limit, "offset": offset})
return envelope({"items": [AreaService.serialize_area(area) for area in areas], "total": total, "limit": limit, "offset": offset})
@router.post("", status_code=201, response_model=dict)
def create_area(project_id: UUID, payload: AreaCreate, db: Session = Depends(get_db)):
area = AreaService.create_area(db, project_id, payload)
return envelope(AreaRead.model_validate(area).model_dump())
return envelope(AreaService.serialize_area(area))
@router.get("/{area_id}", response_model=dict)
@@ -41,7 +41,7 @@ def get_area(
area = AreaService.get_area(db, area_id)
if area.project_id != project_id:
raise HTTPException(status_code=404, detail="Area not found")
return envelope(AreaRead.model_validate(area).model_dump())
return envelope(AreaService.serialize_area(area))
@router.patch("/{area_id}", response_model=dict)
@@ -55,4 +55,4 @@ def update_area(
if not existing or existing.project_id != project_id:
raise HTTPException(status_code=404, detail="Area not found")
area = AreaService.update_area(db, area_id, payload)
return envelope(AreaRead.model_validate(area).model_dump())
return envelope(AreaService.serialize_area(area))
+16 -9
View File
@@ -3,7 +3,8 @@ from __future__ import annotations
import uuid
from sqlalchemy.orm import Session
from geoalchemy2.shape import from_shape
from geoalchemy2.shape import from_shape, to_shape
from shapely.geometry import mapping
from app.core.errors import AppError
from app.models import Area, Project
@@ -13,7 +14,13 @@ from app.utils.geometry import area_m2, geometry_bbox_polygon, normalize_to_mult
class AreaService:
@staticmethod
def list_areas(db: Session, project_id: uuid.UUID, limit: int = 50, offset: int = 0) -> tuple[list[AreaRead], int]:
def serialize_area(area: Area) -> dict:
payload = AreaRead.model_validate(area).model_dump()
payload["geometry"] = mapping(to_shape(area.geometry)) if area.geometry else None
return payload
@staticmethod
def list_areas(db: Session, project_id: uuid.UUID, limit: int = 50, offset: int = 0) -> tuple[list[Area], int]:
total = db.query(Area).filter(Area.project_id == project_id).count()
areas = (
db.query(Area)
@@ -23,10 +30,10 @@ class AreaService:
.limit(limit)
.all()
)
return [AreaRead.model_validate(area) for area in areas], total
return areas, total
@staticmethod
def create_area(db: Session, project_id: uuid.UUID, payload: AreaCreate) -> AreaRead:
def create_area(db: Session, project_id: uuid.UUID, payload: AreaCreate) -> Area:
if not db.get(Project, project_id):
raise AppError(code="PROJECT_NOT_FOUND", message="Project not found", status_code=404)
@@ -46,17 +53,17 @@ class AreaService:
db.add(area)
db.commit()
db.refresh(area)
return AreaRead.model_validate(area)
return area
@staticmethod
def get_area(db: Session, area_id: uuid.UUID) -> AreaRead:
def get_area(db: Session, area_id: uuid.UUID) -> Area:
area = db.get(Area, area_id)
if not area:
raise AppError(code="AREA_NOT_FOUND", message="Area not found", status_code=404)
return AreaRead.model_validate(area)
return area
@staticmethod
def update_area(db: Session, area_id: uuid.UUID, payload: AreaUpdate) -> AreaRead:
def update_area(db: Session, area_id: uuid.UUID, payload: AreaUpdate) -> Area:
area = db.get(Area, area_id)
if not area:
raise AppError(code="AREA_NOT_FOUND", message="Area not found", status_code=404)
@@ -74,4 +81,4 @@ class AreaService:
db.add(area)
db.commit()
db.refresh(area)
return AreaRead.model_validate(area)
return area