# Generated by Django 5.2.6 on 2025-09-18 15:50 import datetime import django.core.validators import django.db.models.deletion import uuid from django.conf import settings from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [ ('incident_intelligence', '0003_incident_auto_remediation_attempted_and_more'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( name='BusinessHours', fields=[ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('name', models.CharField(max_length=200, unique=True)), ('description', models.TextField()), ('timezone', models.CharField(default='UTC', max_length=50)), ('weekday_start', models.TimeField(default=datetime.time(9, 0))), ('weekday_end', models.TimeField(default=datetime.time(17, 0))), ('weekend_start', models.TimeField(default=datetime.time(10, 0))), ('weekend_end', models.TimeField(default=datetime.time(16, 0))), ('day_overrides', models.JSONField(default=dict, help_text='Override hours for specific dates (YYYY-MM-DD format)')), ('holiday_calendar', models.JSONField(default=list, help_text="List of holidays (YYYY-MM-DD format) when business hours don't apply")), ('is_active', models.BooleanField(default=True)), ('is_default', models.BooleanField(default=False, help_text='Default business hours for the system')), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), ], options={ 'ordering': ['name'], }, ), migrations.CreateModel( name='EscalationPolicy', fields=[ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('name', models.CharField(max_length=200, unique=True)), ('description', models.TextField()), ('escalation_type', models.CharField(choices=[('TIME_BASED', 'Time-based Escalation'), ('SEVERITY_BASED', 'Severity-based Escalation'), ('RESOURCE_BASED', 'Resource-based Escalation'), ('CUSTOM', 'Custom Escalation')], max_length=20)), ('trigger_condition', models.CharField(choices=[('SLA_BREACH', 'SLA Breach'), ('SLA_THRESHOLD', 'SLA Threshold Reached'), ('NO_RESPONSE', 'No Response'), ('NO_ACKNOWLEDGMENT', 'No Acknowledgment'), ('CUSTOM', 'Custom Condition')], max_length=20)), ('incident_severities', models.JSONField(default=list, help_text='List of incident severities this policy applies to')), ('incident_categories', models.JSONField(default=list, help_text='List of incident categories this policy applies to')), ('trigger_delay_minutes', models.PositiveIntegerField(default=0, help_text='Delay before escalation triggers (in minutes)')), ('escalation_steps', models.JSONField(default=list, help_text='List of escalation steps with timing and actions')), ('notification_channels', models.JSONField(default=list, help_text='Channels to notify during escalation (email, sms, slack, etc.)')), ('notification_templates', models.JSONField(default=dict, help_text='Templates for different notification channels')), ('is_active', models.BooleanField(default=True)), ('is_default', models.BooleanField(default=False)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), ], options={ 'ordering': ['name'], }, ), migrations.CreateModel( name='NotificationTemplate', fields=[ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('name', models.CharField(max_length=200)), ('template_type', models.CharField(choices=[('ESCALATION', 'Escalation Notification'), ('ONCALL_HANDOFF', 'On-Call Handoff'), ('SLA_BREACH', 'SLA Breach Alert'), ('SLA_WARNING', 'SLA Warning'), ('CUSTOM', 'Custom Notification')], max_length=20)), ('channel_type', models.CharField(choices=[('EMAIL', 'Email'), ('SMS', 'SMS'), ('SLACK', 'Slack'), ('TEAMS', 'Microsoft Teams'), ('WEBHOOK', 'Webhook'), ('CUSTOM', 'Custom Channel')], max_length=20)), ('subject_template', models.CharField(help_text='Subject template with variables', max_length=500)), ('body_template', models.TextField(help_text='Body template with variables')), ('variables', models.JSONField(default=list, help_text='Available variables for this template')), ('is_active', models.BooleanField(default=True)), ('is_default', models.BooleanField(default=False)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), ], options={ 'ordering': ['template_type', 'channel_type', 'name'], }, ), migrations.CreateModel( name='OnCallRotation', fields=[ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('name', models.CharField(max_length=200, unique=True)), ('description', models.TextField()), ('rotation_type', models.CharField(choices=[('WEEKLY', 'Weekly Rotation'), ('DAILY', 'Daily Rotation'), ('MONTHLY', 'Monthly Rotation'), ('CUSTOM', 'Custom Schedule')], max_length=20)), ('status', models.CharField(choices=[('ACTIVE', 'Active'), ('PAUSED', 'Paused'), ('INACTIVE', 'Inactive')], default='ACTIVE', max_length=20)), ('team_name', models.CharField(max_length=100)), ('team_description', models.TextField(blank=True, null=True)), ('schedule_config', models.JSONField(default=dict, help_text='Configuration for the rotation schedule')), ('timezone', models.CharField(default='UTC', max_length=50)), ('external_system', models.CharField(choices=[('PAGERDUTY', 'PagerDuty'), ('OPSGENIE', 'OpsGenie'), ('INTERNAL', 'Internal System'), ('CUSTOM', 'Custom Integration')], default='INTERNAL', max_length=50)), ('external_system_id', models.CharField(blank=True, help_text='ID in external system (PagerDuty schedule ID, etc.)', max_length=255, null=True)), ('integration_config', models.JSONField(default=dict, help_text='Configuration for external system integration')), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), ], options={ 'ordering': ['name'], }, ), migrations.CreateModel( name='OnCallAssignment', fields=[ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('start_time', models.DateTimeField()), ('end_time', models.DateTimeField()), ('status', models.CharField(choices=[('SCHEDULED', 'Scheduled'), ('ACTIVE', 'Active'), ('COMPLETED', 'Completed'), ('CANCELLED', 'Cancelled')], default='SCHEDULED', max_length=20)), ('handoff_notes', models.TextField(blank=True, null=True)), ('handoff_time', models.DateTimeField(blank=True, null=True)), ('incidents_handled', models.PositiveIntegerField(default=0)), ('response_time_avg', models.DurationField(blank=True, null=True)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('handed_off_from', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='handed_off_assignments', to=settings.AUTH_USER_MODEL)), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ('rotation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='assignments', to='sla_oncall.oncallrotation')), ], options={ 'ordering': ['start_time'], }, ), migrations.CreateModel( name='SLADefinition', fields=[ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('name', models.CharField(max_length=200)), ('description', models.TextField()), ('sla_type', models.CharField(choices=[('RESPONSE_TIME', 'Response Time'), ('RESOLUTION_TIME', 'Resolution Time'), ('ACKNOWLEDGMENT_TIME', 'Acknowledgment Time'), ('FIRST_RESPONSE', 'First Response Time')], max_length=20)), ('incident_categories', models.JSONField(default=list, help_text='List of incident categories this SLA applies to')), ('incident_severities', models.JSONField(default=list, help_text='List of incident severities this SLA applies to')), ('incident_priorities', models.JSONField(default=list, help_text='List of incident priorities this SLA applies to')), ('target_duration_minutes', models.PositiveIntegerField(help_text='SLA target in minutes')), ('business_hours_only', models.BooleanField(default=False, help_text='Whether SLA only applies during business hours')), ('escalation_enabled', models.BooleanField(default=True)), ('escalation_threshold_percent', models.FloatField(default=80.0, help_text='Escalate when X% of SLA time has passed', validators=[django.core.validators.MinValueValidator(0.0), django.core.validators.MaxValueValidator(100.0)])), ('is_active', models.BooleanField(default=True)), ('is_default', models.BooleanField(default=False)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('business_hours', models.ForeignKey(blank=True, help_text='Business hours configuration for this SLA', null=True, on_delete=django.db.models.deletion.SET_NULL, to='sla_oncall.businesshours')), ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), ], options={ 'ordering': ['name'], }, ), migrations.CreateModel( name='SLAInstance', fields=[ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('status', models.CharField(choices=[('ACTIVE', 'Active'), ('MET', 'SLA Met'), ('BREACHED', 'SLA Breached'), ('CANCELLED', 'Cancelled')], default='ACTIVE', max_length=20)), ('target_time', models.DateTimeField(help_text='When the SLA should be met')), ('started_at', models.DateTimeField(auto_now_add=True)), ('met_at', models.DateTimeField(blank=True, null=True)), ('breached_at', models.DateTimeField(blank=True, null=True)), ('escalation_triggered', models.BooleanField(default=False)), ('escalation_triggered_at', models.DateTimeField(blank=True, null=True)), ('escalation_level', models.PositiveIntegerField(default=0)), ('response_time', models.DurationField(blank=True, null=True)), ('resolution_time', models.DurationField(blank=True, null=True)), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('escalation_policy', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='sla_oncall.escalationpolicy')), ('incident', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sla_instances', to='incident_intelligence.incident')), ('sla_definition', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sla_oncall.sladefinition')), ], options={ 'ordering': ['-created_at'], }, ), migrations.CreateModel( name='EscalationInstance', fields=[ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('status', models.CharField(choices=[('PENDING', 'Pending'), ('TRIGGERED', 'Triggered'), ('ACKNOWLEDGED', 'Acknowledged'), ('RESOLVED', 'Resolved'), ('CANCELLED', 'Cancelled')], default='PENDING', max_length=20)), ('escalation_level', models.PositiveIntegerField(default=1)), ('current_step', models.PositiveIntegerField(default=0)), ('triggered_at', models.DateTimeField(blank=True, null=True)), ('acknowledged_at', models.DateTimeField(blank=True, null=True)), ('resolved_at', models.DateTimeField(blank=True, null=True)), ('notifications_sent', models.JSONField(default=list, help_text='List of notifications sent during escalation')), ('actions_taken', models.JSONField(default=list, help_text='List of actions taken during escalation')), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('incident', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='escalation_instances', to='incident_intelligence.incident')), ('escalation_policy', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sla_oncall.escalationpolicy')), ('sla_instance', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='escalation_instances', to='sla_oncall.slainstance')), ], options={ 'ordering': ['-created_at'], }, ), migrations.AddIndex( model_name='businesshours', index=models.Index(fields=['is_active', 'is_default'], name='sla_oncall__is_acti_5700c2_idx'), ), migrations.AddIndex( model_name='escalationpolicy', index=models.Index(fields=['escalation_type', 'is_active'], name='sla_oncall__escalat_f6341c_idx'), ), migrations.AddIndex( model_name='escalationpolicy', index=models.Index(fields=['trigger_condition'], name='sla_oncall__trigger_75de52_idx'), ), migrations.AddIndex( model_name='notificationtemplate', index=models.Index(fields=['template_type', 'channel_type'], name='sla_oncall__templat_a3daf6_idx'), ), migrations.AddIndex( model_name='notificationtemplate', index=models.Index(fields=['is_active'], name='sla_oncall__is_acti_cb24d6_idx'), ), migrations.AlterUniqueTogether( name='notificationtemplate', unique_together={('template_type', 'channel_type', 'name')}, ), migrations.AddIndex( model_name='oncallrotation', index=models.Index(fields=['status', 'rotation_type'], name='sla_oncall__status_0522d6_idx'), ), migrations.AddIndex( model_name='oncallrotation', index=models.Index(fields=['external_system'], name='sla_oncall__externa_ad3fd1_idx'), ), migrations.AddIndex( model_name='oncallassignment', index=models.Index(fields=['rotation', 'start_time'], name='sla_oncall__rotatio_2db363_idx'), ), migrations.AddIndex( model_name='oncallassignment', index=models.Index(fields=['user', 'start_time'], name='sla_oncall__user_id_0776dc_idx'), ), migrations.AddIndex( model_name='oncallassignment', index=models.Index(fields=['status', 'start_time'], name='sla_oncall__status_3bec52_idx'), ), migrations.AddIndex( model_name='sladefinition', index=models.Index(fields=['sla_type', 'is_active'], name='sla_oncall__sla_typ_f69c8d_idx'), ), migrations.AddIndex( model_name='sladefinition', index=models.Index(fields=['incident_severities'], name='sla_oncall__inciden_ba4baa_idx'), ), migrations.AddIndex( model_name='sladefinition', index=models.Index(fields=['incident_categories'], name='sla_oncall__inciden_da3c38_idx'), ), migrations.AddIndex( model_name='slainstance', index=models.Index(fields=['incident', 'status'], name='sla_oncall__inciden_723905_idx'), ), migrations.AddIndex( model_name='slainstance', index=models.Index(fields=['sla_definition', 'status'], name='sla_oncall__sla_def_57544b_idx'), ), migrations.AddIndex( model_name='slainstance', index=models.Index(fields=['target_time', 'status'], name='sla_oncall__target__b6b252_idx'), ), migrations.AddIndex( model_name='escalationinstance', index=models.Index(fields=['incident', 'status'], name='sla_oncall__inciden_58c9bd_idx'), ), migrations.AddIndex( model_name='escalationinstance', index=models.Index(fields=['escalation_policy', 'status'], name='sla_oncall__escalat_f748a6_idx'), ), migrations.AddIndex( model_name='escalationinstance', index=models.Index(fields=['triggered_at'], name='sla_oncall__trigger_a8b2b2_idx'), ), ]