Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
13 changes: 13 additions & 0 deletions offsets_db_api/geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ def get_bboxes_for_projects(project_ids: list[str]) -> dict[str, dict[str, float
return {pid: bbox_lookup[pid] for pid in project_ids if pid in bbox_lookup}


def get_projects_with_geometry() -> set[str]:
"""
Get the set of project IDs that have geographic boundaries.

Returns
-------
set
Set of project IDs that have boundaries
"""
bbox_lookup = load_project_bboxes()
return set(bbox_lookup.keys())


def clear_bbox_cache():
"""Clear the cached bbox data to force a reload."""
load_project_bboxes.cache_clear()
Expand Down
10 changes: 10 additions & 0 deletions offsets_db_api/routers/credits.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from offsets_db_api.cache import CACHE_NAMESPACE
from offsets_db_api.common import build_filters
from offsets_db_api.database import get_session
from offsets_db_api.geo import get_projects_with_geometry
from offsets_db_api.log import get_logger
from offsets_db_api.models import Credit, PaginatedCredits, Project
from offsets_db_api.schemas import (
Expand Down Expand Up @@ -36,6 +37,10 @@ async def get_credits(
project_filters: ProjectFilters = Depends(get_project_filters),
credit_filters: CreditFilters = Depends(get_credit_filters),
beneficiary_filters: BeneficiaryFilters = Depends(get_beneficiary_filters),
geography: bool = Query(
False,
description='Filter to only include credits from projects that have geographic boundaries.',
),
sort: list[str] = Query(
default=['project_id'],
description='List of sorting parameters in the format `field_name` or `+field_name` for ascending order or `-field_name` for descending order.',
Expand All @@ -59,6 +64,11 @@ async def get_credits(
if project_id:
filters.insert(0, ('project_id', project_id, '==', Project))

# Filter to only credits from projects with geographic boundaries
if geography:
projects_with_geo = get_projects_with_geometry()
statement = statement.where(col(Project.project_id).in_(projects_with_geo))

for attribute, values, operation, model in filters:
statement = apply_filters(
statement=statement,
Expand Down
15 changes: 14 additions & 1 deletion offsets_db_api/routers/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
from offsets_db_api.cache import CACHE_NAMESPACE
from offsets_db_api.common import build_filters
from offsets_db_api.database import get_session
from offsets_db_api.geo import get_bbox_for_project, get_bboxes_for_projects
from offsets_db_api.geo import (
get_bbox_for_project,
get_bboxes_for_projects,
get_projects_with_geometry,
)
from offsets_db_api.log import get_logger
from offsets_db_api.models import (
Clip,
Expand Down Expand Up @@ -65,6 +69,10 @@ async def get_projects(
description='Case insensitive search string. Currently searches on `project_id` and `name` fields only.',
),
beneficiary_filters: BeneficiaryFilters = Depends(get_beneficiary_filters),
geography: bool = Query(
False,
description='Filter to only include projects that have geographic boundaries.',
),
current_page: int = Query(1, description='Page number', ge=1),
per_page: int = Query(100, description='Items per page', le=200, ge=1),
sort: list[str] = Query(
Expand All @@ -84,6 +92,11 @@ async def get_projects(

filters = build_filters(project_filters=project_filters)

# Filter to only projects with geographic boundaries
if geography:
projects_with_geo = get_projects_with_geometry()
matching_projects = matching_projects.where(col(Project.project_id).in_(projects_with_geo))

if search:
search_pattern = f'%{search}%'
matching_projects = matching_projects.where(
Expand Down
Loading