317 lines
14 KiB
Python
317 lines
14 KiB
Python
from rest_framework import serializers
|
|
from django.contrib.auth import get_user_model
|
|
from ..models import (
|
|
Postmortem, KnowledgeBaseArticle, IncidentRecommendation,
|
|
LearningPattern, KnowledgeBaseUsage, AutomatedPostmortemGeneration
|
|
)
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class PostmortemSerializer(serializers.ModelSerializer):
|
|
"""Serializer for Postmortem model"""
|
|
|
|
owner_username = serializers.CharField(source='owner.username', read_only=True)
|
|
approver_username = serializers.CharField(source='approver.username', read_only=True)
|
|
reviewer_usernames = serializers.StringRelatedField(source='reviewers', many=True, read_only=True)
|
|
incident_title = serializers.CharField(source='incident.title', read_only=True)
|
|
completion_percentage = serializers.ReadOnlyField()
|
|
is_overdue = serializers.ReadOnlyField()
|
|
|
|
class Meta:
|
|
model = Postmortem
|
|
fields = [
|
|
'id', 'title', 'incident', 'incident_title',
|
|
'executive_summary', 'timeline', 'root_cause_analysis',
|
|
'impact_assessment', 'lessons_learned', 'action_items',
|
|
'is_automated', 'generation_confidence', 'auto_generated_sections',
|
|
'status', 'severity', 'owner', 'owner_username',
|
|
'reviewers', 'reviewer_usernames', 'approver', 'approver_username',
|
|
'created_at', 'updated_at', 'published_at', 'due_date',
|
|
'related_incidents', 'affected_services', 'affected_teams',
|
|
'completion_percentage', 'is_overdue'
|
|
]
|
|
read_only_fields = ['id', 'created_at', 'updated_at']
|
|
|
|
def validate(self, data):
|
|
"""Validate postmortem data"""
|
|
if data.get('due_date') and data['due_date'] < timezone.now():
|
|
raise serializers.ValidationError("Due date cannot be in the past")
|
|
return data
|
|
|
|
|
|
class PostmortemListSerializer(serializers.ModelSerializer):
|
|
"""Simplified serializer for postmortem lists"""
|
|
|
|
owner_username = serializers.CharField(source='owner.username', read_only=True)
|
|
incident_title = serializers.CharField(source='incident.title', read_only=True)
|
|
completion_percentage = serializers.ReadOnlyField()
|
|
is_overdue = serializers.ReadOnlyField()
|
|
|
|
class Meta:
|
|
model = Postmortem
|
|
fields = [
|
|
'id', 'title', 'incident', 'incident_title',
|
|
'status', 'severity', 'owner_username',
|
|
'created_at', 'due_date', 'completion_percentage', 'is_overdue'
|
|
]
|
|
|
|
|
|
class KnowledgeBaseArticleSerializer(serializers.ModelSerializer):
|
|
"""Serializer for KnowledgeBaseArticle model"""
|
|
|
|
author_username = serializers.CharField(source='author.username', read_only=True)
|
|
last_updated_by_username = serializers.CharField(source='last_updated_by.username', read_only=True)
|
|
maintainer_username = serializers.CharField(source='maintainer.username', read_only=True)
|
|
is_due_for_review = serializers.ReadOnlyField()
|
|
|
|
class Meta:
|
|
model = KnowledgeBaseArticle
|
|
fields = [
|
|
'id', 'title', 'slug', 'content', 'summary', 'tags',
|
|
'article_type', 'category', 'subcategory',
|
|
'related_services', 'related_components',
|
|
'status', 'is_featured', 'view_count',
|
|
'author', 'author_username', 'last_updated_by', 'last_updated_by_username',
|
|
'maintainer', 'maintainer_username',
|
|
'created_at', 'updated_at', 'last_reviewed', 'next_review_due',
|
|
'related_incidents', 'source_postmortems',
|
|
'confluence_url', 'wiki_url', 'external_references',
|
|
'search_keywords', 'difficulty_level', 'is_due_for_review'
|
|
]
|
|
read_only_fields = ['id', 'created_at', 'updated_at', 'view_count']
|
|
|
|
def create(self, validated_data):
|
|
"""Create a new knowledge base article"""
|
|
if not validated_data.get('slug'):
|
|
validated_data['slug'] = self.generate_slug(validated_data['title'])
|
|
return super().create(validated_data)
|
|
|
|
def generate_slug(self, title):
|
|
"""Generate a URL-friendly slug from title"""
|
|
import re
|
|
slug = re.sub(r'[^\w\s-]', '', title.lower())
|
|
slug = re.sub(r'[-\s]+', '-', slug)
|
|
return slug[:50] # Limit slug length
|
|
|
|
|
|
class KnowledgeBaseArticleListSerializer(serializers.ModelSerializer):
|
|
"""Simplified serializer for knowledge base article lists"""
|
|
|
|
author_username = serializers.CharField(source='author.username', read_only=True)
|
|
is_due_for_review = serializers.ReadOnlyField()
|
|
|
|
class Meta:
|
|
model = KnowledgeBaseArticle
|
|
fields = [
|
|
'id', 'title', 'slug', 'summary', 'article_type',
|
|
'category', 'subcategory', 'status', 'is_featured',
|
|
'view_count', 'author_username', 'created_at', 'updated_at',
|
|
'difficulty_level', 'is_due_for_review'
|
|
]
|
|
|
|
|
|
class IncidentRecommendationSerializer(serializers.ModelSerializer):
|
|
"""Serializer for IncidentRecommendation model"""
|
|
|
|
incident_title = serializers.CharField(source='incident.title', read_only=True)
|
|
related_incident_title = serializers.CharField(source='related_incident.title', read_only=True)
|
|
knowledge_article_title = serializers.CharField(source='knowledge_article.title', read_only=True)
|
|
suggested_expert_username = serializers.CharField(source='suggested_expert.username', read_only=True)
|
|
applied_by_username = serializers.CharField(source='applied_by.username', read_only=True)
|
|
|
|
class Meta:
|
|
model = IncidentRecommendation
|
|
fields = [
|
|
'id', 'incident', 'incident_title', 'recommendation_type',
|
|
'title', 'description', 'similarity_score', 'confidence_level',
|
|
'confidence_score', 'related_incident', 'related_incident_title',
|
|
'knowledge_article', 'knowledge_article_title',
|
|
'suggested_expert', 'suggested_expert_username',
|
|
'suggested_actions', 'expected_outcome', 'time_to_implement',
|
|
'is_applied', 'applied_at', 'applied_by', 'applied_by_username',
|
|
'effectiveness_rating', 'reasoning', 'matching_factors',
|
|
'model_version', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['id', 'created_at', 'updated_at']
|
|
|
|
def validate_effectiveness_rating(self, value):
|
|
"""Validate effectiveness rating"""
|
|
if value is not None and (value < 1 or value > 5):
|
|
raise serializers.ValidationError("Effectiveness rating must be between 1 and 5")
|
|
return value
|
|
|
|
|
|
class IncidentRecommendationListSerializer(serializers.ModelSerializer):
|
|
"""Simplified serializer for incident recommendation lists"""
|
|
|
|
incident_title = serializers.CharField(source='incident.title', read_only=True)
|
|
related_incident_title = serializers.CharField(source='related_incident.title', read_only=True)
|
|
knowledge_article_title = serializers.CharField(source='knowledge_article.title', read_only=True)
|
|
|
|
class Meta:
|
|
model = IncidentRecommendation
|
|
fields = [
|
|
'id', 'incident', 'incident_title', 'recommendation_type',
|
|
'title', 'similarity_score', 'confidence_level', 'confidence_score',
|
|
'related_incident_title', 'knowledge_article_title',
|
|
'is_applied', 'created_at'
|
|
]
|
|
|
|
|
|
class LearningPatternSerializer(serializers.ModelSerializer):
|
|
"""Serializer for LearningPattern model"""
|
|
|
|
validated_by_username = serializers.CharField(source='validated_by.username', read_only=True)
|
|
source_incident_count = serializers.SerializerMethodField()
|
|
source_postmortem_count = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = LearningPattern
|
|
fields = [
|
|
'id', 'name', 'pattern_type', 'description',
|
|
'frequency', 'success_rate', 'confidence_score',
|
|
'triggers', 'actions', 'outcomes',
|
|
'source_incidents', 'source_postmortems',
|
|
'source_incident_count', 'source_postmortem_count',
|
|
'is_validated', 'validated_by', 'validated_by_username',
|
|
'validation_notes', 'times_applied', 'last_applied',
|
|
'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['id', 'created_at', 'updated_at']
|
|
|
|
def get_source_incident_count(self, obj):
|
|
"""Get count of source incidents"""
|
|
return obj.source_incidents.count()
|
|
|
|
def get_source_postmortem_count(self, obj):
|
|
"""Get count of source postmortems"""
|
|
return obj.source_postmortems.count()
|
|
|
|
|
|
class LearningPatternListSerializer(serializers.ModelSerializer):
|
|
"""Simplified serializer for learning pattern lists"""
|
|
|
|
validated_by_username = serializers.CharField(source='validated_by.username', read_only=True)
|
|
|
|
class Meta:
|
|
model = LearningPattern
|
|
fields = [
|
|
'id', 'name', 'pattern_type', 'frequency',
|
|
'success_rate', 'confidence_score', 'is_validated',
|
|
'validated_by_username', 'times_applied', 'created_at'
|
|
]
|
|
|
|
|
|
class KnowledgeBaseUsageSerializer(serializers.ModelSerializer):
|
|
"""Serializer for KnowledgeBaseUsage model"""
|
|
|
|
user_username = serializers.CharField(source='user.username', read_only=True)
|
|
knowledge_article_title = serializers.CharField(source='knowledge_article.title', read_only=True)
|
|
recommendation_title = serializers.CharField(source='recommendation.title', read_only=True)
|
|
incident_title = serializers.CharField(source='incident.title', read_only=True)
|
|
|
|
class Meta:
|
|
model = KnowledgeBaseUsage
|
|
fields = [
|
|
'id', 'user', 'user_username', 'usage_type',
|
|
'knowledge_article', 'knowledge_article_title',
|
|
'recommendation', 'recommendation_title',
|
|
'incident', 'incident_title',
|
|
'context', 'session_id', 'created_at'
|
|
]
|
|
read_only_fields = ['id', 'created_at']
|
|
|
|
|
|
class AutomatedPostmortemGenerationSerializer(serializers.ModelSerializer):
|
|
"""Serializer for AutomatedPostmortemGeneration model"""
|
|
|
|
incident_title = serializers.CharField(source='incident.title', read_only=True)
|
|
generated_postmortem_title = serializers.CharField(source='generated_postmortem.title', read_only=True)
|
|
|
|
class Meta:
|
|
model = AutomatedPostmortemGeneration
|
|
fields = [
|
|
'id', 'incident', 'incident_title', 'status',
|
|
'generation_trigger', 'incident_data', 'timeline_data',
|
|
'log_data', 'generated_content', 'confidence_scores',
|
|
'quality_metrics', 'generated_postmortem', 'generated_postmortem_title',
|
|
'processing_time', 'model_version', 'error_message',
|
|
'started_at', 'completed_at'
|
|
]
|
|
read_only_fields = ['id', 'started_at', 'completed_at']
|
|
|
|
|
|
class PostmortemGenerationRequestSerializer(serializers.Serializer):
|
|
"""Serializer for requesting postmortem generation"""
|
|
|
|
incident_id = serializers.UUIDField()
|
|
include_timeline = serializers.BooleanField(default=True)
|
|
include_logs = serializers.BooleanField(default=True)
|
|
generation_trigger = serializers.CharField(max_length=50, default='manual')
|
|
|
|
def validate_incident_id(self, value):
|
|
"""Validate that incident exists and is resolved"""
|
|
from incident_intelligence.models import Incident
|
|
try:
|
|
incident = Incident.objects.get(id=value)
|
|
if not incident.is_resolved:
|
|
raise serializers.ValidationError("Postmortem can only be generated for resolved incidents")
|
|
return value
|
|
except Incident.DoesNotExist:
|
|
raise serializers.ValidationError("Incident not found")
|
|
|
|
|
|
class RecommendationRequestSerializer(serializers.Serializer):
|
|
"""Serializer for requesting incident recommendations"""
|
|
|
|
incident_id = serializers.UUIDField()
|
|
recommendation_types = serializers.ListField(
|
|
child=serializers.ChoiceField(choices=IncidentRecommendation.RECOMMENDATION_TYPE_CHOICES),
|
|
required=False
|
|
)
|
|
max_recommendations = serializers.IntegerField(min_value=1, max_value=20, default=5)
|
|
min_confidence = serializers.FloatField(min_value=0.0, max_value=1.0, default=0.5)
|
|
|
|
def validate_incident_id(self, value):
|
|
"""Validate that incident exists"""
|
|
from incident_intelligence.models import Incident
|
|
try:
|
|
Incident.objects.get(id=value)
|
|
return value
|
|
except Incident.DoesNotExist:
|
|
raise serializers.ValidationError("Incident not found")
|
|
|
|
|
|
class KnowledgeBaseSearchSerializer(serializers.Serializer):
|
|
"""Serializer for knowledge base search"""
|
|
|
|
query = serializers.CharField(max_length=200)
|
|
article_types = serializers.ListField(
|
|
child=serializers.ChoiceField(choices=KnowledgeBaseArticle.ARTICLE_TYPE_CHOICES),
|
|
required=False
|
|
)
|
|
categories = serializers.ListField(child=serializers.CharField(), required=False)
|
|
difficulty_levels = serializers.ListField(
|
|
child=serializers.ChoiceField(choices=KnowledgeBaseArticle._meta.get_field('difficulty_level').choices),
|
|
required=False
|
|
)
|
|
limit = serializers.IntegerField(min_value=1, max_value=100, default=20)
|
|
offset = serializers.IntegerField(min_value=0, default=0)
|
|
|
|
|
|
class KnowledgeBaseArticleRatingSerializer(serializers.Serializer):
|
|
"""Serializer for rating knowledge base articles"""
|
|
|
|
article_id = serializers.UUIDField()
|
|
rating = serializers.IntegerField(min_value=1, max_value=5)
|
|
feedback = serializers.CharField(max_length=500, required=False)
|
|
|
|
def validate_article_id(self, value):
|
|
"""Validate that article exists"""
|
|
try:
|
|
KnowledgeBaseArticle.objects.get(id=value)
|
|
return value
|
|
except KnowledgeBaseArticle.DoesNotExist:
|
|
raise serializers.ValidationError("Knowledge base article not found")
|