From 5090c2d95982d1864312f226d7a9d7e69024a0f9 Mon Sep 17 00:00:00 2001
From: Ernesto Rico Schmidt <ernesto@helsinki.at>
Date: Mon, 1 Jul 2024 19:39:55 -0400
Subject: [PATCH] refactor: remove duplicated code and simplify updating links

---
 program/serializers.py | 17 ++++-------------
 program/utils.py       | 27 +++++++++++++++++++++++----
 2 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/program/serializers.py b/program/serializers.py
index 6ed9770a..8d47ae22 100644
--- a/program/serializers.py
+++ b/program/serializers.py
@@ -52,7 +52,7 @@ from program.models import (
     Type,
     UserProfile,
 )
-from program.utils import delete_links
+from program.utils import update_links
 
 SOLUTION_CHOICES = {
     "theirs": "Discard projected timeslot. Keep existing timeslot(s).",
@@ -462,10 +462,7 @@ class HostSerializer(serializers.ModelSerializer):
 
         # optional nested objects
         if "links" in validated_data:
-            instance = delete_links(instance)
-
-            for link_data in validated_data.get("links"):
-                HostLink.objects.create(host=instance, **link_data)
+            instance = update_links(instance, validated_data.get("links"))
 
         instance.updated_by = self.context.get("request").user.username
 
@@ -764,10 +761,7 @@ class ShowSerializer(serializers.HyperlinkedModelSerializer):
 
         # optional nested objects
         if "links" in validated_data:
-            instance = delete_links(instance)
-
-            for link_data in validated_data.get("links"):
-                ShowLink.objects.create(show=instance, **link_data)
+            instance = update_links(instance, validated_data.get("links"))
 
         instance.updated_by = self.context.get("request").user.username
 
@@ -1170,10 +1164,7 @@ class NoteSerializer(serializers.ModelSerializer):
 
         # optional nested objects
         if "links" in validated_data:
-            instance = delete_links(instance)
-
-            for link_data in validated_data.get("links"):
-                NoteLink.objects.create(note=instance, **link_data)
+            instance = update_links(instance, validated_data.get("links"))
 
         instance.updated_by = self.context.get("request").user.username
 
diff --git a/program/utils.py b/program/utils.py
index 5d536037..591dbdfd 100644
--- a/program/utils.py
+++ b/program/utils.py
@@ -21,7 +21,7 @@
 import json
 import typing
 from datetime import date, datetime, time
-from typing import Dict, Optional, Tuple, Union
+from typing import Dict, Optional, Tuple, TypedDict, Union
 
 import requests
 
@@ -29,7 +29,12 @@ from django.conf import settings
 from django.utils import timezone
 
 if typing.TYPE_CHECKING:
-    from program.models import Host, Note, Show
+    from program.models import Host, HostLink, Note, NoteLink, Show, ShowLink
+
+
+class Link(TypedDict):
+    type_id: int
+    url: str
 
 
 def parse_datetime(date_string: str | None) -> datetime | None:
@@ -134,11 +139,25 @@ def get_values(
         return int_if_digit(values[0])
 
 
-def delete_links(instance: Union["Host", "Note", "Show"]) -> Union["Host", "Note", "Show"]:
-    """Delete the links associated with the instance."""
+def update_links(
+    instance: Union["Host", "Note", "Show"], links: list[Link]
+) -> Union["Host", "Note", "Show"]:
+    """Update the links associated with the instance"""
 
+    # delete the links associated with the instance
     if instance.links.count() > 0:
         for link in instance.links.all():
             link.delete(keep_parents=True)
 
+    match type(instance):
+        case "Host":
+            for link_data in links:
+                HostLink.objects.create(host=instance, **link_data)
+        case "Note":
+            for link_data in links:
+                NoteLink.objects.create(note=instance, **link_data)
+        case "Show":
+            for link_data in links:
+                ShowLink.objects.create(show=instance, **link_data)
+
     return instance
-- 
GitLab