Files
GNX-WEB/gnx-react/backend/career/views.py
Iliyan Angelov 5ad9cbe3a6 update
2025-10-13 01:49:06 +03:00

168 lines
6.3 KiB
Python

from rest_framework import viewsets, status, filters
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import AllowAny, IsAdminUser
from rest_framework.parsers import MultiPartParser, FormParser, JSONParser
from django_filters.rest_framework import DjangoFilterBackend
from django.shortcuts import get_object_or_404
import logging
from .models import JobPosition, JobApplication
from .serializers import (
JobPositionListSerializer,
JobPositionDetailSerializer,
JobApplicationSerializer,
JobApplicationListSerializer
)
from .email_service import CareerEmailService
logger = logging.getLogger(__name__)
class JobPositionViewSet(viewsets.ReadOnlyModelViewSet):
"""
ViewSet for job positions
GET /api/career/jobs/ - List all active job positions
GET /api/career/jobs/{slug}/ - Get job position by slug
"""
queryset = JobPosition.objects.filter(status='active')
permission_classes = [AllowAny]
lookup_field = 'slug'
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_fields = ['department', 'employment_type', 'location_type', 'featured']
search_fields = ['title', 'department', 'location', 'short_description']
ordering_fields = ['posted_date', 'priority', 'title']
ordering = ['-priority', '-posted_date']
def get_serializer_class(self):
if self.action == 'retrieve':
return JobPositionDetailSerializer
return JobPositionListSerializer
@action(detail=False, methods=['get'])
def featured(self, request):
"""Get featured job positions"""
featured_jobs = self.queryset.filter(featured=True)
serializer = self.get_serializer(featured_jobs, many=True)
return Response(serializer.data)
@action(detail=True, methods=['get'])
def applications_count(self, request, slug=None):
"""Get number of applications for a job"""
job = self.get_object()
count = job.applications.count()
return Response({'count': count})
class JobApplicationViewSet(viewsets.ModelViewSet):
"""
ViewSet for job applications
POST /api/career/applications/ - Submit a job application
GET /api/career/applications/ - List applications (admin only)
"""
queryset = JobApplication.objects.all()
serializer_class = JobApplicationSerializer
parser_classes = [MultiPartParser, FormParser, JSONParser]
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_fields = ['job', 'status']
search_fields = ['first_name', 'last_name', 'email', 'job__title']
ordering_fields = ['applied_date', 'status']
ordering = ['-applied_date']
def get_permissions(self):
"""
Allow anyone to create (submit) applications
Only admins can list/view/update/delete applications
"""
if self.action == 'create':
return [AllowAny()]
return [IsAdminUser()]
def get_serializer_class(self):
if self.action == 'list':
return JobApplicationListSerializer
return JobApplicationSerializer
def create(self, request, *args, **kwargs):
"""Submit a job application"""
try:
# Build data dict - Django QueryDict returns lists, so we need to get first item
data = {}
# Get POST data (text fields)
for key in request.POST.keys():
value = request.POST.get(key)
data[key] = value
# Get FILES data
for key in request.FILES.keys():
file_obj = request.FILES.get(key)
data[key] = file_obj
except Exception as e:
logger.error(f"Error parsing request: {str(e)}")
return Response(
{'error': 'Error parsing request data'},
status=status.HTTP_400_BAD_REQUEST
)
serializer = self.get_serializer(data=data)
if not serializer.is_valid():
logger.error(f"Validation errors: {serializer.errors}")
return Response(
{'error': 'Validation failed', 'details': serializer.errors},
status=status.HTTP_400_BAD_REQUEST
)
try:
# Save the application
application = serializer.save()
logger.info(f"New job application received: {application.full_name} for {application.job.title}")
# Try to send email notifications (non-blocking - don't fail if emails fail)
try:
email_service = CareerEmailService()
email_service.send_application_confirmation(application)
email_service.send_application_notification_to_admin(application)
logger.info(f"Email notifications sent successfully for application {application.id}")
except Exception as email_error:
# Log email error but don't fail the application submission
logger.warning(f"Failed to send email notifications for application {application.id}: {str(email_error)}")
return Response(
{
'message': 'Application submitted successfully',
'data': serializer.data
},
status=status.HTTP_201_CREATED
)
except Exception as e:
logger.error(f"Error submitting job application: {str(e)}", exc_info=True)
return Response(
{'error': 'Failed to submit application. Please try again.'},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
@action(detail=True, methods=['post'])
def update_status(self, request, pk=None):
"""Update application status"""
application = self.get_object()
new_status = request.data.get('status')
if new_status not in dict(JobApplication.STATUS_CHOICES):
return Response(
{'error': 'Invalid status'},
status=status.HTTP_400_BAD_REQUEST
)
application.status = new_status
application.save()
serializer = self.get_serializer(application)
return Response(serializer.data)