# FastApi imports # Pydantic imports from datetime import datetime, timedelta from typing import List from fastapi import APIRouter, Depends, HTTPException # Sqlalchemy imports from sqlalchemy.orm import Session from starlette.responses import Response # My imports from config.settings import DECIMAL_PLACES from cruds.companies import get_company_by_id from cruds.fincas import get_finca_by_station_code, get_fincas_filter_company from database.sqlalchemy import get_db from routes.calculations.degrees_accumulated import monthly_avr_day_degrees from routes.calculations.gnral_summary import general_summary from routes.calculations.montly_precip import montly_precipitations from routes.login import get_current_user from schemas.tables import ( DegreesAccumulatedAvgMonth as DegreesAccumulatedAvgMonthSchema, ) from schemas.tables import MonthlyPrecipitations as MonthlyPrecipitationsSchema from schemas.tables import Summary as SummarySchema from schemas.tables import SummarySeason as SummarySeasonSchema from schemas.users import User as UserSchema router = APIRouter() # Futuro Decorator def check_daytimes_order(start_datetime, end_datetime): """Verifico que end_datetime sea despues que start_datetime""" if start_datetime > end_datetime: raise HTTPException( status_code=400, detail="start_datetime es mas grande que end_datetime", ) """Verifico que el diff no supere una temporada (240 dias aprox)""" delta = end_datetime - start_datetime if delta.days > 240: raise HTTPException( status_code=400, detail="El rango de fechas pedido supera la cantidad de dias de una temporada", ) # Futuro Decorator def finca_exists(db, station_code): """Verifico que la estacion exista""" if get_finca_by_station_code(db, station_code) == None: raise HTTPException( status_code=400, detail="ingrese un station_code valido", ) def has_finca_access(db, finca, user): if finca in get_fincas_filter_company(db, user.company_id): return True else: raise HTTPException( status_code=401, detail="no tienes acceso a esta finca", ) @router.get("/station/all/summary", response_model=List[SummarySchema]) async def get_fincas_summaries( start_datetime: datetime, end_datetime: datetime, db: Session = Depends(get_db), current_user: UserSchema = Depends(get_current_user), ) -> Response: check_daytimes_order(start_datetime, end_datetime) fincas = get_fincas_filter_company(db, current_user.company_id) response = [] for finca in fincas: response.append(general_summary(finca, start_datetime, end_datetime)) return response @router.get("/station/{station_code}/summary", response_model=List[SummarySeasonSchema]) async def get_finca_summary( start_datetime: datetime, end_datetime: datetime, station_code: str, db: Session = Depends(get_db), current_user: UserSchema = Depends(get_current_user), ) -> Response: finca_exists(db, station_code) check_daytimes_order(start_datetime, end_datetime) finca = get_finca_by_station_code(db, station_code) has_finca_access(db, finca, current_user) response = [] for i in range(5): new_start_date = start_datetime.replace(year=(start_datetime.year - i)) new_end_date = end_datetime.replace(year=(end_datetime.year - i)) summary = general_summary(finca, new_start_date, new_end_date) # REVIEW: Should write a new from_parent constructor summary_season = SummarySeasonSchema( station=summary.station, initial_date=summary.initial_date, final_date=summary.final_date, lt10=summary.lt10, gt30=summary.gt30, gt33=summary.gt33, grados_acumulados=summary.grados_acumulados, grados_acumulados_promedio=summary.grados_acumulados_promedio, amplitud_termica=summary.amplitud_termica, precip_acumulada=summary.precip_acumulada, data_percentage=summary.data_percentage, ) if i == 0: summary_season.dias_igualar_temporada = 0 else: this_camp_deg_acc = response[0].grados_acumulados this_camp_deg_acc_avg = response[0].grados_acumulados_promedio if ( this_camp_deg_acc and this_camp_deg_acc_avg and summary_season.grados_acumulados ) is not None: summary_season.dias_igualar_temporada = round( (summary_season.grados_acumulados - this_camp_deg_acc) / this_camp_deg_acc_avg, DECIMAL_PLACES, ) response.append(summary_season) return response @router.get( "/station/{station_code}/monthly-precip", response_model=List[MonthlyPrecipitationsSchema], ) async def get_monthy_precipitations( start_datetime: datetime, end_datetime: datetime, station_code: str, db: Session = Depends(get_db), current_user: UserSchema = Depends(get_current_user), ) -> Response: finca_exists(db, station_code) check_daytimes_order(start_datetime, end_datetime) finca = get_finca_by_station_code(db, station_code) has_finca_access(db, finca, current_user) response = [] for i in range(5): new_start_date = start_datetime.replace(year=(start_datetime.year - i)) new_end_date = end_datetime.replace(year=(end_datetime.year - i)) summary = montly_precipitations(finca, new_start_date, new_end_date) print(summary) if summary: response.append(summary) return response @router.get( "/station/{station_code}/monthly-degrees", response_model=List[DegreesAccumulatedAvgMonthSchema], ) async def get_monthly_avr_day_degrees( start_datetime: datetime, end_datetime: datetime, station_code: str, db: Session = Depends(get_db), current_user: UserSchema = Depends(get_current_user), ) -> Response: finca_exists(db, station_code) check_daytimes_order(start_datetime, end_datetime) finca = get_finca_by_station_code(db, station_code) has_finca_access(db, finca, current_user) response = [] for i in range(5): new_start_date = start_datetime.replace(year=(start_datetime.year - i)) new_end_date = end_datetime.replace(year=(end_datetime.year - i)) summary = monthly_avr_day_degrees(finca, new_start_date, new_end_date) print(summary) if summary: response.append(summary) return response