models.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. from django.db import models
  2. from .validators import json_email_array, json_not_empty_string_array, valid_frequency_format
  3. from django.utils import timezone
  4. from django.conf import settings
  5. from django.utils.timezone import timedelta as delta
  6. from dateutil.relativedelta import relativedelta as reldelta
  7. from pytz import timezone as tz
  8. import requests
  9. import logging
  10. logger = logging.getLogger('django')
  11. class ProgrammedReport(models.Model):
  12. REPORT_FORMATS = [
  13. ("excel", "Excel"),
  14. ("csv", "CSV")
  15. ]
  16. name = models.CharField(max_length=100)
  17. user_id = models.CharField(max_length=2048)
  18. frequency = models.CharField(max_length=20, default="monthly", validators=[valid_frequency_format])
  19. start_report_date = models.DateTimeField(
  20. default=timezone.now)
  21. due_date = models.DateTimeField(blank=True, null=True, default=None)
  22. # Valores que configuran al reporte:
  23. format = models.CharField(
  24. max_length=5, choices=REPORT_FORMATS)
  25. option = models.CharField(max_length=50, default="all")
  26. stations = models.JSONField(validators=[json_not_empty_string_array])
  27. modules = models.JSONField(validators=[json_not_empty_string_array])
  28. notified_emails = models.JSONField(
  29. validators=[json_not_empty_string_array, json_email_array])
  30. # Calculamos el rango del reporte y lo guardamos en UTC en la base de datos.
  31. def save(self, *args, **kwargs):
  32. range = self.get_report_range()
  33. self.start_report_date = range[0].astimezone(tz('UTC'))
  34. self.due_date = range[1].astimezone(tz('UTC'))
  35. super().save(*args, **kwargs)
  36. def get_report_range(self):
  37. # Por defecto frequencia Diaria:
  38. start_date = self.start_report_date.astimezone(tz('America/Argentina/Cordoba')).replace(hour=0, minute=0, second=0, microsecond=0)
  39. end_date = self.start_report_date.astimezone(tz('America/Argentina/Cordoba')).replace(hour=23, minute=59, second=59, microsecond=0)
  40. if self.frequency == "weekly":
  41. start_date -= delta(days=start_date.weekday())
  42. end_date += delta(days=(6 - end_date.weekday())) # Lunes de la siguiente semana
  43. elif self.frequency == "monthly":
  44. start_date = start_date.replace(day=1)
  45. end_date = (end_date.replace(day=1) + reldelta(months=1)).replace(day=1) - delta(days=1)
  46. elif self.frequency == "yearly":
  47. start_date = start_date.replace(day=1, month=1)
  48. end_date = (end_date.replace(day=1, month=1) + reldelta(years=1)) - delta(days=1)
  49. elif self.frequency != 'daily':
  50. return None
  51. return start_date, end_date
  52. # Metodo que envía la petición a Clima para enviar el reporte.
  53. def send_report(self):
  54. # Calculamos el formato en el que Clima requiere recibir los rangos.
  55. start_date = self.start_report_date.astimezone(tz('America/Argentina/Cordoba')).strftime("%d/%m/%Y %H:%M")
  56. end_date = self.due_date.astimezone(tz('America/Argentina/Cordoba')).strftime("%d/%m/%Y %H:%M")
  57. # Enviamos la request:
  58. response = requests.post(settings.CLIMA_URL + "/async_report_handler", {
  59. "id": self.id,
  60. "name": self.name,
  61. "user_id": self.user_id,
  62. "format": self.format,
  63. "stations": self.stations,
  64. "modules": self.modules,
  65. "option": self.option,
  66. "start_date": start_date,
  67. "end_date": end_date,
  68. "notified_emails": self.notified_emails
  69. }, headers={"AUTHORIZATION": settings.PROGRAMMED_REPORTS_SERVICE_AUTH_TOKEN})
  70. if response.status_code != 200:
  71. logger.critical(
  72. "No se pudo enviar el reporte asincrono: %s\n Reason: %s", self, response.reason)
  73. # TODO! Seria ideal enviar un email al administrador para ver que paso.
  74. return False
  75. self.start_report_date = self.due_date + delta(seconds=1) # Pass to next cycle
  76. self.save()
  77. return True
  78. def send_report_now(self):
  79. # Calculamos el formato en el que Clima requiere recibir los rangos.
  80. start_date = self.start_report_date.astimezone(tz('America/Argentina/Cordoba')).strftime("%d/%m/%Y %H:%M")
  81. end_date = timezone.datetime.now().strftime("%d/%m/%Y %H:%M")
  82. # Enviamos la request:
  83. response = requests.post(settings.CLIMA_URL + "/async_report_handler", {
  84. "id": self.id,
  85. "name": self.name,
  86. "user_id": self.user_id,
  87. "format": self.format,
  88. "stations": self.stations,
  89. "modules": self.modules,
  90. "option": self.option,
  91. "start_date": start_date,
  92. "end_date": end_date,
  93. "notified_emails": self.notified_emails
  94. }, headers={"AUTHORIZATION": settings.PROGRAMMED_REPORTS_SERVICE_AUTH_TOKEN})
  95. if response.status_code != 200:
  96. logger.critical(
  97. "No se pudo enviar el reporte asincrono: %s\n Reason: %s", self, response.reason)
  98. # TODO! Seria ideal enviar un email al administrador para ver que paso.
  99. return False
  100. return True