HH/apps/complaints/management/commands/seed_complaint_configs.py
ismail c5f76b3855
Some checks are pending
Build and Push Docker Image / build (push) Waiting to run
updates
2026-05-11 14:45:30 +03:00

295 lines
11 KiB
Python

"""
Management command to seed default complaint configurations
"""
from django.core.management.base import BaseCommand
from django.db import transaction
from apps.complaints.models import (
ComplaintCategory,
ComplaintSLAConfig,
ComplaintThreshold,
EscalationRule,
InquirySLAConfig,
)
from apps.organizations.models import Hospital
class Command(BaseCommand):
help = 'Seed default complaint configurations (categories, SLA configs, thresholds, escalation rules)'
def add_arguments(self, parser):
parser.add_argument(
'--hospital-id',
type=str,
help='Specific hospital ID to seed configs for',
)
def handle(self, *args, **options):
hospital_id = options.get('hospital_id')
if hospital_id:
try:
hospitals = [Hospital.objects.get(id=hospital_id)]
self.stdout.write(f"Seeding configs for hospital: {hospitals[0].name}")
except Hospital.DoesNotExist:
self.stdout.write(self.style.ERROR(f"Hospital with ID {hospital_id} not found"))
return
else:
hospitals = Hospital.objects.filter(status='active')
self.stdout.write(f"Seeding configs for {hospitals.count()} active hospitals")
with transaction.atomic():
# Seed system-wide categories first
self.seed_system_categories()
# Seed per-hospital configurations
for hospital in hospitals:
self.stdout.write(f"\nProcessing hospital: {hospital.name}")
self.seed_sla_configs(hospital)
self.seed_thresholds(hospital)
self.seed_escalation_rules(hospital)
self.seed_inquiry_dept_response_sla(hospital)
self.stdout.write(self.style.SUCCESS('\nSuccessfully seeded complaint configurations!'))
def seed_system_categories(self):
"""Seed system-wide complaint categories"""
self.stdout.write("Seeding system-wide categories...")
categories = [
{
'code': 'clinical_care',
'name_en': 'Clinical Care',
'name_ar': 'الرعاية السريرية',
'description_en': 'Issues related to medical treatment and clinical services',
'order': 1
},
{
'code': 'staff_behavior',
'name_en': 'Staff Behavior',
'name_ar': 'سلوك الموظفين',
'description_en': 'Issues related to staff conduct and professionalism',
'order': 2
},
{
'code': 'facility',
'name_en': 'Facility & Environment',
'name_ar': 'المرافق والبيئة',
'description_en': 'Issues related to hospital facilities and cleanliness',
'order': 3
},
{
'code': 'wait_time',
'name_en': 'Wait Time',
'name_ar': 'وقت الانتظار',
'description_en': 'Issues related to waiting times and delays',
'order': 4
},
{
'code': 'billing',
'name_en': 'Billing',
'name_ar': 'الفواتير',
'description_en': 'Issues related to billing and payments',
'order': 5
},
{
'code': 'communication',
'name_en': 'Communication',
'name_ar': 'التواصل',
'description_en': 'Issues related to communication with staff',
'order': 6
},
{
'code': 'other',
'name_en': 'Other',
'name_ar': 'أخرى',
'description_en': 'Other complaints not covered by above categories',
'order': 7
},
]
created_count = 0
for cat_data in categories:
category, created = ComplaintCategory.objects.get_or_create(
code=cat_data['code'],
parent__isnull=True, # System-wide categories have no parent
defaults={
'name_en': cat_data['name_en'],
'name_ar': cat_data['name_ar'],
'description_en': cat_data['description_en'],
'order': cat_data['order'],
'is_active': True
}
)
if created:
created_count += 1
self.stdout.write(f" Created category: {category.name_en}")
self.stdout.write(self.style.SUCCESS(f" Created {created_count} system categories"))
def seed_sla_configs(self, hospital):
"""Seed SLA configurations for a hospital"""
self.stdout.write(f" Seeding SLA configs...")
# Define SLA hours based on severity and priority
sla_matrix = [
# (severity, priority, sla_hours, reminder_hours)
('critical', 'urgent', 4, 2),
('critical', 'high', 8, 4),
('critical', 'medium', 12, 6),
('critical', 'low', 24, 12),
('high', 'urgent', 8, 4),
('high', 'high', 12, 6),
('high', 'medium', 24, 12),
('high', 'low', 48, 24),
('medium', 'urgent', 12, 6),
('medium', 'high', 24, 12),
('medium', 'medium', 48, 24),
('medium', 'low', 72, 36),
('low', 'urgent', 24, 12),
('low', 'high', 48, 24),
('low', 'medium', 72, 36),
('low', 'low', 120, 48),
]
created_count = 0
for severity, priority, sla_hours, reminder_hours in sla_matrix:
config, created = ComplaintSLAConfig.objects.get_or_create(
hospital=hospital,
severity=severity,
priority=priority,
defaults={
'sla_hours': sla_hours,
'reminder_hours_before': reminder_hours,
'is_active': True
}
)
if created:
created_count += 1
self.stdout.write(f" Created {created_count} SLA configs")
def seed_thresholds(self, hospital):
"""Seed complaint thresholds for a hospital"""
self.stdout.write(f" Seeding thresholds...")
thresholds = [
{
'threshold_type': 'resolution_survey_score',
'threshold_value': 50.0,
'comparison_operator': 'lt',
'action_type': 'create_px_action',
},
]
created_count = 0
for threshold_data in thresholds:
threshold, created = ComplaintThreshold.objects.get_or_create(
hospital=hospital,
threshold_type=threshold_data['threshold_type'],
defaults={
'threshold_value': threshold_data['threshold_value'],
'comparison_operator': threshold_data['comparison_operator'],
'action_type': threshold_data['action_type'],
'is_active': True
}
)
if created:
created_count += 1
self.stdout.write(f" Created {created_count} thresholds")
def seed_escalation_rules(self, hospital):
"""Seed escalation rules for a hospital"""
self.stdout.write(f" Seeding escalation rules...")
rules = [
{
'name': 'Default Escalation to Department Manager',
'description': 'Escalate overdue complaints to department manager',
'trigger_on_overdue': True,
'trigger_hours_overdue': 0,
'escalate_to_role': 'department_manager',
'order': 1,
},
{
'name': 'Critical Escalation to Hospital Admin',
'description': 'Escalate critical complaints to hospital admin after 4 hours overdue',
'trigger_on_overdue': True,
'trigger_hours_overdue': 4,
'escalate_to_role': 'hospital_admin',
'severity_filter': 'critical',
'order': 2,
},
{
'name': 'Final Escalation to PX Admin',
'description': 'Escalate to PX Admin after 24 hours overdue',
'trigger_on_overdue': True,
'trigger_hours_overdue': 24,
'escalate_to_role': 'px_admin',
'order': 3,
},
]
created_count = 0
for rule_data in rules:
rule, created = EscalationRule.objects.get_or_create(
hospital=hospital,
name=rule_data['name'],
defaults={
'description': rule_data['description'],
'trigger_on_overdue': rule_data['trigger_on_overdue'],
'trigger_hours_overdue': rule_data['trigger_hours_overdue'],
'escalate_to_role': rule_data['escalate_to_role'],
'severity_filter': rule_data.get('severity_filter', ''),
'order': rule_data['order'],
'is_active': True
}
)
if created:
created_count += 1
self.stdout.write(f" Created {created_count} escalation rules")
def seed_inquiry_dept_response_sla(self, hospital):
"""Seed department response SLA defaults for inquiry configs"""
self.stdout.write(f" Seeding inquiry dept response SLA defaults...")
updated_count = 0
configs = InquirySLAConfig.objects.filter(hospital=hospital, is_active=True)
for config in configs:
if config.dept_response_hours == 48:
continue
config.dept_response_hours = 48
config.dept_response_reminder_hours_before = 12
config.dept_response_second_reminder_enabled = True
config.dept_response_second_reminder_hours_before = 4
config.dept_response_auto_escalate_enabled = True
config.dept_response_escalation_hours_overdue = 0
config.save()
updated_count += 1
if updated_count == 0:
config, created = InquirySLAConfig.objects.get_or_create(
hospital=hospital,
source=None,
defaults={
'sla_hours': 72,
'reminder_hours_before': 24,
'dept_response_hours': 48,
'dept_response_reminder_hours_before': 12,
'dept_response_second_reminder_enabled': True,
'dept_response_second_reminder_hours_before': 4,
'dept_response_auto_escalate_enabled': True,
'dept_response_escalation_hours_overdue': 0,
'is_active': True,
},
)
if created:
updated_count = 1
self.stdout.write(f" Updated/created {updated_count} inquiry SLA configs with dept response defaults")