From d704292a551d23c6bf99fcb0d76d8b388ef5306e Mon Sep 17 00:00:00 2001
From: Ernesto Rico Schmidt <ernesto@helsinki.at>
Date: Wed, 26 Jul 2023 17:35:04 -0400
Subject: [PATCH] refactor: remove unnecessary fields from Timeslot

Closes: #171
---
 CHANGELOG.md                                  | 10 +++++++
 ...e_timeslot_note_id_remove_timeslot_show.py | 20 ++++++++++++++
 program/models.py                             | 15 +----------
 program/serializers.py                        | 27 +++++++++----------
 program/views.py                              |  2 +-
 5 files changed, 44 insertions(+), 30 deletions(-)
 create mode 100644 program/migrations/0065_remove_timeslot_note_id_remove_timeslot_show.py

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92b81e78..72a9603e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [Unreleased]
+
+### Changed
+
+- `note_id` and `show_id` are read-only fields of the `TimeslotSerializer` (steering#171)
+
+### Removed
+
+- `note_id` and `show` fields from the `Timeslot` model (steering#171)
+
 ## [1.0.0-alpha2] - 2023-06-20
 
 ### Added
diff --git a/program/migrations/0065_remove_timeslot_note_id_remove_timeslot_show.py b/program/migrations/0065_remove_timeslot_note_id_remove_timeslot_show.py
new file mode 100644
index 00000000..e65ee71b
--- /dev/null
+++ b/program/migrations/0065_remove_timeslot_note_id_remove_timeslot_show.py
@@ -0,0 +1,20 @@
+# Generated by Django 4.2.2 on 2023-07-26 19:19
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("program", "0064_alter_note_contributors"),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name="timeslot",
+            name="note_id",
+        ),
+        migrations.RemoveField(
+            model_name="timeslot",
+            name="show",
+        ),
+    ]
diff --git a/program/models.py b/program/models.py
index 866e320c..f9d9e0bf 100644
--- a/program/models.py
+++ b/program/models.py
@@ -388,13 +388,11 @@ class TimeSlotManager(models.Manager):
 class TimeSlot(models.Model):
     end = models.DateTimeField()
     memo = models.TextField(blank=True)
-    note_id = models.IntegerField(null=True)
     playlist_id = models.IntegerField(null=True)
     repetition_of = models.ForeignKey(
         "self", blank=True, null=True, on_delete=models.CASCADE, related_name="repetitions"
     )
     schedule = models.ForeignKey(Schedule, on_delete=models.CASCADE, related_name="timeslots")
-    show = models.ForeignKey(Show, on_delete=models.CASCADE, related_name="timeslots")
     start = models.DateTimeField()
 
     objects = TimeSlotManager()
@@ -414,12 +412,8 @@ class TimeSlot(models.Model):
                 self.start.strftime("%X %x"),
                 self.end.strftime("%X %x"),
             )
-        return f"{str(self.show)} ({time_span})"
 
-    def save(self, *args, **kwargs):
-        self.show = self.schedule.show
-        super(TimeSlot, self).save(*args, **kwargs)
-        return self
+        return f"{str(self.schedule.show)} ({time_span})"
 
     @property
     def hash(self):
@@ -455,13 +449,6 @@ class Note(models.Model):
     def __str__(self):
         return self.title
 
-    def save(self, *args, **kwargs):
-        timeslot = TimeSlot.objects.get(pk=self.timeslot.id)
-        timeslot.note_id = self.id
-        timeslot.save()
-
-        super(Note, self).save(*args, **kwargs)
-
 
 class NoteLink(Link):
     note = models.ForeignKey(Note, on_delete=models.CASCADE, related_name="links")
diff --git a/program/serializers.py b/program/serializers.py
index 54570d12..eadc158d 100644
--- a/program/serializers.py
+++ b/program/serializers.py
@@ -697,10 +697,8 @@ class ScheduleDryRunResponseSerializer(serializers.Serializer):
 
 
 class TimeSlotSerializer(serializers.ModelSerializer):
-    note_id = serializers.PrimaryKeyRelatedField(
-        allow_null=True, queryset=Note.objects.all(), required=False
-    )
-    show_id = serializers.PrimaryKeyRelatedField(queryset=Show.objects.all(), required=False)
+    note_id = serializers.SerializerMethodField()
+    show_id = serializers.SerializerMethodField()
     schedule_id = serializers.PrimaryKeyRelatedField(
         queryset=Schedule.objects.all(), required=False
     )
@@ -713,19 +711,27 @@ class TimeSlotSerializer(serializers.ModelSerializer):
     class Meta:
         model = TimeSlot
         read_only_fields = (
-            "id",
             "end",
+            "id",
+            "note_id",
             "schedule_id",
             "show_id",
             "start",
         )
         fields = (
             "memo",
-            "note_id",
             "playlist_id",
             "repetition_of_id",
         ) + read_only_fields
 
+    @staticmethod
+    def get_show_id(obj):
+        return obj.schedule.show.id
+
+    @staticmethod
+    def get_note_id(obj):
+        return obj.note.id
+
     def update(self, instance, validated_data):
         """Update and return an existing Show instance, given the validated data."""
 
@@ -816,15 +822,6 @@ class NoteSerializer(serializers.ModelSerializer):
 
         note.save()
 
-        # Assign note to timeslot
-        if note.timeslot_id is not None:
-            try:
-                timeslot = TimeSlot.objects.get(pk=note.timeslot_id)
-                timeslot.note_id = note.id
-                timeslot.save(update_fields=["note_id"])
-            except ObjectDoesNotExist:
-                pass
-
         return note
 
     def update(self, instance, validated_data):
diff --git a/program/views.py b/program/views.py
index 9d5304fd..455ece82 100644
--- a/program/views.py
+++ b/program/views.py
@@ -759,7 +759,7 @@ class APITimeSlotViewSet(
             # We do this because the Dashboard needs to update the repetition timeslot as well
             # but with another playlist containing the recording instead of the original playlist
             if first_repetition := TimeSlot.objects.filter(
-                show=show_pk, start__gt=timeslot.start, repetition_of=timeslot
+                schedule__show=show_pk, start__gt=timeslot.start, repetition_of=timeslot
             ).first():
                 serializer = TimeSlotSerializer(first_repetition)
                 return Response(serializer.data)
-- 
GitLab