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

PR HDX-9844 national risk endpoint #101

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
87 changes: 42 additions & 45 deletions hdx_hapi/db/dao/national_risk_view_dao.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we see location here because this dataset does not use admin1 and admin2

Original file line number Diff line number Diff line change
@@ -1,68 +1,65 @@
import datetime
from typing import Optional

from hapi_schema.utils.enums import RiskClass
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select

from hdx_hapi.db.models.views.db_national_risk_view import NationalRiskView
from hdx_hapi.db.dao.util.util import apply_pagination, case_insensitive_filter
from hdx_hapi.endpoints.util.util import PaginationParams

from hdx_hapi.db.models.views.all_views import NationalRiskView
from hdx_hapi.db.dao.util.util import apply_pagination, apply_reference_period_filter, case_insensitive_filter
from hdx_hapi.endpoints.util.util import PaginationParams, ReferencePeriodParameters


async def national_risks_view_list(
pagination_parameters: PaginationParams,
ref_period_parameters: ReferencePeriodParameters,
db: AsyncSession,
risk_class: int = None,
global_rank: int = None,
overall_risk: float = None,
hazard_exposure_risk: float = None,
vulnerability_risk: float = None,
coping_capacity_risk: float = None,
dataset_hdx_provider_stub: str = None,
resource_update_date_min: datetime = None,
resource_update_date_max: datetime = None,
hapi_updated_date_min: datetime = None,
hapi_updated_date_max: datetime = None,
hapi_replaced_date_min: datetime = None,
hapi_replaced_date_max: datetime = None,
# sector_name: str = None,
location_code: str = None,
location_name: str = None,
risk_class: Optional[RiskClass] = None,
global_rank_min: Optional[int] = None,
global_rank_max: Optional[int] = None,
overall_risk_min: Optional[float] = None,
overall_risk_max: Optional[float] = None,
hazard_exposure_risk_min: Optional[float] = None,
hazard_exposure_risk_max: Optional[float] = None,
vulnerability_risk_min: Optional[float] = None,
vulnerability_risk_max: Optional[float] = None,
coping_capacity_risk_min: Optional[float] = None,
coping_capacity_risk_max: Optional[float] = None,
location_code: Optional[str] = None,
location_name: Optional[str] = None,
):
query = select(NationalRiskView)
if risk_class:
query = query.where(NationalRiskView.risk_class == risk_class)
if global_rank:
query = query.where(NationalRiskView.global_rank == global_rank)
if overall_risk:
query = query.where(NationalRiskView.overall_risk == overall_risk)
if hazard_exposure_risk:
query = query.where(NationalRiskView.hazard_exposure_risk == hazard_exposure_risk)
if vulnerability_risk:
query = query.where(NationalRiskView.vulnerability_risk == vulnerability_risk)
if coping_capacity_risk:
query = query.where(NationalRiskView.coping_capacity_risk == coping_capacity_risk)
if dataset_hdx_provider_stub:
query = case_insensitive_filter(query, NationalRiskView.dataset_hdx_provider_stub, dataset_hdx_provider_stub)
if resource_update_date_min:
query = query.where(NationalRiskView.resource_update_date >= resource_update_date_min)
if resource_update_date_max:
query = query.where(NationalRiskView.resource_update_date < resource_update_date_max)
if hapi_updated_date_min:
query = query.where(NationalRiskView.hapi_updated_date >= hapi_updated_date_min)
if hapi_updated_date_max:
query = query.where(NationalRiskView.hapi_updated_date < hapi_updated_date_max)
if hapi_replaced_date_min:
query = query.where(NationalRiskView.hapi_replaced_date >= hapi_replaced_date_min)
if hapi_replaced_date_max:
query = query.where(NationalRiskView.hapi_replaced_date < hapi_replaced_date_max)
if global_rank_min:
query = query.where(NationalRiskView.global_rank >= global_rank_min)
if global_rank_max:
query = query.where(NationalRiskView.global_rank < global_rank_max)
if overall_risk_min:
query = query.where(NationalRiskView.overall_risk >= overall_risk_min)
if overall_risk_max:
query = query.where(NationalRiskView.overall_risk < overall_risk_max)
if hazard_exposure_risk_min:
query = query.where(NationalRiskView.hazard_exposure_risk >= hazard_exposure_risk_min)
if hazard_exposure_risk_max:
query = query.where(NationalRiskView.hazard_exposure_risk < hazard_exposure_risk_max)
if vulnerability_risk_min:
query = query.where(NationalRiskView.vulnerability_risk >= vulnerability_risk_min)
if vulnerability_risk_max:
query = query.where(NationalRiskView.vulnerability_risk < vulnerability_risk_max)
if coping_capacity_risk_min:
query = query.where(NationalRiskView.coping_capacity_risk >= coping_capacity_risk_min)
if coping_capacity_risk_max:
query = query.where(NationalRiskView.coping_capacity_risk < coping_capacity_risk_max)

# if sector_name:
# query = query.where(NationalRiskView.sector_name.icontains(sector_name))
if location_code:
query = case_insensitive_filter(query, NationalRiskView.location_code, location_code)
if location_name:
query = query.where(NationalRiskView.location_name.icontains(location_name))

query = apply_reference_period_filter(query, ref_period_parameters, NationalRiskView)

query = apply_pagination(query, pagination_parameters)

result = await db.execute(query)
Expand Down
3 changes: 2 additions & 1 deletion hdx_hapi/db/models/views/all_views.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to make sure the generated views for hdx-class use the enums we see here (RiskClass)

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This code was generated automatically using src/hapi_schema/utils/hapi_views_code_generator.py
"""

from hapi_schema.utils.enums import RiskClass
from sqlalchemy import DateTime
from sqlalchemy.orm import column_property, Mapped
from hdx_hapi.db.models.views.util.util import view
Expand Down Expand Up @@ -189,7 +190,7 @@ class NationalRiskView(Base):
__table__ = national_risk_view
resource_hdx_id: Mapped[str] = column_property(national_risk_view.c.resource_hdx_id)
location_ref: Mapped[int] = column_property(national_risk_view.c.location_ref)
risk_class: Mapped[str] = column_property(national_risk_view.c.risk_class)
risk_class: Mapped[RiskClass] = column_property(national_risk_view.c.risk_class)
global_rank: Mapped[int] = column_property(national_risk_view.c.global_rank)
overall_risk: Mapped[float] = column_property(national_risk_view.c.overall_risk)
hazard_exposure_risk: Mapped[float] = column_property(national_risk_view.c.hazard_exposure_risk)
Expand Down
96 changes: 38 additions & 58 deletions hdx_hapi/endpoints/get_national_risk.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering whether we should remove the un-versioned roots - they don't represent compatibility with the legacy version. The only reason to keep them is for a route to the "latest" version.

Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
from datetime import date
from typing import Annotated
from typing import Annotated, Optional
from fastapi import Depends, Query, APIRouter
from pydantic import NaiveDatetime
from hapi_schema.utils.enums import RiskClass


from sqlalchemy.ext.asyncio import AsyncSession

from hdx_hapi.config.doc_snippets import (
DOC_HDX_PROVIDER_STUB,
DOC_LOCATION_CODE,
DOC_LOCATION_NAME,
DOC_SEE_LOC,
DOC_UPDATE_DATE_MAX,
DOC_UPDATE_DATE_MIN,
DOC_HAPI_UPDATED_DATE_MIN,
DOC_HAPI_UPDATED_DATE_MAX,
DOC_HAPI_REPLACED_DATE_MIN,
DOC_HAPI_REPLACED_DATE_MAX,
)

from hdx_hapi.endpoints.models.base import HapiGenericResponse
from hdx_hapi.endpoints.models.national_risk import NationalRiskResponse
from hdx_hapi.endpoints.util.util import CommonEndpointParams, OutputFormat, common_endpoint_parameters
from hdx_hapi.endpoints.util.util import (
CommonEndpointParams,
OutputFormat,
ReferencePeriodParameters,
common_endpoint_parameters,
reference_period_parameters,
)
from hdx_hapi.services.csv_transform_logic import transform_result_to_csv_stream_if_requested
from hdx_hapi.services.national_risk_logic import get_national_risks_srv
from hdx_hapi.services.sql_alchemy_session import get_db
Expand All @@ -32,75 +30,57 @@


@router.get(
'/api/themes/national_risk',
'/api/coordination-context/national-risk',
response_model=HapiGenericResponse[NationalRiskResponse],
summary='Get national risk data',
include_in_schema=False,
)
@router.get(
'/api/v1/themes/national_risk',
'/api/v1/coordination-context/national-risk',
response_model=HapiGenericResponse[NationalRiskResponse],
summary='Get national risk data',
)
async def get_national_risks(
ref_period_parameters: Annotated[ReferencePeriodParameters, Depends(reference_period_parameters)],
common_parameters: Annotated[CommonEndpointParams, Depends(common_endpoint_parameters)],
db: AsyncSession = Depends(get_db),
risk_class: Annotated[int, Query(description='Risk class')] = None,
global_rank: Annotated[int, Query(description='Global rank')] = None,
overall_risk: Annotated[float, Query(description='Overall risk')] = None,
hazard_exposure_risk: Annotated[float, Query(description='Hazard exposure risk')] = None,
vulnerability_risk: Annotated[float, Query(description='Vulnerability risk')] = None,
coping_capacity_risk: Annotated[float, Query(description='Coping capacity risk')] = None,
dataset_hdx_provider_stub: Annotated[str, Query(max_length=128, description=f'{DOC_HDX_PROVIDER_STUB}')] = None,
resource_update_date_min: Annotated[
NaiveDatetime | date,
Query(description=f'{DOC_UPDATE_DATE_MIN}', openapi_examples={'2020-01-01': {'value': '2020-01-01'}}),
] = None,
resource_update_date_max: Annotated[
NaiveDatetime | date,
Query(description=f'{DOC_UPDATE_DATE_MAX}', openapi_examples={'2024-12-31': {'value': '2024-12-31'}}),
] = None,
hapi_updated_date_min: Annotated[
NaiveDatetime | date,
Query(description=f'{DOC_HAPI_UPDATED_DATE_MIN}'),
] = None,
hapi_updated_date_max: Annotated[
NaiveDatetime | date,
Query(description=f'{DOC_HAPI_UPDATED_DATE_MAX}'),
] = None,
hapi_replaced_date_min: Annotated[
NaiveDatetime | date,
Query(description=f'{DOC_HAPI_REPLACED_DATE_MIN}'),
risk_class: Annotated[Optional[RiskClass], Query(description='Risk class')] = None,
global_rank_min: Annotated[Optional[int], Query(description='Global rank, lower bound')] = None,
global_rank_max: Annotated[Optional[int], Query(description='Global rank, upper bound')] = None,
overall_risk_min: Annotated[Optional[float], Query(description='Overall risk, lower bound')] = None,
overall_risk_max: Annotated[Optional[float], Query(description='Overall risk, upper bound')] = None,
hazard_exposure_risk_min: Annotated[Optional[float], Query(description='Hazard exposure risk, lower bound')] = None,
hazard_exposure_risk_max: Annotated[Optional[float], Query(description='Hazard exposure risk, upper bound')] = None,
vulnerability_risk_min: Annotated[Optional[float], Query(description='Vulnerability risk, lower bound')] = None,
vulnerability_risk_max: Annotated[Optional[float], Query(description='Vulnerability risk, upper bound')] = None,
coping_capacity_risk_min: Annotated[Optional[float], Query(description='Coping capacity risk, lower bound')] = None,
coping_capacity_risk_max: Annotated[Optional[float], Query(description='Coping capacity risk, upper bound')] = None,
location_code: Annotated[
Optional[str], Query(max_length=128, description=f'{DOC_LOCATION_CODE} {DOC_SEE_LOC}')
] = None,
hapi_replaced_date_max: Annotated[
NaiveDatetime | date,
Query(description=f'{DOC_HAPI_REPLACED_DATE_MAX}'),
location_name: Annotated[
Optional[str], Query(max_length=512, description=f'{DOC_LOCATION_NAME} {DOC_SEE_LOC}')
] = None,
# sector_name: Annotated[str, Query(max_length=512, description=f'{DOC_SECTOR_NAME}')] = None,
location_code: Annotated[str, Query(max_length=128, description=f'{DOC_LOCATION_CODE} {DOC_SEE_LOC}')] = None,
location_name: Annotated[str, Query(max_length=512, description=f'{DOC_LOCATION_NAME} {DOC_SEE_LOC}')] = None,
output_format: OutputFormat = OutputFormat.JSON,
):
"""
Return the list of national risks
"""
result = await get_national_risks_srv(
pagination_parameters=common_parameters,
ref_period_parameters=ref_period_parameters,
db=db,
risk_class=risk_class,
global_rank=global_rank,
overall_risk=overall_risk,
hazard_exposure_risk=hazard_exposure_risk,
vulnerability_risk=vulnerability_risk,
coping_capacity_risk=coping_capacity_risk,
dataset_hdx_provider_stub=dataset_hdx_provider_stub,
resource_update_date_min=resource_update_date_min,
resource_update_date_max=resource_update_date_max,
hapi_updated_date_min=hapi_updated_date_min,
hapi_updated_date_max=hapi_updated_date_max,
hapi_replaced_date_min=hapi_replaced_date_min,
hapi_replaced_date_max=hapi_replaced_date_max,
# sector_name=sector_name,
global_rank_min=global_rank_min,
global_rank_max=global_rank_max,
overall_risk_min=overall_risk_min,
overall_risk_max=overall_risk_max,
hazard_exposure_risk_min=hazard_exposure_risk_min,
hazard_exposure_risk_max=hazard_exposure_risk_max,
vulnerability_risk_min=vulnerability_risk_min,
vulnerability_risk_max=vulnerability_risk_max,
coping_capacity_risk_min=coping_capacity_risk_min,
coping_capacity_risk_max=coping_capacity_risk_max,
location_code=location_code,
location_name=location_name,
)
Expand Down
29 changes: 16 additions & 13 deletions hdx_hapi/endpoints/models/national_risk.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
from datetime import datetime
from hapi_schema.utils.enums import RiskClass
from pydantic import ConfigDict, Field, NaiveDatetime
from typing import Optional

from hdx_hapi.endpoints.models.base import HapiBaseModel
from hdx_hapi.endpoints.models.util.constants import PERCENTAGE_TYPE

RISK_TYPE = Field(ge=0, le=10)


class NationalRiskResponse(HapiBaseModel):
risk_class: int
global_rank: int
overall_risk: float
hazard_exposure_risk: float
vulnerability_risk: float
coping_capacity_risk: float
risk_class: RiskClass
global_rank: int = Field(ge=1, le=250)
overall_risk: float = RISK_TYPE
hazard_exposure_risk: float = RISK_TYPE
vulnerability_risk: float = RISK_TYPE
coping_capacity_risk: float = RISK_TYPE

meta_missing_indicators_pct: Optional[float] = None
meta_avg_recentness_years: Optional[float] = None
meta_missing_indicators_pct: Optional[float] = PERCENTAGE_TYPE
meta_avg_recentness_years: Optional[float] = Field(ge=0)

reference_period_start: Optional[NaiveDatetime]
reference_period_end: Optional[NaiveDatetime]

dataset_hdx_stub: str = Field(max_length=128)
dataset_hdx_provider_stub: str = Field(max_length=128)
# dataset_hdx_stub: str = Field(max_length=128)
# dataset_hdx_provider_stub: str = Field(max_length=128)
resource_hdx_id: str = Field(max_length=36)
hapi_updated_date: datetime
hapi_replaced_date: Optional[datetime]
# hapi_updated_date: datetime
# hapi_replaced_date: Optional[datetime]

# sector_name: str = Field(max_length=512)

Expand Down
Empty file.
4 changes: 4 additions & 0 deletions hdx_hapi/endpoints/models/util/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from pydantic import Field


PERCENTAGE_TYPE = Field(ge=0, le=100)
59 changes: 28 additions & 31 deletions hdx_hapi/services/national_risk_logic.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must admit I don't like this pattern of having a "srv" function which does nothing but call the "view_list" function with all its arguments. I guess it gives us a place to change / modify arguments between user and query logic.

Original file line number Diff line number Diff line change
@@ -1,48 +1,45 @@
from datetime import datetime
from typing import Optional

from hapi_schema.utils.enums import RiskClass
from sqlalchemy.ext.asyncio import AsyncSession

from hdx_hapi.db.dao.national_risk_view_dao import national_risks_view_list
from hdx_hapi.endpoints.util.util import PaginationParams
from hdx_hapi.endpoints.util.util import PaginationParams, ReferencePeriodParameters


async def get_national_risks_srv(
pagination_parameters: PaginationParams,
ref_period_parameters: ReferencePeriodParameters,
db: AsyncSession,
risk_class: int = None,
global_rank: int = None,
overall_risk: float = None,
hazard_exposure_risk: float = None,
vulnerability_risk: float = None,
coping_capacity_risk: float = None,
dataset_hdx_provider_stub: str = None,
resource_update_date_min=None,
resource_update_date_max=None,
hapi_updated_date_min: datetime = None,
hapi_updated_date_max: datetime = None,
hapi_replaced_date_min: datetime = None,
hapi_replaced_date_max: datetime = None,
# sector_name: str = None,
location_code: str = None,
location_name: str = None,
risk_class: Optional[RiskClass] = None,
global_rank_min: Optional[int] = None,
global_rank_max: Optional[int] = None,
overall_risk_min: Optional[float] = None,
overall_risk_max: Optional[float] = None,
hazard_exposure_risk_min: Optional[float] = None,
hazard_exposure_risk_max: Optional[float] = None,
vulnerability_risk_min: Optional[float] = None,
vulnerability_risk_max: Optional[float] = None,
coping_capacity_risk_min: Optional[float] = None,
coping_capacity_risk_max: Optional[float] = None,
location_code: Optional[str] = None,
location_name: Optional[str] = None,
):
return await national_risks_view_list(
pagination_parameters=pagination_parameters,
ref_period_parameters=ref_period_parameters,
db=db,
risk_class=risk_class,
global_rank=global_rank,
overall_risk=overall_risk,
hazard_exposure_risk=hazard_exposure_risk,
vulnerability_risk=vulnerability_risk,
coping_capacity_risk=coping_capacity_risk,
dataset_hdx_provider_stub=dataset_hdx_provider_stub,
resource_update_date_min=resource_update_date_min,
resource_update_date_max=resource_update_date_max,
hapi_updated_date_min=hapi_updated_date_min,
hapi_updated_date_max=hapi_updated_date_max,
hapi_replaced_date_min=hapi_replaced_date_min,
hapi_replaced_date_max=hapi_replaced_date_max,
# sector_name=sector_name,
global_rank_min=global_rank_min,
global_rank_max=global_rank_max,
overall_risk_min=overall_risk_min,
overall_risk_max=overall_risk_max,
hazard_exposure_risk_min=hazard_exposure_risk_min,
hazard_exposure_risk_max=hazard_exposure_risk_max,
vulnerability_risk_min=vulnerability_risk_min,
vulnerability_risk_max=vulnerability_risk_max,
coping_capacity_risk_min=coping_capacity_risk_min,
coping_capacity_risk_max=coping_capacity_risk_max,
location_code=location_code,
location_name=location_name,
)
Loading
Loading