diff --git a/apps/accounts/migrations/0001_initial.py b/apps/accounts/migrations/0001_initial.py index 67f5b30..85e0527 100644 --- a/apps/accounts/migrations/0001_initial.py +++ b/apps/accounts/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.utils.timezone import uuid diff --git a/apps/accounts/migrations/0002_initial.py b/apps/accounts/migrations/0002_initial.py index 3d923a7..7467e3b 100644 --- a/apps/accounts/migrations/0002_initial.py +++ b/apps/accounts/migrations/0002_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion from django.conf import settings diff --git a/apps/accounts/migrations/0003_user_explanation_notification_channel_and_more.py b/apps/accounts/migrations/0003_user_explanation_notification_channel_and_more.py new file mode 100644 index 0000000..7b55378 --- /dev/null +++ b/apps/accounts/migrations/0003_user_explanation_notification_channel_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 6.0.1 on 2026-01-12 18:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('accounts', '0002_initial'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='explanation_notification_channel', + field=models.CharField(choices=[('email', 'Email'), ('sms', 'SMS'), ('both', 'Both')], default='email', help_text='Preferred channel for explanation requests', max_length=10), + ), + migrations.AddField( + model_name='user', + name='notification_email_enabled', + field=models.BooleanField(default=True, help_text='Enable email notifications'), + ), + migrations.AddField( + model_name='user', + name='notification_sms_enabled', + field=models.BooleanField(default=False, help_text='Enable SMS notifications'), + ), + migrations.AddField( + model_name='user', + name='preferred_notification_channel', + field=models.CharField(choices=[('email', 'Email'), ('sms', 'SMS'), ('both', 'Both')], default='email', help_text='Preferred notification channel for general notifications', max_length=10), + ), + ] diff --git a/apps/ai_engine/migrations/0001_initial.py b/apps/ai_engine/migrations/0001_initial.py index 3f4e143..5b7fbd5 100644 --- a/apps/ai_engine/migrations/0001_initial.py +++ b/apps/ai_engine/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/analytics/migrations/0001_initial.py b/apps/analytics/migrations/0001_initial.py index 66e3d3d..5dad3d1 100644 --- a/apps/analytics/migrations/0001_initial.py +++ b/apps/analytics/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/appreciation/migrations/0001_initial.py b/apps/appreciation/migrations/0001_initial.py index 572d681..2816c46 100644 --- a/apps/appreciation/migrations/0001_initial.py +++ b/apps/appreciation/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/callcenter/migrations/0001_initial.py b/apps/callcenter/migrations/0001_initial.py index 27f9002..981d56b 100644 --- a/apps/callcenter/migrations/0001_initial.py +++ b/apps/callcenter/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/complaints/forms.py b/apps/complaints/forms.py index ab0e771..ba845d6 100644 --- a/apps/complaints/forms.py +++ b/apps/complaints/forms.py @@ -254,6 +254,153 @@ class PublicComplaintForm(forms.ModelForm): return cleaned_data +class SLAConfigForm(forms.ModelForm): + """Form for creating and editing SLA configurations""" + + class Meta: + model = ComplaintSLAConfig + fields = ['hospital', 'severity', 'priority', 'sla_hours', 'reminder_hours_before', 'is_active'] + widgets = { + 'hospital': forms.Select(attrs={'class': 'form-select'}), + 'severity': forms.Select(attrs={'class': 'form-select'}), + 'priority': forms.Select(attrs={'class': 'form-select'}), + 'sla_hours': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}), + 'reminder_hours_before': forms.NumberInput(attrs={'class': 'form-control', 'min': '0'}), + 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}), + } + + def __init__(self, *args, **kwargs): + user = kwargs.pop('user', None) + super().__init__(*args, **kwargs) + + # Filter hospitals based on user role + if user and not user.is_px_admin() and user.hospital: + self.fields['hospital'].queryset = Hospital.objects.filter(id=user.hospital.id) + self.fields['hospital'].initial = user.hospital + self.fields['hospital'].widget.attrs['readonly'] = True + + def clean(self): + cleaned_data = super().clean() + hospital = cleaned_data.get('hospital') + severity = cleaned_data.get('severity') + priority = cleaned_data.get('priority') + sla_hours = cleaned_data.get('sla_hours') + reminder_hours = cleaned_data.get('reminder_hours_before') + + # Validate SLA hours is positive + if sla_hours and sla_hours <= 0: + raise ValidationError({'sla_hours': 'SLA hours must be greater than 0'}) + + # Validate reminder hours < SLA hours + if sla_hours and reminder_hours and reminder_hours >= sla_hours: + raise ValidationError({'reminder_hours_before': 'Reminder hours must be less than SLA hours'}) + + # Check for unique combination (excluding current instance when editing) + if hospital and severity and priority: + queryset = ComplaintSLAConfig.objects.filter( + hospital=hospital, + severity=severity, + priority=priority + ) + if self.instance.pk: + queryset = queryset.exclude(pk=self.instance.pk) + if queryset.exists(): + raise ValidationError( + 'An SLA configuration for this hospital, severity, and priority already exists.' + ) + + return cleaned_data + + +class EscalationRuleForm(forms.ModelForm): + """Form for creating and editing escalation rules""" + + class Meta: + model = EscalationRule + fields = [ + 'hospital', 'name', 'description', 'escalation_level', 'max_escalation_level', + 'trigger_on_overdue', 'trigger_hours_overdue', + 'reminder_escalation_enabled', 'reminder_escalation_hours', + 'escalate_to_role', 'escalate_to_user', + 'severity_filter', 'priority_filter', 'is_active' + ] + widgets = { + 'hospital': forms.Select(attrs={'class': 'form-select'}), + 'name': forms.TextInput(attrs={'class': 'form-control'}), + 'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 3}), + 'escalation_level': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}), + 'max_escalation_level': forms.NumberInput(attrs={'class': 'form-control', 'min': '1'}), + 'trigger_on_overdue': forms.CheckboxInput(attrs={'class': 'form-check-input'}), + 'trigger_hours_overdue': forms.NumberInput(attrs={'class': 'form-control', 'min': '0'}), + 'reminder_escalation_enabled': forms.CheckboxInput(attrs={'class': 'form-check-input'}), + 'reminder_escalation_hours': forms.NumberInput(attrs={'class': 'form-control', 'min': '0'}), + 'escalate_to_role': forms.Select(attrs={'class': 'form-select', 'id': 'escalate_to_role'}), + 'escalate_to_user': forms.Select(attrs={'class': 'form-select'}), + 'severity_filter': forms.Select(attrs={'class': 'form-select'}), + 'priority_filter': forms.Select(attrs={'class': 'form-select'}), + 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}), + } + + def __init__(self, *args, **kwargs): + user = kwargs.pop('user', None) + super().__init__(*args, **kwargs) + + # Filter hospitals based on user role + if user and not user.is_px_admin() and user.hospital: + self.fields['hospital'].queryset = Hospital.objects.filter(id=user.hospital.id) + self.fields['hospital'].initial = user.hospital + self.fields['hospital'].widget.attrs['readonly'] = True + + # Filter users for escalate_to_user field + from apps.accounts.models import User + if user and user.is_px_admin(): + self.fields['escalate_to_user'].queryset = User.objects.filter(is_active=True) + elif user and user.hospital: + self.fields['escalate_to_user'].queryset = User.objects.filter( + is_active=True, + hospital=user.hospital + ) + else: + self.fields['escalate_to_user'].queryset = User.objects.none() + + def clean(self): + cleaned_data = super().clean() + escalate_to_role = cleaned_data.get('escalate_to_role') + escalate_to_user = cleaned_data.get('escalate_to_user') + + # If role is 'specific_user', user must be specified + if escalate_to_role == 'specific_user' and not escalate_to_user: + raise ValidationError({'escalate_to_user': 'Please select a user when role is set to Specific User'}) + + return cleaned_data + + +class ComplaintThresholdForm(forms.ModelForm): + """Form for creating and editing complaint thresholds""" + + class Meta: + model = ComplaintThreshold + fields = ['hospital', 'threshold_type', 'threshold_value', 'comparison_operator', 'action_type', 'is_active'] + widgets = { + 'hospital': forms.Select(attrs={'class': 'form-select'}), + 'threshold_type': forms.Select(attrs={'class': 'form-select'}), + 'threshold_value': forms.NumberInput(attrs={'class': 'form-control', 'step': '0.1'}), + 'comparison_operator': forms.Select(attrs={'class': 'form-select'}), + 'action_type': forms.Select(attrs={'class': 'form-select'}), + 'is_active': forms.CheckboxInput(attrs={'class': 'form-check-input'}), + } + + def __init__(self, *args, **kwargs): + user = kwargs.pop('user', None) + super().__init__(*args, **kwargs) + + # Filter hospitals based on user role + if user and not user.is_px_admin() and user.hospital: + self.fields['hospital'].queryset = Hospital.objects.filter(id=user.hospital.id) + self.fields['hospital'].initial = user.hospital + self.fields['hospital'].widget.attrs['readonly'] = True + + class ComplaintForm(forms.ModelForm): """ Form for creating complaints by authenticated users. diff --git a/apps/complaints/migrations/0001_initial.py b/apps/complaints/migrations/0001_initial.py index d856b47..23a92f4 100644 --- a/apps/complaints/migrations/0001_initial.py +++ b/apps/complaints/migrations/0001_initial.py @@ -1,5 +1,4 @@ -# Generated by Django 6.0.1 on 2026-01-15 12:02 -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/complaints/migrations/0002_initial.py b/apps/complaints/migrations/0002_initial.py index 78f119d..2f57c66 100644 --- a/apps/complaints/migrations/0002_initial.py +++ b/apps/complaints/migrations/0002_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion from django.conf import settings diff --git a/apps/complaints/migrations/0003_initial.py b/apps/complaints/migrations/0003_initial.py index b38faa2..8f9537a 100644 --- a/apps/complaints/migrations/0003_initial.py +++ b/apps/complaints/migrations/0003_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion from django.conf import settings diff --git a/apps/complaints/migrations/0004_add_second_reminder_sent_at.py b/apps/complaints/migrations/0004_add_second_reminder_sent_at.py new file mode 100644 index 0000000..d1586b1 --- /dev/null +++ b/apps/complaints/migrations/0004_add_second_reminder_sent_at.py @@ -0,0 +1,68 @@ +# Generated by Django 6.0.1 on 2026-01-13 20:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('complaints', '0003_initial'), + ] + + operations = [ + migrations.AddField( + model_name='complaint', + name='second_reminder_sent_at', + field=models.DateTimeField(blank=True, help_text='Second SLA reminder timestamp', null=True), + ), + migrations.AddField( + model_name='complaintslaconfig', + name='second_reminder_enabled', + field=models.BooleanField(default=False, help_text='Enable sending a second reminder'), + ), + migrations.AddField( + model_name='complaintslaconfig', + name='second_reminder_hours_before', + field=models.IntegerField(default=6, help_text='Send second reminder X hours before deadline'), + ), + migrations.AddField( + model_name='complaintslaconfig', + name='thank_you_email_enabled', + field=models.BooleanField(default=False, help_text='Send thank you email when complaint is closed'), + ), + migrations.AddField( + model_name='escalationrule', + name='escalation_level', + field=models.IntegerField(default=1, help_text='Escalation level (1 = first level, 2 = second, etc.)'), + ), + migrations.AddField( + model_name='escalationrule', + name='max_escalation_level', + field=models.IntegerField(default=3, help_text='Maximum escalation level before stopping (default: 3)'), + ), + migrations.AddField( + model_name='escalationrule', + name='reminder_escalation_enabled', + field=models.BooleanField(default=False, help_text='Enable escalation after reminder if no action taken'), + ), + migrations.AddField( + model_name='escalationrule', + name='reminder_escalation_hours', + field=models.IntegerField(default=24, help_text='Escalate X hours after reminder if no action'), + ), + migrations.AlterField( + model_name='complaint', + name='reminder_sent_at', + field=models.DateTimeField(blank=True, help_text='First SLA reminder timestamp', null=True), + ), + migrations.AlterField( + model_name='complaintslaconfig', + name='reminder_hours_before', + field=models.IntegerField(default=24, help_text='Send first reminder X hours before deadline'), + ), + migrations.AlterField( + model_name='escalationrule', + name='escalate_to_role', + field=models.CharField(choices=[('department_manager', 'Department Manager'), ('hospital_admin', 'Hospital Admin'), ('px_admin', 'PX Admin'), ('ceo', 'CEO'), ('specific_user', 'Specific User')], help_text='Role to escalate to', max_length=50), + ), + ] diff --git a/apps/complaints/migrations/0005_complaintexplanation_escalated_at_and_more.py b/apps/complaints/migrations/0005_complaintexplanation_escalated_at_and_more.py new file mode 100644 index 0000000..f1cfc1d --- /dev/null +++ b/apps/complaints/migrations/0005_complaintexplanation_escalated_at_and_more.py @@ -0,0 +1,62 @@ +# Generated by Django 6.0.1 on 2026-01-14 12:36 + +import django.db.models.deletion +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('complaints', '0004_add_second_reminder_sent_at'), + ('organizations', '0004_staff_location_staff_name_staff_phone'), + ] + + operations = [ + migrations.AddField( + model_name='complaintexplanation', + name='escalated_at', + field=models.DateTimeField(blank=True, help_text='When explanation was escalated to manager', null=True), + ), + migrations.AddField( + model_name='complaintexplanation', + name='escalated_to_manager', + field=models.ForeignKey(blank=True, help_text="Escalated to this explanation (manager's explanation request)", null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='escalated_from_staff', to='complaints.complaintexplanation'), + ), + migrations.AddField( + model_name='complaintexplanation', + name='is_overdue', + field=models.BooleanField(db_index=True, default=False, help_text='Explanation request is overdue'), + ), + migrations.AddField( + model_name='complaintexplanation', + name='reminder_sent_at', + field=models.DateTimeField(blank=True, help_text='Reminder sent to staff about overdue explanation', null=True), + ), + migrations.AddField( + model_name='complaintexplanation', + name='sla_due_at', + field=models.DateTimeField(blank=True, db_index=True, help_text='SLA deadline for staff to submit explanation', null=True), + ), + migrations.CreateModel( + name='ExplanationSLAConfig', + 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)), + ('response_hours', models.IntegerField(default=48, help_text='Hours staff has to submit explanation')), + ('reminder_hours_before', models.IntegerField(default=12, help_text='Send reminder X hours before deadline')), + ('auto_escalate_enabled', models.BooleanField(default=True, help_text='Automatically escalate to manager if no response')), + ('escalation_hours_overdue', models.IntegerField(default=0, help_text='Escalate X hours after overdue (0 = immediately)')), + ('max_escalation_levels', models.IntegerField(default=3, help_text='Maximum levels to escalate up staff hierarchy')), + ('is_active', models.BooleanField(default=True)), + ('hospital', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='explanation_sla_configs', to='organizations.hospital')), + ], + options={ + 'verbose_name': 'Explanation SLA Config', + 'verbose_name_plural': 'Explanation SLA Configs', + 'ordering': ['hospital'], + 'indexes': [models.Index(fields=['hospital', 'is_active'], name='complaints__hospita_fe4ec5_idx')], + }, + ), + ] diff --git a/apps/complaints/models.py b/apps/complaints/models.py index faad4ff..8cc7f35 100644 --- a/apps/complaints/models.py +++ b/apps/complaints/models.py @@ -169,7 +169,7 @@ class Complaint(UUIDModel, TimeStampedModel): related_name="complaints", null=True, blank=True, - help_text="Source of complaint" + help_text="Source of complaint", ) # Creator tracking @@ -761,7 +761,7 @@ class Inquiry(UUIDModel, TimeStampedModel): related_name="inquiries", null=True, blank=True, - help_text="Source of inquiry" + help_text="Source of inquiry", ) # Status diff --git a/apps/complaints/ui_views.py b/apps/complaints/ui_views.py index fdc6cc4..b368f5e 100644 --- a/apps/complaints/ui_views.py +++ b/apps/complaints/ui_views.py @@ -1,8 +1,6 @@ """ Complaints UI views - Server-rendered templates for complaints console """ - - from django.contrib import messages from django.contrib.auth.decorators import login_required from django.core.paginator import Paginator @@ -242,14 +240,17 @@ def complaint_detail(request, pk): explanation_attachments = explanation.attachments.all() context = { - 'complaint': complaint, - 'timeline': timeline, - 'attachments': attachments, - 'px_actions': px_actions, - 'assignable_users': assignable_users, - 'status_choices': ComplaintStatus.choices, - 'can_edit': user.is_px_admin() or user.is_hospital_admin(), - 'hospital_departments': hospital_departments, + "complaint": complaint, + "timeline": timeline, + "attachments": attachments, + "px_actions": px_actions, + "assignable_users": assignable_users, + "status_choices": ComplaintStatus.choices, + "can_edit": user.is_px_admin() or user.is_hospital_admin(), + "hospital_departments": hospital_departments, + "explanation": explanation, + "explanations": explanations, + "explanation_attachments": explanation_attachments, 'base_layout': base_layout, 'source_user': source_user, "complaint": complaint, @@ -403,6 +404,9 @@ def complaint_create(request): except ComplaintCategory.DoesNotExist: messages.error(request, "Selected category not found.") return redirect("complaints:complaint_create") + except Exception as e: + messages.error(request, f"Error creating complaint: {str(e)}") + return redirect("complaints:complaint_create") # GET request - show form # Check for hospital parameter from URL (for pre-selection) diff --git a/apps/core/migrations/0001_initial.py b/apps/core/migrations/0001_initial.py index 7fae5e7..d4b7acc 100644 --- a/apps/core/migrations/0001_initial.py +++ b/apps/core/migrations/0001_initial.py @@ -1,4 +1,8 @@ +<<<<<<< HEAD # Generated by Django 6.0 on 2026-01-12 09:50 +======= +# Generated by Django 6.0.1 on 2026-01-12 09:50 +>>>>>>> 1f9d8a7 (update on the complaint sla and staff hierarchy) import django.db.models.deletion import uuid diff --git a/apps/feedback/migrations/0001_initial.py b/apps/feedback/migrations/0001_initial.py index 8ac4855..f05b8c7 100644 --- a/apps/feedback/migrations/0001_initial.py +++ b/apps/feedback/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0.1 on 2026-01-15 12:02 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/feedback/migrations/0002_initial.py b/apps/feedback/migrations/0002_initial.py index 7a12514..2dd8502 100644 --- a/apps/feedback/migrations/0002_initial.py +++ b/apps/feedback/migrations/0002_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion from django.conf import settings diff --git a/apps/feedback/migrations/0003_initial.py b/apps/feedback/migrations/0003_initial.py index b86ab6a..44d2190 100644 --- a/apps/feedback/migrations/0003_initial.py +++ b/apps/feedback/migrations/0003_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion from django.conf import settings diff --git a/apps/integrations/migrations/0001_initial.py b/apps/integrations/migrations/0001_initial.py index dc082dc..3175c56 100644 --- a/apps/integrations/migrations/0001_initial.py +++ b/apps/integrations/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/journeys/migrations/0001_initial.py b/apps/journeys/migrations/0001_initial.py index 07dedf4..bcddf72 100644 --- a/apps/journeys/migrations/0001_initial.py +++ b/apps/journeys/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/journeys/migrations/0002_initial.py b/apps/journeys/migrations/0002_initial.py index fb75bfe..1df1564 100644 --- a/apps/journeys/migrations/0002_initial.py +++ b/apps/journeys/migrations/0002_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion from django.db import migrations, models diff --git a/apps/notifications/migrations/0001_initial.py b/apps/notifications/migrations/0001_initial.py index 12978eb..7e3295c 100644 --- a/apps/notifications/migrations/0001_initial.py +++ b/apps/notifications/migrations/0001_initial.py @@ -1,4 +1,8 @@ +<<<<<<< HEAD # Generated by Django 6.0 on 2026-01-12 09:50 +======= +# Generated by Django 6.0.1 on 2026-01-12 09:50 +>>>>>>> 1f9d8a7 (update on the complaint sla and staff hierarchy) import django.db.models.deletion import uuid diff --git a/apps/observations/migrations/0001_initial.py b/apps/observations/migrations/0001_initial.py index dfaacfd..a059f26 100644 --- a/apps/observations/migrations/0001_initial.py +++ b/apps/observations/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import apps.observations.models import django.db.models.deletion diff --git a/apps/organizations/migrations/0001_initial.py b/apps/organizations/migrations/0001_initial.py index 04d519d..8b6a98d 100644 --- a/apps/organizations/migrations/0001_initial.py +++ b/apps/organizations/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/organizations/migrations/0002_hospital_ceo_hospital_cfo_hospital_coo_and_more.py b/apps/organizations/migrations/0002_hospital_ceo_hospital_cfo_hospital_coo_and_more.py new file mode 100644 index 0000000..c72a07b --- /dev/null +++ b/apps/organizations/migrations/0002_hospital_ceo_hospital_cfo_hospital_coo_and_more.py @@ -0,0 +1,41 @@ +# Generated by Django 6.0.1 on 2026-01-13 13:07 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('organizations', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AddField( + model_name='hospital', + name='ceo', + field=models.ForeignKey(blank=True, help_text='Chief Executive Officer', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='hospitals_as_ceo', to=settings.AUTH_USER_MODEL, verbose_name='CEO'), + ), + migrations.AddField( + model_name='hospital', + name='cfo', + field=models.ForeignKey(blank=True, help_text='Chief Financial Officer', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='hospitals_as_cfo', to=settings.AUTH_USER_MODEL, verbose_name='CFO'), + ), + migrations.AddField( + model_name='hospital', + name='coo', + field=models.ForeignKey(blank=True, help_text='Chief Operating Officer', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='hospitals_as_coo', to=settings.AUTH_USER_MODEL, verbose_name='COO'), + ), + migrations.AddField( + model_name='hospital', + name='medical_director', + field=models.ForeignKey(blank=True, help_text='Medical Director', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='hospitals_as_medical_director', to=settings.AUTH_USER_MODEL, verbose_name='Medical Director'), + ), + migrations.AlterField( + model_name='hospital', + name='metadata', + field=models.JSONField(blank=True, default=dict, help_text='Hospital configuration settings'), + ), + ] diff --git a/apps/organizations/migrations/0003_staff_country_staff_department_name_staff_gender_and_more.py b/apps/organizations/migrations/0003_staff_country_staff_department_name_staff_gender_and_more.py new file mode 100644 index 0000000..d94f088 --- /dev/null +++ b/apps/organizations/migrations/0003_staff_country_staff_department_name_staff_gender_and_more.py @@ -0,0 +1,44 @@ +# Generated by Django 6.0.1 on 2026-01-13 13:35 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('organizations', '0002_hospital_ceo_hospital_cfo_hospital_coo_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='staff', + name='country', + field=models.CharField(blank=True, max_length=100, verbose_name='Country'), + ), + migrations.AddField( + model_name='staff', + name='department_name', + field=models.CharField(blank=True, max_length=200, verbose_name='Department (Original)'), + ), + migrations.AddField( + model_name='staff', + name='gender', + field=models.CharField(blank=True, choices=[('male', 'Male'), ('female', 'Female'), ('other', 'Other')], max_length=10), + ), + migrations.AddField( + model_name='staff', + name='report_to', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='direct_reports', to='organizations.staff', verbose_name='Reports To'), + ), + migrations.AddField( + model_name='staff', + name='section', + field=models.CharField(blank=True, max_length=200, verbose_name='Section'), + ), + migrations.AddField( + model_name='staff', + name='subsection', + field=models.CharField(blank=True, max_length=200, verbose_name='Subsection'), + ), + ] diff --git a/apps/organizations/migrations/0004_staff_location_staff_name_staff_phone.py b/apps/organizations/migrations/0004_staff_location_staff_name_staff_phone.py new file mode 100644 index 0000000..78aad8c --- /dev/null +++ b/apps/organizations/migrations/0004_staff_location_staff_name_staff_phone.py @@ -0,0 +1,28 @@ +# Generated by Django 6.0.1 on 2026-01-13 13:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('organizations', '0003_staff_country_staff_department_name_staff_gender_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='staff', + name='location', + field=models.CharField(blank=True, max_length=200, verbose_name='Location'), + ), + migrations.AddField( + model_name='staff', + name='name', + field=models.CharField(blank=True, max_length=300, verbose_name='Full Name (Original)'), + ), + migrations.AddField( + model_name='staff', + name='phone', + field=models.CharField(blank=True, max_length=20, verbose_name='Phone Number'), + ), + ] diff --git a/apps/physicians/migrations/0001_initial.py b/apps/physicians/migrations/0001_initial.py index bba5ef5..211d14c 100644 --- a/apps/physicians/migrations/0001_initial.py +++ b/apps/physicians/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/projects/migrations/0001_initial.py b/apps/projects/migrations/0001_initial.py index de3c36b..f547dca 100644 --- a/apps/projects/migrations/0001_initial.py +++ b/apps/projects/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0 on 2026-01-12 09:50 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/projects/migrations/0002_initial.py b/apps/projects/migrations/0002_initial.py index 2fe3f6d..46a13cb 100644 --- a/apps/projects/migrations/0002_initial.py +++ b/apps/projects/migrations/0002_initial.py @@ -1,4 +1,8 @@ +<<<<<<< HEAD # Generated by Django 6.0 on 2026-01-12 09:50 +======= +# Generated by Django 6.0.1 on 2026-01-12 09:50 +>>>>>>> 1f9d8a7 (update on the complaint sla and staff hierarchy) import django.db.models.deletion from django.conf import settings diff --git a/apps/px_action_center/migrations/0001_initial.py b/apps/px_action_center/migrations/0001_initial.py index 0374b7b..6161572 100644 --- a/apps/px_action_center/migrations/0001_initial.py +++ b/apps/px_action_center/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0.1 on 2026-01-15 12:02 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/px_sources/migrations/0001_initial.py b/apps/px_sources/migrations/0001_initial.py index e209df0..2195c2c 100644 --- a/apps/px_sources/migrations/0001_initial.py +++ b/apps/px_sources/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0.1 on 2026-01-15 12:02 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.db.models.deletion import uuid diff --git a/apps/references/migrations/0001_initial.py b/apps/references/migrations/0001_initial.py index 0059d7a..4fde651 100644 --- a/apps/references/migrations/0001_initial.py +++ b/apps/references/migrations/0001_initial.py @@ -1,4 +1,8 @@ +<<<<<<< HEAD # Generated by Django 6.0 on 2026-01-12 09:50 +======= +# Generated by Django 6.0.1 on 2026-01-12 09:50 +>>>>>>> 1f9d8a7 (update on the complaint sla and staff hierarchy) import apps.references.models import django.db.models.deletion diff --git a/apps/social/migrations/0001_initial.py b/apps/social/migrations/0001_initial.py index c48e640..f0204af 100644 --- a/apps/social/migrations/0001_initial.py +++ b/apps/social/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0.1 on 2026-01-15 12:02 +# Generated by Django 6.0.1 on 2026-01-12 09:50 from django.db import migrations, models diff --git a/apps/standards/migrations/0001_initial.py b/apps/standards/migrations/0001_initial.py index 0cfae8c..62877fe 100644 --- a/apps/standards/migrations/0001_initial.py +++ b/apps/standards/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 6.0.1 on 2026-01-15 12:02 +# Generated by Django 6.0.1 on 2026-01-12 09:50 import django.core.validators import django.db.models.deletion diff --git a/apps/surveys/migrations/0001_initial.py b/apps/surveys/migrations/0001_initial.py index 96193fb..de07dd1 100644 --- a/apps/surveys/migrations/0001_initial.py +++ b/apps/surveys/migrations/0001_initial.py @@ -1,4 +1,8 @@ +<<<<<<< HEAD # Generated by Django 6.0 on 2026-01-12 09:50 +======= +# Generated by Django 6.0.1 on 2026-01-12 09:50 +>>>>>>> 1f9d8a7 (update on the complaint sla and staff hierarchy) import django.db.models.deletion import uuid