Support Ticket System
Django-CFG includes a comprehensive support ticket system for managing customer support, help desk operations, and user communications.
Overview
The Support app provides:
- Ticket management with status tracking
- Real-time chat interface for ticket conversations
- User-friendly ticket creation and management
- Admin dashboard for support team management
- Email notifications for ticket updates
- Ticket analytics and performance metrics
- File attachments and rich text support
Quick Start
Enable Support in Configuration
# config.py
from django_cfg import DjangoConfig
from .environment import env
class MyConfig(DjangoConfig):
enable_support: bool = True # Enable support system
# Email configuration for notifications
email: EmailConfig = EmailConfig(
backend="django.core.mail.backends.smtp.EmailBackend",
host="smtp.gmail.com",
port=587,
use_tls=True,
username=env.email.username,
password=env.email.password,
default_from_email="[email protected]"
)Create Support Ticket
from django_cfg.apps.support.models import Ticket, Message
# Create ticket
ticket = Ticket.objects.create(
user=user,
subject="Login Issue",
status=Ticket.TicketStatus.OPEN
)
# Add initial message
message = Message.objects.create(
ticket=ticket,
user=user,
content="I'm having trouble logging into my account",
is_from_user=True
)Data Models
Ticket Model
class Ticket(models.Model):
"""Support ticket model."""
class TicketStatus(models.TextChoices):
OPEN = 'open', 'Open'
WAITING_FOR_USER = 'waiting_for_user', 'Waiting for User'
WAITING_FOR_ADMIN = 'waiting_for_admin', 'Waiting for Admin'
RESOLVED = 'resolved', 'Resolved'
CLOSED = 'closed', 'Closed'
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='support_tickets')
subject = models.CharField(max_length=255)
status = models.CharField(max_length=32, choices=TicketStatus.choices, default=TicketStatus.OPEN)
created_at = models.DateTimeField(auto_now_add=True)
@property
def last_message(self):
return self.messages.order_by('-created_at').first()
def is_author(self, user):
"""Check if the given user is the author of this ticket."""
return self.user == user
@property
def unanswered_messages_count(self) -> int:
"""Get count of unanswered messages for this specific ticket."""
return Ticket.objects.get_unanswered_messages_count_for_ticket(self)Message Model
class Message(models.Model):
"""Support ticket message model."""
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE, related_name='messages')
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
content = models.TextField()
is_from_user = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['created_at']API Usage
Ticket Management API
# Create support ticket
POST /api/support/tickets/
{
"subject": "Payment Issue",
"initial_message": "I was charged twice for my subscription"
}
# Get user's tickets
GET /api/support/tickets/
# Get ticket details
GET /api/support/tickets/{uuid}/
# Add message to ticket
POST /api/support/tickets/{uuid}/messages/
{
"content": "Thank you for contacting support. We'll investigate this issue."
}
# Update ticket status
PATCH /api/support/tickets/{uuid}/
{
"status": "resolved"
}Ticket Management
from django_cfg.apps.support.models import Ticket, Message
# Create ticket with initial message
def create_support_ticket(user, subject, initial_message):
ticket = Ticket.objects.create(
user=user,
subject=subject,
status=Ticket.TicketStatus.OPEN
)
Message.objects.create(
ticket=ticket,
user=user,
content=initial_message,
is_from_user=True
)
return ticket
# Add admin response
def add_admin_response(ticket, admin_user, content):
message = Message.objects.create(
ticket=ticket,
user=admin_user,
content=content,
is_from_user=False
)
# Update ticket status
ticket.status = Ticket.TicketStatus.WAITING_FOR_USER
ticket.save()
return messageđź’¬ Chat Interface
Real-time Chat
The support system includes a real-time chat interface for seamless communication:
<!-- ticket_chat.html -->
<div class="chat-container">
<div class="chat-messages" id="chat-messages">
{% for message in ticket.messages.all %}
<div class="message {% if message.is_from_user %}user-message{% else %}admin-message{% endif %}">
<div class="message-content">{{ message.content }}</div>
<div class="message-time">{{ message.created_at|date:"M d, H:i" }}</div>
</div>
{% endfor %}
</div>
<form class="chat-form" id="message-form">
<textarea name="content" placeholder="Type your message..." required></textarea>
<button type="submit">Send</button>
</form>
</div>Chat JavaScript
// Real-time message updates
class TicketChat {
constructor(ticketUuid) {
this.ticketUuid = ticketUuid;
this.initializeChat();
}
initializeChat() {
// Poll for new messages
setInterval(() => {
this.checkForNewMessages();
}, 5000);
// Handle form submission
document.getElementById('message-form').addEventListener('submit', (e) => {
e.preventDefault();
this.sendMessage();
});
}
async sendMessage() {
const form = document.getElementById('message-form');
const content = form.content.value;
const response = await fetch(`/api/support/tickets/${this.ticketUuid}/messages/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': getCookie('csrftoken')
},
body: JSON.stringify({ content })
});
if (response.ok) {
form.content.value = '';
this.loadMessages();
}
}
async checkForNewMessages() {
const response = await fetch(`/api/support/tickets/${this.ticketUuid}/messages/`);
const messages = await response.json();
this.updateChatDisplay(messages);
}
}Admin Interface
Support Dashboard
The admin interface provides:
- Ticket queue with priority and status filtering
- Real-time chat for admin responses
- Bulk actions for ticket management
- Analytics dashboard with support metrics
- User lookup and ticket history
- Canned responses for common issues
Ticket Management
# admin.py (automatically configured)
from django_cfg.apps.support.admin import TicketAdmin, MessageAdmin
# Features included:
# - Status-based filtering
# - User filtering
# - Date range filtering
# - Bulk status updates
# - Message inline editing
# - Ticket analyticsManagement Commands
# Support system statistics
python manage.py support_stats
# Close old resolved tickets
python manage.py close_old_tickets --days=30
# Send ticket reminders
python manage.py send_ticket_reminders
# Export support data
python manage.py export_support_data --format=csv --days=90Analytics & Metrics
Support Metrics
from django_cfg.apps.support.models import Ticket, Message
from django.db.models import Count, Avg
from django.utils import timezone
from datetime import timedelta
# Support statistics
def get_support_stats(days=30):
cutoff_date = timezone.now() - timedelta(days=days)
stats = {
# Ticket counts
'total_tickets': Ticket.objects.filter(created_at__gte=cutoff_date).count(),
'open_tickets': Ticket.objects.filter(status='open').count(),
'resolved_tickets': Ticket.objects.filter(
status='resolved',
created_at__gte=cutoff_date
).count(),
# Response metrics
'avg_response_time': get_avg_response_time(),
'avg_resolution_time': get_avg_resolution_time(),
# User satisfaction
'tickets_by_status': Ticket.objects.values('status').annotate(count=Count('uuid')),
}
return stats
def get_avg_response_time():
"""Calculate average time to first admin response"""
# Implementation for calculating response time metrics
pass
def get_avg_resolution_time():
"""Calculate average time to ticket resolution"""
# Implementation for calculating resolution time metrics
passPerformance Dashboard
# Support team performance
def get_team_performance():
return {
'tickets_per_agent': get_tickets_per_agent(),
'resolution_rates': get_resolution_rates(),
'customer_satisfaction': get_satisfaction_scores(),
'response_time_trends': get_response_time_trends()
}Integration Examples
Email Integration
# Email notifications for ticket updates
from django_cfg.apps.support.utils.support_email_service import SupportEmailService
class TicketNotificationService:
def __init__(self):
self.email_service = SupportEmailService()
def notify_ticket_created(self, ticket):
"""Notify admins of new ticket"""
self.email_service.send_ticket_notification(
ticket=ticket,
template='support/ticket_created.html',
recipients=settings.SUPPORT_TEAM_EMAILS
)
def notify_ticket_updated(self, ticket, message):
"""Notify user of ticket update"""
self.email_service.send_ticket_update(
ticket=ticket,
message=message,
recipient=ticket.user.email
)Webhook Integration
# Webhook for external integrations
from django_cfg.apps.support.views.webhook import SupportWebhookView
class SupportWebhookView(APIView):
"""Handle external support system webhooks"""
def post(self, request):
# Handle external ticket creation
external_data = request.data
ticket = Ticket.objects.create(
user=self.get_or_create_user(external_data['email']),
subject=external_data['subject'],
status=Ticket.TicketStatus.OPEN
)
Message.objects.create(
ticket=ticket,
user=ticket.user,
content=external_data['message'],
is_from_user=True
)
return Response({'ticket_id': str(ticket.uuid)})Configuration Options
Support Settings
# config.py
class MyConfig(DjangoConfig):
enable_support: bool = True
# Support-specific settings
support_email: str = "[email protected]"
support_auto_assign: bool = True
support_max_tickets_per_user: int = 10
support_ticket_retention_days: int = 365
support_enable_chat: bool = True
support_enable_file_uploads: bool = TrueNotification Settings
# Automatic notifications
SUPPORT_NOTIFICATIONS = {
'ticket_created': True,
'ticket_updated': True,
'ticket_resolved': True,
'admin_response': True,
'escalation_alerts': True
}đź§Ş Testing
Support System Testing
# tests/test_support.py
from django.test import TestCase
from django.contrib.auth import get_user_model
from django_cfg.apps.support.models import Ticket, Message
User = get_user_model()
class SupportSystemTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(
username='testuser',
email='[email protected]'
)
def test_ticket_creation(self):
ticket = Ticket.objects.create(
user=self.user,
subject="Test Issue",
status=Ticket.TicketStatus.OPEN
)
self.assertEqual(str(ticket), f"Ticket #{ticket.pk} - testuser (Open)")
def test_message_creation(self):
ticket = Ticket.objects.create(
user=self.user,
subject="Test Issue"
)
message = Message.objects.create(
ticket=ticket,
user=self.user,
content="Test message",
is_from_user=True
)
self.assertEqual(ticket.last_message, message)
def test_ticket_status_workflow(self):
ticket = Ticket.objects.create(
user=self.user,
subject="Test Issue"
)
# Test status progression
ticket.status = Ticket.TicketStatus.WAITING_FOR_ADMIN
ticket.save()
self.assertEqual(ticket.status, Ticket.TicketStatus.WAITING_FOR_ADMIN)Related Documentation
- User Management - User account system
- Newsletter System - Email integration
- Leads System - Customer relationship management
- Email Configuration - Email setup
The Support system provides comprehensive customer support for your Django applications! 🎫
TAGS: support, tickets, helpdesk, customer-service, chat DEPENDS_ON: [accounts, email, tasks] USED_BY: [leads, newsletter, admin]