measures.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. # FastApi imports
  2. # Pydantic imports
  3. from datetime import datetime, timedelta
  4. from typing import List
  5. from fastapi import APIRouter, Depends, HTTPException
  6. # Sqlalchemy imports
  7. from sqlalchemy.orm import Session
  8. from starlette.responses import Response
  9. # My imports
  10. from config.settings import DECIMAL_PLACES
  11. from cruds.companies import get_company_by_id
  12. from cruds.fincas import get_finca_by_station_code, get_fincas_filter_company
  13. from database.sqlalchemy import get_db
  14. from routes.calculations.degrees_accumulated import monthly_avr_day_degrees
  15. from routes.calculations.gnral_summary import general_summary
  16. from routes.calculations.montly_precip import montly_precipitations
  17. from routes.login import get_current_user
  18. from schemas.tables import (
  19. DegreesAccumulatedAvgMonth as DegreesAccumulatedAvgMonthSchema,
  20. )
  21. from schemas.tables import MonthlyPrecipitations as MonthlyPrecipitationsSchema
  22. from schemas.tables import Summary as SummarySchema
  23. from schemas.tables import SummarySeason as SummarySeasonSchema
  24. from schemas.users import User as UserSchema
  25. router = APIRouter()
  26. # Futuro Decorator
  27. def check_daytimes_order(start_datetime, end_datetime):
  28. """Verifico que end_datetime sea despues que start_datetime"""
  29. if start_datetime > end_datetime:
  30. raise HTTPException(
  31. status_code=400,
  32. detail="start_datetime es mas grande que end_datetime",
  33. )
  34. """Verifico que el diff no supere una temporada (240 dias aprox)"""
  35. delta = end_datetime - start_datetime
  36. if delta.days > 240:
  37. raise HTTPException(
  38. status_code=400,
  39. detail="El rango de fechas pedido supera la cantidad de dias de una temporada",
  40. )
  41. # Futuro Decorator
  42. def finca_exists(db, station_code):
  43. """Verifico que la estacion exista"""
  44. if get_finca_by_station_code(db, station_code) == None:
  45. raise HTTPException(
  46. status_code=400,
  47. detail="ingrese un station_code valido",
  48. )
  49. def has_finca_access(db, finca, user):
  50. if finca in get_fincas_filter_company(db, user.company_id):
  51. return True
  52. else:
  53. raise HTTPException(
  54. status_code=401,
  55. detail="no tienes acceso a esta finca",
  56. )
  57. @router.get("/station/all/summary", response_model=List[SummarySchema])
  58. async def get_fincas_summaries(
  59. start_datetime: datetime,
  60. end_datetime: datetime,
  61. db: Session = Depends(get_db),
  62. current_user: UserSchema = Depends(get_current_user),
  63. ) -> Response:
  64. check_daytimes_order(start_datetime, end_datetime)
  65. fincas = get_fincas_filter_company(db, current_user.company_id)
  66. response = []
  67. for finca in fincas:
  68. response.append(general_summary(finca, start_datetime, end_datetime))
  69. return response
  70. @router.get("/station/{station_code}/summary", response_model=List[SummarySeasonSchema])
  71. async def get_finca_summary(
  72. start_datetime: datetime,
  73. end_datetime: datetime,
  74. station_code: str,
  75. db: Session = Depends(get_db),
  76. current_user: UserSchema = Depends(get_current_user),
  77. ) -> Response:
  78. finca_exists(db, station_code)
  79. check_daytimes_order(start_datetime, end_datetime)
  80. finca = get_finca_by_station_code(db, station_code)
  81. has_finca_access(db, finca, current_user)
  82. response = []
  83. for i in range(5):
  84. new_start_date = start_datetime.replace(year=(start_datetime.year - i))
  85. new_end_date = end_datetime.replace(year=(end_datetime.year - i))
  86. summary = general_summary(finca, new_start_date, new_end_date)
  87. # REVIEW: Should write a new from_parent constructor
  88. summary_season = SummarySeasonSchema(
  89. station=summary.station,
  90. initial_date=summary.initial_date,
  91. final_date=summary.final_date,
  92. lt10=summary.lt10,
  93. gt30=summary.gt30,
  94. gt33=summary.gt33,
  95. grados_acumulados=summary.grados_acumulados,
  96. grados_acumulados_promedio=summary.grados_acumulados_promedio,
  97. amplitud_termica=summary.amplitud_termica,
  98. precip_acumulada=summary.precip_acumulada,
  99. data_percentage=summary.data_percentage,
  100. )
  101. if i == 0:
  102. summary_season.dias_igualar_temporada = 0
  103. else:
  104. this_camp_deg_acc = response[0].grados_acumulados
  105. this_camp_deg_acc_avg = response[0].grados_acumulados_promedio
  106. if (
  107. this_camp_deg_acc
  108. and this_camp_deg_acc_avg
  109. and summary_season.grados_acumulados
  110. ) is not None:
  111. summary_season.dias_igualar_temporada = round(
  112. (summary_season.grados_acumulados - this_camp_deg_acc)
  113. / this_camp_deg_acc_avg,
  114. DECIMAL_PLACES,
  115. )
  116. response.append(summary_season)
  117. return response
  118. @router.get(
  119. "/station/{station_code}/monthly-precip",
  120. response_model=List[MonthlyPrecipitationsSchema],
  121. )
  122. async def get_monthy_precipitations(
  123. start_datetime: datetime,
  124. end_datetime: datetime,
  125. station_code: str,
  126. db: Session = Depends(get_db),
  127. current_user: UserSchema = Depends(get_current_user),
  128. ) -> Response:
  129. finca_exists(db, station_code)
  130. check_daytimes_order(start_datetime, end_datetime)
  131. finca = get_finca_by_station_code(db, station_code)
  132. has_finca_access(db, finca, current_user)
  133. response = []
  134. for i in range(5):
  135. new_start_date = start_datetime.replace(year=(start_datetime.year - i))
  136. new_end_date = end_datetime.replace(year=(end_datetime.year - i))
  137. summary = montly_precipitations(finca, new_start_date, new_end_date)
  138. print(summary)
  139. if summary:
  140. response.append(summary)
  141. return response
  142. @router.get(
  143. "/station/{station_code}/monthly-degrees",
  144. response_model=List[DegreesAccumulatedAvgMonthSchema],
  145. )
  146. async def get_monthly_avr_day_degrees(
  147. start_datetime: datetime,
  148. end_datetime: datetime,
  149. station_code: str,
  150. db: Session = Depends(get_db),
  151. current_user: UserSchema = Depends(get_current_user),
  152. ) -> Response:
  153. finca_exists(db, station_code)
  154. check_daytimes_order(start_datetime, end_datetime)
  155. finca = get_finca_by_station_code(db, station_code)
  156. has_finca_access(db, finca, current_user)
  157. response = []
  158. for i in range(5):
  159. new_start_date = start_datetime.replace(year=(start_datetime.year - i))
  160. new_end_date = end_datetime.replace(year=(end_datetime.year - i))
  161. summary = monthly_avr_day_degrees(finca, new_start_date, new_end_date)
  162. print(summary)
  163. if summary:
  164. response.append(summary)
  165. return response