HH/apps/complaints/management/commands/load_shct_taxonomy.py

249 lines
14 KiB
Python

"""
Django management command to load the complete Saudi Healthcare Complaint Taxonomy (SHCT)
This command loads a 4-level taxonomy:
- Level 1: Domain (CLINICAL, MANAGEMENT, RELATIONSHIPS)
- Level 2: Category (Quality, Safety, Communication, etc.)
- Level 3: Subcategory (Examination, Patient Journey, etc.)
- Level 4: Classification (Examination not performed, etc.)
Usage:
python manage.py load_shct_taxonomy
"""
from django.core.management.base import BaseCommand
from apps.complaints.models import ComplaintCategory
class Command(BaseCommand):
help = 'Loads the complete Saudi Healthcare Complaint Taxonomy (Bilingual)'
def handle(self, *args, **kwargs):
# Full SHCT Data Structure: (EN, AR)
shct_data = {
('CLINICAL', 'سريري'): {
('Quality', 'الجودة'): {
('Examination', 'الفحص'): [
('Examination not performed', 'لم يتم إجراء الفحص'),
('Inadequate/incomplete assessment', 'تقييم غير كافٍ / غير مكتمل'),
('Not having enough knowledge regarding patient condition', 'عدم الإلمام الكافي بحالة المريض'),
('Lab tests not performed', 'لم يتم إجراء الفحوصات المخبرية'),
('Diagnostic Imaging not performed', 'لم يتم إجراء التصوير التشخيصي'),
('Loss of a patient sample', 'فقدان عينة المريض'),
],
('Patient Journey', 'رحلة المريض'): [
('Miscoordination', 'سوء التنسيق'),
('Patient flow issues', 'مشاكل تدفق المرضى'),
('Lack of follow up', 'عدم المتابعة'),
],
('Quality of Care', 'جودة الرعاية'): [
('Substandard clinical/nursing care', 'رعاية سريرية/تمريضية دون المستوى'),
('No Frequent rounding on patient', 'عدم المرور الدوري على المريض'),
('Rough treatment', 'المعاملة القاسية'),
('Insensitive to patient needs', 'عدم الحساسية تجاه احتياجات المريض'),
('Rushed, not time to see patients', 'الاستعجال، عدم وجود وقت لرؤية المرضى'),
('No assistance from staff in feeding a patient', 'عدم وجود مساعدة من الموظفين في إطعام المريض'),
],
('Treatment', 'العلاج'): [
('Treatment plan issues', 'مشاكل في الخطة العلاجية'),
('Treatment plan not followed', 'عدم اتباع الخطة العلاجية'),
('Ineffective treatment', 'علاج غير فعال'),
('Inadequate pain management', 'إدارة غير كافية للألم'),
('Patient Discharged before completing treatment', 'خروج المريض قبل استكمال العلاج'),
],
('Diagnosis', 'التشخيص'): [
('Errors in diagnosis', 'أخطاء في التشخيص'),
('Errors in lab results', 'أخطاء في نتائج المختبر'),
('Errors in diagnostic imaging', 'أخطاء في التصوير التشخيصي'),
('Errors in Pre-marriage lab test', 'أخطاء في فحص ما قبل الزواج'),
],
},
('Safety', 'السلامة'): {
('Medication & Vaccination', 'الأدوية واللقاحات'): [
('Prescribing errors', 'أخطاء وصف الدواء'),
('Dispensing errors', 'أخطاء صرف الدواء'),
('No medication prescribed', 'لم يتم وصف دواء'),
('Insufficient medication prescribed', 'وصف دواء غير كافٍ'),
('Dispensing medication without prescription', 'صرف دواء بدون وصفة طبية'),
('Prescription of expired medication', 'وصف دواء منتهي الصلاحية'),
('Medication shortages', 'نقص في الأدوية'),
('Vaccination timing errors', 'أخطاء في توقيت اللقاحات'),
('Refusal to vaccinate', 'الامتناع عن التطعيم'),
],
('Safety Incidents', 'حوادث السلامة'): [
('Equipment failure/malfunction', 'فشل أو عطل في المعدات'),
('No patient ID band', 'عدم وجود سوار تعريف المريض'),
('Wrong treatment', 'علاج خاطئ'),
('Patient Fall', 'سقوط المريض'),
('Hospital acquired infection', 'عدوى مكتسبة من المستشفى'),
('Wrong surgery / Wrong site surgery', 'جراحة خاطئة / موقع جراحة خاطئ'),
('Patient death', 'وفاة المريض'),
],
('Skills and Conduct', 'المهارات والسلوك'): [
('Practice without a clinical license', 'الممارسة بدون ترخيص طبي'),
('Poor hand-hygiene', 'ضعف نظافة اليدين'),
('Improper practice of infection control', 'ممارسة غير صحيحة لمكافحة العدوى'),
]
}
},
('MANAGEMENT', 'إداري'): {
('Institutional Issues', 'القضايا المؤسسية'): {
('Administrative Policies', 'السياسات الإدارية'): [
('Paperwork delays', 'تأخير في المعاملات الورقية'),
('Non-compliance with visiting hours', 'عدم الالتزام بساعات الزيارة'),
('Inadequate reception service', 'خدمة استقبال غير كافية'),
],
('Environment', 'البيئة'): [
('Poor cleanliness/sanitizing', 'ضعف النظافة/التعقيم'),
('Heating, Ventilation, Air condition (HVAC) Failure', 'عطل في التكييف والتهوية'),
('Elevators not available/Failure', 'المصاعد غير متوفرة / معطلة'),
('Building not accessible for special needs', 'المبنى غير مجهز لذوي الاحتياجات الخاصة'),
],
('Safety & Security', 'الأمن والسلامة'): [
('Fire and safety hazards', 'مخاطر الحريق والسلامة'),
('Theft and lost', 'السرقة والمفقودات'),
('Lack of parking slots', 'نقص في مواقف السيارات'),
],
('Finance and Billing', 'المالية والفواتير'): [
('Miscalculation', 'خطأ في الحساب'),
('Pricing variations', 'اختلاف في الأسعار'),
('Unnecessary health services', 'خدمات صحية غير ضرورية'),
],
('Resources', 'الموارد'): [
('Medical supply shortage', 'نقص في المستلزمات الطبية'),
('Unavailable Beds', 'عدم توفر أسرة'),
('Unavailable ambulance', 'عدم توفر سيارة إسعاف'),
],
},
('Accessibility', 'سهولة الوصول'): {
('Access', 'الوصول'): [
('Appointment scheduling refusal', 'رفض تحديد موعد'),
('Appointment cancellation', 'إلغاء الموعد'),
('Scheduling far appointment', 'مواعيد بعيدة جداً'),
],
('Delays', 'التأخير'): [
('Examination delay in emergency', 'تأخير الفحص في الطوارئ'),
('Delayed test result', 'تأخير نتائج الفحوصات'),
('Treatment delay', 'تأخير العلاج'),
],
}
},
('RELATIONSHIPS', 'علاقات'): {
('Communication', 'التواصل'): {
('Patient-staff communication', 'التواصل بين المريض والموظفين'): [
('Miscommunication with Patient', 'سوء فهم مع المريض'),
('Failure to clarify patient case to family', 'عدم توضيح حالة المريض لأسرته'),
('Communication of wrong information', 'تقديم معلومات خاطئة'),
]
},
('Humanness / Caring', 'الإنسانية / الرعاية'): {
('Emotional Support', 'الدعم العاطفي'): [
('Inadequate emotional support', 'دعم عاطفي غير كافٍ'),
],
('Assault and Harassment', 'الاعتداء والمضايقة'): [
('Inappropriate/aggressive behavior', 'سلوك غير لائق / عدواني'),
('Discrimination', 'التمييز'),
]
},
('Consent', 'الموافقة'): {
('Consent Process', 'إجراءات الموافقة'): [
('Consent not explained', 'لم يتم شرح الموافقة'),
('No/Invalid consent obtained', 'لم يتم الحصول على موافقة / موافقة غير صالحة'),
]
},
('Confidentiality', 'الخصوصية'): {
('Privacy', 'خصوصية المعلومات'): [
('Breach of confidentiality', 'انتهاك السرية'),
('Breach of patient privacy', 'انتهاك خصوصية المريض'),
]
}
}
}
self.stdout.write("Starting full bilingual SHCT load...")
# Counter for tracking created items
domains_created = 0
categories_created = 0
subcategories_created = 0
classifications_created = 0
total_created = 0
for (dom_en, dom_ar), categories in shct_data.items():
# Level 1: Domain
domain, created = ComplaintCategory.objects.get_or_create(
name_en=dom_en,
name_ar=dom_ar,
level=ComplaintCategory.LevelChoices.DOMAIN,
domain_type=dom_en.upper()
)
if created:
domains_created += 1
self.stdout.write(f" Created Domain: {dom_en} / {dom_ar}")
order = 0
for (cat_en, cat_ar), subcats in categories.items():
# Level 2: Category
category, created = ComplaintCategory.objects.get_or_create(
name_en=cat_en,
name_ar=cat_ar,
level=ComplaintCategory.LevelChoices.CATEGORY,
domain_type=dom_en.upper(),
parent=domain
)
if created:
categories_created += 1
category.order = order
category.save()
order += 1
self.stdout.write(f" Created Category: {cat_en} / {cat_ar}")
subcat_order = 0
for (sub_en, sub_ar), classifications in subcats.items():
# Level 3: Subcategory
subcategory, created = ComplaintCategory.objects.get_or_create(
name_en=sub_en,
name_ar=sub_ar,
level=ComplaintCategory.LevelChoices.SUBCATEGORY,
domain_type=dom_en.upper(),
parent=category
)
if created:
subcategories_created += 1
subcategory.order = subcat_order
subcategory.save()
subcat_order += 1
self.stdout.write(f" Created Subcategory: {sub_en} / {sub_ar}")
class_order = 0
for class_item in classifications:
class_en, class_ar = class_item
# Generate code from English name
code = class_en.lower().replace(' ', '_').replace('/', '_')
# Level 4: Classification
classification, created = ComplaintCategory.objects.get_or_create(
name_en=class_en,
name_ar=class_ar,
code=code,
level=ComplaintCategory.LevelChoices.CLASSIFICATION,
domain_type=dom_en.upper(),
parent=subcategory
)
if created:
classifications_created += 1
classification.order = class_order
classification.save()
class_order += 1
total_created = domains_created + categories_created + subcategories_created + classifications_created
self.stdout.write(self.style.SUCCESS(
f"\nFull Saudi Healthcare Complaint Taxonomy loaded successfully!\n"
f" Domains: {domains_created}\n"
f" Categories: {categories_created}\n"
f" Subcategories: {subcategories_created}\n"
f" Classifications: {classifications_created}\n"
f" Total created: {total_created}"
))