HH/dep.md
ismail 7369d08012
All checks were successful
Build and Push Docker Image / build (push) Successful in 4m14s
feat: unified reference numbers + feedback modules QA audit
Reference numbers (unified scheme PREFIX-YYYYMM-HOSP-NNNN, e.g. CMP-202606-HHN-0001):
- new ReferenceSequence model + generate_reference() helper (apps/core)
- Complaint/Inquiry/Observation/Appreciation/Suggestion emit unified refs via save()
- prefix-based auto-routing in public track API (CMP/INQ/OBS trackable; APR/SGT internal-only)
- removed legacy CMP-/INQ- generators in ui_views, integrations, px_sources
- migrations: core.0003_referencesequence, appreciation.0006, feedback.0008, observations.0012
- unit tests (format, sanitization, monthly reset, 40-thread concurrency)

QA audit:
- isolated E2E hospital sandbox mirroring HH-N + 10 role users (create_e2e_isolated_env)
- feedback-modules-audit.spec.ts + audit helper (headed, run-to-completion)
- reports/feedback-modules-qa-report.md

Also bundles accumulated in-progress work across complaints, observations,
organizations, templates, and other modules.
2026-06-14 14:29:23 +03:00

7.2 KiB

PX360 Organizational Structure Refactor (Final Architecture)

Objective

Refactor the current Department Hierarchy implementation into a simpler and more maintainable model that:

  • Uses a single source of truth for routing.
  • Uses a single source of truth for reporting.
  • Preserves legacy complaint mappings for historical records.
  • Removes unnecessary hierarchy levels.
  • Aligns with the latest organizational spreadsheet.
  • Supports future department and section changes without impacting reporting.

Key Business Findings

After reviewing:

  • Legacy complaint hierarchy
  • Existing reports
  • Final organization spreadsheet

the following conclusions were reached.

Legacy Structure

Historical complaints used:

Location → Main Section → Sub Section

Example:

Outpatient → Medical → Radiology

The old Sub Section was the actual operational unit receiving complaints.


Current Organization Structure

The latest organization file contains:

  • Main Section
  • Department
  • Section

Examples:

Medical → Pharmacy Department → Central Outpatient Pharmacy

Medical → Pharmacy Department → General


Important Discovery

Area is not a valid hierarchy level.

Evidence:

  • Frequently empty
  • Often duplicates Department concepts
  • Not used in reporting
  • Not used in routing
  • Not used in ownership

Therefore:

Area should not become a first-class model.


Reporting Structure

All management reports are grouped by:

  • Medical
  • Non-Medical
  • Nursing
  • Support Services

These values come from:

Main Section

Therefore Main Section is actually the reporting category.


Target Hierarchy

Department Category

Represents:

  • Medical
  • Non-Medical
  • Nursing
  • Support Services

Model:

class DepartmentCategory(models.TextChoices):
    MEDICAL = "medical"
    NON_MEDICAL = "non_medical"
    NURSING = "nursing"
    SUPPORT_SERVICES = "support_services"

This replaces the old concept of:

Main Section


Department

Primary accountable organizational unit.

Model:

class Department(models.Model):

    category

    name
    code

    champion

    manager_1st
    manager_2nd
    manager_3rd

    deputy_manager
    supervisor
    deputy_supervisor

    is_active

Examples:

  • Pharmacy Department
  • Radiology Department
  • Laboratory Department
  • Emergency Department

Departments always have ownership.

Departments always have a Champion.

Departments are the fallback routing target.


Section

Optional child unit under a Department.

Model:

class Section(models.Model):

    department = models.ForeignKey(
        Department,
        related_name="sections"
    )

    name
    code

    champion = models.ForeignKey(
        Staff,
        null=True,
        blank=True
    )

    location_type

    location_code
    zone
    floor

    is_active

Examples:

  • Central Outpatient Pharmacy
  • ER Pharmacy
  • Pediatric Pharmacy

Not every Department requires Sections.

Not every Section requires a Champion.


Remove Sub-Section

Current model:

OrgSubSubSection

Findings:

  • Mostly empty in source data.
  • Not used in reports.
  • Not used in routing.
  • Not used in escalation.

Action:

Deprecate and remove.


Complaint Model

Target Structure

class Complaint(models.Model):

    department = models.ForeignKey(
        Department
    )

    section = models.ForeignKey(
        Section,
        null=True,
        blank=True
    )

    legacy_mapping = models.ForeignKey(
        LegacyHierarchyMapping,
        null=True,
        blank=True
    )

Ownership Rules

Single ownership strategy.

def get_owner():

    if complaint.section and complaint.section.champion:
        return complaint.section.champion

    return complaint.department.champion

Rules:

  1. Section Champion takes ownership when available.
  2. Otherwise Department Champion owns the complaint.

This becomes the only routing rule in the system.


Legacy Data Strategy

Legacy Mapping Table

Keep:

class LegacyHierarchyMapping(models.Model):

    old_location
    old_main_section
    old_subsection

    department
    section

Purpose:

Legacy Complaint → Legacy Mapping → Department / Section


Legacy Fields

The following fields become historical reference only:

  • legacy_location
  • legacy_main_section
  • legacy_subsection

Rules:

  • No reporting usage
  • No routing usage
  • No escalation usage
  • No dashboard usage

May remain temporarily for audit purposes.


Reporting Strategy

Single Source of Truth

All reports must use:

complaint.department
complaint.section

only.

Never use legacy hierarchy fields.


Category Reports

Medical / Nursing / Support Services reports:

Complaint.objects.values(
    "department__category"
)

Department Reports

Complaint.objects.values(
    "department__name"
)

Section Reports

Complaint.objects.values(
    "section__name"
)

Location Handling

Location is metadata.

It is not part of ownership hierarchy.

Examples:

  • Outpatient Clinics
  • Inpatient
  • Emergency
  • General Services

Used for:

  • Display
  • Filtering
  • Analytics

Not used for routing ownership.


Location Type

Retain:

  • OP
  • IP
  • ER
  • GENERAL

This becomes the preferred reporting dimension instead of string matching location names.

Example:

class LocationType(models.TextChoices):
    OP = "OP"
    IP = "IP"
    ER = "ER"
    GENERAL = "GENERAL"

Import Strategy

Department uniqueness:

(category, department_name)

must create a single Department.

Never create duplicate Departments from repeated spreadsheet rows.


Sections:

(department, section_name)

must be unique.


Migration Plan

Phase 1

Create:

  • DepartmentCategory
  • LocationType enums

Remove Area dependency.


Phase 2

Rename:

OrgSubSection

to:

Section

Update:

  • models
  • serializers
  • views
  • APIs
  • templates
  • services

Phase 3

Deprecate:

OrgSubSubSection

Backfill any valid data.

Remove references.


Phase 4

Backfill all historical complaints.

Populate:

  • department
  • section

using LegacyHierarchyMapping.

Target:

100% coverage.


Phase 5

Update routing services.

Replace all routing logic with:

complaint.get_owner()

Phase 6

Update:

  • Dashboards
  • KPI services
  • Reports
  • Exports
  • Analytics

to use:

  • Department
  • Section
  • Department Category

only.


Phase 7

Update forms.

Replace:

Location → Main Section → Sub Section

with:

Category → Department → Section

Section optional.


Phase 8

Mark legacy hierarchy fields as deprecated.

Prevent all new writes.

Keep read-only until final cleanup release.


Success Criteria

✓ Department is the primary accountable entity.

✓ Section is optional.

✓ Reporting uses Department Category.

✓ Routing uses Department / Section only.

✓ Legacy hierarchy is used only for historical mapping.

✓ Area is removed from operational design.

✓ OrgSubSubSection is removed.

✓ OrgSubSection is renamed to Section.

✓ Dashboards no longer depend on legacy hierarchy.

✓ Complaint ownership has a single source of truth.