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)