# Generated by Django 5.0.14 on 2026-01-08 06:56 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 = [ ('contenttypes', '0002_remove_content_type_name'), ('organizations', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( name='PXAction', fields=[ ('created_at', models.DateTimeField(auto_now_add=True, db_index=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('source_type', models.CharField(choices=[('survey', 'Negative Survey'), ('complaint', 'Complaint'), ('complaint_resolution', 'Negative Complaint Resolution'), ('social_media', 'Social Media'), ('call_center', 'Call Center'), ('kpi', 'KPI Decline'), ('manual', 'Manual')], db_index=True, max_length=50)), ('object_id', models.UUIDField(blank=True, null=True)), ('title', models.CharField(max_length=500)), ('description', models.TextField()), ('category', models.CharField(choices=[('clinical_quality', 'Clinical Quality'), ('patient_safety', 'Patient Safety'), ('service_quality', 'Service Quality'), ('staff_behavior', 'Staff Behavior'), ('facility', 'Facility & Environment'), ('process_improvement', 'Process Improvement'), ('other', 'Other')], db_index=True, max_length=100)), ('priority', models.CharField(choices=[('low', 'Low'), ('medium', 'Medium'), ('high', 'High'), ('critical', 'Critical')], db_index=True, default='medium', max_length=20)), ('severity', models.CharField(choices=[('low', 'Low'), ('medium', 'Medium'), ('high', 'High'), ('critical', 'Critical')], db_index=True, default='medium', max_length=20)), ('status', models.CharField(choices=[('open', 'Open'), ('in_progress', 'In Progress'), ('pending_approval', 'Pending Approval'), ('approved', 'Approved'), ('closed', 'Closed'), ('cancelled', 'Cancelled')], db_index=True, default='open', max_length=20)), ('assigned_at', models.DateTimeField(blank=True, null=True)), ('due_at', models.DateTimeField(db_index=True, help_text='SLA deadline')), ('is_overdue', models.BooleanField(db_index=True, default=False)), ('reminder_sent_at', models.DateTimeField(blank=True, null=True)), ('escalated_at', models.DateTimeField(blank=True, null=True)), ('escalation_level', models.IntegerField(default=0, help_text='Number of times escalated')), ('requires_approval', models.BooleanField(default=True, help_text='Requires PX Admin approval before closure')), ('approved_at', models.DateTimeField(blank=True, null=True)), ('closed_at', models.DateTimeField(blank=True, null=True)), ('action_plan', models.TextField(blank=True)), ('outcome', models.TextField(blank=True)), ('metadata', models.JSONField(blank=True, default=dict)), ('approved_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='approved_actions', to=settings.AUTH_USER_MODEL)), ('assigned_to', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned_actions', to=settings.AUTH_USER_MODEL)), ('closed_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='closed_actions', to=settings.AUTH_USER_MODEL)), ('content_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), ('department', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='px_actions', to='organizations.department')), ('hospital', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='px_actions', to='organizations.hospital')), ], options={ 'ordering': ['-created_at'], }, ), migrations.CreateModel( name='PXActionAttachment', fields=[ ('created_at', models.DateTimeField(auto_now_add=True, db_index=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('file', models.FileField(upload_to='actions/%Y/%m/%d/')), ('filename', models.CharField(max_length=500)), ('file_type', models.CharField(blank=True, max_length=100)), ('file_size', models.IntegerField(help_text='File size in bytes')), ('description', models.TextField(blank=True)), ('is_evidence', models.BooleanField(default=False, help_text='Mark as evidence for closure')), ('action', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to='px_action_center.pxaction')), ('uploaded_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='action_attachments', to=settings.AUTH_USER_MODEL)), ], options={ 'ordering': ['-created_at'], }, ), migrations.CreateModel( name='PXActionLog', fields=[ ('created_at', models.DateTimeField(auto_now_add=True, db_index=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('log_type', models.CharField(choices=[('status_change', 'Status Change'), ('assignment', 'Assignment'), ('escalation', 'Escalation'), ('note', 'Note'), ('evidence', 'Evidence Added'), ('approval', 'Approval'), ('sla_reminder', 'SLA Reminder')], db_index=True, max_length=50)), ('message', models.TextField()), ('old_status', models.CharField(blank=True, max_length=20)), ('new_status', models.CharField(blank=True, max_length=20)), ('metadata', models.JSONField(blank=True, default=dict)), ('action', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='logs', to='px_action_center.pxaction')), ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='action_logs', to=settings.AUTH_USER_MODEL)), ], options={ 'ordering': ['-created_at'], }, ), migrations.CreateModel( name='PXActionSLAConfig', fields=[ ('created_at', models.DateTimeField(auto_now_add=True, db_index=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('name', models.CharField(max_length=200)), ('critical_hours', models.IntegerField(default=24)), ('high_hours', models.IntegerField(default=48)), ('medium_hours', models.IntegerField(default=72)), ('low_hours', models.IntegerField(default=120)), ('reminder_hours_before', models.IntegerField(default=4, help_text='Send reminder X hours before due')), ('auto_escalate', models.BooleanField(default=True, help_text='Automatically escalate when overdue')), ('escalation_delay_hours', models.IntegerField(default=2, help_text='Hours after overdue before escalation')), ('is_active', models.BooleanField(default=True)), ('department', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='action_sla_configs', to='organizations.department')), ('hospital', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='action_sla_configs', to='organizations.hospital')), ], options={ 'ordering': ['hospital', 'name'], }, ), migrations.CreateModel( name='RoutingRule', fields=[ ('created_at', models.DateTimeField(auto_now_add=True, db_index=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), ('name', models.CharField(max_length=200)), ('description', models.TextField(blank=True)), ('source_type', models.CharField(blank=True, choices=[('survey', 'Negative Survey'), ('complaint', 'Complaint'), ('complaint_resolution', 'Negative Complaint Resolution'), ('social_media', 'Social Media'), ('call_center', 'Call Center'), ('kpi', 'KPI Decline'), ('manual', 'Manual')], max_length=50)), ('category', models.CharField(blank=True, max_length=100)), ('severity', models.CharField(blank=True, choices=[('low', 'Low'), ('medium', 'Medium'), ('high', 'High'), ('critical', 'Critical')], max_length=20)), ('assign_to_role', models.CharField(blank=True, help_text="Role to assign to (e.g., 'PX Coordinator')", max_length=50)), ('priority', models.IntegerField(default=0, help_text='Higher priority rules are evaluated first')), ('is_active', models.BooleanField(default=True)), ('assign_to_department', models.ForeignKey(blank=True, help_text='Department to assign to', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='routing_target_rules', to='organizations.department')), ('assign_to_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='routing_rules', to=settings.AUTH_USER_MODEL)), ('department', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='routing_rules', to='organizations.department')), ('hospital', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='routing_rules', to='organizations.hospital')), ], options={ 'ordering': ['-priority', 'name'], }, ), migrations.AddIndex( model_name='pxaction', index=models.Index(fields=['status', '-created_at'], name='px_action_c_status_3bd857_idx'), ), migrations.AddIndex( model_name='pxaction', index=models.Index(fields=['hospital', 'status', '-created_at'], name='px_action_c_hospita_6b2d44_idx'), ), migrations.AddIndex( model_name='pxaction', index=models.Index(fields=['is_overdue', 'status'], name='px_action_c_is_over_e0d12c_idx'), ), migrations.AddIndex( model_name='pxaction', index=models.Index(fields=['due_at', 'status'], name='px_action_c_due_at_947f38_idx'), ), migrations.AddIndex( model_name='pxaction', index=models.Index(fields=['source_type', '-created_at'], name='px_action_c_source__3f0ae5_idx'), ), migrations.AddIndex( model_name='pxactionlog', index=models.Index(fields=['action', '-created_at'], name='px_action_c_action__656e57_idx'), ), ]