284 lines
18 KiB
Python
284 lines
18 KiB
Python
# 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'),
|
|
),
|
|
]
|