agdar/IMPLEMENTATION_PLAN.md
2025-11-02 14:35:35 +03:00

757 lines
21 KiB
Markdown

# 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 support
- `User` - Custom user with roles (ADMIN, DOCTOR, NURSE, OT, SLP, ABA, FRONT_DESK, FINANCE)
- `Patient` - Demographics, bilingual names, caregiver info
- `Clinic` - Specialties (MEDICAL, NURSING, ABA, OT, SLP)
- `File` - Main patient file
- `SubFile` - Per-clinic sub-files
- `Consent` - E-signature support with multiple types
- `Attachment` - Generic file attachments
- `AuditLog` - Action tracking
**Base Mixins Created:**
- `UUIDPrimaryKeyMixin` - UUID primary keys
- `TimeStampedMixin` - created_at, updated_at
- `TenantOwnedMixin` - tenant FK
- `ClinicallySignableMixin` - signed_by, signed_at
- `SoftDeleteMixin` - soft delete support
### 1.2 Appointments App - TO DO
**Models to Create:**
```python
# 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:**
```python
# 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:**
```python
# 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):**
```python
# 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):**
```python
# 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):**
```python
# 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):**
```python
# 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):**
```python
# 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:**
```python
# 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:**
```python
# 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 registration
- `ConsentForm` - With signature capture
- `AttachmentForm` - File upload
**Appointments Forms:**
- `AppointmentBookingForm`
- `AppointmentConfirmForm`
- `AppointmentRescheduleForm`
- `AppointmentCancelForm`
**Nursing Forms:**
- `NursingEncounterForm` - Auto-calculate BMI
**Medical Forms:**
- `MedicalConsultationForm` - Sections matching MD-F-1
- `MedicationPlanFormSet` - Inline formset
- `MedicalFollowUpForm` - Sections matching MD-F-2
**ABA Forms:**
- `ABAConsultForm`
- `ABABehaviorFormSet` - Inline formset
**OT Forms:**
- `OTConsultForm`
- `OTSessionForm`
- `OTTargetSkillFormSet` - Inline formset
**SLP Forms:**
- `SLPConsultForm` - Variant-specific sections
- `SLPAssessmentForm`
- `SLPInterventionForm`
- `SLPTargetFormSet` - Inline formset
- `SLPProgressReportForm`
**Finance Forms:**
- `InvoiceForm`
- `PaymentForm`
---
## 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
1. ✅ Complete core models
2. ⏭️ Create appointments models
3. ⏭️ Create finance models
4. ⏭️ Create notifications models
5. ⏭️ Create nursing models
6. ⏭️ Create medical models
7. ⏭️ Create aba models
8. ⏭️ Create ot models
9. ⏭️ Create slp models
10. ⏭️ Create referrals models
11. ⏭️ Create integrations models
12. ⏭️ Run migrations
13. ⏭️ Create signals for auto-generation (MRN, file numbers)
14. ⏭️ 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`