426 lines
10 KiB
Markdown
426 lines
10 KiB
Markdown
# OT Consultation Form - Quick Start Guide
|
||
|
||
## Overview
|
||
The OT Consultation Form (OT-F-1) is now fully implemented with comprehensive database schema, automatic scoring, and dynamic configuration.
|
||
|
||
## Quick Usage
|
||
|
||
### Creating a New Consultation
|
||
|
||
```python
|
||
from ot.models import OTConsult
|
||
from ot.scoring_service import initialize_consultation_data, OTScoringService
|
||
|
||
# 1. Create consultation
|
||
consult = OTConsult.objects.create(
|
||
patient=patient,
|
||
tenant=tenant,
|
||
consultation_date=date.today(),
|
||
provider=provider,
|
||
referral_reason='Assessment'
|
||
)
|
||
|
||
# 2. Initialize all related data (auto-creates 55 records)
|
||
initialize_consultation_data(consult)
|
||
|
||
# 3. Fill in data through formsets or admin
|
||
# ... user fills in difficulty areas, milestones, skills, behaviors ...
|
||
|
||
# 4. Calculate scores
|
||
scoring_service = OTScoringService(consult)
|
||
scores = scoring_service.calculate_total_score()
|
||
scoring_service.save_scores()
|
||
|
||
# 5. View results
|
||
print(f"Total Score: {consult.total_score}")
|
||
print(f"Interpretation: {consult.score_interpretation}")
|
||
print(f"Recommendation: {consult.recommendation_notes}")
|
||
```
|
||
|
||
### Accessing Through Admin
|
||
|
||
1. Navigate to Django Admin → OT → OT Consultations
|
||
2. Click "Add OT Consultation"
|
||
3. Fill in patient and provider information
|
||
4. Use inline editors to fill in:
|
||
- Difficulty Areas (max 3)
|
||
- Milestones (16 total, 3 required)
|
||
- Self-Help Skills (15 total)
|
||
- Infant Behaviors (12 total)
|
||
- Current Behaviors (12 total)
|
||
5. Save - scores calculate automatically
|
||
6. Use "Recalculate scores" action if needed
|
||
|
||
### Accessing Through Views
|
||
|
||
**Create:**
|
||
```
|
||
/ot/consult/create/?patient=<patient_id>
|
||
```
|
||
|
||
**Update:**
|
||
```
|
||
/ot/consult/<pk>/update/
|
||
```
|
||
|
||
**Detail:**
|
||
```
|
||
/ot/consult/<pk>/
|
||
```
|
||
|
||
## Data Structure
|
||
|
||
### Main Consultation Fields
|
||
- `patient` - ForeignKey to Patient
|
||
- `consultation_date` - Date of consultation
|
||
- `provider` - ForeignKey to User (OT therapist)
|
||
- `referral_reason` - Choice field (5 options)
|
||
- `motor_learning_difficulty` - Boolean
|
||
- `motor_skill_regression` - Boolean
|
||
- `eats_healthy_variety` - Boolean
|
||
- `eats_variety_textures` - Boolean
|
||
- `participates_family_meals` - Boolean
|
||
- `recommendation` - Choice field
|
||
- `recommendation_notes` - Auto-generated or manual
|
||
- `clinician_name` - Text
|
||
- `clinician_signature` - Text
|
||
|
||
### Related Data (Auto-initialized)
|
||
|
||
**Difficulty Areas (max 3):**
|
||
- 12 predefined areas
|
||
- Each with details field
|
||
- Enforced max 3 via formset
|
||
|
||
**Milestones (16 total):**
|
||
- headControl, reachObject, rollOver, fingerFeed
|
||
- **sitting** (required), pullStand, **crawling** (required)
|
||
- drawCircle, spoon, cutScissors
|
||
- **walking** (required), drinkCup, jump, hop, hopOneFoot, bike
|
||
|
||
**Self-Help Skills (15 total):**
|
||
- 8-9 months: 2 skills
|
||
- 12-18 months: 4 skills
|
||
- 18-24 months: 2 skills
|
||
- 2-3 years: 4 skills
|
||
- 3-4 years: 2 skills
|
||
- 5-6 years: 1 skill
|
||
|
||
**Infant Behaviors (12 total):**
|
||
- cried, good, alert, quiet, passive, active
|
||
- likedHeld, resistedHeld, floppy, tense
|
||
- sleepGood, sleepIrregular
|
||
|
||
**Current Behaviors (12 total):**
|
||
- quiet, active, tires, talks, impulsive, restless
|
||
- stubborn, resistant, fights, tantrums, clumsy, frustrated
|
||
|
||
## Scoring System
|
||
|
||
### Score Calculation
|
||
|
||
**Self-Help (max 24):**
|
||
- Yes = 2 points
|
||
- No = 0 points
|
||
- 15 skills × 2 = 30 possible, capped at 24
|
||
|
||
**Behavior (max 48):**
|
||
- Yes = 2 points
|
||
- Sometimes = 1 point
|
||
- No = 0 points
|
||
- 24 behaviors × 2 = 48 possible
|
||
|
||
**Developmental (max 6):**
|
||
- Required milestones only (sitting, crawling, walking)
|
||
- Achieved = 2 points each
|
||
- 3 milestones × 2 = 6 possible
|
||
|
||
**Eating (max 6):**
|
||
- Yes = 2 points each
|
||
- 3 questions × 2 = 6 possible
|
||
|
||
**Total: 0-84 points**
|
||
|
||
### Interpretation Thresholds
|
||
|
||
| Score Range | Interpretation | Recommendation |
|
||
|-------------|----------------|----------------|
|
||
| 0-30 | ⚠️ Needs Immediate Attention | Immediate referral to OT and interdisciplinary evaluation |
|
||
| 31-60 | ⚠ Moderate Difficulty | Start OT sessions, monitor progress in 2-4 months |
|
||
| 61-84 | ✅ Age-Appropriate Skills | Regular developmental screening as preventive care |
|
||
|
||
### Critical Flags (Auto-detected)
|
||
|
||
1. Developmental regression reported
|
||
2. Irregular sleep patterns (infancy)
|
||
3. Feeding difficulty with textures
|
||
4. Frequent aggressive behavior (fights)
|
||
5. Frequent temper tantrums
|
||
6. High restlessness and inattention
|
||
7. Strong resistance to change or routines
|
||
|
||
## Dynamic Configuration
|
||
|
||
### Creating Custom Scoring Config
|
||
|
||
```python
|
||
from ot.models import OTScoringConfig
|
||
|
||
config = OTScoringConfig.objects.create(
|
||
tenant=tenant,
|
||
name="Custom Scoring for Ages 3-5",
|
||
is_active=True,
|
||
|
||
# Custom max scores
|
||
self_help_max=30,
|
||
behavior_max=50,
|
||
developmental_max=10,
|
||
eating_max=8,
|
||
|
||
# Custom thresholds
|
||
immediate_attention_threshold=35,
|
||
moderate_difficulty_threshold=70,
|
||
|
||
# Custom labels
|
||
immediate_attention_label="Urgent Intervention Required",
|
||
moderate_difficulty_label="Needs Support",
|
||
age_appropriate_label="Developing Well",
|
||
|
||
# Custom recommendations
|
||
immediate_attention_recommendation="Custom recommendation text...",
|
||
moderate_difficulty_recommendation="Custom recommendation text...",
|
||
age_appropriate_recommendation="Custom recommendation text..."
|
||
)
|
||
```
|
||
|
||
### Using Custom Config
|
||
|
||
The scoring service automatically uses the active configuration for the tenant:
|
||
|
||
```python
|
||
scoring_service = OTScoringService(consult)
|
||
# Automatically uses tenant's active OTScoringConfig
|
||
scores = scoring_service.calculate_total_score()
|
||
```
|
||
|
||
## API Examples
|
||
|
||
### Get Score Summary
|
||
|
||
```python
|
||
scoring_service = OTScoringService(consult)
|
||
summary = scoring_service.get_score_summary()
|
||
|
||
# Returns:
|
||
{
|
||
'scores': {
|
||
'self_help': 18,
|
||
'behavior': 32,
|
||
'developmental': 6,
|
||
'eating': 4,
|
||
'total': 60,
|
||
'interpretation': '⚠ Moderate Difficulty - Follow-Up Needed',
|
||
'recommendation': 'The child shows moderate concerns...',
|
||
'critical_flags': ['Frequent temper tantrums'],
|
||
'max_scores': {
|
||
'self_help': 24,
|
||
'behavior': 48,
|
||
'developmental': 6,
|
||
'eating': 6,
|
||
'total': 84
|
||
}
|
||
},
|
||
'percentages': {
|
||
'self_help': 75.0,
|
||
'behavior': 66.7,
|
||
'developmental': 100.0,
|
||
'eating': 66.7,
|
||
'total': 71.4
|
||
},
|
||
'chart_data': {
|
||
'labels': ['Self-Help', 'Behavior', 'Developmental', 'Eating'],
|
||
'scores': [18, 32, 6, 4],
|
||
'max_scores': [24, 48, 6, 6]
|
||
}
|
||
}
|
||
```
|
||
|
||
### Recalculate Scores
|
||
|
||
```python
|
||
# After updating any related data
|
||
consult.calculate_scores()
|
||
consult.save()
|
||
|
||
# Or use the service
|
||
scoring_service = OTScoringService(consult)
|
||
scoring_service.save_scores()
|
||
```
|
||
|
||
## Common Tasks
|
||
|
||
### Add a Difficulty Area
|
||
|
||
```python
|
||
from ot.models import OTDifficultyArea
|
||
|
||
# Check current count (max 3)
|
||
current_count = consult.difficulty_areas.count()
|
||
|
||
if current_count < 3:
|
||
OTDifficultyArea.objects.create(
|
||
consult=consult,
|
||
area='sensory',
|
||
details='Hypersensitivity to loud noises',
|
||
order=current_count
|
||
)
|
||
```
|
||
|
||
### Update a Milestone
|
||
|
||
```python
|
||
milestone = consult.milestones.get(milestone='sitting')
|
||
milestone.age_achieved = '6 months'
|
||
milestone.save()
|
||
|
||
# Recalculate scores
|
||
consult.calculate_scores()
|
||
consult.save()
|
||
```
|
||
|
||
### Update Self-Help Skill
|
||
|
||
```python
|
||
skill = consult.self_help_skills.get(
|
||
age_range='2-3',
|
||
skill_name='Able to feed self with little to no spilling'
|
||
)
|
||
skill.response = 'yes'
|
||
skill.comments = 'Mastered this skill recently'
|
||
skill.save()
|
||
|
||
# Recalculate scores
|
||
consult.calculate_scores()
|
||
consult.save()
|
||
```
|
||
|
||
### Update Behavior
|
||
|
||
```python
|
||
behavior = consult.current_behaviors.get(behavior='tantrums')
|
||
behavior.response = 'yes'
|
||
behavior.save()
|
||
|
||
# Recalculate scores (will add to critical flags)
|
||
consult.calculate_scores()
|
||
consult.save()
|
||
```
|
||
|
||
## Formset Usage in Views
|
||
|
||
### In Create View
|
||
|
||
```python
|
||
def form_valid(self, form):
|
||
# Get formsets from context
|
||
difficulty_formset = context['difficulty_formset']
|
||
milestone_formset = context['milestone_formset']
|
||
# ... etc
|
||
|
||
# Validate all
|
||
if not all([difficulty_formset.is_valid(), ...]):
|
||
return self.form_invalid(form)
|
||
|
||
# Save main form
|
||
self.object = form.save()
|
||
|
||
# Initialize data
|
||
initialize_consultation_data(self.object)
|
||
|
||
# Save formsets
|
||
difficulty_formset.instance = self.object
|
||
difficulty_formset.save()
|
||
# ... etc
|
||
|
||
# Calculate scores
|
||
scoring_service = OTScoringService(self.object)
|
||
scoring_service.save_scores()
|
||
|
||
return HttpResponseRedirect(self.get_success_url())
|
||
```
|
||
|
||
## Troubleshooting
|
||
|
||
### Scores Not Calculating
|
||
|
||
```python
|
||
# Check if related data exists
|
||
print(f"Difficulty areas: {consult.difficulty_areas.count()}")
|
||
print(f"Milestones: {consult.milestones.count()}")
|
||
print(f"Self-help skills: {consult.self_help_skills.count()}")
|
||
print(f"Infant behaviors: {consult.infant_behaviors.count()}")
|
||
print(f"Current behaviors: {consult.current_behaviors.count()}")
|
||
|
||
# If counts are 0, initialize data
|
||
if consult.milestones.count() == 0:
|
||
initialize_consultation_data(consult)
|
||
|
||
# Recalculate
|
||
scoring_service = OTScoringService(consult)
|
||
scoring_service.save_scores()
|
||
```
|
||
|
||
### Max 3 Difficulty Areas Not Enforced
|
||
|
||
Check formset configuration:
|
||
```python
|
||
# In forms.py
|
||
OTDifficultyAreaFormSet = inlineformset_factory(
|
||
OTConsult,
|
||
OTDifficultyArea,
|
||
form=OTDifficultyAreaForm,
|
||
extra=3,
|
||
max_num=3, # This enforces max 3
|
||
can_delete=True,
|
||
validate_max=True, # This validates max 3
|
||
)
|
||
```
|
||
|
||
### Custom Config Not Being Used
|
||
|
||
```python
|
||
# Check active config
|
||
config = OTScoringConfig.objects.filter(
|
||
tenant=consult.tenant,
|
||
is_active=True
|
||
).first()
|
||
|
||
if not config:
|
||
# Create default config
|
||
config = OTScoringConfig.objects.create(
|
||
tenant=consult.tenant,
|
||
name="Default OT Scoring Configuration",
|
||
is_active=True
|
||
)
|
||
```
|
||
|
||
## Best Practices
|
||
|
||
1. **Always initialize consultation data** after creating a new consultation
|
||
2. **Recalculate scores** after updating any related data
|
||
3. **Use formsets** for managing related data in views
|
||
4. **Check critical flags** in the score summary
|
||
5. **Configure scoring per tenant** for customization
|
||
6. **Use admin actions** for bulk score recalculation
|
||
7. **Monitor required milestones** (sitting, crawling, walking)
|
||
8. **Enforce max 3 difficulty areas** via formset validation
|
||
|
||
## References
|
||
|
||
- Full Implementation: `OT_CONSULTATION_FORM_IMPLEMENTATION.md`
|
||
- Models: `ot/models.py`
|
||
- Forms: `ot/forms.py`
|
||
- Scoring Service: `ot/scoring_service.py`
|
||
- Views: `ot/views.py`
|
||
- Admin: `ot/admin.py`
|