update
This commit is contained in:
262
backEnd/contact/views.py
Normal file
262
backEnd/contact/views.py
Normal file
@@ -0,0 +1,262 @@
|
||||
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 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)
|
||||
Reference in New Issue
Block a user