Ver código fonte

Optimizado el envío de reportes y mejorada la precisión del calculo de la fecha de envío

Tomás Ponce Gessi 3 anos atrás
pai
commit
faf2b9d57f

+ 18 - 0
app/api/migrations/0003_programmedreport_due_date.py

@@ -0,0 +1,18 @@
+# Generated by Django 4.0.4 on 2022-10-17 01:59
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('api', '0002_alter_programmedreport_option'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='programmedreport',
+            name='due_date',
+            field=models.DateTimeField(blank=True, default=None, null=True),
+        ),
+    ]

+ 20 - 6
app/api/models.py

@@ -2,7 +2,7 @@ from django.db import models
 from .validators import json_email_array, json_not_empty_string_array
 from django.utils import timezone
 from django.conf import settings
-
+from dateutil.relativedelta import relativedelta as reldelta
 
 class ProgrammedReport(models.Model):
     REPORT_FORMATS = [
@@ -17,6 +17,7 @@ class ProgrammedReport(models.Model):
         default=timezone.now)
     last_report_date = models.DateTimeField(
         blank=True, null=True, default=None)
+    due_date = models.DateTimeField(blank=True, null=True, default=None)
 
     # Valores que configuran al reporte:
     format = models.CharField(
@@ -27,14 +28,27 @@ class ProgrammedReport(models.Model):
     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):
+        base_date = self.last_report_date if self.last_report_date is not None else self.start_report_date
+        due_date = None
+        if self.frequency.total_seconds() == 0: # Cada mes calendario
+            due_date = base_date + reldelta(months=1)
+        else:
+            due_date= base_date + self.frequency
+        self.due_date = due_date
+        super().save(*args, **kwargs)
+
     # Metodo que envía la petición a Clima para enviar el reporte.
-    def send_report(self, start_date, end_date):
+    def send_report(self):
         import requests
         from django.conf import settings
 
         # Calculamos el formato en el que Clima requiere recibir los rangos.
-        start = start_date.strftime("%d/%m/%Y %H:%M")
-        end = end_date.strftime("%d/%m/%Y %H:%M")
+        start_date = (self.last_report_date if self.last_report_date is not None else self.start_report_date).strftime("%d/%m/%Y %H:%M")
+        end_date = self.due_date.strftime("%d/%m/%Y %H:%M")
+
+        # Enviamos la request:
         response = requests.post(settings.CLIMA_URL + "/async_report_handler", {
             "id": self.id,
             "user_id": self.user_id,
@@ -42,8 +56,8 @@ class ProgrammedReport(models.Model):
             "stations": self.stations,
             "modules": self.modules,
             "option": self.option,
-            "start_date": start,
-            "end_date": end,
+            "start_date": start_date,
+            "end_date": end_date,
             "notified_emails": self.notified_emails
         }, headers={"AUTHORIZATION": settings.PROGRAMMED_REPORTS_SERVICE_AUTH_TOKEN})
 

+ 4 - 11
app/api/tasks.py

@@ -1,18 +1,11 @@
 from .models import ProgrammedReport
 from django.utils import timezone
 
-
 # Task que determina que reportes deben ser enviados:
 # Ejecutado por Cron (Ver settings.py)
 def send_programmed_reports_task():
     timenow = timezone.now()
-    for preport in ProgrammedReport.objects.all():
-        # Calculamos la fecha en la que debe ser enviado
-        duedate = (preport.last_report_date +
-                   preport.frequency) if preport.last_report_date is not None else preport.start_report_date
-        if timenow > duedate:
-            # Calculamos el rango de envio:
-            start_date = preport.last_report_date if preport.last_report_date is not None else preport.start_report_date
-            end_date = start_date + preport.frequency
-            # Se envía el reporte
-            preport.send_report(start_date, end_date)
+    for preport in ProgrammedReport.objects.all():        
+        if timenow > preport.due_date:
+            sent = preport.send_report()
+            print("Se envio" if sent else "No se pudo enviar","el Programmed Report ID:", preport.id)

+ 1 - 0
app/requirements.txt

@@ -14,3 +14,4 @@ sqlparse==0.4.2
 urllib3==1.26.9
 zipp==3.8.0
 django-crontab==0.7.1
+python-dateutil==2.8.2