This commit is contained in:
Iliyan Angelov
2025-09-19 11:58:53 +03:00
parent 306b20e24a
commit 6b247e5b9f
11423 changed files with 1500615 additions and 778 deletions

View File

@@ -0,0 +1 @@
# Knowledge Learning Serializers

View File

@@ -0,0 +1,316 @@
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")