""" Populate the `name_ar` (Arabic name) field on Department rows from a hard-coded English -> Arabic mapping. The mapping covers every department name present in the database. Keys are normalized (case-insensitive, trailing "department" stripped, whitespace collapsed) so that "Surgery", "Surgery Department" and "surgery department" all resolve to the same Arabic value. Arabic terms are cross-referenced with apps/complaints/management/commands/arabic_dept_mapping.py to keep the project's Arabic vocabulary consistent. Usage: python manage.py set_department_arabic_names # fill empties python manage.py set_department_arabic_names --dry-run # preview only python manage.py set_department_arabic_names --overwrite # re-translate all python manage.py set_department_arabic_names --hospital-code HH-N """ import re from django.core.management.base import BaseCommand from django.db import transaction from apps.organizations.models import Department ENGLISH_TO_ARABIC = { "laboratory": "قسم المختبر", "icu": "وحدة العناية المركزة", "security": "قسم الأمن", "maintenance": "قسم الصيانة", "housekeeping": "قسم النظافة", "medical reports": "قسم التقارير الطبية", "reception": "الاستقبال", "administration": "الإدارة", "surgery": "قسم الجراحة", "cardiology": "قسم القلب", "orthopedics": "قسم جراحة العظام", "orthopedic": "قسم جراحة العظام", "nursing": "قسم التمريض", "pharmacy": "قسم الصيدلية", "pediatrics": "قسم الأطفال", "pediatric": "قسم الأطفال", "emergency": "قسم الطوارئ", "anesthesia": "قسم التخدير", "biomedical": "قسم الهندسة الطبية الحيوية", "contact center": "قسم مركز الاتصال", "critical care": "قسم العناية المركزة", "dental": "قسم الأسنان", "dermatology": "قسم الجلدية", "emergency administrative": "إدارة الطوارئ", "emergency medicine": "قسم طب الطوارئ", "executive administration": "الإدارة التنفيذية", "facility management & maintenance": "قسم إدارة المرافق والصيانة", "financial collection & claims": "قسم المالية والتحصيل والمطالبات", "food services": "قسم خدمات الطعام", "hr": "قسم الموارد البشرية", "housekeeping & hospitality": "قسم النظافة والضيافة", "ivf": "قسم أطفال الأنابيب", "infection control": "قسم مكافحة العدوى", "information technology": "قسم تقنية المعلومات", "inpatient": "قسم التنويم", "internal medicine": "قسم الباطنية", "laundry": "قسم الغسيل", "medical administration": "الإدارة الطبية", "medical ancillary services": "قسم الخدمات الطبية المساندة", "medical approvals": "قسم الموافقات الطبية", "medical records": "قسم السجلات الطبية", "oncology": "قسم الأورام", "obstetrics & gynecology": "قسم النساء والولادة", "operating rooms": "قسم غرف العمليات", "operating rooms (or)": "قسم غرف العمليات", "ophthalmology": "قسم العيون", "outpatient": "قسم العيادات الخارجية", "patient affairs": "قسم علاقات المرضى", "patient experience": "قسم تجربة المريض", "radiology": "قسم الأشعة", "support services": "قسم الخدمات المساندة", } _DEPT_SUFFIX_RE = re.compile(r"\s+department$", re.IGNORECASE) _WS_RE = re.compile(r"\s+") def _normalize_en(value: str) -> str: """Normalize an English department name for mapping lookup.""" if not value: return "" value = _DEPT_SUFFIX_RE.sub("", str(value).strip()) value = _WS_RE.sub(" ", value).strip() return value.lower() class Command(BaseCommand): help = "Populate Department.name_ar from a hard-coded English -> Arabic mapping" def add_arguments(self, parser): parser.add_argument( "--dry-run", action="store_true", help="Preview changes without writing to the database", ) parser.add_argument( "--overwrite", action="store_true", help="Re-translate even departments that already have name_ar set", ) parser.add_argument( "--hospital-code", type=str, help="Limit to a single hospital code (default: all hospitals)", ) def handle(self, *args, **options): dry_run = options["dry_run"] overwrite = options["overwrite"] hospital_code = options["hospital_code"] qs = Department.objects.select_related("hospital").order_by("hospital__code", "name_en", "name") if hospital_code: qs = qs.filter(hospital__code=hospital_code) if not overwrite: qs = qs.filter(name_ar="") self.stdout.write(self.style.MIGRATE_HEADING( f"Department Arabic names (hospital={hospital_code or 'ALL'}, " f"overwrite={overwrite}, dry_run={dry_run})" )) updated = 0 skipped = 0 unmapped = [] with transaction.atomic(): for dept in qs.iterator(): key = _normalize_en(dept.name_en) or _normalize_en(dept.name) arabic = ENGLISH_TO_ARABIC.get(key) if not arabic: unmapped.append((dept, key)) skipped += 1 continue if dept.name_ar == arabic: skipped += 1 continue label = f"[{dept.hospital.code if dept.hospital else '-'}] {dept.code}: " \ f"{dept.name_en or dept.name!r}" if dry_run: self.stdout.write(f" ~ {label} -> {arabic}") else: dept.name_ar = arabic dept.save(update_fields=["name_ar"]) self.stdout.write(self.style.SUCCESS(f" + {label} -> {arabic}")) updated += 1 self.stdout.write("") self.stdout.write(self.style.SUCCESS( f"Done: {updated} {'would be ' if dry_run else ''}updated, {skipped} skipped" )) if unmapped: self.stdout.write(self.style.WARNING( f"\n{len(unmapped)} department(s) had no mapping (left unchanged):" )) for dept, key in unmapped: self.stdout.write(self.style.WARNING( f" - [{dept.hospital.code if dept.hospital else '-'}] {dept.code}: " f"{dept.name_en or dept.name!r} (key={key!r})" )) self.stdout.write(self.style.WARNING( "\nAdd the missing keys to ENGLISH_TO_ARABIC and re-run." ))