diff --git a/revelio/settings.py b/revelio/settings.py index 6c32faa..373a140 100644 --- a/revelio/settings.py +++ b/revelio/settings.py @@ -45,6 +45,7 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'authentication', + 'venue', 'rest_framework', 'rest_framework_simplejwt', ] diff --git a/revelio/settings_dev.py b/revelio/settings_dev.py index 77c6a07..beb3b0a 100644 --- a/revelio/settings_dev.py +++ b/revelio/settings_dev.py @@ -44,6 +44,7 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'authentication', + 'venue', 'rest_framework', 'rest_framework_simplejwt', ] diff --git a/revelio/urls.py b/revelio/urls.py index ad7927f..74bfb52 100644 --- a/revelio/urls.py +++ b/revelio/urls.py @@ -20,4 +20,5 @@ urlpatterns = [ path('', include('authentication.urls')), path('admin/', admin.site.urls), + path('venue/', include('venue.urls')), ] diff --git a/venue/__init__.py b/venue/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venue/admin.py b/venue/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/venue/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/venue/apps.py b/venue/apps.py new file mode 100644 index 0000000..20f968a --- /dev/null +++ b/venue/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class VenueConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'venue' diff --git a/venue/migrations/0001_initial.py b/venue/migrations/0001_initial.py new file mode 100644 index 0000000..b744821 --- /dev/null +++ b/venue/migrations/0001_initial.py @@ -0,0 +1,36 @@ +# Generated by Django 4.2.9 on 2024-02-25 02:58 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Venue', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('address', models.CharField(max_length=255)), + ('price', models.IntegerField()), + ('status', models.CharField(max_length=255)), + ('contact_name', models.CharField(max_length=255)), + ('contact_phone_number', models.CharField(max_length=15)), + ('event', models.IntegerField()), + ], + ), + migrations.CreateModel( + name='Photo', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('image', models.ImageField(upload_to='venue_photos/')), + ('venue', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='photos', to='venue.venue')), + ], + ), + ] diff --git a/venue/migrations/0002_alter_photo_image.py b/venue/migrations/0002_alter_photo_image.py new file mode 100644 index 0000000..86c7011 --- /dev/null +++ b/venue/migrations/0002_alter_photo_image.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.9 on 2024-02-25 03:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('venue', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='photo', + name='image', + field=models.URLField(), + ), + ] diff --git a/venue/migrations/__init__.py b/venue/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/venue/models.py b/venue/models.py new file mode 100644 index 0000000..66a1436 --- /dev/null +++ b/venue/models.py @@ -0,0 +1,24 @@ +from django.db import models + +# Create your models here. + +from django.db import models + +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) + contact_name = models.CharField(max_length=255) + contact_phone_number = models.CharField(max_length=15) + event = models.IntegerField() + + def __str__(self): + return self.name + +class Photo(models.Model): + venue = models.ForeignKey(Venue, related_name='photos', on_delete=models.CASCADE) + image = models.URLField() + + def __str__(self): + return self.image diff --git a/venue/serializers.py b/venue/serializers.py new file mode 100644 index 0000000..c08a404 --- /dev/null +++ b/venue/serializers.py @@ -0,0 +1,14 @@ +from rest_framework import serializers +from .models import Venue, Photo + +class PhotoSerializer(serializers.ModelSerializer): + class Meta: + model = Photo + fields = '__all__' + +class VenueSerializer(serializers.ModelSerializer): + photos = PhotoSerializer(many=True, read_only=True) + + class Meta: + model = Venue + fields = '__all__' diff --git a/venue/tests.py b/venue/tests.py new file mode 100644 index 0000000..4b0519c --- /dev/null +++ b/venue/tests.py @@ -0,0 +1,187 @@ +from django.test import TestCase + +# Create your tests here. + +from django.test import TestCase +from django.urls import reverse +from rest_framework import status +from rest_framework.test import APIClient + +from authentication.models import AppUser +from .models import Venue, Photo +from .serializers import VenueSerializer, PhotoSerializer + +class VenueModelTestCase(TestCase): + 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="123 Test St", + price=50, + status="Active", + contact_name="John Doe", + contact_phone_number="123-456-7890", + event=1, + ) + + def test_venue_model(self): + self.assertEqual(str(self.venue), "Test Venue") + +class VenueAPITestCase(TestCase): + 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_data = { + "name": "Test Venue", + "address": "123 Test St", + "price": 50, + "status": "Active", + "contact_name": "John Doe", + "contact_phone_number": "123-456-7890", + "event": 1, + } + self.venue = Venue.objects.create(**self.venue_data) + + def test_get_venue_list(self): + url = reverse('venue-list-create') + response = self.client.get(url) + venues = Venue.objects.all() + serializer = VenueSerializer(venues, many=True) + self.assertEqual(response.data, serializer.data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_create_venue(self): + url = reverse('venue-list-create') + response = self.client.post(url, self.venue_data, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + def test_get_venue_detail(self): + url = reverse('venue-retrieve-update-destroy', args=[self.venue.id]) + response = self.client.get(url) + serializer = VenueSerializer(self.venue) + self.assertEqual(response.data, serializer.data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + 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,} + 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") + + def test_delete_venue(self): + url = reverse('venue-retrieve-update-destroy', args=[self.venue.id]) + response = self.client.delete(url) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + self.assertFalse(Venue.objects.filter(id=self.venue.id).exists()) + +class VenueEventListViewTest(TestCase): + 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.event_id = 1 + + self.venue1_data = { + "name": "Venue 1", + "address": "123 Test St", + "price": 50, + "status": "Active", + "contact_name": "John Doe", + "contact_phone_number": "123-456-7890", + "event": self.event_id, + } + self.venue1 = Venue.objects.create(**self.venue1_data) + + self.venue2_data = { + "name": "Venue 2", + "address": "456 Test St", + "price": 60, + "status": "Inactive", + "contact_name": "Jane Doe", + "contact_phone_number": "987-654-3210", + "event": self.event_id, + } + self.venue2 = Venue.objects.create(**self.venue2_data) + + def test_get_venues_for_event(self): + url = reverse('venue-event-list', kwargs={'event_id': self.event_id}) + + response = self.client.get(url) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + expected_data = VenueSerializer([self.venue1, self.venue2], many=True).data + self.assertEqual(response.data, expected_data) + +class PhotoModelTestCase(TestCase): + 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="123 Test St", + price=50, + status="Active", + contact_name="John Doe", + contact_phone_number="123-456-7890", + event=1, + ) + self.photo = Photo.objects.create( + venue=self.venue, + image="https://example.com/path/to/your/image.jpg" + ) + + def test_photo_model(self): + self.assertEqual(self.photo.venue, self.venue) + self.assertEqual(str(self.photo), "https://example.com/path/to/your/image.jpg") + +class PhotoAPITestCase(TestCase): + 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="123 Test St", + price=50, + status="Active", + contact_name="John Doe", + contact_phone_number="123-456-7890", + event=1, + ) + self.photo_data = { + "venue": self.venue.id, + "image": "https://example.com/path/to/your/image.jpg" + } + self.photo = Photo.objects.create(venue=self.venue, image=self.photo_data["image"]) + + def test_create_photo(self): + url = reverse('photo-create') + response = self.client.post(url, self.photo_data, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + + def test_get_photo_detail(self): + url = reverse('photo-retrieve-update-destroy', args=[self.photo.id]) + response = self.client.get(url) + serializer = PhotoSerializer(self.photo) + self.assertEqual(response.data, serializer.data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_update_photo(self): + url = reverse('photo-retrieve-update-destroy', args=[self.photo.id]) + updated_data = {"venue": self.venue.id, "image": "https://example.com/path/to/your/updated/image.jpg"} + response = self.client.put(url, updated_data, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['image'], "https://example.com/path/to/your/updated/image.jpg") + + def test_delete_photo(self): + url = reverse('photo-retrieve-update-destroy', args=[self.photo.id]) + response = self.client.delete(url) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + self.assertFalse(Photo.objects.filter(id=self.photo.id).exists()) diff --git a/venue/urls.py b/venue/urls.py new file mode 100644 index 0000000..a3d49c2 --- /dev/null +++ b/venue/urls.py @@ -0,0 +1,16 @@ +from django.urls import path +from .views import ( + VenueEventListView, + VenueListCreateView, + VenueRetrieveUpdateDestroyView, + PhotoCreateView, + PhotoRetrieveUpdateDestroyView, +) + +urlpatterns = [ + path('venues/', VenueListCreateView.as_view(), name='venue-list-create'), + path('venues//', VenueRetrieveUpdateDestroyView.as_view(), name='venue-retrieve-update-destroy'), + 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 new file mode 100644 index 0000000..bfcb5f1 --- /dev/null +++ b/venue/views.py @@ -0,0 +1,33 @@ +from django.shortcuts import render + +# Create your views here. + +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 + + +class VenueListCreateView(generics.ListCreateAPIView): + queryset = Venue.objects.all() + serializer_class = VenueSerializer + +class VenueRetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView): + queryset = Venue.objects.all() + serializer_class = VenueSerializer + +class VenueEventListView(APIView): + def get(self, request, *args, **kwargs): + event_id = kwargs.get('event_id') + venues = Venue.objects.filter(event=event_id) + serializer = VenueSerializer(venues, many=True) + return Response(serializer.data) + +class PhotoCreateView(generics.CreateAPIView): + queryset = Photo.objects.all() + serializer_class = PhotoSerializer + +class PhotoRetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView): + queryset = Photo.objects.all() + serializer_class = PhotoSerializer