update on the complaint sla and staff hierarchy
This commit is contained in:
parent
dcb6455819
commit
aac8698df4
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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),
|
||||
),
|
||||
]
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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),
|
||||
),
|
||||
]
|
||||
@ -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')],
|
||||
},
|
||||
),
|
||||
]
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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'),
|
||||
),
|
||||
]
|
||||
@ -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'),
|
||||
),
|
||||
]
|
||||
@ -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'),
|
||||
),
|
||||
]
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user