Group Therapy Domain - Workflow Narrative
A conversational guide to understanding group therapy session workflows
What is the Group Therapy Domain?
Not all healthcare encounters are one-on-one. Group therapy, support groups, educational sessions, and family therapy all involve multiple participants in a single clinical encounter.
The Group Therapy domain enables the EMR to manage these multi-participant sessions. It tracks therapy groups, their members (both registered patients and lightweight guests), and links encounters to groups rather than individual patients.
The Core Challenge
Traditional EMR encounters assume one provider meeting one patient. But consider:
- A depression support group meeting weekly with 8-12 participants
- A family therapy session with a patient plus family members who aren't patients
- An educational workshop where some attendees are registered patients and others are community members
The Group Therapy domain solves this by introducing:
- Groups as organizational containers for recurring sessions
- Guests as lightweight participant records for non-patients
- Group Encounters that link to a group rather than a single patient
- Per-participant form submissions for surveys and assessments
Groups: The Container
What Makes a Group
A group represents a recurring clinical activity:
- name - "Anxiety Management Group - Session A"
- type - therapy, support, or education
- status - active or archived
- max_participants - Optional capacity limit
- facilitator_id - The practitioner who leads sessions
Group Types
therapy - Clinical therapeutic groups (CBT groups, DBT groups)
support - Peer support without active therapy (grief, addiction)
education - Psychoeducational workshops (diabetes management class)
Group Lifecycle
Groups start as active and can be archived when they conclude. The archive is a soft delete - all historical data remains for reporting.
Guests: Lightweight Participants
When Guests Are Needed
Not everyone at a group session is a registered patient:
- A patient's spouse attending family therapy
- A community member at an educational workshop
- A family member participating in a support group
Creating full patient records for these participants is overkill and may be inappropriate.
Guest Records
Guests are lightweight:
- display_name - How to address them ("Maria's Mother")
- contact - Optional JSON for phone/email
- notes - Any relevant notes
- is_active - For soft-delete
Guests belong to an organization just like patients, maintaining multi-tenancy.
Group Members: The Roster
Two Types of Members
A group can have members who are:
- Patients - Linked by
patient_idto a full patient record - Guests - Linked by
guest_idto a lightweight guest record
The member_type field distinguishes which reference is used.
Membership Status
Members have a status:
- active - Currently participating
- left - Previously participated, now removed
The joined_at and left_at timestamps track participation periods.
Preventing Duplicates
Unique partial indexes prevent the same patient or guest from being an active member twice in the same group. They can rejoin after leaving.
Capacity Management
If a group has max_participants set, the service checks active member count before adding new members. When capacity is reached, new additions are rejected.
Group Encounters: The Session Record
How It Works
The Encounter model was extended with:
- subject_type - "patient" (default) or "group"
- group_id - Foreign key to groups (nullable)
- patient_id - Made nullable for group encounters
A group encounter represents a session:
subject_type: "group"
group_id: "grp25121304229e0j"
patient_id: null
encounter_date: 2024-12-12T10:00:00Z
type: "group-therapy"
Session Notes
Clinical notes for a group encounter document the session as a whole. Individual participant observations can be linked through encounter notes with participant references.
Form Submissions: Per-Participant Data
The Challenge
During group sessions, clinicians often administer surveys or assessments to each participant. How do we link survey responses to both:
- The group encounter (the session where it was collected)
- The specific participant (patient or guest who answered)
GroupFormSubmission Model
This model links everything together:
- encounter_id - Which session
- group_id - Which group
- participant_type - "patient" or "guest"
- patient_id or guest_id - The responder
- form_id - Which form/survey
- external_submission_id - Link to form response data
API Workflow: Creating a Group Session
1. Create the Group (Once)
POST /api/groups
{
"name": "Depression Support - Monday AM",
"type": "support",
"max_participants": 12,
"facilitator_id": "prac_abc123"
}
2. Add Members (As They Join)
POST /api/groups/{group_id}/members
{
"member_type": "patient",
"patient_id": "pa_xyz789"
}
Or for a guest:
POST /api/groups/guests
{
"display_name": "Patient's Spouse",
"contact": {"phone": "555-1234"}
}
POST /api/groups/{group_id}/members
{
"member_type": "guest",
"guest_id": "gst_abc123"
}
2b. Batch Add Members (For Initial Setup)
When setting up a group with many participants, use batch add:
POST /api/groups/{group_id}/members/batch
{
"members": [
{"member_type": "patient", "patient_id": "pa_xyz789"},
{"member_type": "patient", "patient_id": "pa_abc123"},
{"member_type": "guest", "guest_id": "gst_def456"}
]
}
Response includes summary:
{
"success": true,
"data": {
"created": 3,
"skipped": 0,
"errors": [],
"items": [...]
}
}
The batch endpoint validates capacity upfront and gracefully handles duplicates (skipping already-active members).
3. Create Session Encounter
POST /api/groups/{group_id}/encounters
{
"encounter_date": "2024-12-12T10:00:00Z",
"type": "group-therapy",
"chief_complaint": "Weekly session - Topic: Coping Strategies"
}
4. Document the Session
Use standard encounter notes for session documentation:
POST /api/encounters/{encounter_id}/notes
{
"note_type": "session_note",
"content": "Group discussion focused on CBT techniques..."
}
Permission Model
Granular Control
Group operations have dedicated permissions:
| Permission | Allows |
|---|---|
group.create | Create groups and guests |
group.read | View groups and members |
group.update | Edit group details |
group.delete | Archive groups |
group.member.add | Add members to groups |
group.member.remove | Remove members from groups |
group.encounter.create | Start group sessions |
group.encounter.read | View group encounters |
group.encounter.note.create | Write session notes |
group.encounter.note.read | View session notes |
Role Assignments
- SUPERUSER / ADMIN / MANAGER: All group permissions
- DOCTOR / ALLIED_HEALTH: Full clinical access including notes
- NURSE: Read access + add members
- RECEPTIONIST: Read-only access
Database Schema
Four New Tables
guests
├── id (gst prefix)
├── organization_id (FK)
├── display_name
├── contact (JSON)
├── notes
├── is_active
└── created_by_user
groups
├── id (grp prefix)
├── organization_id (FK)
├── name
├── description
├── type
├── status
├── max_participants
├── facilitator_id (FK → practitioners)
├── custom_data (JSON)
└── created_by_user
group_members
├── id (gm prefix)
├── group_id (FK)
├── member_type (patient | guest)
├── patient_id (FK, nullable)
├── guest_id (FK, nullable)
├── joined_at
├── left_at
├── status
└── notes
group_form_submissions
├── id (gfs prefix)
├── organization_id (FK)
├── encounter_id (FK)
├── group_id (FK)
├── participant_type (patient | guest)
├── patient_id (FK, nullable)
├── guest_id (FK, nullable)
├── form_id
├── external_submission_id
├── submitted_at
└── submission_metadata (JSON)
Encounter Table Updates
encounters
+ subject_type: varchar (default 'patient')
+ group_id: FK → groups (nullable)
~ patient_id: now nullable
Indexes for Performance
Query Patterns Supported
| Query | Index |
|---|---|
| Groups by org + status | ix_groups_org_status |
| Active members by group | ix_group_members_group_status |
| Prevent duplicate patients | ix_group_members_unique_patient (partial) |
| Prevent duplicate guests | ix_group_members_unique_guest (partial) |
| Encounters by group | ix_encounters_group_id |
| Group encounters by org | ix_encounters_org_subject_type |
Integration Points
With Encounters
Group encounters flow into the normal encounter workflow. Finalization, documentation statuses, and practitioner assignments all work the same.
With Forms/Surveys
The GroupFormSubmission model links external form data to group sessions. If using a survey service, submission IDs can be stored and retrieved per-participant.
With Patients
Patients can be members of multiple groups. Patient-centric views can show which groups they belong to.
With Care Teams
A group could conceptually serve as a care team variant for participants who share a condition focus.
Key Takeaways
-
Groups are containers - For recurring clinical activities with multiple participants
-
Guests are lightweight - For non-patient participants without full records
-
Polymorphic members - Groups can have both patients and guests
-
Extended encounters -
subject_typefield switches between patient and group focus -
Per-participant data - Form submissions track who answered what in each session
-
Capacity management - Optional max_participants enforced on add
-
Batch operations - Add multiple members at once for efficient group setup
-
Soft delete everywhere - Members leave (not delete), groups archive
-
Full permission control - 10 granular permissions for different operations
Previous: Read about the Organization & Practitioner Domain for organizational setup Next: Explore the Access Control Domain for understanding ACL and permissions