21 KiB
21 KiB
Tenhal Multidisciplinary Healthcare Platform - Detailed Implementation Plan
Project Status
Current Phase: Phase 1 - Models Implementation (In Progress)
Completed:
- ✅ Phase 0: Project Foundation & Configuration
- Environment configuration (.env.example)
- Dependencies (pyproject.toml with all required packages)
- Django settings (PostgreSQL, i18n, DRF, Celery, integrations)
- All 11 Django apps created
- Base model mixins (UUID, TimeStamped, TenantOwned, ClinicallySignable, SoftDelete)
- Core app models complete
Next Steps:
- Continue with remaining app models (appointments, finance, notifications, nursing, medical, aba, ot, slp, referrals, integrations)
Phase 1: Models Implementation (Current Phase)
1.1 Core App ✅ COMPLETE
Models Created:
Tenant- Multi-tenancy supportUser- Custom user with roles (ADMIN, DOCTOR, NURSE, OT, SLP, ABA, FRONT_DESK, FINANCE)Patient- Demographics, bilingual names, caregiver infoClinic- Specialties (MEDICAL, NURSING, ABA, OT, SLP)File- Main patient fileSubFile- Per-clinic sub-filesConsent- E-signature support with multiple typesAttachment- Generic file attachmentsAuditLog- Action tracking
Base Mixins Created:
UUIDPrimaryKeyMixin- UUID primary keysTimeStampedMixin- created_at, updated_atTenantOwnedMixin- tenant FKClinicallySignableMixin- signed_by, signed_atSoftDeleteMixin- soft delete support
1.2 Appointments App - TO DO
Models to Create:
# appointments/models.py
class Provider(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Provider (doctor/therapist) with specialties"""
user = OneToOneField(User)
specialties = ManyToManyField(Clinic)
is_available = BooleanField
max_daily_appointments = PositiveIntegerField
class Room(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Clinic rooms"""
name, room_number, clinic FK, is_available
class Schedule(UUIDPrimaryKeyMixin, TimeStampedMixin):
"""Provider availability schedule"""
provider FK, day_of_week, start_time, end_time, slot_duration, is_active
class Appointment(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Main appointment model with state machine"""
appointment_number (auto-generated)
patient FK, clinic FK, provider FK, room FK
service_type, scheduled_date, scheduled_time, duration
status: BOOKED, CONFIRMED, RESCHEDULED, CANCELLED, NO_SHOW, ARRIVED, IN_PROGRESS, COMPLETED
confirmation_sent_at, confirmation_method
arrival_at, start_at, end_at
reschedule_reason, reschedule_count
cancel_reason, cancelled_by FK
notes, finance_cleared, consent_verified
history = HistoricalRecords()
class AppointmentReminder(UUIDPrimaryKeyMixin, TimeStampedMixin):
"""Scheduled reminders"""
appointment FK, reminder_type (SMS/WHATSAPP/EMAIL)
scheduled_for, sent_at, status, message_id FK
1.3 Finance App - TO DO
Models to Create:
# finance/models.py
class Service(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Billable services"""
code, name_en, name_ar, clinic FK
base_price (MoneyField), duration_minutes, is_active
class Package(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Service packages (e.g., 10 SLP sessions)"""
name_en, name_ar, services M2M
total_sessions, price (MoneyField), validity_days, is_active
class Invoice(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Patient invoices"""
invoice_number (auto-generated)
patient FK, appointment FK (nullable)
issue_date, due_date
subtotal, tax, discount, total
status: DRAFT, ISSUED, PAID, PARTIALLY_PAID, CANCELLED
notes
history = HistoricalRecords()
class InvoiceLineItem(UUIDPrimaryKeyMixin):
"""Invoice line items"""
invoice FK, service FK (nullable), package FK (nullable)
description, quantity, unit_price, total
class Payment(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Payment records"""
invoice FK, payment_date, amount
method: CASH, CARD, BANK_TRANSFER, INSURANCE
transaction_id, reference, status
processed_by FK
class Payer(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Insurance/payer information"""
name, type: SELF, INSURANCE, GOVERNMENT
policy_number, coverage_percentage
patient FK, is_active
1.4 Notifications App - TO DO
Models to Create:
# notifications/models.py
class MessageTemplate(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Message templates"""
code (unique), name
channel: SMS, WHATSAPP, EMAIL
subject (for email), body_en, body_ar
variables (JSONField), is_active
class Message(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Outbound messages"""
template FK, channel, recipient
subject, body, variables_used (JSONField)
status: QUEUED, SENT, DELIVERED, FAILED, BOUNCED
sent_at, delivered_at
provider_message_id, provider_response (JSONField)
error_message, retry_count
class NotificationPreference(UUIDPrimaryKeyMixin, TimeStampedMixin):
"""Patient notification preferences"""
patient FK
sms_enabled, whatsapp_enabled, email_enabled
appointment_reminders, appointment_confirmations, results_notifications
1.5 Nursing App - TO DO
Models to Create (Based on MD-N-F-1 form):
# nursing/models.py
class NursingEncounter(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin):
"""Nursing vitals and assessment"""
patient FK, appointment FK (nullable)
encounter_date, filled_by FK
# Anthropometrics
height_cm, weight_kg, head_circumference_cm
bmi (calculated property)
# Vitals
hr_bpm, bp_systolic, bp_diastolic
respiratory_rate, spo2, temperature
crt: LESS_THAN_2S, MORE_THAN_2S
pain_score (0-10)
# Allergies
allergy_present, allergy_details
# Observations
observations (TextField)
history = HistoricalRecords()
class GrowthChart(UUIDPrimaryKeyMixin):
"""Growth chart data points"""
patient FK, measurement_date
height_cm, weight_kg, head_circ_cm
age_months
percentile_height, percentile_weight
1.6 Medical App - TO DO
Models to Create (Based on MD-F-1 and MD-F-2 forms):
# medical/models.py
class MedicalConsultation(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin):
"""Medical consultation (MD-F-1)"""
patient FK, appointment FK, consultation_date, provider FK
# History sections
chief_complaint, present_illness_history
past_medical_history, vaccination_status
family_history, social_history
pregnancy_history, neonatal_history
# Developmental milestones
developmental_motor_milestones
developmental_language_milestones
developmental_social_milestones
developmental_cognitive_milestones
# Behavioral symptoms (JSONField checklist)
behavioral_symptoms
# Physical exam (JSONField structured)
physical_exam
# Assessment & Plan
clinical_summary, recommendations
referrals_needed
lab_orders (JSONField), radiology_orders (JSONField)
history = HistoricalRecords()
class MedicationPlan(UUIDPrimaryKeyMixin):
"""Medication details"""
consultation FK
drug_name, dose
frequency: DAILY, BID, TID, QID, PRN, OTHER
frequency_other
compliance: GOOD, PARTIAL, BAD
gains, side_effects
target_behavior, improved
class MedicalFollowUp(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin):
"""Medical follow-up (MD-F-2)"""
patient FK, appointment FK
previous_consultation FK
followup_date, provider FK
# Previous complaints status (JSONField: complaint → RESOLVED/STATIC/WORSE)
previous_complaints_status
new_complaints
# Links
nursing_vitals FK (to NursingEncounter)
# Assessment
assessment, recommendations
family_satisfaction: ZERO, FIFTY, HUNDRED
medication_snapshot (JSONField)
history = HistoricalRecords()
1.7 ABA App - TO DO
Models to Create (Based on ABA-F-1 form):
# aba/models.py
class ABAConsult(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin):
"""ABA consultation"""
patient FK, appointment FK, consultation_date, provider FK
reason_of_referral: (TextChoices with options from form)
parental_concern, school_concern
respondents, interviewer
diagnosed_condition
interaction_hours_per_day
# Factors (JSONField with booleans)
physiological_factors
medical_factors
recommendations
history = HistoricalRecords()
class ABABehavior(UUIDPrimaryKeyMixin):
"""Behavior details"""
consult FK
behavior_description
frequency: HOURLY, DAILY, WEEKLY, LESS_THAN_WEEKLY
duration
intensity: MILD, MODERATE, SEVERE
antecedents_likely, antecedents_least_likely
consequences
order (for sorting)
1.8 OT App - TO DO
Models to Create (Based on OT-F-1 and OT-F-3 forms):
# ot/models.py
class OTConsult(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin):
"""OT consultation (OT-F-1)"""
patient FK, appointment FK, consultation_date, provider FK
reasons (ArrayField or M2M with choices)
top_difficulty_areas (JSONField: 3 text fields)
# Developmental & skills (JSONField matrices)
developmental_motor_milestones
self_help_skills
feeding_participation
# Behavior descriptors (JSONField)
infant_behavior_descriptors
current_behavior_descriptors
recommendation: CONTINUE, DISCHARGE, REFER_TO_OTHER
recommendation_notes
history = HistoricalRecords()
class OTSession(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin):
"""OT session notes (OT-F-3)"""
patient FK, appointment FK (nullable), session_date, provider FK
session_type: CONSULT, INDIVIDUAL, GROUP, PARENT_TRAINING
cooperative_level (1-4)
distraction_tolerance (1-4)
activities_checklist (JSONField: "Today we work on...")
observations, activities_performed
recommendations
history = HistoricalRecords()
class OTTargetSkill(UUIDPrimaryKeyMixin):
"""Target skills with 0-10 scoring"""
session FK
skill_name
score (0-10)
notes
order
1.9 SLP App - TO DO
Models to Create (Based on SLP-F-1, F-2, F-3, F-4 forms):
# slp/models.py
class SLPConsult(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin):
"""SLP consultation (SLP-F-1 with variants)"""
patient FK, appointment FK, consultation_date, provider FK
consult_variant: ASD, LANGUAGE_DELAY, FLUENCY
primary_concern
suspected_areas (JSONField)
type_of_service: CONSULT, EVAL, INTERVENTION, PARENT_TRAINING
communication_modes (JSONField checklist)
screen_time_hours
# Variant-specific questionnaires (JSONField)
variant_questionnaire
# Skills to observe (JSONField matrix)
skills_to_observe
# Oral motor screening (JSONField)
oral_motor_screening
recommendations
history = HistoricalRecords()
class SLPAssessment(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin):
"""SLP assessment (SLP-F-2)"""
patient FK, appointment FK, assessment_date, provider FK
diagnosis_statement, case_history
# History sections
prenatal_history, perinatal_history, postnatal_history
developmental_history, medical_status
# Speech/Language detail (JSONField)
speech_language_detail
# Test scores
gfta3_score, jat_score, ssi_score
# Oral mechanism (JSONField)
oral_mechanism
# Rossetti domains (JSONField: domain → age level)
rossetti_domains
# Joint attention skills (JSONField)
joint_attention_skills
# Summary & Plan
clinical_summary, recommendations
frequency_per_week, session_duration_minutes
referral_rules (JSONField)
history = HistoricalRecords()
class SLPIntervention(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin):
"""SLP intervention session (SLP-F-3)"""
patient FK, appointment FK
session_number, session_date, session_time
provider FK
previous_session FK (self-referential, nullable)
history = HistoricalRecords()
class SLPTarget(UUIDPrimaryKeyMixin):
"""Intervention targets (SOAP format)"""
intervention FK
target_number (1 or 2)
subjective, objective, assessment, plan
prompt_strategies (JSONField)
class SLPProgressReport(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin, ClinicallySignableMixin):
"""SLP progress report (SLP-F-4)"""
patient FK, report_date, provider FK
sessions_scheduled, sessions_attended
final_diagnosis
# Objectives & progress (JSONField: objective → % accuracy)
objectives_progress
# Plan details (JSONField)
plan_details
overall_progress, participation_level
attendance_rate, carryover_level
prognosis, recommendations
package_sessions_count
reassessment_needed
history = HistoricalRecords()
1.10 Referrals App - TO DO
Models to Create:
# referrals/models.py
class Referral(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Inter-discipline and external referrals"""
patient FK
from_clinic FK, to_clinic FK (nullable)
from_provider FK, to_provider FK (nullable)
external_provider_name
reason
urgency: ROUTINE, URGENT, EMERGENCY
status: PENDING, ACCEPTED, REJECTED, COMPLETED
created_at, responded_at
notes
1.11 Integrations App - TO DO
Models to Create:
# integrations/models.py
# Lab/Radiology
class ExternalOrder(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Lab and radiology orders"""
patient FK
order_type: LAB, RADIOLOGY
order_details (JSONField)
status: ORDERED, IN_PROGRESS, COMPLETED, CANCELLED
result_url, result_data (JSONField)
ordered_by FK, ordered_at, completed_at
# NPHIES (Insurance e-Claims)
class NphiesMessage(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""NPHIES FHIR messages"""
direction: OUTBOUND, INBOUND
resource_type: ELIGIBILITY, PRIOR_AUTH, CLAIM, PAYMENT_NOTICE, PAYMENT_RECONCILIATION
fhir_json (JSONField)
status: QUEUED, SENT, ACK, ERROR
correlation_id
response_http_status, error_code, error_message
created_at, sent_at
class NphiesEncounterLink(UUIDPrimaryKeyMixin, TenantOwnedMixin):
"""Link appointments to NPHIES encounters"""
patient FK, appointment FK
encounter_id, claim_id, claim_response_id
class PayerContract(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""Insurance payer configurations"""
payer_code, payer_name
credentials (JSONField encrypted)
endpoints (JSONField)
supports_eligibility, supports_prior_auth, supports_claims
is_active
# ZATCA (E-Invoicing)
class EInvoice(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""ZATCA e-invoices"""
invoice FK (to finance.Invoice)
uuid, xml_payload, qr_base64
clearance_status: PENDING, CLEARED, REJECTED, REPORTED
zatca_document_type
submission_mode: CLEARANCE, REPORTING
response_payload (JSONField)
error_code, error_message
submitted_at
class ZatcaCredential(UUIDPrimaryKeyMixin, TimeStampedMixin, TenantOwnedMixin):
"""ZATCA credentials (CSIDs)"""
environment: SIMULATION, COMPLIANCE, PRODUCTION
csid, certificate, private_key (encrypted)
is_active, expires_at
Phase 2: Forms Implementation (4-5 days)
Forms to Create Per App
Core Forms:
PatientForm- Bilingual patient registrationConsentForm- With signature captureAttachmentForm- File upload
Appointments Forms:
AppointmentBookingFormAppointmentConfirmFormAppointmentRescheduleFormAppointmentCancelForm
Nursing Forms:
NursingEncounterForm- Auto-calculate BMI
Medical Forms:
MedicalConsultationForm- Sections matching MD-F-1MedicationPlanFormSet- Inline formsetMedicalFollowUpForm- Sections matching MD-F-2
ABA Forms:
ABAConsultFormABABehaviorFormSet- Inline formset
OT Forms:
OTConsultFormOTSessionFormOTTargetSkillFormSet- Inline formset
SLP Forms:
SLPConsultForm- Variant-specific sectionsSLPAssessmentFormSLPInterventionFormSLPTargetFormSet- Inline formsetSLPProgressReportForm
Finance Forms:
InvoiceFormPaymentForm
Phase 3: Views Implementation (5-7 days)
Views Structure Per App
Core Views:
- Patient CRUD (List, Detail, Create, Update)
- Patient Dashboard (hub with tabs)
- Consent CRUD
Appointments Views:
- Calendar view (weekly grid)
- Appointment CRUD
- HTMX partials for state transitions
Clinical Document Views (per app):
- List, Detail, Create, Update for each document type
- HTMX partials for dynamic forms
Finance Views:
- Invoice CRUD
- Payment processing
Notifications Views:
- Message outbox
- Message detail
Audit Views:
- Audit timeline
- Version comparison
Phase 4: URLs Configuration (1-2 days)
- Namespaced URLs for all apps
- HTMX partial endpoints
- DRF routers for API apps
Phase 5: Templates Implementation (5-7 days)
- Base templates with RTL/LTR
- Patient hub with tabs
- Clinical form templates matching paper forms
- Charts (OT/SLP target progress, growth charts)
- Appointment calendar
Phase 6: DRF API Implementation (3-4 days)
APIs to Create:
- Appointments API (CRUD + state transitions)
- Notifications API (create, webhook receiver)
- Referrals API (CRUD)
- Integrations API:
- NPHIES endpoints (eligibility, prior-auth, claims, payment)
- ZATCA endpoints (prepare, submit, onboard)
- Lab/Radiology stubs
- Consent verification
Phase 7: Signals, Services & Tasks (3-4 days)
Signals:
- Patient created → create File
- Appointment created → create SubFile (if first for clinic)
- Appointment status changed → enqueue notification
Services:
- Notification service (SMS/WhatsApp/Email)
- NPHIES FHIR client
- ZATCA e-invoicing service
- Lab/Radiology service
Celery Tasks:
- Appointment reminders (T-24h, T-12h)
- NPHIES polling
- Payment reconciliation
- ZATCA batch submission
Phase 8: Admin, RBAC & Auditing (2-3 days)
- Django admin for all models
- Permission matrix implementation
- Audit trail views
- Export functionality
Phase 9: Testing (4-5 days)
- Model tests
- Form tests
- View tests (permissions, HTMX)
- API tests
- Integration tests
- i18n tests
Phase 10: Documentation & Deployment (2-3 days)
- README.md
- DEPLOYMENT.md
- API_DOCS.md
- RBAC_MATRIX.md
- INTEGRATION_GUIDE.md
Timeline Summary
| Phase | Duration | Status |
|---|---|---|
| 0: Foundation | 2-3 days | ✅ COMPLETE |
| 1: Models | 7-10 days | 🔄 IN PROGRESS (Core complete) |
| 2: Forms | 4-5 days | ⏳ PENDING |
| 3: Views | 5-7 days | ⏳ PENDING |
| 4: URLs | 1-2 days | ⏳ PENDING |
| 5: Templates | 5-7 days | ⏳ PENDING |
| 6: DRF APIs | 3-4 days | ⏳ PENDING |
| 7: Services/Tasks | 3-4 days | ⏳ PENDING |
| 8: Admin/RBAC | 2-3 days | ⏳ PENDING |
| 9: Testing | 4-5 days | ⏳ PENDING |
| 10: Docs/Deploy | 2-3 days | ⏳ PENDING |
| TOTAL | 38-53 days | ~8-11 weeks |
Next Immediate Steps
- ✅ Complete core models
- ⏭️ Create appointments models
- ⏭️ Create finance models
- ⏭️ Create notifications models
- ⏭️ Create nursing models
- ⏭️ Create medical models
- ⏭️ Create aba models
- ⏭️ Create ot models
- ⏭️ Create slp models
- ⏭️ Create referrals models
- ⏭️ Create integrations models
- ⏭️ Run migrations
- ⏭️ Create signals for auto-generation (MRN, file numbers)
- ⏭️ Begin Phase 2 (Forms)
Critical Notes
- DO NOT skip phases - Each phase builds on the previous
- Models must be complete before starting forms
- All clinical documents must use
simple_history - All user-facing strings must use
gettext_lazy - UUID primary keys for all models
- Tenant isolation must be enforced everywhere
- RBAC must be checked in every view
- Audit trail for all clinical document changes
Reference Documents
- Clinical forms in project root (DOCX files)
- Original prompt:
multidisciplinary_django_prompt_1.md - Settings:
AgdarCentre/settings.py - Environment:
.env.example