add ticketing app and endpoints

This commit is contained in:
AmirHossein Shirazi
2024-12-14 14:28:47 +03:30
parent 0f76be9f11
commit 8ab4006ee3
12 changed files with 177 additions and 0 deletions
+1
View File
@@ -97,6 +97,7 @@ INSTALLED_APPS = [
'product', 'product',
'account', 'account',
'entertainment', 'entertainment',
'ticket',
] ]
MIDDLEWARE = [ MIDDLEWARE = [
+1
View File
@@ -20,6 +20,7 @@ urlpatterns = [
# path('comment/<int:pk>', views.CommentView.as_view(), name='comment-list'), # path('comment/<int:pk>', views.CommentView.as_view(), name='comment-list'),
path('products/', include('product.urls')), path('products/', include('product.urls')),
path('accounts/', include('account.urls')), path('accounts/', include('account.urls')),
path('tickets/', include('ticket.urls')),
path('', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), path('', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
] ]
View File
+3
View File
@@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.
+6
View File
@@ -0,0 +1,6 @@
from django.apps import AppConfig
class TicketConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'ticket'
+39
View File
@@ -0,0 +1,39 @@
# Generated by Django 5.1.2 on 2024-12-14 10:51
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Ticket',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('subject', models.CharField(max_length=255)),
('status', models.CharField(choices=[('open', 'Open'), ('in_progress', 'In Progress'), ('resolved', 'Resolved'), ('closed', 'Closed')], default='open', max_length=20)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('admin', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned_tickets', to=settings.AUTH_USER_MODEL)),
('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tickets', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Message',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('content', models.TextField()),
('created_at', models.DateTimeField(auto_now_add=True)),
('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='ticket.ticket')),
],
),
]
+29
View File
@@ -0,0 +1,29 @@
from django.db import models
from account.models import User
class Ticket(models.Model):
STATUS_CHOICES = [
('open', 'Open'),
('in_progress', 'In Progress'),
('resolved', 'Resolved'),
('closed', 'Closed'),
]
subject = models.CharField(max_length=255)
customer = models.ForeignKey(User, on_delete=models.CASCADE, related_name="tickets")
admin = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="assigned_tickets")
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='open')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.subject
class Message(models.Model):
ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE, related_name="messages")
sender = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"Message by {self.sender.username} on {self.ticket.subject}"
+14
View File
@@ -0,0 +1,14 @@
from rest_framework import serializers
from .models import Ticket, Message
class MessageSerializer(serializers.ModelSerializer):
class Meta:
model = Message
fields = '__all__'
class TicketSerializer(serializers.ModelSerializer):
messages = MessageSerializer(many=True, read_only=True)
class Meta:
model = Ticket
fields = '__all__'
+3
View File
@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.
+16
View File
@@ -0,0 +1,16 @@
from django.urls import path
from .views import (
TicketCreateView,
TicketListView,
TicketDetailView,
MessageCreateView,
UpdateTicketStatusView
)
urlpatterns = [
path('create', TicketCreateView.as_view(), name='ticket-create'),
path('', TicketListView.as_view(), name='ticket-list'),
path('<int:pk>', TicketDetailView.as_view(), name='ticket-detail'),
path('<int:pk>/messages', MessageCreateView.as_view(), name='message-create'),
path('<int:pk>/update-status', UpdateTicketStatusView.as_view(), name='update-ticket-status'),
]
+65
View File
@@ -0,0 +1,65 @@
from rest_framework import generics, permissions
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Ticket, Message
from .serializers import TicketSerializer, MessageSerializer
class TicketCreateView(generics.CreateAPIView):
queryset = Ticket.objects.all()
serializer_class = TicketSerializer
permission_classes = [permissions.IsAuthenticated]
def perform_create(self, serializer):
serializer.save(customer=self.request.user)
class TicketListView(generics.ListAPIView):
serializer_class = TicketSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
user = self.request.user
if user.is_staff:
return Ticket.objects.all()
return Ticket.objects.filter(customer=user)
class TicketDetailView(generics.RetrieveAPIView):
queryset = Ticket.objects.all()
serializer_class = TicketSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
user = self.request.user
if user.is_staff:
return Ticket.objects.all()
return Ticket.objects.filter(customer=user)
class MessageCreateView(generics.CreateAPIView):
queryset = Message.objects.all()
serializer_class = MessageSerializer
permission_classes = [permissions.IsAuthenticated]
def perform_create(self, serializer):
ticket = serializer.validated_data.get('ticket')
if self.request.user != ticket.customer and not self.request.user.is_staff:
raise permissions.PermissionDenied("You are not authorized to send a message to this ticket.")
serializer.save(sender=self.request.user)
class UpdateTicketStatusView(APIView):
permission_classes = [permissions.IsAdminUser]
def post(self, request, pk):
try:
ticket = Ticket.objects.get(pk=pk)
except Ticket.DoesNotExist:
return Response({"error": "Ticket not found"}, status=404)
new_status = request.data.get('status')
if new_status not in ['open', 'in_progress', 'resolved', 'closed']:
return Response({"error": "Invalid status"}, status=400)
ticket.status = new_status
ticket.save()
return Response({"message": "Ticket status updated successfully"})