diff --git a/.gitignore b/.gitignore
index 6bd33c1..41818d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -175,3 +175,6 @@ cython_debug/
# django
static
+
+# JetBrains
+.idea
diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index 13566b8..0000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/.idea/dictionaries/project.xml b/.idea/dictionaries/project.xml
deleted file mode 100644
index 779eda8..0000000
--- a/.idea/dictionaries/project.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
- mpaa
- viewset
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
deleted file mode 100644
index 105ce2d..0000000
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index f6f7e02..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 60235a5..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/movie-night-py.iml b/.idea/movie-night-py.iml
deleted file mode 100644
index 7a7a8e5..0000000
--- a/.idea/movie-night-py.iml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index 94a25f7..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/movie_manager/serializers.py b/movie_manager/serializers.py
index 3b7a517..c9bb829 100644
--- a/movie_manager/serializers.py
+++ b/movie_manager/serializers.py
@@ -1,6 +1,6 @@
-from django.utils import timezone
from gunicorn.config import User
from rest_framework import serializers
+
from movie_manager.models import Movie, MovieList, Schedule, Showing
@@ -28,6 +28,7 @@ class MovieSerializer(serializers.ModelSerializer):
def get_has_been_scheduled(self, obj):
return Showing.objects.filter(movie_id=obj.id).exists()
+
class MovieListListSerializer(serializers.ModelSerializer):
movie_count = serializers.SerializerMethodField()
@@ -45,17 +46,13 @@ class MovieListSerializer(serializers.ModelSerializer):
owner = serializers.PrimaryKeyRelatedField(read_only=True)
def get_queryset(self):
- return MovieList.objects.prefetch_related(
- "movies",
- "movies__showing_set"
- )
+ return MovieList.objects.prefetch_related("movies", "movies__showing_set")
class Meta:
model = MovieList
fields = ["id", "name", "owner", "public", "movies"]
-
class UserSerializer(serializers.Serializer):
class Meta:
model = User
@@ -69,19 +66,18 @@ class ShowingSerializer(serializers.ModelSerializer):
model = Showing
fields = ["id", "public", "showtime", "movie", "owner"]
- def to_internal_value(self, data):
- validated_data = super().to_internal_value(data)
+ # def to_internal_value(self, data):
+ # validated_data = super().to_internal_value(data)
- if "showtime" in validated_data and timezone.is_naive(
- validated_data["showtime"]
- ):
- validated_data["showtime"] = timezone.make_aware(validated_data["showtime"])
+ # if "showtime" in validated_data and timezone.is_naive(
+ # validated_data["showtime"]
+ # ):
+ # validated_data["showtime"] = timezone.make_aware(validated_data["showtime"])
- return validated_data
+ # return validated_data
class ScheduleSerializer(serializers.ModelSerializer):
- name = serializers.CharField(read_only=True)
showings = ShowingSerializer(source="showing_set", read_only=True, many=True)
class Meta:
diff --git a/movie_manager/tests.py b/movie_manager/tests.py
index 7ce503c..078bc13 100644
--- a/movie_manager/tests.py
+++ b/movie_manager/tests.py
@@ -1,3 +1,89 @@
-from django.test import TestCase
+import json
-# Create your tests here.
+from django.contrib.auth.models import User
+from django.utils import timezone
+from freezegun import freeze_time
+from rest_framework import status
+from rest_framework.test import APITestCase, APIClient
+
+from movie_manager.models import Movie, Schedule, Showing
+
+
+class ShowingModelTestCase(APITestCase):
+ def setUp(self):
+ self.client: APIClient = APIClient()
+ self.movie: Movie = Movie.objects.create(title="Test Movie")
+ self.owner: User = User.objects.create(id=1, username="test_user")
+ self.schedule: Schedule = Schedule.objects.create(
+ owner=self.owner, name="Test Schedule"
+ )
+
+ def test_it_creates_a_new_showing(self):
+ self.client.force_authenticate(user=self.owner)
+
+ showing_time = timezone.now().isoformat().replace("+00:00", "Z")
+ response = self.client.post(
+ "/v1/showings/",
+ {
+ "movie": self.movie.id,
+ "public": True,
+ "schedule": self.schedule.id,
+ "showtime": showing_time,
+ },
+ )
+
+ response_data = json.loads(response.content)
+ self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+ self.assertEqual(response_data.get("showtime"), showing_time)
+ self.assertEqual(response_data.get("movie").get("title"), "Test Movie")
+
+ @freeze_time("2025-07-02 23:59:00", tz_offset=-5)
+ def test_it_returns_active_showings(self):
+ self.client.force_authenticate(user=self.schedule.owner)
+
+ showtimes_america_chicago_utc = [
+ "2025-07-03T04:00:59.000Z", # 7/2/25 11:59pm
+ "2025-07-01T04:00:59.000Z", # 6/30/25 11:59pm
+ "2025-07-08T04:00:59.000Z", # 7/7/25 11:59pm
+ ]
+
+ for showtime in showtimes_america_chicago_utc:
+ Showing.objects.create(
+ movie=self.movie,
+ schedule=self.schedule,
+ showtime=showtime,
+ public=True,
+ owner=self.schedule.owner,
+ )
+
+ response = self.client.get(f"/v1/schedules/{self.schedule.id}/")
+ parsed_schedule = json.loads(response.content)
+
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(len(parsed_schedule.get("showings")), 2)
+
+
+class ScheduleModelTestCase(APITestCase):
+ def setUp(self):
+ self.client: APIClient = APIClient()
+ self.test_user: User = User.objects.create(id=1, username="test_user")
+
+ def test_it_creates_a_new_schedule(self):
+ self.client.force_authenticate(user=self.test_user)
+ response = self.client.post(
+ "/v1/schedules/",
+ {
+ "name": "Test Schedule",
+ "owner": self.test_user.id,
+ "public": True,
+ "slug": "test-schedule",
+ },
+ )
+
+ response_data = json.loads(response.content)
+
+ self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+ self.assertEqual(response_data.get("name"), "Test Schedule")
+ self.assertEqual(response_data.get("owner"), 1)
+ self.assertEqual(response_data.get("public"), True)
+ self.assertEqual(response_data.get("slug"), "test-schedule")
diff --git a/movie_manager/viewsets/schedule.py b/movie_manager/viewsets/schedule.py
index 856605a..57d5ec2 100644
--- a/movie_manager/viewsets/schedule.py
+++ b/movie_manager/viewsets/schedule.py
@@ -1,6 +1,7 @@
import datetime
from django.http import JsonResponse
+from django.utils import timezone
from knox.auth import TokenAuthentication
from rest_framework import viewsets, permissions
@@ -23,15 +24,14 @@ class ScheduleViewset(viewsets.ModelViewSet):
def retrieve(self, request, pk=None, *args, **kwargs):
# Get the schedule instance
instance = self.get_object()
- now = datetime.datetime.now()
+ now = timezone.now()
# get time from start of day
- today = datetime.datetime(now.year, now.month, now.day)
+ today = timezone.make_aware(datetime.datetime(now.year, now.month, now.day))
upcoming_showings = Showing.objects.filter(
showtime__gte=today, schedule=instance
)
- # Create a serialized response
serializer = self.get_serializer(instance)
data = serializer.data
diff --git a/movie_manager/viewsets/showing.py b/movie_manager/viewsets/showing.py
index 1f3c887..a52f7c1 100644
--- a/movie_manager/viewsets/showing.py
+++ b/movie_manager/viewsets/showing.py
@@ -33,4 +33,4 @@ class ShowingViewset(viewsets.ModelViewSet):
owner=request.user,
)
- return JsonResponse(ShowingSerializer(showing).data)
+ return JsonResponse(ShowingSerializer(showing).data, status=201)
diff --git a/requirements.txt b/requirements.txt
index 7350802..1a4cbee 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -6,4 +6,5 @@ django-filter
gunicorn==23.0.0
psycopg2-binary==2.9.10
django-cors-headers==4.7.0
-requests==2.32.3
\ No newline at end of file
+requests==2.32.3
+freezegun==1.5.2
\ No newline at end of file