272 lines
9.5 KiB
Python
272 lines
9.5 KiB
Python
from rest_framework import viewsets, status
|
|
from rest_framework.decorators import action
|
|
from rest_framework.response import Response
|
|
from rest_framework.permissions import IsAuthenticated, AllowAny
|
|
from django_filters.rest_framework import DjangoFilterBackend
|
|
from rest_framework.filters import SearchFilter, OrderingFilter
|
|
from django.db.models import Q
|
|
from .models import ContactSubmission
|
|
from .serializers import (
|
|
ContactSubmissionSerializer,
|
|
ContactSubmissionCreateSerializer,
|
|
ContactSubmissionListSerializer,
|
|
ContactSubmissionUpdateSerializer
|
|
)
|
|
from .email_service import (
|
|
send_contact_submission_notification,
|
|
send_contact_submission_confirmation,
|
|
check_email_health,
|
|
send_test_email
|
|
)
|
|
|
|
|
|
class ContactSubmissionViewSet(viewsets.ModelViewSet):
|
|
"""
|
|
ViewSet for managing contact form submissions.
|
|
|
|
Provides endpoints for:
|
|
- Creating new contact submissions (public)
|
|
- Listing submissions (admin only)
|
|
- Retrieving individual submissions (admin only)
|
|
- Updating submission status (admin only)
|
|
"""
|
|
|
|
queryset = ContactSubmission.objects.all()
|
|
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
|
filterset_fields = ['status', 'priority', 'industry', 'company_size', 'project_type']
|
|
search_fields = ['first_name', 'last_name', 'email', 'company', 'job_title']
|
|
ordering_fields = ['created_at', 'updated_at', 'priority']
|
|
ordering = ['-created_at']
|
|
|
|
def get_serializer_class(self):
|
|
"""
|
|
Return appropriate serializer class based on action.
|
|
"""
|
|
if self.action == 'create':
|
|
return ContactSubmissionCreateSerializer
|
|
elif self.action == 'list':
|
|
return ContactSubmissionListSerializer
|
|
elif self.action in ['update', 'partial_update']:
|
|
return ContactSubmissionUpdateSerializer
|
|
return ContactSubmissionSerializer
|
|
|
|
def get_permissions(self):
|
|
"""
|
|
Set permissions based on action.
|
|
"""
|
|
if self.action == 'create':
|
|
# Allow anyone to create contact submissions
|
|
permission_classes = [AllowAny]
|
|
else:
|
|
# Require authentication for all other actions
|
|
permission_classes = [IsAuthenticated]
|
|
return [permission() for permission in permission_classes]
|
|
|
|
def get_authenticators(self):
|
|
"""
|
|
Override authentication for create action to bypass CSRF.
|
|
By returning an empty list, DRF won't enforce CSRF for this action.
|
|
"""
|
|
if hasattr(self, 'action') and self.action == 'create':
|
|
return []
|
|
return super().get_authenticators()
|
|
|
|
def create(self, request, *args, **kwargs):
|
|
"""
|
|
Create a new contact submission.
|
|
Public endpoint for form submissions.
|
|
"""
|
|
serializer = self.get_serializer(data=request.data)
|
|
serializer.is_valid(raise_exception=True)
|
|
|
|
# Set initial priority based on company size and budget
|
|
instance = serializer.save()
|
|
self._set_initial_priority(instance)
|
|
|
|
# Send email notifications
|
|
try:
|
|
# Send notification to company email
|
|
send_contact_submission_notification(instance)
|
|
|
|
# Send confirmation email to customer
|
|
send_contact_submission_confirmation(instance)
|
|
|
|
except Exception as e:
|
|
# Log the error but don't fail the submission
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
logger.error(f"Failed to send email notifications for submission #{instance.id}: {str(e)}")
|
|
|
|
# Return success response
|
|
return Response({
|
|
'message': 'Thank you for your submission! We\'ll contact you within 24 hours.',
|
|
'submission_id': instance.id,
|
|
'status': 'success'
|
|
}, status=status.HTTP_201_CREATED)
|
|
|
|
def _set_initial_priority(self, instance):
|
|
"""
|
|
Set initial priority based on submission data.
|
|
"""
|
|
priority = 'medium' # default
|
|
|
|
# High priority for enterprise clients with large budgets
|
|
if (instance.company_size in ['201-1000', '1000+'] and
|
|
instance.budget in ['250k-500k', '500k-1m', 'over-1m']):
|
|
priority = 'high'
|
|
|
|
# Urgent for immediate timeline with high budget
|
|
elif (instance.timeline == 'immediate' and
|
|
instance.budget in ['100k-250k', '250k-500k', '500k-1m', 'over-1m']):
|
|
priority = 'urgent'
|
|
|
|
# Low priority for small companies with small budgets
|
|
elif (instance.company_size in ['1-10', '11-50'] and
|
|
instance.budget in ['under-50k', '50k-100k']):
|
|
priority = 'low'
|
|
|
|
instance.priority = priority
|
|
instance.save(update_fields=['priority'])
|
|
|
|
@action(detail=True, methods=['post'])
|
|
def mark_contacted(self, request, pk=None):
|
|
"""
|
|
Mark a submission as contacted.
|
|
"""
|
|
submission = self.get_object()
|
|
submission.status = 'contacted'
|
|
submission.save(update_fields=['status'])
|
|
|
|
return Response({
|
|
'message': 'Submission marked as contacted',
|
|
'status': submission.status
|
|
})
|
|
|
|
@action(detail=True, methods=['post'])
|
|
def mark_qualified(self, request, pk=None):
|
|
"""
|
|
Mark a submission as qualified.
|
|
"""
|
|
submission = self.get_object()
|
|
submission.status = 'qualified'
|
|
submission.save(update_fields=['status'])
|
|
|
|
return Response({
|
|
'message': 'Submission marked as qualified',
|
|
'status': submission.status
|
|
})
|
|
|
|
@action(detail=True, methods=['post'])
|
|
def close_submission(self, request, pk=None):
|
|
"""
|
|
Close a submission.
|
|
"""
|
|
submission = self.get_object()
|
|
submission.status = 'closed'
|
|
submission.save(update_fields=['status'])
|
|
|
|
return Response({
|
|
'message': 'Submission closed',
|
|
'status': submission.status
|
|
})
|
|
|
|
@action(detail=False, methods=['get'])
|
|
def stats(self, request):
|
|
"""
|
|
Get statistics about contact submissions.
|
|
"""
|
|
total = self.get_queryset().count()
|
|
new = self.get_queryset().filter(status='new').count()
|
|
in_progress = self.get_queryset().filter(status='in_progress').count()
|
|
contacted = self.get_queryset().filter(status='contacted').count()
|
|
qualified = self.get_queryset().filter(status='qualified').count()
|
|
closed = self.get_queryset().filter(status='closed').count()
|
|
|
|
# Priority breakdown
|
|
urgent = self.get_queryset().filter(priority='urgent').count()
|
|
high = self.get_queryset().filter(priority='high').count()
|
|
medium = self.get_queryset().filter(priority='medium').count()
|
|
low = self.get_queryset().filter(priority='low').count()
|
|
|
|
# Enterprise clients
|
|
enterprise = self.get_queryset().filter(
|
|
company_size__in=['201-1000', '1000+']
|
|
).count()
|
|
|
|
return Response({
|
|
'total_submissions': total,
|
|
'status_breakdown': {
|
|
'new': new,
|
|
'in_progress': in_progress,
|
|
'contacted': contacted,
|
|
'qualified': qualified,
|
|
'closed': closed,
|
|
},
|
|
'priority_breakdown': {
|
|
'urgent': urgent,
|
|
'high': high,
|
|
'medium': medium,
|
|
'low': low,
|
|
},
|
|
'enterprise_clients': enterprise,
|
|
})
|
|
|
|
@action(detail=False, methods=['get'])
|
|
def recent(self, request):
|
|
"""
|
|
Get recent submissions (last 7 days).
|
|
"""
|
|
from datetime import datetime, timedelta
|
|
|
|
recent_date = datetime.now() - timedelta(days=7)
|
|
recent_submissions = self.get_queryset().filter(
|
|
created_at__gte=recent_date
|
|
).order_by('-created_at')[:10]
|
|
|
|
serializer = ContactSubmissionListSerializer(recent_submissions, many=True)
|
|
return Response(serializer.data)
|
|
|
|
@action(detail=False, methods=['get'])
|
|
def high_priority(self, request):
|
|
"""
|
|
Get high priority submissions.
|
|
"""
|
|
high_priority_submissions = self.get_queryset().filter(
|
|
priority__in=['urgent', 'high']
|
|
).order_by('-created_at')
|
|
|
|
serializer = ContactSubmissionListSerializer(high_priority_submissions, many=True)
|
|
return Response(serializer.data)
|
|
|
|
@action(detail=False, methods=['get'])
|
|
def email_health(self, request):
|
|
"""
|
|
Check email service health for production monitoring.
|
|
"""
|
|
health_status = check_email_health()
|
|
return Response(health_status)
|
|
|
|
@action(detail=False, methods=['post'])
|
|
def send_test_email(self, request):
|
|
"""
|
|
Send a test email to verify email configuration.
|
|
"""
|
|
email = request.data.get('email')
|
|
if not email:
|
|
return Response({
|
|
'error': 'Email address is required'
|
|
}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
success = send_test_email(email)
|
|
|
|
if success:
|
|
return Response({
|
|
'message': f'Test email sent successfully to {email}',
|
|
'status': 'success'
|
|
})
|
|
else:
|
|
return Response({
|
|
'error': 'Failed to send test email',
|
|
'status': 'error'
|
|
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|