from django.core.management.base import BaseCommand, CommandError from django.utils import timezone from datetime import timedelta from incident_intelligence.models import Incident from knowledge_learning.services.recommendation_engine import RecommendationEngine from knowledge_learning.models import IncidentRecommendation class Command(BaseCommand): help = 'Generate recommendations for incidents' def add_arguments(self, parser): parser.add_argument( '--days', type=int, default=1, help='Number of days back to look for incidents (default: 1)' ) parser.add_argument( '--status', type=str, choices=['OPEN', 'IN_PROGRESS', 'RESOLVED', 'CLOSED'], default='OPEN', help='Only generate recommendations for incidents with specific status (default: OPEN)' ) parser.add_argument( '--severity', type=str, choices=['LOW', 'MEDIUM', 'HIGH', 'CRITICAL', 'EMERGENCY'], help='Only generate recommendations for incidents with specific severity' ) parser.add_argument( '--force', action='store_true', help='Force generation even if recommendations already exist' ) parser.add_argument( '--dry-run', action='store_true', help='Show what would be generated without actually creating recommendations' ) parser.add_argument( '--max-recommendations', type=int, default=5, help='Maximum number of recommendations per incident (default: 5)' ) def handle(self, *args, **options): days = options['days'] status = options['status'] severity = options['severity'] force = options['force'] dry_run = options['dry_run'] max_recommendations = options['max_recommendations'] # Calculate date range end_date = timezone.now() start_date = end_date - timedelta(days=days) self.stdout.write( self.style.SUCCESS(f'Looking for {status} incidents from {start_date.date()} to {end_date.date()}') ) # Build queryset for incidents queryset = Incident.objects.filter( status=status, created_at__gte=start_date, created_at__lte=end_date ) if severity: queryset = queryset.filter(severity=severity) # Filter out incidents that already have recommendations (unless force is used) if not force: existing_recommendation_incidents = IncidentRecommendation.objects.values_list('incident_id', flat=True) queryset = queryset.exclude(id__in=existing_recommendation_incidents) incidents = list(queryset) if not incidents: self.stdout.write( self.style.WARNING('No incidents found matching criteria') ) return self.stdout.write( self.style.SUCCESS(f'Found {len(incidents)} incidents to process') ) if dry_run: self.stdout.write(self.style.WARNING('DRY RUN - No recommendations will be created')) for incident in incidents: self.stdout.write(f' - {incident.title} ({incident.severity}) - {incident.created_at}') return # Initialize recommendation engine recommendation_engine = RecommendationEngine() success_count = 0 error_count = 0 total_recommendations = 0 for incident in incidents: try: self.stdout.write(f'Generating recommendations for: {incident.title}') recommendations = recommendation_engine.generate_recommendations( incident_id=str(incident.id), max_recommendations=max_recommendations, min_confidence=0.5 ) self.stdout.write( self.style.SUCCESS(f' ✓ Generated {len(recommendations)} recommendations') ) success_count += 1 total_recommendations += len(recommendations) except Exception as e: self.stdout.write( self.style.ERROR(f' ✗ Failed to generate recommendations: {str(e)}') ) error_count += 1 # Summary self.stdout.write('\n' + '='*50) self.stdout.write( self.style.SUCCESS(f'Recommendation generation completed:') ) self.stdout.write(f' Incidents processed: {success_count}') self.stdout.write(f' Total recommendations generated: {total_recommendations}') if error_count > 0: self.stdout.write( self.style.ERROR(f' Failed: {error_count}') ) self.stdout.write('='*50)