From ad0e494165416fa4c71598adc913b4dc146942a7 Mon Sep 17 00:00:00 2001
From: borzechof99 <borzechof99@mi.fu-berlin.de>
Date: Sat, 26 Jun 2021 14:21:54 +0200
Subject: [PATCH] Add last_used and currently_active to Sports model, Views,
 and Tests

---
 .../migrations/0007_auto_20210626_1130.py     | 30 +++++++++++++++++++
 .../migrations/0008_alter_sport_last_used.py  | 22 ++++++++++++++
 .../migrations/0009_alter_sport_last_used.py  | 22 ++++++++++++++
 .../migrations/0010_alter_sport_last_used.py  | 22 ++++++++++++++
 .../migrations/0011_alter_sport_last_used.py  | 19 ++++++++++++
 unisportomat/quiz/models.py                   | 17 +++++++++++
 unisportomat/quiz/serializers.py              |  5 ++++
 unisportomat/quiz/tests.py                    | 27 +++++++++++++++++
 unisportomat/quiz/views.py                    | 29 +++++++++++++++---
 9 files changed, 189 insertions(+), 4 deletions(-)
 create mode 100644 unisportomat/quiz/migrations/0007_auto_20210626_1130.py
 create mode 100644 unisportomat/quiz/migrations/0008_alter_sport_last_used.py
 create mode 100644 unisportomat/quiz/migrations/0009_alter_sport_last_used.py
 create mode 100644 unisportomat/quiz/migrations/0010_alter_sport_last_used.py
 create mode 100644 unisportomat/quiz/migrations/0011_alter_sport_last_used.py

diff --git a/unisportomat/quiz/migrations/0007_auto_20210626_1130.py b/unisportomat/quiz/migrations/0007_auto_20210626_1130.py
new file mode 100644
index 0000000..d9c59df
--- /dev/null
+++ b/unisportomat/quiz/migrations/0007_auto_20210626_1130.py
@@ -0,0 +1,30 @@
+# Generated by Django 3.2 on 2021-06-26 11:30
+
+import datetime
+from django.db import migrations, models
+import quiz.models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("quiz", "0006_auto_20210612_1230"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="sport",
+            name="currently_active",
+            field=models.BooleanField(default=True),
+        ),
+        migrations.AddField(
+            model_name="sport",
+            name="last_used",
+            field=models.DateField(default=datetime.date(2021, 6, 26)),
+        ),
+        migrations.AlterField(
+            model_name="criterionrating",
+            name="rating",
+            field=models.IntegerField(validators=[quiz.models.validate_rating]),
+        ),
+    ]
diff --git a/unisportomat/quiz/migrations/0008_alter_sport_last_used.py b/unisportomat/quiz/migrations/0008_alter_sport_last_used.py
new file mode 100644
index 0000000..5a5e06b
--- /dev/null
+++ b/unisportomat/quiz/migrations/0008_alter_sport_last_used.py
@@ -0,0 +1,22 @@
+# Generated by Django 3.2 on 2021-06-26 11:32
+
+import datetime
+from django.db import migrations, models
+from django.utils.timezone import utc
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("quiz", "0007_auto_20210626_1130"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="sport",
+            name="last_used",
+            field=models.DateField(
+                default=datetime.datetime(2021, 6, 26, 11, 32, 52, 231135, tzinfo=utc)
+            ),
+        ),
+    ]
diff --git a/unisportomat/quiz/migrations/0009_alter_sport_last_used.py b/unisportomat/quiz/migrations/0009_alter_sport_last_used.py
new file mode 100644
index 0000000..fdff24a
--- /dev/null
+++ b/unisportomat/quiz/migrations/0009_alter_sport_last_used.py
@@ -0,0 +1,22 @@
+# Generated by Django 3.2 on 2021-06-26 11:33
+
+import datetime
+from django.db import migrations, models
+from django.utils.timezone import utc
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("quiz", "0008_alter_sport_last_used"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="sport",
+            name="last_used",
+            field=models.DateField(
+                default=datetime.datetime(2021, 6, 26, 11, 33, 26, 967602, tzinfo=utc)
+            ),
+        ),
+    ]
diff --git a/unisportomat/quiz/migrations/0010_alter_sport_last_used.py b/unisportomat/quiz/migrations/0010_alter_sport_last_used.py
new file mode 100644
index 0000000..cf01355
--- /dev/null
+++ b/unisportomat/quiz/migrations/0010_alter_sport_last_used.py
@@ -0,0 +1,22 @@
+# Generated by Django 3.2 on 2021-06-26 11:39
+
+import datetime
+from django.db import migrations, models
+from django.utils.timezone import utc
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("quiz", "0009_alter_sport_last_used"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="sport",
+            name="last_used",
+            field=models.DateTimeField(
+                default=datetime.datetime(2021, 6, 26, 11, 39, 12, 106108, tzinfo=utc)
+            ),
+        ),
+    ]
diff --git a/unisportomat/quiz/migrations/0011_alter_sport_last_used.py b/unisportomat/quiz/migrations/0011_alter_sport_last_used.py
new file mode 100644
index 0000000..798a235
--- /dev/null
+++ b/unisportomat/quiz/migrations/0011_alter_sport_last_used.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.2 on 2021-06-26 11:39
+
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("quiz", "0010_alter_sport_last_used"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="sport",
+            name="last_used",
+            field=models.DateField(default=django.utils.timezone.now),
+        ),
+    ]
diff --git a/unisportomat/quiz/models.py b/unisportomat/quiz/models.py
index 2a0fd62..5ddc375 100644
--- a/unisportomat/quiz/models.py
+++ b/unisportomat/quiz/models.py
@@ -2,6 +2,7 @@
 
 from django.core.exceptions import ValidationError
 from django.db import models
+from django.utils import timezone
 
 
 def validate_rating(value):
@@ -43,6 +44,8 @@ class SportManager(models.Manager):
         Creates new Sport Object and every CriterionRating for it
         """
         sport = self.create(**kwargs)
+        sport.currently_active = True
+        sport.last_used = timezone.localdate()
 
         for crit in Criterion.objects.iterator():
             sport.rate(crit, -1)
@@ -61,6 +64,13 @@ class Sport(models.Model):
     url = models.URLField()
     criteria_ratings = models.ManyToManyField("Criterion", through="CriterionRating")
 
+    # The Date Field last_used is set to now-time everytime a sport is activated
+    # either through manual activation or activation through the scraper
+    last_used = models.DateField(default=timezone.localdate)
+
+    # Boolean currently_active states whether the sport is in the archive or not
+    currently_active = models.BooleanField(default=True)
+
     objects = SportManager()
 
     def __str__(self):
@@ -91,6 +101,13 @@ class Sport(models.Model):
 
         return True
 
+    def reactivate(self):
+        """
+        Sets currently_active to True and updates the last_used Date
+        """
+        self.currently_active = True
+        self.last_used = timezone.localdate()
+
 
 class CriterionManager(models.Manager):
     """
diff --git a/unisportomat/quiz/serializers.py b/unisportomat/quiz/serializers.py
index 0b8605d..fd53a48 100644
--- a/unisportomat/quiz/serializers.py
+++ b/unisportomat/quiz/serializers.py
@@ -76,6 +76,8 @@ class SingleSportSerializer(serializers.BaseSerializer):
         serialized_data["id"] = sport.pk
         serialized_data["name"] = sport.name
         serialized_data["url"] = sport.url
+        serialized_data["currently_active"] = sport.currently_active
+        serialized_data["last_used"] = sport.last_used
 
         criteria = []
 
@@ -113,6 +115,9 @@ class SingleSportSerializer(serializers.BaseSerializer):
         if "url" in request.data.keys():
             sport_dictionary["url"] = request.data["url"]
 
+        if "currently_active" in request.data.keys():
+            sport_dictionary["currently_active"] = request.data["currently_active"]
+
         # If the Sport is only now created with a POST-Request, no Criteria can be filled out for it
         # This is because the Admin Frontend doesn't have a list of Criteria ready
         if "criteria" in request.data.keys():
diff --git a/unisportomat/quiz/tests.py b/unisportomat/quiz/tests.py
index 4eec683..6a9d64f 100644
--- a/unisportomat/quiz/tests.py
+++ b/unisportomat/quiz/tests.py
@@ -7,6 +7,7 @@ import tempfile
 from django.core.files.uploadedfile import SimpleUploadedFile
 from django.core.management import call_command
 from django.utils.translation import get_language, activate
+from django.utils import timezone
 from django.urls import reverse
 from django.test import TestCase, override_settings
 from rest_framework.test import APITestCase
@@ -395,6 +396,8 @@ class APITest(APITestCase):
             "id": 1,
             "name": "Jiu Jitsu",
             "url": "http://www.test.de",
+            "currently_active": True,
+            "last_used": timezone.localdate(),
             "criteria": [{"id": 1, "name": "Outdoorsport", "value": 1}],
         }
         self.assertDictEqual(response.data, sport_data)
@@ -406,6 +409,7 @@ class APITest(APITestCase):
         sport_data = {
             "name": "Karate",
             "url": "http://www.test2.de",
+            "currently_active": True,
             "criteria": [{"id": 1, "name": "Outdoorsport", "value": 1}],
         }
 
@@ -414,8 +418,12 @@ class APITest(APITestCase):
             data=sport_data,
             format="json",
         )
+
+        response = self.client.get(reverse("small-sport-list-detail", kwargs={"pk": 1}))
+
         self.assertEqual(response.data["name"], sport_data["name"])
         self.assertEqual(response.data["url"], sport_data["url"])
+        self.assertEqual(response.data["currently_active"], True)
         self.assertEqual(len(response.data["criteria"]), Criterion.objects.count())
         self.assertDictEqual(
             response.data["criteria"][0], {"id": 1, "name": "Outdoorsport", "value": 1}
@@ -434,6 +442,9 @@ class APITest(APITestCase):
             data=sport_data,
             format="json",
         )
+
+        response = self.client.get(reverse("small-sport-list-detail", kwargs={"pk": 1}))
+
         self.assertEqual(response.data["name"], "Jiu Jitsu")
         self.assertEqual(response.data["url"], "http://www.test.de")
         self.assertEqual(len(response.data["criteria"]), Criterion.objects.count())
@@ -515,3 +526,19 @@ class APITest(APITestCase):
         self.assertEqual(len(response.data), Criterion.objects.count())
         self.assertEqual(response.data[0]["number_of_sports_active"], 1)
         self.assertEqual(response.data[0]["sum_of_weights"], 7)
+
+    def test_currently_active(self):
+        """
+        Tests if PATCHing the "currently_active" value to false correctly changes the sport
+        """
+
+        # Set Up Values
+        response = self.client.patch(
+            reverse("small-sport-list-detail", kwargs={"pk": 1}),
+            data={"currently_active": False},
+            format="json",
+        )
+
+        response = self.client.get(reverse("small-sport-list-detail", kwargs={"pk": 1}))
+
+        self.assertEqual(response.data["currently_active"], False)
diff --git a/unisportomat/quiz/views.py b/unisportomat/quiz/views.py
index a860a21..079f7aa 100644
--- a/unisportomat/quiz/views.py
+++ b/unisportomat/quiz/views.py
@@ -75,7 +75,7 @@ class SmallSportListView(viewsets.ViewSet):
 
         paginator = PageNumberWithPageSizePagination()
 
-        sports = Sport.objects.all().order_by("name")
+        sports = Sport.objects.filter(currently_active=True).order_by("name")
         sports = paginator.paginate_queryset(sports, request)
         is_filled_tuples = []
 
@@ -146,10 +146,18 @@ class SmallSportListView(viewsets.ViewSet):
         sport.name = request_data["name"]
         sport.url = request_data["url"]
 
+        if request_data["currently_active"] is True and sport.currently_active is False:
+            # If the Sport is just now being activated, update the Date
+            sport.reactivate()
+        else:
+            sport.currently_active = request_data["currently_active"]
+
         # Overwrite Criterion Ratings
         for criterion, value in request_data["criteria"]:
             sport.rate(criterion, value)
 
+        sport.save()
+
         # Re-Serialize changed Sport and Send it back
         response = SingleSportSerializer(sport)
 
@@ -180,9 +188,22 @@ class SmallSportListView(viewsets.ViewSet):
         if "url" in request_data.keys():
             sport.url = request_data["url"]
 
+        if "currently_active" in request_data.keys():
+            if (
+                request_data["currently_active"] is True
+                and sport.currently_active is False
+            ):
+                # If the Sport is just now being activated, update the Date
+                sport.reactivate()
+            else:
+                sport.currently_active = request_data["currently_active"]
+
         # Overwrite Criterion Ratings
-        for criterion, value in request_data["criteria"]:
-            sport.rate(criterion, value)
+        if "criteria" in request_data.keys():
+            for criterion, value in request_data["criteria"]:
+                sport.rate(criterion, value)
+
+        sport.save()
 
         # Re-Serialize changed Sport and Send it back
         response = SingleSportSerializer(sport)
@@ -220,7 +241,7 @@ class IncompleteSportView(APIView):
 
         incomplete_sport_list = []
 
-        for sport in Sport.objects.iterator():
+        for sport in Sport.objects.filter(currently_active=True).iterator():
 
             if not sport.is_filled():
                 incomplete_sport_list.append(sport)
-- 
GitLab