Cleaning Management Data Specifications
Shared Entity References
This module references the following shared entities defined in their owning modules. Cleaning Management does not redefine these tables — it uses foreign-key references only.
| Shared Entity |
Owning Module |
Table(s) |
FK Used Here |
| Facilities |
ehr-patient-mgmt |
facilities |
facilities.facility_id |
| Departments |
ehr-patient-mgmt |
departments |
departments.department_id |
| Locations |
ehr-patient-mgmt |
locations |
locations.location_id |
| Users & Auth |
ehr-patient-mgmt |
users, roles, permissions |
users.user_id |
| Beds |
scheduling |
beds |
beds.bed_id |
| Encounters |
scheduling |
encounters, encounter_details |
encounters.encounter_id |
Note: Patients are not directly referenced in this module; patient context is via encounters.encounter_id.
Entity Relationship Diagram
erDiagram
facilities ||--o{ cleaning_zones : "has"
cleaning_zones ||--o{ cleaning_schedules : "scheduled in"
cleaning_zones ||--o{ cleaning_staff : "assigned to"
cleaning_zones ||--o{ cleaning_tasks : "tasks in"
locations ||--o{ cleaning_tasks : "at"
beds ||--o{ cleaning_tasks : "for bed"
encounters ||--o{ cleaning_tasks : "triggered by"
users ||--o{ cleaning_staff : "linked user"
users ||--o{ cleaning_tasks : "created/updated by"
users ||--o{ cleaning_inspections : "inspectors"
cleaning_protocols ||--o{ cleaning_checklists : "use"
cleaning_protocols ||--o{ cleaning_zones : "default protocol"
cleaning_protocols ||--o{ cleaning_tasks : "protocol applied"
cleaning_checklists ||--o{ cleaning_checklist_items : "contains"
cleaning_tasks ||--o{ cleaning_inspections : "inspected by"
cleaning_tasks ||--o{ cleaning_supplies_usage : "consumes"
facilities {
bigint facility_id PK
}
locations {
bigint location_id PK
bigint facility_id FK
}
beds {
bigint bed_id PK
bigint location_id FK
}
encounters {
bigint encounter_id PK
}
users {
bigint user_id PK
}
cleaning_zones {
bigint zone_id PK
bigint facility_id FK
bigint default_protocol_id FK
}
cleaning_staff {
bigint staff_id PK
bigint user_id FK
bigint zone_id FK
}
cleaning_protocols {
bigint protocol_id PK
bigint checklist_id FK
}
cleaning_checklists {
bigint checklist_id PK
bigint protocol_id FK
}
cleaning_checklist_items {
bigint item_id PK
bigint checklist_id FK
}
cleaning_schedules {
bigint schedule_id PK
bigint zone_id FK
bigint facility_id FK
bigint protocol_id FK
}
cleaning_tasks {
bigint task_id PK
bigint facility_id FK
bigint zone_id FK
bigint location_id FK
bigint bed_id FK
bigint encounter_id FK
bigint protocol_id FK
bigint assigned_to FK
bigint created_by FK
bigint updated_by FK
}
cleaning_inspections {
bigint inspection_id PK
bigint task_id FK
bigint location_id FK
bigint inspector_id FK
bigint re_clean_task_id FK
}
cleaning_supplies_usage {
bigint usage_id PK
bigint task_id FK
bigint recorded_by FK
}
Table Definitions
1. cleaning_zones
Purpose
Defines logical cleaning zones within each facility (e.g., “Tower A – 3rd Floor – East Wing”) used for task routing, scheduling, and staff assignment. Supports UAE facility layouts and DOH/DHA infection-prevention zoning.
Field Specifications
| Field |
Type |
Nullable |
Default |
Constraint |
Description |
zone_id |
BIGINT |
NO |
IDENTITY |
PK |
Unique zone identifier |
facility_id |
BIGINT |
NO |
— |
FK → facilities.facility_id |
Facility owning the zone |
zone_name |
VARCHAR(100) |
NO |
— |
UNIQUE per facility |
Human-readable zone name |
floor |
VARCHAR(20) |
YES |
NULL |
— |
Floor label (e.g., L3, GF) |
wing |
VARCHAR(50) |
YES |
NULL |
— |
Wing/block (e.g., East, Tower B) |
location_ids |
JSONB |
YES |
NULL |
Array of BIGINTs |
List of locations.location_id in this zone |
default_protocol_id |
BIGINT |
YES |
NULL |
FK → cleaning_protocols.protocol_id |
Default cleaning protocol for routine tasks |
is_active |
BOOLEAN |
NO |
TRUE |
— |
Active flag |
created_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Creation timestamp |
updated_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Last update timestamp |
SQL DDL
SQLCREATE TABLE cleaning_zones (
zone_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
facility_id BIGINT NOT NULL,
zone_name VARCHAR(100) NOT NULL,
floor VARCHAR(20),
wing VARCHAR(50),
location_ids JSONB,
default_protocol_id BIGINT,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_cleaning_zones_facility_name
UNIQUE (facility_id, zone_name),
CONSTRAINT fk_cleaning_zones_facility
FOREIGN KEY (facility_id)
REFERENCES facilities(facility_id)
ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT fk_cleaning_zones_default_protocol
FOREIGN KEY (default_protocol_id)
REFERENCES cleaning_protocols(protocol_id)
ON UPDATE CASCADE ON DELETE SET NULL
);
CREATE INDEX idx_cleaning_zones_facility
ON cleaning_zones(facility_id);
CREATE INDEX idx_cleaning_zones_active
ON cleaning_zones(facility_id, is_active);
Terminology Bindings
| Field |
Terminology |
Example Value |
floor |
Local facility code system |
L3 |
wing |
Local facility code system |
Tower A |
FHIR Mapping
| Table Field |
FHIR Resource |
FHIR Path |
zone_id |
Location |
Location.id |
zone_name |
Location |
Location.name |
facility_id |
Location |
Location.partOf.reference (→ Organization/Location for facility) |
floor |
Location |
Location.extension[floor].valueString (local extension) |
wing |
Location |
Location.extension[wing].valueString |
location_ids |
Location |
Location.partOf / related Location resources |
2. cleaning_staff
Purpose
Registry of cleaning personnel, linked to HIS users, with zone assignments and infection-control/biohazard certifications. Supports staffing, task assignment, and PDPL-compliant contact storage.
Field Specifications
| Field |
Type |
Nullable |
Default |
Constraint |
Description |
staff_id |
BIGINT |
NO |
IDENTITY |
PK |
Unique staff identifier |
user_id |
BIGINT |
NO |
— |
FK → users.user_id |
Linked HIS user account |
full_name |
VARCHAR(150) |
NO |
— |
— |
English full name |
full_name_ar |
VARCHAR(150) |
YES |
NULL |
— |
Arabic full name |
zone_id |
BIGINT |
YES |
NULL |
FK → cleaning_zones.zone_id |
Primary zone assignment |
shift |
VARCHAR(50) |
YES |
NULL |
CHECK in allowed values |
Shift label (e.g., morning, night) |
certification_infection_control |
BOOLEAN |
NO |
FALSE |
— |
Has infection-control training |
certification_biohazard |
BOOLEAN |
NO |
FALSE |
— |
Authorized for biohazard cleanup |
is_active |
BOOLEAN |
NO |
TRUE |
— |
Active employment flag |
phone |
VARCHAR(20) |
YES |
NULL |
UAE phone format |
Staff mobile |
emirates_id |
VARCHAR(25) |
YES |
NULL |
Unique if not null |
Emirates ID (PDPL personal data) |
created_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Creation timestamp |
updated_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Last update timestamp |
SQL DDL
SQLCREATE TABLE cleaning_staff (
staff_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
user_id BIGINT NOT NULL,
full_name VARCHAR(150) NOT NULL,
full_name_ar VARCHAR(150),
zone_id BIGINT,
shift VARCHAR(50),
certification_infection_control BOOLEAN NOT NULL DEFAULT FALSE,
certification_biohazard BOOLEAN NOT NULL DEFAULT FALSE,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
phone VARCHAR(20),
emirates_id VARCHAR(25),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_cleaning_staff_user
FOREIGN KEY (user_id)
REFERENCES users(user_id)
ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT fk_cleaning_staff_zone
FOREIGN KEY (zone_id)
REFERENCES cleaning_zones(zone_id)
ON UPDATE CASCADE ON DELETE SET NULL,
CONSTRAINT uq_cleaning_staff_emirates_id
UNIQUE (emirates_id),
CONSTRAINT chk_cleaning_staff_shift
CHECK (shift IS NULL OR shift IN (
'morning', 'evening', 'night', 'split', 'on_call'
)),
CONSTRAINT chk_cleaning_staff_phone
CHECK (phone IS NULL OR phone ~ '^\+971[0-9 ]+$')
);
CREATE INDEX idx_cleaning_staff_zone_active
ON cleaning_staff(zone_id, is_active);
CREATE INDEX idx_cleaning_staff_user
ON cleaning_staff(user_id);
Terminology Bindings
| Field |
Terminology |
Example Value |
shift |
Local HR shift code list |
morning |
FHIR Mapping
Cleaning staff are non-clinical; when exposed via FHIR, they are typically Practitioner or RelatedPerson in a facility-specific profile.
| Table Field |
FHIR Resource |
FHIR Path |
staff_id |
Practitioner |
Practitioner.id |
full_name |
Practitioner |
Practitioner.name.text |
phone |
Practitioner |
Practitioner.telecom[phone].value |
is_active |
Practitioner |
Practitioner.active |
zone_id |
PractitionerRole |
PractitionerRole.location (→ Location for zone) |
3. cleaning_protocols
Purpose
Master list of cleaning protocols (standard, enhanced, terminal, OR turnover) aligned with UAE DOH/DHA infection-prevention policies and facility-specific infection-control committee decisions.
Field Specifications
| Field |
Type |
Nullable |
Default |
Constraint |
Description |
protocol_id |
BIGINT |
NO |
IDENTITY |
PK |
Unique protocol identifier |
protocol_name |
VARCHAR(150) |
NO |
— |
UNIQUE |
Protocol name |
protocol_type |
VARCHAR(50) |
NO |
— |
CHECK |
standard, enhanced, terminal, or_turnover, biohazard |
description |
TEXT |
YES |
NULL |
— |
Narrative description |
estimated_duration_minutes |
INT |
YES |
NULL |
> 0 if not null |
Expected duration |
required_agents |
JSONB |
YES |
NULL |
— |
List of cleaning agents (by code/name) |
ppe_requirements |
JSONB |
YES |
NULL |
— |
Required PPE items |
checklist_id |
BIGINT |
YES |
NULL |
FK → cleaning_checklists.checklist_id |
Default checklist |
is_active |
BOOLEAN |
NO |
TRUE |
— |
Active flag |
pathogen_codes |
JSONB |
YES |
NULL |
SNOMED CT / ICD-10-AM |
Pathogen/condition codes triggering protocol |
created_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Creation timestamp |
updated_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Last update timestamp |
SQL DDL
SQLCREATE TABLE cleaning_protocols (
protocol_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
protocol_name VARCHAR(150) NOT NULL,
protocol_type VARCHAR(50) NOT NULL,
description TEXT,
estimated_duration_minutes INT,
required_agents JSONB,
ppe_requirements JSONB,
checklist_id BIGINT,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
pathogen_codes JSONB,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_cleaning_protocols_name
UNIQUE (protocol_name),
CONSTRAINT chk_cleaning_protocols_type
CHECK (protocol_type IN (
'standard', 'enhanced', 'terminal', 'or_turnover', 'biohazard'
)),
CONSTRAINT chk_cleaning_protocols_duration
CHECK (estimated_duration_minutes IS NULL OR estimated_duration_minutes > 0),
CONSTRAINT fk_cleaning_protocols_checklist
FOREIGN KEY (checklist_id)
REFERENCES cleaning_checklists(checklist_id)
ON UPDATE CASCADE ON DELETE SET NULL
);
CREATE INDEX idx_cleaning_protocols_type_active
ON cleaning_protocols(protocol_type, is_active);
CREATE INDEX idx_cleaning_protocols_pathogen
ON cleaning_protocols USING GIN (pathogen_codes);
Terminology Bindings
| Field |
Terminology |
Example Value |
pathogen_codes |
SNOMED CT / ICD-10-AM |
{"system":"http://snomed.info/sct","code":"6142004","display":"Clostridioides difficile infection"} |
required_agents |
Local formulary / EDE-registered disinfectants |
{"code":"QAC-001","name":"Quaternary Ammonium Disinfectant"} |
ppe_requirements |
Local PPE code list |
["N95","gown","face_shield","gloves"] |
FHIR Mapping
Protocols map to PlanDefinition or ActivityDefinition in FHIR.
| Table Field |
FHIR Resource |
FHIR Path |
protocol_id |
PlanDefinition |
PlanDefinition.id |
protocol_name |
PlanDefinition |
PlanDefinition.title |
protocol_type |
PlanDefinition |
PlanDefinition.type.coding (local code system) |
description |
PlanDefinition |
PlanDefinition.description |
estimated_duration_minutes |
PlanDefinition |
PlanDefinition.action.timingDuration |
required_agents |
PlanDefinition |
PlanDefinition.action.productCodeableConcept (local codes) |
ppe_requirements |
PlanDefinition |
PlanDefinition.action.extension[ppe] |
pathogen_codes |
PlanDefinition |
PlanDefinition.useContext / PlanDefinition.topic |
4. cleaning_checklists
Purpose
Checklist templates associated with protocols, defining the set of items to be completed during a cleaning task (e.g., bed rails, bathroom surfaces, high-touch areas).
Field Specifications
| Field |
Type |
Nullable |
Default |
Constraint |
Description |
checklist_id |
BIGINT |
NO |
IDENTITY |
PK |
Unique checklist identifier |
protocol_id |
BIGINT |
NO |
— |
FK → cleaning_protocols.protocol_id |
Owning protocol |
checklist_name |
VARCHAR(150) |
NO |
— |
— |
Name (e.g., “Standard Inpatient Room”) |
items_count |
INT |
NO |
0 |
≥ 0 |
Number of items (denormalized) |
is_active |
BOOLEAN |
NO |
TRUE |
— |
Active flag |
notes |
TEXT |
YES |
NULL |
— |
Additional guidance |
created_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Creation timestamp |
updated_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Last update timestamp |
SQL DDL
SQLCREATE TABLE cleaning_checklists (
checklist_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
protocol_id BIGINT NOT NULL,
checklist_name VARCHAR(150) NOT NULL,
items_count INT NOT NULL DEFAULT 0,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
notes TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_cleaning_checklists_protocol
FOREIGN KEY (protocol_id)
REFERENCES cleaning_protocols(protocol_id)
ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT chk_cleaning_checklists_items_count
CHECK (items_count >= 0)
);
CREATE INDEX idx_cleaning_checklists_protocol
ON cleaning_checklists(protocol_id);
Terminology Bindings
None (free-text names; categories handled at item level).
FHIR Mapping
| Table Field |
FHIR Resource |
FHIR Path |
checklist_id |
PlanDefinition |
PlanDefinition.id (if checklist modeled as separate plan) |
checklist_name |
PlanDefinition |
PlanDefinition.title |
protocol_id |
PlanDefinition |
PlanDefinition.relatedArtifact (dependsOn) |
5. cleaning_checklist_items
Purpose
Defines individual checklist items for a given checklist, including mandatory flags and scoring criteria used in inspections and quality audits.
Field Specifications
| Field |
Type |
Nullable |
Default |
Constraint |
Description |
item_id |
BIGINT |
NO |
IDENTITY |
PK |
Unique item identifier |
checklist_id |
BIGINT |
NO |
— |
FK → cleaning_checklists.checklist_id |
Parent checklist |
item_description |
VARCHAR(255) |
NO |
— |
— |
Description of task (e.g., “Disinfect bed rails”) |
display_order |
INT |
NO |
0 |
≥ 0 |
Order in UI |
is_mandatory |
BOOLEAN |
NO |
TRUE |
— |
Must be completed to close task |
category |
VARCHAR(50) |
YES |
NULL |
— |
e.g., bed, bathroom, floor, equipment |
criteria |
JSONB |
YES |
NULL |
— |
Structured scoring/inspection criteria |
is_active |
BOOLEAN |
NO |
TRUE |
— |
Active flag |
SQL DDL
SQLCREATE TABLE cleaning_checklist_items (
item_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
checklist_id BIGINT NOT NULL,
item_description VARCHAR(255) NOT NULL,
display_order INT NOT NULL DEFAULT 0,
is_mandatory BOOLEAN NOT NULL DEFAULT TRUE,
category VARCHAR(50),
criteria JSONB,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
CONSTRAINT fk_cleaning_checklist_items_checklist
FOREIGN KEY (checklist_id)
REFERENCES cleaning_checklists(checklist_id)
ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT chk_cleaning_checklist_items_order
CHECK (display_order >= 0)
);
CREATE INDEX idx_cleaning_checklist_items_checklist
ON cleaning_checklist_items(checklist_id, display_order);
Terminology Bindings
| Field |
Terminology |
Example Value |
category |
Local checklist category codes |
bathroom |
FHIR Mapping
Checklist items can be represented as PlanDefinition.action elements.
| Table Field |
FHIR Resource |
FHIR Path |
item_description |
PlanDefinition |
PlanDefinition.action.description |
display_order |
PlanDefinition |
PlanDefinition.action.sequence |
is_mandatory |
PlanDefinition |
PlanDefinition.action.requiredBehavior (e.g., must) |
category |
PlanDefinition |
PlanDefinition.action.code (local code) |
6. cleaning_schedules
Purpose
Defines recurring routine cleaning schedules per zone/facility (daily corridors, weekly deep cleaning, monthly vents), used to auto-generate tasks (WF-CLN-003).
Field Specifications
| Field |
Type |
Nullable |
Default |
Constraint |
Description |
schedule_id |
BIGINT |
NO |
IDENTITY |
PK |
Unique schedule identifier |
zone_id |
BIGINT |
NO |
— |
FK → cleaning_zones.zone_id |
Zone to be cleaned |
facility_id |
BIGINT |
NO |
— |
FK → facilities.facility_id |
Redundant for reporting |
frequency |
VARCHAR(20) |
NO |
— |
CHECK |
daily, weekly, monthly, quarterly, ad_hoc |
day_of_week |
VARCHAR(10) |
YES |
NULL |
CHECK or NULL |
sun–sat for weekly |
time_slot |
VARCHAR(20) |
NO |
— |
— |
e.g., 08:00-12:00 |
protocol_id |
BIGINT |
NO |
— |
FK → cleaning_protocols.protocol_id |
Protocol to apply |
assigned_team |
VARCHAR(100) |
YES |
NULL |
— |
Team label (e.g., “Night Shift A”) |
is_active |
BOOLEAN |
NO |
TRUE |
— |
Active schedule flag |
start_date |
DATE |
NO |
CURRENT_DATE |
— |
Effective from |
end_date |
DATE |
YES |
NULL |
≥ start_date |
Effective until |
exceptions |
JSONB |
YES |
NULL |
— |
Holiday/closure exceptions |
created_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Creation timestamp |
updated_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Last update timestamp |
SQL DDL
SQLCREATE TABLE cleaning_schedules (
schedule_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
zone_id BIGINT NOT NULL,
facility_id BIGINT NOT NULL,
frequency VARCHAR(20) NOT NULL,
day_of_week VARCHAR(10),
time_slot VARCHAR(20) NOT NULL,
protocol_id BIGINT NOT NULL,
assigned_team VARCHAR(100),
is_active BOOLEAN NOT NULL DEFAULT TRUE,
start_date DATE NOT NULL DEFAULT CURRENT_DATE,
end_date DATE,
exceptions JSONB,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_cleaning_schedules_zone
FOREIGN KEY (zone_id)
REFERENCES cleaning_zones(zone_id)
ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT fk_cleaning_schedules_facility
FOREIGN KEY (facility_id)
REFERENCES facilities(facility_id)
ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT fk_cleaning_schedules_protocol
FOREIGN KEY (protocol_id)
REFERENCES cleaning_protocols(protocol_id)
ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT chk_cleaning_schedules_frequency
CHECK (frequency IN ('daily','weekly','monthly','quarterly','ad_hoc')),
CONSTRAINT chk_cleaning_schedules_day_of_week
CHECK (
day_of_week IS NULL OR
day_of_week IN ('sun','mon','tue','wed','thu','fri','sat')
),
CONSTRAINT chk_cleaning_schedules_dates
CHECK (end_date IS NULL OR end_date >= start_date)
);
CREATE INDEX idx_cleaning_schedules_zone_active
ON cleaning_schedules(zone_id, is_active);
CREATE INDEX idx_cleaning_schedules_facility_freq
ON cleaning_schedules(facility_id, frequency);
Terminology Bindings
| Field |
Terminology |
Example Value |
frequency |
Local scheduling code list |
daily |
day_of_week |
ISO-like local code |
sun |
FHIR Mapping
Schedules can be mapped to Schedule or PlanDefinition.
| Table Field |
FHIR Resource |
FHIR Path |
schedule_id |
Schedule |
Schedule.id |
zone_id |
Schedule |
Schedule.actor (Location) |
frequency/day_of_week/time_slot |
Schedule |
Schedule.planningHorizon / Schedule.extension[recurrence] |
protocol_id |
PlanDefinition |
PlanDefinition.id referenced from Schedule via extension |
7. cleaning_tasks
Purpose
Core operational table representing individual cleaning tasks (bed turnover, OR turnover, terminal cleaning, routine, ad-hoc). Tracks lifecycle from creation to completion, including protocol, assignment, timestamps, and inspection flags. Drives KPIs such as Bed Turnaround Time and Terminal Cleaning Compliance.
Field Specifications
| Field |
Type |
Nullable |
Default |
Constraint |
Description |
task_id |
BIGINT |
NO |
IDENTITY |
PK |
Unique task identifier |
task_type |
VARCHAR(30) |
NO |
— |
CHECK |
bed_discharge, bed_transfer, or_turnover, routine, terminal, ad_hoc |
facility_id |
BIGINT |
NO |
— |
FK → facilities.facility_id |
Facility context |
zone_id |
BIGINT |
YES |
NULL |
FK → cleaning_zones.zone_id |
Zone context |
location_id |
BIGINT |
YES |
NULL |
FK → locations.location_id |
Room/area location |
bed_id |
BIGINT |
YES |
NULL |
FK → beds.bed_id |
Bed (for bed-related tasks) |
encounter_id |
BIGINT |
YES |
NULL |
FK → encounters.encounter_id |
Triggering encounter (if applicable) |
priority |
VARCHAR(20) |
NO |
'routine' |
CHECK |
stat, high, routine, low |
protocol_id |
BIGINT |
NO |
— |
FK → cleaning_protocols.protocol_id |
Protocol applied |
assigned_to |
BIGINT |
YES |
NULL |
FK → cleaning_staff.staff_id |
Assigned staff |
task_created_datetime |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
When task was created |
assigned_datetime |
TIMESTAMP |
YES |
NULL |
≥ created |
When assigned |
started_datetime |
TIMESTAMP |
YES |
NULL |
≥ assigned |
When staff started |
completed_datetime |
TIMESTAMP |
YES |
NULL |
≥ started |
When completed |
status |
VARCHAR(20) |
NO |
'pending' |
CHECK |
pending, assigned, in_progress, completed, cancelled |
trigger_source |
VARCHAR(30) |
NO |
— |
CHECK |
adt_discharge, adt_transfer, or_case, schedule, manual, infection_flag |
inspection_required |
BOOLEAN |
NO |
FALSE |
— |
Whether inspection is required |
inspection_result |
VARCHAR(20) |
YES |
NULL |
CHECK or NULL |
pass, fail |
is_terminal_cleaning |
BOOLEAN |
NO |
FALSE |
— |
Terminal cleaning flag |
infection_flag_source |
VARCHAR(50) |
YES |
NULL |
— |
e.g., isolation_contact, isolation_airborne |
created_by |
BIGINT |
YES |
NULL |
FK → users.user_id |
User creating task (for manual/ad-hoc) |
updated_by |
BIGINT |
YES |
NULL |
FK → users.user_id |
Last updating user |
created_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Creation timestamp |
updated_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Last update timestamp |
SQL DDL
SQLCREATE TABLE cleaning_tasks (
task_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
task_type VARCHAR(30) NOT NULL,
facility_id BIGINT NOT NULL,
zone_id BIGINT,
location_id BIGINT,
bed_id BIGINT,
encounter_id BIGINT,
priority VARCHAR(20) NOT NULL DEFAULT 'routine',
protocol_id BIGINT NOT NULL,
assigned_to BIGINT,
task_created_datetime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
assigned_datetime TIMESTAMP,
started_datetime TIMESTAMP,
completed_datetime TIMESTAMP,
status VARCHAR(20) NOT NULL DEFAULT 'pending',
trigger_source VARCHAR(30) NOT NULL,
inspection_required BOOLEAN NOT NULL DEFAULT FALSE,
inspection_result VARCHAR(20),
is_terminal_cleaning BOOLEAN NOT NULL DEFAULT FALSE,
infection_flag_source VARCHAR(50),
created_by BIGINT,
updated_by BIGINT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_cleaning_tasks_facility
FOREIGN KEY (facility_id)
REFERENCES facilities(facility_id)
ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT fk_cleaning_tasks_zone
FOREIGN KEY (zone_id)
REFERENCES cleaning_zones(zone_id)
ON UPDATE CASCADE ON DELETE SET NULL,
CONSTRAINT fk_cleaning_tasks_location
FOREIGN KEY (location_id)
REFERENCES locations(location_id)
ON UPDATE CASCADE ON DELETE SET NULL,
CONSTRAINT fk_cleaning_tasks_bed
FOREIGN KEY (bed_id)
REFERENCES beds(bed_id)
ON UPDATE CASCADE ON DELETE SET NULL,
CONSTRAINT fk_cleaning_tasks_encounter
FOREIGN KEY (encounter_id)
REFERENCES encounters(encounter_id)
ON UPDATE CASCADE ON DELETE SET NULL,
CONSTRAINT fk_cleaning_tasks_protocol
FOREIGN KEY (protocol_id)
REFERENCES cleaning_protocols(protocol_id)
ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT fk_cleaning_tasks_assigned_staff
FOREIGN KEY (assigned_to)
REFERENCES cleaning_staff(staff_id)
ON UPDATE CASCADE ON DELETE SET NULL,
CONSTRAINT fk_cleaning_tasks_created_by
FOREIGN KEY (created_by)
REFERENCES users(user_id)
ON UPDATE CASCADE ON DELETE SET NULL,
CONSTRAINT fk_cleaning_tasks_updated_by
FOREIGN KEY (updated_by)
REFERENCES users(user_id)
ON UPDATE CASCADE ON DELETE SET NULL,
CONSTRAINT chk_cleaning_tasks_type
CHECK (task_type IN (
'bed_discharge','bed_transfer','or_turnover',
'routine','terminal','ad_hoc'
)),
CONSTRAINT chk_cleaning_tasks_priority
CHECK (priority IN ('stat','high','routine','low')),
CONSTRAINT chk_cleaning_tasks_status
CHECK (status IN ('pending','assigned','in_progress','completed','cancelled')),
CONSTRAINT chk_cleaning_tasks_trigger_source
CHECK (trigger_source IN (
'adt_discharge','adt_transfer','or_case',
'schedule','manual','infection_flag'
)),
CONSTRAINT chk_cleaning_tasks_inspection_result
CHECK (inspection_result IS NULL OR inspection_result IN ('pass','fail')),
CONSTRAINT chk_cleaning_tasks_timestamps
CHECK (
(assigned_datetime IS NULL OR assigned_datetime >= task_created_datetime) AND
(started_datetime IS NULL OR started_datetime >= COALESCE(assigned_datetime, task_created_datetime)) AND
(completed_datetime IS NULL OR completed_datetime >= COALESCE(started_datetime, task_created_datetime))
)
);
CREATE INDEX idx_cleaning_tasks_facility_status
ON cleaning_tasks(facility_id, status);
CREATE INDEX idx_cleaning_tasks_zone_status
ON cleaning_tasks(zone_id, status);
CREATE INDEX idx_cleaning_tasks_bed_status
ON cleaning_tasks(bed_id, status);
CREATE INDEX idx_cleaning_tasks_assigned_status
ON cleaning_tasks(assigned_to, status);
CREATE INDEX idx_cleaning_tasks_created_datetime
ON cleaning_tasks(task_created_datetime);
CREATE INDEX idx_cleaning_tasks_terminal
ON cleaning_tasks(is_terminal_cleaning)
WHERE is_terminal_cleaning = TRUE;
Terminology Bindings
| Field |
Terminology |
Example Value |
task_type |
Local cleaning task type codes |
bed_discharge |
priority |
Local priority codes |
stat |
trigger_source |
Local trigger codes |
adt_discharge |
infection_flag_source |
Local isolation/flag codes |
isolation_contact |
FHIR Mapping
Tasks can be mapped to Task in FHIR.
| Table Field |
FHIR Resource |
FHIR Path |
task_id |
Task |
Task.id |
task_type |
Task |
Task.code (local code system) |
status |
Task |
Task.status (requested, accepted, in-progress, completed, cancelled) |
priority |
Task |
Task.priority (stat → urgent) |
facility_id |
Task |
Task.location (via Location/Organization) |
zone_id |
Task |
Task.location (Location for zone) |
location_id |
Task |
Task.location (Location for room) |
bed_id |
Task |
Task.focus (Location/Device extension) |
encounter_id |
Task |
Task.encounter |
protocol_id |
Task |
Task.basedOn (PlanDefinition reference) |
assigned_to |
Task |
Task.owner (Practitioner) |
task_created_datetime |
Task |
Task.authoredOn |
started_datetime |
Task |
Task.start (extension) |
completed_datetime |
Task |
Task.lastModified |
is_terminal_cleaning |
Task |
Task.extension[terminalCleaning] |
8. cleaning_inspections
Purpose
Stores quality inspection records for completed or in-progress cleaning tasks, including scores, pass/fail, deficiencies, photos, and whether re-cleaning is required. Supports DOH/DHA infection-control audits and internal quality KPIs.
Field Specifications
| Field |
Type |
Nullable |
Default |
Constraint |
Description |
inspection_id |
BIGINT |
NO |
IDENTITY |
PK |
Unique inspection identifier |
task_id |
BIGINT |
NO |
— |
FK → cleaning_tasks.task_id |
Inspected task |
location_id |
BIGINT |
YES |
NULL |
FK → locations.location_id |
Inspected location |
inspector_id |
BIGINT |
NO |
— |
FK → users.user_id |
Inspector user |
inspection_datetime |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
When inspection occurred |
score |
NUMERIC(5,2) |
YES |
NULL |
0–100 |
Numeric score |
pass_fail |
VARCHAR(10) |
NO |
— |
CHECK |
pass, fail |
deficiencies |
TEXT |
YES |
NULL |
— |
Free-text notes |
photo_paths |
JSONB |
YES |
NULL |
— |
List of photo URIs/paths |
re_clean_required |
BOOLEAN |
NO |
FALSE |
— |
Whether re-cleaning is required |
re_clean_task_id |
BIGINT |
YES |
NULL |
FK → cleaning_tasks.task_id |
Linked re-cleaning task |
created_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Creation timestamp |
updated_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
Last update timestamp |
SQL DDL
SQLCREATE TABLE cleaning_inspections (
inspection_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
task_id BIGINT NOT NULL,
location_id BIGINT,
inspector_id BIGINT NOT NULL,
inspection_datetime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
score NUMERIC(5,2),
pass_fail VARCHAR(10) NOT NULL,
deficiencies TEXT,
photo_paths JSONB,
re_clean_required BOOLEAN NOT NULL DEFAULT FALSE,
re_clean_task_id BIGINT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_cleaning_inspections_task
FOREIGN KEY (task_id)
REFERENCES cleaning_tasks(task_id)
ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT fk_cleaning_inspections_location
FOREIGN KEY (location_id)
REFERENCES locations(location_id)
ON UPDATE CASCADE ON DELETE SET NULL,
CONSTRAINT fk_cleaning_inspections_inspector
FOREIGN KEY (inspector_id)
REFERENCES users(user_id)
ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT fk_cleaning_inspections_reclean_task
FOREIGN KEY (re_clean_task_id)
REFERENCES cleaning_tasks(task_id)
ON UPDATE CASCADE ON DELETE SET NULL,
CONSTRAINT chk_cleaning_inspections_pass_fail
CHECK (pass_fail IN ('pass','fail')),
CONSTRAINT chk_cleaning_inspections_score
CHECK (score IS NULL OR (score >= 0 AND score <= 100)),
CONSTRAINT chk_cleaning_inspections_reclean
CHECK (re_clean_required = FALSE OR re_clean_task_id IS NOT NULL)
);
CREATE INDEX idx_cleaning_inspections_task
ON cleaning_inspections(task_id);
CREATE INDEX idx_cleaning_inspections_inspector
ON cleaning_inspections(inspector_id);
CREATE INDEX idx_cleaning_inspections_pass_fail
ON cleaning_inspections(pass_fail);
Terminology Bindings
| Field |
Terminology |
Example Value |
pass_fail |
Local inspection outcome codes |
pass |
FHIR Mapping
Inspections can be modeled as Observation or Procedure.
| Table Field |
FHIR Resource |
FHIR Path |
inspection_id |
Observation |
Observation.id |
task_id |
Observation |
Observation.basedOn (Task) |
inspection_datetime |
Observation |
Observation.effectiveDateTime |
score |
Observation |
Observation.valueQuantity (0–100) |
pass_fail |
Observation |
Observation.interpretation (local code) |
deficiencies |
Observation |
Observation.note.text |
photo_paths |
Observation |
Observation.media.link (Attachment/Media) |
9. cleaning_supplies_usage
Purpose
Tracks cleaning agents and supplies used per task for cost allocation, stock management, and infection-control traceability (e.g., lot numbers for disinfectants approved by Emirates Drug Establishment).
Field Specifications
| Field |
Type |
Nullable |
Default |
Constraint |
Description |
usage_id |
BIGINT |
NO |
IDENTITY |
PK |
Unique usage record |
task_id |
BIGINT |
NO |
— |
FK → cleaning_tasks.task_id |
Related cleaning task |
supply_name |
VARCHAR(150) |
NO |
— |
— |
Name of supply/agent |
supply_code |
VARCHAR(50) |
YES |
NULL |
— |
Local inventory code |
quantity_used |
NUMERIC(10,3) |
NO |
— |
> 0 |
Quantity used |
unit |
VARCHAR(20) |
NO |
— |
— |
Unit (e.g., ml, piece) |
lot_number |
VARCHAR(50) |
YES |
NULL |
— |
Batch/lot number |
expiry_date |
DATE |
YES |
NULL |
— |
Expiry date of supply |
supplier_name |
VARCHAR(150) |
YES |
NULL |
— |
Supplier/manufacturer |
recorded_at |
TIMESTAMP |
NO |
CURRENT_TIMESTAMP |
— |
When recorded |
recorded_by |
BIGINT |
YES |
NULL |
FK → users.user_id |
User who recorded usage |
SQL DDL
SQLCREATE TABLE cleaning_supplies_usage (
usage_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
task_id BIGINT NOT NULL,
supply_name VARCHAR(150) NOT NULL,
supply_code VARCHAR(50),
quantity_used NUMERIC(10,3) NOT NULL,
unit VARCHAR(20) NOT NULL,
lot_number VARCHAR(50),
expiry_date DATE,
supplier_name VARCHAR(150),
recorded_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
recorded_by BIGINT,
CONSTRAINT fk_cleaning_supplies_usage_task
FOREIGN KEY (task_id)
REFERENCES cleaning_tasks(task_id)
ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT fk_cleaning_supplies_usage_user
FOREIGN KEY (recorded_by)
REFERENCES users(user_id)
ON UPDATE CASCADE ON DELETE SET NULL,
CONSTRAINT chk_cleaning_supplies_usage_qty
CHECK (quantity_used > 0)
);
CREATE INDEX idx_cleaning_supplies_usage_task
ON cleaning_supplies_usage(task_id);
CREATE INDEX idx_cleaning_supplies_usage_supply
ON cleaning_supplies_usage(supply_code);
Terminology Bindings
| Field |
Terminology |
Example Value |
supply_code |
Local materials master / EDE-registered disinfectant codes |
DISINF-CHG-2PCT |
unit |
UCUM / local unit codes |
ml |
FHIR Mapping
Supply usage can be mapped to MedicationAdministration or Procedure with devices/agents.
| Table Field |
FHIR Resource |
FHIR Path |
usage_id |
MedicationAdministration |
MedicationAdministration.id (if modeled) |
task_id |
MedicationAdministration |
MedicationAdministration.context (Task/Encounter) |
supply_name/supply_code |
Medication |
Medication.code (local code) |
quantity_used/unit |
MedicationAdministration |
MedicationAdministration.dosage.dose |
lot_number |
Medication |
Medication.batch.lotNumber |
expiry_date |
Medication |
Medication.batch.expirationDate |
Data Volume Estimates
Estimated for a 500-bed UAE tertiary hospital.
| Table |
Initial Rows |
Monthly Growth |
Notes |
cleaning_zones |
30–60 |
+1–2 |
Changes only with layout updates |
cleaning_staff |
80–150 |
+2–5 |
HR-driven changes |
cleaning_protocols |
10–30 |
+1 |
Rare changes (infection-control updates) |
cleaning_checklists |
10–25 |
+1 |
Occasional revisions |
cleaning_checklist_items |
200–600 |
+10–20 |
Grows with new checklists |
cleaning_schedules |
50–150 |
+5–10 |
Per zone/frequency |
cleaning_tasks |
40,000–60,000 |
+40,000–60,000 |
High volume (all workflows) |
cleaning_inspections |
4,000–8,000 |
+4,000–8,000 |
~10–15% of tasks inspected |
cleaning_supplies_usage |
60,000–90,000 |
+60,000–90,000 |
Multiple entries per task |
Indexing and partitioning recommendations:
- Partition
cleaning_tasks, cleaning_inspections, and cleaning_supplies_usage by month or quarter for large hospitals.
- Maintain composite indexes on
(facility_id, status, task_created_datetime) for real-time boards.
Data Retention Policy
Retention must comply with UAE MOH/DOH/DHA guidance and UAE PDPL. Cleaning data is operational/quality data, not primary clinical record, but may be required for infection-control investigations and medico-legal purposes.
| Table |
Recommended Retention |
Rationale |
cleaning_zones |
Retain current + 10 years of history |
Facility layout audit trail |
cleaning_staff |
Active + 10 years after staff leaves |
Occupational health, incident investigations |
cleaning_protocols |
Permanent |
Infection-control policy history |
cleaning_checklists |
Permanent |
Demonstrate historical standards to regulators |
cleaning_checklist_items |
Permanent |
Linked to historical checklists/protocols |
cleaning_schedules |
10 years |
Evidence of routine cleaning programs |
cleaning_tasks |
10 years (minimum) |
Supports infection outbreaks, medico-legal review, DOH/DHA audits |
cleaning_inspections |
10 years |
Quality and infection-control compliance evidence |
cleaning_supplies_usage |
10 years |
Traceability of disinfectant use, especially for outbreaks |
PDPL considerations:
cleaning_staff.emirates_id and phone are personal data; access must be role-based and logged.
- For data beyond retention, apply anonymisation or deletion in line with facility policy and PDPL.
- Any export to NABIDH/Malaffi (if required for infection-control analytics) must use pseudonymised identifiers where possible.