from django.db import models from .validators import json_email_array, json_not_empty_string_array, valid_frequency_format from django.utils import timezone from api.config import get_next_calendar_date, get_previous_calendar_date from django.conf import settings from django.utils.timezone import timedelta as delta from pytz import timezone as tz import requests import logging logger = logging.getLogger('django') class ProgrammedReport(models.Model): REPORT_FORMATS = [ ("excel", "Excel"), ("csv", "CSV") ] name = models.CharField(max_length=100) user_id = models.CharField(max_length=2048) frequency = models.CharField(max_length=20, default="monthly", validators=[valid_frequency_format]) start_report_date = models.DateTimeField( default=timezone.now) due_date = models.DateTimeField(blank=True, null=True, default=None) # Valores que configuran al reporte: format = models.CharField( max_length=5, choices=REPORT_FORMATS) option = models.CharField(max_length=50, default="all") stations = models.JSONField(validators=[json_not_empty_string_array]) modules = models.JSONField(validators=[json_not_empty_string_array]) notified_emails = models.JSONField( validators=[json_not_empty_string_array, json_email_array]) # Actualiza la due_date en cada save del modelo: def save(self, *args, **kwargs): self.start_report_date = get_previous_calendar_date(self.start_report_date.replace(tzinfo=tz('UTC')), self.frequency) + delta(seconds=1) self.due_date = get_next_calendar_date(self.start_report_date, self.frequency) super().save(*args, **kwargs) # Metodo que envía la petición a Clima para enviar el reporte. def send_report(self): # Calculamos el formato en el que Clima requiere recibir los rangos. start_date = self.start_report_date.astimezone(tz('America/Argentina/Cordoba')).strftime("%d/%m/%Y %H:%M") end_date = self.due_date.astimezone(tz('America/Argentina/Cordoba')).strftime("%d/%m/%Y %H:%M") # Enviamos la request: response = requests.post(settings.CLIMA_URL + "/async_report_handler", { "id": self.id, "name": self.name, "user_id": self.user_id, "format": self.format, "stations": self.stations, "modules": self.modules, "option": self.option, "start_date": start_date, "end_date": end_date, "notified_emails": self.notified_emails }, headers={"AUTHORIZATION": settings.PROGRAMMED_REPORTS_SERVICE_AUTH_TOKEN}) if response.status_code != 200: logger.critical( "No se pudo enviar el reporte asincrono: %s\n Reason: %s", self, response.reason) # TODO! Seria ideal enviar un email al administrador para ver que paso. return False self.start_report_date = self.due_date + delta(seconds=1) # Pass to next cycle self.save() return True def send_report_now(self): # Calculamos el formato en el que Clima requiere recibir los rangos. start_date = self.start_report_date.astimezone(tz('America/Argentina/Cordoba')).strftime("%d/%m/%Y %H:%M") end_date = timezone.datetime.now().strftime("%d/%m/%Y %H:%M") # Enviamos la request: response = requests.post(settings.CLIMA_URL + "/async_report_handler", { "id": self.id, "name": self.name, "user_id": self.user_id, "format": self.format, "stations": self.stations, "modules": self.modules, "option": self.option, "start_date": start_date, "end_date": end_date, "notified_emails": self.notified_emails }, headers={"AUTHORIZATION": settings.PROGRAMMED_REPORTS_SERVICE_AUTH_TOKEN}) if response.status_code != 200: logger.critical( "No se pudo enviar el reporte asincrono: %s\n Reason: %s", self, response.reason) # TODO! Seria ideal enviar un email al administrador para ver que paso. return False return True