From 21b180b3241b6c686f71a669e6de56e9f6897d9a Mon Sep 17 00:00:00 2001 From: Catherine Angel Date: Sun, 25 Feb 2024 22:23:00 +0700 Subject: [PATCH 1/4] [RED] add test case for update venue status --- venue/tests.py | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/venue/tests.py b/venue/tests.py index d4644e5..3c249d6 100644 --- a/venue/tests.py +++ b/venue/tests.py @@ -12,6 +12,7 @@ from .models import Venue, Photo from .serializers import VenueSerializer, PhotoSerializer + class BaseTestCase(TestCase): def setUp(self): self.client = APIClient() @@ -21,7 +22,7 @@ def setUp(self): "name": "Test Venue", "address": "123 Test St", "price": 50, - "status": "Active", + "status": "PENDING", "contact_name": "John Doe", "contact_phone_number": "123-456-7890", "event": 1, @@ -34,7 +35,7 @@ def setUp(self): "name": "Venue 1", "address": "123 Test St", "price": 50, - "status": "Active", + "status": "PENDING", "contact_name": "John Doe", "contact_phone_number": "123-456-7890", "event": self.event_id, @@ -45,7 +46,7 @@ def setUp(self): "name": "Venue 2", "address": "456 Test St", "price": 60, - "status": "Inactive", + "status": "NONE", "contact_name": "Jane Doe", "contact_phone_number": "987-654-3210", "event": self.event_id, @@ -94,7 +95,7 @@ def test_get_venue_detail(self): def test_update_venue(self): url = reverse('venue-retrieve-update-destroy', args=[self.venue.id]) - updated_data = {"name": "Updated Venue", "address": "123 Test St", "price": 50, "status": "Active", "contact_name": "John Doe", "contact_phone_number": "123-456-7890", "event": 1,} + updated_data = {"name": "Updated Venue", "address": "123 Test St", "price": 50, "status": "PENDING", "contact_name": "John Doe", "contact_phone_number": "123-456-7890", "event": 1,} response = self.client.put(url, updated_data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data['name'], "Updated Venue") @@ -219,3 +220,31 @@ def test_delete_photo_does_not_exist(self): url = reverse('photo-retrieve-update-destroy', args=[999]) response = self.client.delete(url) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + +class VenueStatusUpdateAPITest(BaseTestCase): + def setUp(self): + self.client = APIClient() + self.user = AppUser.objects.create_user(email='email@email.com',username='testuser',password='test') + self.client.force_authenticate(user=self.user) + self.venue = Venue.objects.create(name='Test Venue', address='Test Address', price=100, status='PENDING', + contact_name='Test Contact', contact_phone_number='123456789', event=1) + + def test_venue_status_update(self): + url = reverse('venue-status-update', kwargs={'pk': self.venue.pk}) + data = {'status': 'CONFIRMED'} + response = self.client.patch(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['status'], 'CONFIRMED') + + def test_venue_status_update_invalid_venue_id(self): + url = reverse('venue-status-update', kwargs={'pk': 999}) + data = {'status': 'CONFIRMED'} + response = self.client.patch(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + def test_venue_status_update_invalid_status(self): + url = reverse('venue-status-update', kwargs={'pk': self.venue.pk}) + data = {'status': 'INVALID_STATUS'} + response = self.client.patch(url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + From d373664e94b68e5c4a70e2a20c73d694d9e880af Mon Sep 17 00:00:00 2001 From: Catherine Angel Date: Sun, 25 Feb 2024 22:28:47 +0700 Subject: [PATCH 2/4] [GREEN] update field status in venue and add update status view --- venue/migrations/0003_alter_venue_status.py | 18 ++++++++++++++++ venue/models.py | 8 ++++++- venue/serializers.py | 5 +++++ venue/urls.py | 2 ++ venue/views.py | 23 +++++++++++++++------ 5 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 venue/migrations/0003_alter_venue_status.py diff --git a/venue/migrations/0003_alter_venue_status.py b/venue/migrations/0003_alter_venue_status.py new file mode 100644 index 0000000..05df8ee --- /dev/null +++ b/venue/migrations/0003_alter_venue_status.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.9 on 2024-02-25 15:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('venue', '0002_alter_photo_image'), + ] + + operations = [ + migrations.AlterField( + model_name='venue', + name='status', + field=models.CharField(choices=[('NONE', 'NONE'), ('PENDING', 'PENDING'), ('WAITLIST', 'WAITLIST'), ('CONFIRMED', 'CONFIRMED'), ('CANCELLED', 'CANCELLED')], default='NONE', max_length=16), + ), + ] diff --git a/venue/models.py b/venue/models.py index 66a1436..9558a8c 100644 --- a/venue/models.py +++ b/venue/models.py @@ -8,7 +8,13 @@ class Venue(models.Model): name = models.CharField(max_length=255) address = models.CharField(max_length=255) price = models.IntegerField() - status = models.CharField(max_length=255) + status = models.CharField(max_length=16, default='NONE', choices=[ + ('NONE', 'NONE'), + ('PENDING', 'PENDING'), + ('WAITLIST', 'WAITLIST'), + ('CONFIRMED', 'CONFIRMED'), + ('CANCELLED', 'CANCELLED'), + ]) contact_name = models.CharField(max_length=255) contact_phone_number = models.CharField(max_length=15) event = models.IntegerField() diff --git a/venue/serializers.py b/venue/serializers.py index c08a404..94f263f 100644 --- a/venue/serializers.py +++ b/venue/serializers.py @@ -12,3 +12,8 @@ class VenueSerializer(serializers.ModelSerializer): class Meta: model = Venue fields = '__all__' + +class VenueStatusSerializer(serializers.ModelSerializer): + class Meta: + model = Venue + fields = ['status'] \ No newline at end of file diff --git a/venue/urls.py b/venue/urls.py index a3d49c2..eb058d8 100644 --- a/venue/urls.py +++ b/venue/urls.py @@ -5,11 +5,13 @@ VenueRetrieveUpdateDestroyView, PhotoCreateView, PhotoRetrieveUpdateDestroyView, + VenueStatusUpdateAPIView ) urlpatterns = [ path('venues/', VenueListCreateView.as_view(), name='venue-list-create'), path('venues//', VenueRetrieveUpdateDestroyView.as_view(), name='venue-retrieve-update-destroy'), + path('venues//status/', VenueStatusUpdateAPIView.as_view(), name='venue-status-update'), path('venues/event//', VenueEventListView.as_view(), name='venue-event-list'), path('photos/', PhotoCreateView.as_view(), name='photo-create'), path('photos//', PhotoRetrieveUpdateDestroyView.as_view(), name='photo-retrieve-update-destroy'), diff --git a/venue/views.py b/venue/views.py index bfcb5f1..2017dc7 100644 --- a/venue/views.py +++ b/venue/views.py @@ -1,13 +1,10 @@ -from django.shortcuts import render - -# Create your views here. - +from rest_framework import status from rest_framework import generics from rest_framework.views import APIView from rest_framework.response import Response from .models import Venue, Photo -from .serializers import VenueSerializer, PhotoSerializer - +from .serializers import VenueSerializer, PhotoSerializer, VenueStatusSerializer +from rest_framework.permissions import IsAuthenticated class VenueListCreateView(generics.ListCreateAPIView): queryset = Venue.objects.all() @@ -31,3 +28,17 @@ class PhotoCreateView(generics.CreateAPIView): class PhotoRetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView): queryset = Photo.objects.all() serializer_class = PhotoSerializer + +class VenueStatusUpdateAPIView(APIView): + permission_classes = [IsAuthenticated] + def patch(self, request, pk): + try: + venue = Venue.objects.get(pk=pk) + except Venue.DoesNotExist: + return Response({'message': 'Venue not found'}, status=status.HTTP_404_NOT_FOUND) + + serializer = VenueStatusSerializer(venue, data=request.data) + if serializer.is_valid(): + serializer.save() + return Response(serializer.data) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) \ No newline at end of file From c3c44831c006ec78ac9742f7c415a05f95157424 Mon Sep 17 00:00:00 2001 From: Catherine Angel Date: Sun, 25 Feb 2024 22:35:25 +0700 Subject: [PATCH 3/4] [REFACTOR] change url to plural forms --- revelio/urls.py | 4 ++-- venue/urls.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/revelio/urls.py b/revelio/urls.py index 6ad0e3e..16b8b02 100644 --- a/revelio/urls.py +++ b/revelio/urls.py @@ -21,6 +21,6 @@ path('', include('authentication.urls')), path('ai/', include('ai.urls')), path('admin/', admin.site.urls), - path('venue/', include('venue.urls')), - path('event/', include('event.urls')), + path('venues/', include('venue.urls')), + path('events/', include('event.urls')), ] diff --git a/venue/urls.py b/venue/urls.py index eb058d8..9bf603a 100644 --- a/venue/urls.py +++ b/venue/urls.py @@ -9,10 +9,10 @@ ) urlpatterns = [ - path('venues/', VenueListCreateView.as_view(), name='venue-list-create'), - path('venues//', VenueRetrieveUpdateDestroyView.as_view(), name='venue-retrieve-update-destroy'), - path('venues//status/', VenueStatusUpdateAPIView.as_view(), name='venue-status-update'), - path('venues/event//', VenueEventListView.as_view(), name='venue-event-list'), + path('', VenueListCreateView.as_view(), name='venue-list-create'), + path('/', VenueRetrieveUpdateDestroyView.as_view(), name='venue-retrieve-update-destroy'), + path('/status/', VenueStatusUpdateAPIView.as_view(), name='venue-status-update'), + path('event//', VenueEventListView.as_view(), name='venue-event-list'), path('photos/', PhotoCreateView.as_view(), name='photo-create'), path('photos//', PhotoRetrieveUpdateDestroyView.as_view(), name='photo-retrieve-update-destroy'), ] From 4a285b43007a5d3b4adb0f477dc7e98467486fcb Mon Sep 17 00:00:00 2001 From: Catherine Angel Date: Sun, 25 Feb 2024 22:47:45 +0700 Subject: [PATCH 4/4] [REFACTOR] remove permission class since there is default value for it --- venue/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/venue/views.py b/venue/views.py index 2017dc7..42d7867 100644 --- a/venue/views.py +++ b/venue/views.py @@ -30,7 +30,6 @@ class PhotoRetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView): serializer_class = PhotoSerializer class VenueStatusUpdateAPIView(APIView): - permission_classes = [IsAuthenticated] def patch(self, request, pk): try: venue = Venue.objects.get(pk=pk)