from rest_framework import serializers from .models import ( SupportTicket, TicketStatus, TicketPriority, TicketCategory, TicketMessage, TicketActivity, KnowledgeBaseCategory, KnowledgeBaseArticle, SupportSettings ) from .email_service import SupportEmailService import logging logger = logging.getLogger(__name__) class TicketStatusSerializer(serializers.ModelSerializer): class Meta: model = TicketStatus fields = ['id', 'name', 'color', 'description', 'is_closed', 'display_order'] class TicketPrioritySerializer(serializers.ModelSerializer): class Meta: model = TicketPriority fields = ['id', 'name', 'level', 'color', 'description', 'sla_hours'] class TicketCategorySerializer(serializers.ModelSerializer): class Meta: model = TicketCategory fields = ['id', 'name', 'description', 'color', 'icon', 'display_order'] class TicketMessageSerializer(serializers.ModelSerializer): class Meta: model = TicketMessage fields = [ 'id', 'ticket', 'message_type', 'content', 'author_name', 'author_email', 'is_internal', 'created_at', 'updated_at', 'attachments', 'is_read' ] read_only_fields = ['created_at', 'updated_at'] class TicketActivitySerializer(serializers.ModelSerializer): class Meta: model = TicketActivity fields = [ 'id', 'activity_type', 'description', 'user_name', 'old_value', 'new_value', 'created_at' ] read_only_fields = ['created_at'] class SupportTicketSerializer(serializers.ModelSerializer): status_name = serializers.CharField(source='status.name', read_only=True) status_color = serializers.CharField(source='status.color', read_only=True) priority_name = serializers.CharField(source='priority.name', read_only=True) priority_color = serializers.CharField(source='priority.color', read_only=True) category_name = serializers.CharField(source='category.name', read_only=True) messages = TicketMessageSerializer(many=True, read_only=True) activities = TicketActivitySerializer(many=True, read_only=True) class Meta: model = SupportTicket fields = [ 'id', 'ticket_number', 'title', 'description', 'ticket_type', 'user_name', 'user_email', 'user_phone', 'company', 'category', 'category_name', 'priority', 'priority_name', 'priority_color', 'status', 'status_name', 'status_color', 'assigned_to', 'assigned_at', 'created_at', 'updated_at', 'closed_at', 'last_activity', 'first_response_at', 'sla_deadline', 'tags', 'is_escalated', 'escalation_reason', 'attachments', 'messages', 'activities' ] read_only_fields = [ 'ticket_number', 'created_at', 'updated_at', 'last_activity', 'assigned_at', 'closed_at', 'first_response_at', 'sla_deadline' ] class SupportTicketCreateSerializer(serializers.ModelSerializer): """Simplified serializer for creating tickets from public form""" ticket_number = serializers.CharField(read_only=True) class Meta: model = SupportTicket fields = [ 'ticket_number', 'title', 'description', 'ticket_type', 'user_name', 'user_email', 'user_phone', 'company', 'category' ] read_only_fields = ['ticket_number'] def validate_user_email(self, value): """ Validate email format and optionally check if registered """ from .models import RegisteredEmail from django.core.validators import validate_email from django.core.exceptions import ValidationError as DjangoValidationError # Basic email format validation try: validate_email(value) except DjangoValidationError: raise serializers.ValidationError("Please enter a valid email address.") # Optional: Check if email is registered (for analytics/tracking) # But don't block ticket creation if not registered try: registered_email = RegisteredEmail.objects.get(email=value) if not registered_email.is_active: # Log this but don't block the ticket logger.warning(f'Ticket submitted by deactivated registered email: {value}') except RegisteredEmail.DoesNotExist: # This is fine - unregistered users can submit tickets logger.info(f'Ticket submitted by unregistered email: {value}') return value def create(self, validated_data): from .models import RegisteredEmail # Set default status and priority if not set if not validated_data.get('status'): default_status = TicketStatus.objects.filter(name='Open').first() if default_status: validated_data['status'] = default_status if not validated_data.get('priority'): default_priority = TicketPriority.objects.filter(name='Medium').first() if default_priority: validated_data['priority'] = default_priority ticket = SupportTicket.objects.create(**validated_data) # Create initial activity TicketActivity.objects.create( ticket=ticket, activity_type='created', description=f'Ticket created by {ticket.user_name}', user_name=ticket.user_name ) # Update registered email statistics (only if email is registered) try: registered_email = RegisteredEmail.objects.get(email=validated_data['user_email']) registered_email.increment_ticket_count() logger.info(f'Updated ticket count for registered email: {validated_data["user_email"]}') except RegisteredEmail.DoesNotExist: # This is normal now - unregistered users can submit tickets logger.info(f'Ticket created by unregistered email: {validated_data["user_email"]}') # Send email notifications try: email_results = SupportEmailService.send_ticket_created_emails(ticket) logger.info(f'Email notifications sent for ticket {ticket.ticket_number}: {email_results}') except Exception as e: logger.error(f'Failed to send email notifications for ticket {ticket.ticket_number}: {str(e)}') # Don't fail ticket creation if emails fail return ticket class TicketStatusCheckSerializer(serializers.Serializer): """Serializer for checking ticket status by ticket number""" ticket_number = serializers.CharField(max_length=20) class KnowledgeBaseCategorySerializer(serializers.ModelSerializer): article_count = serializers.SerializerMethodField() class Meta: model = KnowledgeBaseCategory fields = [ 'id', 'name', 'slug', 'description', 'icon', 'color', 'display_order', 'article_count' ] def get_article_count(self, obj): return obj.articles.filter(is_published=True).count() class KnowledgeBaseArticleListSerializer(serializers.ModelSerializer): category_name = serializers.CharField(source='category.name', read_only=True) category_slug = serializers.CharField(source='category.slug', read_only=True) class Meta: model = KnowledgeBaseArticle fields = [ 'id', 'title', 'slug', 'category', 'category_name', 'category_slug', 'summary', 'is_featured', 'view_count', 'helpful_count', 'not_helpful_count', 'created_at', 'updated_at', 'published_at' ] class KnowledgeBaseArticleDetailSerializer(serializers.ModelSerializer): category_name = serializers.CharField(source='category.name', read_only=True) category_slug = serializers.CharField(source='category.slug', read_only=True) class Meta: model = KnowledgeBaseArticle fields = [ 'id', 'title', 'slug', 'category', 'category_name', 'category_slug', 'content', 'summary', 'meta_description', 'keywords', 'is_featured', 'view_count', 'helpful_count', 'not_helpful_count', 'created_at', 'updated_at', 'published_at' ] class SupportSettingsSerializer(serializers.ModelSerializer): class Meta: model = SupportSettings fields = ['id', 'setting_name', 'setting_value', 'description', 'is_active']