From ab9ef842da93142dcb8d359441dd5be8d1909753 Mon Sep 17 00:00:00 2001 From: marthevienne <123016211+marthevienne@users.noreply.github.com> Date: Fri, 13 Dec 2024 18:40:41 +0100 Subject: [PATCH] feat #204: global endpoints for dashboard rankings --- backend/bloom/domain/metrics.py | 4 +- backend/bloom/routers/v1/metrics.py | 29 ++++++++-- backend/bloom/services/metrics.py | 86 +++++++++++++++++++++++------ 3 files changed, 97 insertions(+), 22 deletions(-) diff --git a/backend/bloom/domain/metrics.py b/backend/bloom/domain/metrics.py index 133c5d75..c7294177 100644 --- a/backend/bloom/domain/metrics.py +++ b/backend/bloom/domain/metrics.py @@ -39,10 +39,10 @@ class ResponseMetricsVesselInActivitySchema(BaseModel): vessel: VesselListView total_time_at_sea: Optional[timedelta] -class ResponseMetricsVesselInMpasSchema(BaseModel): +class ResponseMetricsVesselInZonesSchema(BaseModel): model_config = ConfigDict(from_attributes=True) vessel: VesselListView - total_time_in_mpas: Optional[timedelta] + total_time_in_zones: Optional[timedelta] class ResponseMetricsZoneVisitedSchema(BaseModel): zone: ZoneListView diff --git a/backend/bloom/routers/v1/metrics.py b/backend/bloom/routers/v1/metrics.py index 1b5566bc..b86827e4 100644 --- a/backend/bloom/routers/v1/metrics.py +++ b/backend/bloom/routers/v1/metrics.py @@ -125,11 +125,12 @@ async def read_metrics_all_vessels_visiting_time_by_zone(request: Request, return jsonable_encoder(payload) -@router.get("/metrics/vessels/activity-in-mpas") +@router.get("/metrics/vessels-activity/{category}") # @cache -async def read_metrics_all_vessels_visiting_time_in_mpas( +async def read_metrics_all_vessels_visiting_time_in_zones( request: Request, datetime_range: DatetimeRangeRequest = Depends(), + category: Optional[str] = None, pagination: PageParams = Depends(), order: OrderByRequest = Depends(), key: str = Depends(X_API_KEY_HEADER), @@ -137,9 +138,29 @@ async def read_metrics_all_vessels_visiting_time_in_mpas( check_apikey(key) use_cases = UseCases() MetricsService = use_cases.metrics_service() - payload = MetricsService.get_vessels_in_mpas( + payload = MetricsService.get_vessels_activity_in_zones( datetime_range=datetime_range, pagination=pagination, - order=order + order=order, + category=category, + ) + return jsonable_encoder(payload) + + +@router.get("/metrics/zones-visited/{category}") +# @cache +async def read_metrics_all_zones_visited( + request: Request, + datetime_range: DatetimeRangeRequest = Depends(), + category: Optional[str] = None, + pagination: PageParams = Depends(), + order: OrderByRequest = Depends(), + key: str = Depends(X_API_KEY_HEADER), +): + check_apikey(key) + use_cases = UseCases() + MetricsService = use_cases.metrics_service() + payload = MetricsService.get_zones_visited( + datetime_range=datetime_range, pagination=pagination, order=order, category=category ) return jsonable_encoder(payload) diff --git a/backend/bloom/services/metrics.py b/backend/bloom/services/metrics.py index 6279d94c..b9d11351 100644 --- a/backend/bloom/services/metrics.py +++ b/backend/bloom/services/metrics.py @@ -16,12 +16,14 @@ from bloom.infra.repositories.repository_zone import ZoneRepository from bloom.domain.metrics import TotalTimeActivityTypeRequest -from bloom.domain.metrics import (ResponseMetricsVesselInActivitySchema, - ResponseMetricsZoneVisitedSchema, - ResponseMetricsVesselInMpasSchema, - ResponseMetricsZoneVisitingTimeByVesselSchema, - ResponseMetricsVesselTotalTimeActivityByActivityTypeSchema, - ResponseMetricsVesselVisitingTimeByZoneSchema) +from bloom.domain.metrics import ( + ResponseMetricsVesselInActivitySchema, + ResponseMetricsZoneVisitedSchema, + ResponseMetricsVesselInZonesSchema, + ResponseMetricsZoneVisitingTimeByVesselSchema, + ResponseMetricsVesselTotalTimeActivityByActivityTypeSchema, + ResponseMetricsVesselVisitingTimeByZoneSchema, +) class MetricsService(): def __init__( @@ -74,17 +76,20 @@ def getVesselsInActivity(self, )\ for item in payload] - def get_vessels_in_mpas(self, - datetime_range: DatetimeRangeRequest, - pagination: PageParams, - order: OrderByRequest): + def get_vessels_activity_in_zones( + self, + datetime_range: DatetimeRangeRequest, + pagination: PageParams, + order: OrderByRequest, + category: Optional[str] = None, + ): payload=[] with self.session_factory() as session: stmt = ( select( sql_model.Vessel, func.sum(sql_model.Metrics.duration_total).label( - "total_time_in_mpas" + "total_time_in_zones" ), ) .select_from(sql_model.Metrics) @@ -97,22 +102,71 @@ def get_vessels_in_mpas(self, datetime_range.start_at, datetime_range.end_at ) ) - .where(sql_model.Metrics.zone_category == "amp") .group_by(sql_model.Vessel) ) stmt = stmt.offset(pagination.offset) if pagination.offset != None else stmt + if category: + stmt = stmt.where(sql_model.Zone.category == category) stmt = ( - stmt.order_by(asc("total_time_in_mpas")) + stmt.order_by(asc("total_time_in_zones")) if order.order == OrderByEnum.ascending - else stmt.order_by(desc("total_time_in_mpas")) + else stmt.order_by(desc("total_time_in_zones")) ) stmt = stmt.limit(pagination.limit) if pagination.limit != None else stmt payload=session.execute(stmt).all() return [ - ResponseMetricsVesselInMpasSchema( + ResponseMetricsVesselInZonesSchema( vessel=VesselRepository.map_to_domain(item[0]).model_dump(), - total_time_in_mpas=item[1], + total_time_in_zones=item[1], + ) + for item in payload + ] + + def get_zones_visited( + self, + datetime_range: DatetimeRangeRequest, + pagination: PageParams, + order: OrderByRequest, + category: Optional[str] = None, + ): + payload = [] + with self.session_factory() as session: + stmt = ( + select( + sql_model.Zone, + func.sum(sql_model.Metrics.duration_total).label( + "visiting_duration" + ), + ) + .select_from(sql_model.Metrics) + .join( + sql_model.Zone, + sql_model.Zone.id == sql_model.Metrics.zone_id, + ) + .where( + sql_model.Metrics.timestamp.between( + datetime_range.start_at, datetime_range.end_at + ) + ) + .where(sql_model.Metrics.zone_category == category) + .group_by(sql_model.Zone) + ) + stmt = stmt.offset(pagination.offset) if pagination.offset != None else stmt + if category: + stmt = stmt.where(sql_model.Zone.category == category) + stmt = ( + stmt.order_by(asc("visiting_duration")) + if order.order == OrderByEnum.ascending + else stmt.order_by(desc("visiting_duration")) + ) + stmt = stmt.limit(pagination.limit) if pagination.limit != None else stmt + payload = session.execute(stmt).all() + + return [ + ResponseMetricsZoneVisitedSchema( + zone=ZoneRepository.map_to_domain(item[0]).model_dump(), + visiting_duration=item[1], ) for item in payload ]