Repository: AlexsLemonade/refinebio

Issue:
Store locations from where our users download data
### Context

https://github.com/AlexsLemonade/refinebio/pull/2216#discussion_r401233850

### Problem or idea

Our engagement bot only stores IPs from the users, but we are also interested in their locations which can change over the years.

### Solution or next step

We should modify the `post_engagement_bot_summary` command to also store the location from where people are downloading datasets.



Discussion:

Resolving patch:
diff --git a/api/data_refinery_api/management/commands/post_downloads_summary.py b/api/data_refinery_api/management/commands/post_downloads_summary.py
--- a/api/data_refinery_api/management/commands/post_downloads_summary.py
+++ b/api/data_refinery_api/management/commands/post_downloads_summary.py
@@ -39,8 +39,18 @@ def handle(self, *args, **options):
             if annotation.data["start"] and should_display_email(annotation.dataset.email_address)
         ]
 
+        # Save the locations permanently, since IP addresses can cycle over time
+        location_cache = dict()
+        for annotation in annotation_queryset:
+            if not "location" in annotation.data:
+                ip = annotation.data["ip"]
+                if not ip in location_cache:
+                    location_cache[ip] = get_ip_location(ip)
+                annotation.data["location"] = location_cache[ip]
+                annotation.save()
+
         unique_users = list(set(annotation.dataset.email_address for annotation in annotations))
-        unique_ips = list(set(annotation.data["ip"] for annotation in annotations))
+        unique_locations = list(set(annotation.data["location"] for annotation in annotations))
 
         new_users = ""
         returning_users = ""
@@ -49,8 +59,9 @@ def handle(self, *args, **options):
             user_annotations = annotation_queryset.filter(dataset__email_address=email)
             downloads = user_annotations.count()
             total_downloads += downloads
-            unique_locations = list(set(annotation.data["ip"] for annotation in user_annotations))
-            locations = ", ".join(get_ip_location(ip) for ip in unique_locations)
+            locations = ", ".join(
+                list(set(annotation.data["location"] for annotation in user_annotations))
+            )
             is_returning_user = DatasetAnnotation.objects.filter(
                 created_at__lt=start_time, dataset__email_address=email
             )
@@ -62,7 +73,7 @@ def handle(self, *args, **options):
 
         if total_downloads > 0:
             fallback_text = "In the last {0} days, {1} users downloaded {2} datasets from {3} locations.".format(
-                days, len(unique_users), total_downloads, len(unique_ips)
+                days, len(unique_users), total_downloads, len(unique_locations)
             )
         else:
             fallback_text = "There were no downloads in the last {0} days.".format(days)
diff --git a/common/data_refinery_common/migrations/0055_auto_20200529_1230.py b/common/data_refinery_common/migrations/0055_auto_20200529_1230.py
new file mode 100644
--- /dev/null
+++ b/common/data_refinery_common/migrations/0055_auto_20200529_1230.py
@@ -0,0 +1,22 @@
+# Generated by Django 2.2.10 on 2020-05-29 12:30
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("data_refinery_common", "0054_datasetannotation"),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name="datasetannotation", options={"base_manager_name": "objects"},
+        ),
+        migrations.AlterModelManagers(name="datasetannotation", managers=[],),
+        migrations.AlterField(
+            model_name="datasetannotation",
+            name="is_public",
+            field=models.BooleanField(default=False),
+        ),
+    ]
diff --git a/common/data_refinery_common/models/dataset_annotation.py b/common/data_refinery_common/models/dataset_annotation.py
--- a/common/data_refinery_common/models/dataset_annotation.py
+++ b/common/data_refinery_common/models/dataset_annotation.py
@@ -11,7 +11,7 @@ class DatasetAnnotation(models.Model):
 
     class Meta:
         db_table = "dataset_annotations"
-        base_manager_name = "public_objects"
+        base_manager_name = "objects"
 
     # Managers
     objects = models.Manager()


Test patch: