# Clinical Document Signing Implementation Plan ## Overview This document outlines the implementation of clinical document signing functionality across all therapy modules that use `ClinicallySignableMixin`. ## Completed Implementation ### ✅ ABA Module - **Models**: ABAConsult, ABASession - **Views**: Added `ABASessionSignView` for signing sessions - **URLs**: Added `/sessions//sign/` route - **Templates**: - `session_detail.html`: Sign button for unsigned sessions - `session_list.html`: Unsigned sessions notification banner + signature status column - **Features**: - Role-based access (provider or admin only) - Confirmation dialog before signing - Audit trail (signed_by, signed_at) - Visual indicators (badges, alerts) ## Pending Implementation ### 1. OT (Occupational Therapy) Module #### Models to Implement - **OTConsult** - Consultation forms - **OTSession** - Session notes - **OTProgressReport** - Progress reports #### Required Changes **Views** (`ot/views.py`): ```python # Add sign views for each model class OTConsultSignView(LoginRequiredMixin, RolePermissionMixin, TenantFilterMixin, View): allowed_roles = [User.Role.ADMIN, User.Role.OT] # Similar implementation to ABASessionSignView class OTSessionSignView(LoginRequiredMixin, RolePermissionMixin, TenantFilterMixin, View): allowed_roles = [User.Role.ADMIN, User.Role.OT] class OTProgressReportSignView(LoginRequiredMixin, RolePermissionMixin, TenantFilterMixin, View): allowed_roles = [User.Role.ADMIN, User.Role.OT] ``` **URLs** (`ot/urls.py`): ```python # Add sign routes path('consults//sign/', views.OTConsultSignView.as_view(), name='consult_sign'), path('sessions//sign/', views.OTSessionSignView.as_view(), name='session_sign'), path('progress-reports//sign/', views.OTProgressReportSignView.as_view(), name='progress_report_sign'), ``` **Templates**: - `ot/templates/ot/consult_detail.html` - Add signature status card with sign button - `ot/templates/ot/consult_list.html` - Add unsigned notifications + signature column - `ot/templates/ot/session_detail.html` - Add signature status card with sign button - `ot/templates/ot/session_list.html` - Add unsigned notifications + signature column - `ot/templates/ot/progress_report_detail.html` - Add signature status card with sign button - `ot/templates/ot/progress_report_list.html` - Add unsigned notifications + signature column **List Views** - Update `get_context_data()`: ```python def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) user = self.request.user # Get unsigned documents for current user unsigned_query = ModelName.objects.filter( tenant=user.tenant, signed_by__isnull=True ) if user.role == User.Role.OT: unsigned_query = unsigned_query.filter(provider=user) context['unsigned_count'] = unsigned_query.count() context['unsigned_items'] = unsigned_query.select_related('patient', 'provider').order_by('-date_field')[:10] return context ``` ### 2. SLP (Speech-Language Pathology) Module #### Models to Implement - **SLPConsult** - Consultation forms - **SLPAssessment** - Assessment reports - **SLPIntervention** - Intervention notes - **SLPProgressReport** - Progress reports #### Required Changes Same pattern as OT module: - Add 4 sign views (one per model) - Add 4 URL routes - Update 8 templates (4 detail + 4 list) - Update 4 list views with unsigned counts **Views** (`slp/views.py`): ```python class SLPConsultSignView(...) class SLPAssessmentSignView(...) class SLPInterventionSignView(...) class SLPProgressReportSignView(...) ``` **URLs** (`slp/urls.py`): ```python path('consults//sign/', ...), path('assessments//sign/', ...), path('interventions//sign/', ...), path('progress-reports//sign/', ...), ``` ### 3. Medical Module #### Models to Implement - **MedicalConsultation** - Medical consultations - **MedicalFollowUp** - Follow-up visits #### Required Changes Same pattern: - Add 2 sign views - Add 2 URL routes - Update 4 templates (2 detail + 2 list) - Update 2 list views **Views** (`medical/views.py`): ```python class MedicalConsultationSignView(...) class MedicalFollowUpSignView(...) ``` **URLs** (`medical/urls.py`): ```python path('consultations//sign/', ...), path('follow-ups//sign/', ...), ``` ### 4. Nursing Module #### Models to Implement - **NursingEncounter** - Nursing encounters #### Required Changes - Add 1 sign view - Add 1 URL route - Update 2 templates (1 detail + 1 list) - Update 1 list view **Views** (`nursing/views.py`): ```python class NursingEncounterSignView(...) ``` **URLs** (`nursing/urls.py`): ```python path('encounters//sign/', ...), ``` ## Implementation Checklist ### Per Model Implementation Steps: - [ ] Create sign view class in views.py - [ ] Add URL route in urls.py - [ ] Update detail template with signature status card - [ ] Update list template with unsigned notification banner - [ ] Add signature status column to list table - [ ] Update list view to include unsigned counts - [ ] Test signing functionality - [ ] Test role-based access control - [ ] Verify audit trail (signed_by, signed_at) ### OT Module - [ ] OTConsult signing (3 steps above) - [ ] OTSession signing (3 steps above) - [ ] OTProgressReport signing (3 steps above) ### SLP Module - [ ] SLPConsult signing - [ ] SLPAssessment signing - [ ] SLPIntervention signing - [ ] SLPProgressReport signing ### Medical Module - [ ] MedicalConsultation signing - [ ] MedicalFollowUp signing ### Nursing Module - [ ] NursingEncounter signing ## Code Reusability ### Generic Sign View Template Consider creating a generic mixin or base class to reduce code duplication: ```python # core/mixins.py class ClinicalDocumentSignMixin: """Mixin for signing clinical documents.""" def post(self, request, pk): model = self.model document = get_object_or_404( model, pk=pk, tenant=request.user.tenant ) # Check if already signed if document.signed_by: messages.warning(request, "This document has already been signed.") return HttpResponseRedirect(self.get_success_url(pk)) # Check if user is the provider or admin if document.provider != request.user and request.user.role != User.Role.ADMIN: messages.error(request, "Only the provider or an administrator can sign this document.") return HttpResponseRedirect(self.get_success_url(pk)) # Sign the document document.signed_by = request.user document.signed_at = timezone.now() document.save() messages.success(request, f"{model._meta.verbose_name} signed successfully!") return HttpResponseRedirect(self.get_success_url(pk)) def get_success_url(self, pk): raise NotImplementedError("Subclasses must implement get_success_url()") ``` ### Template Includes Create reusable template snippets: **`templates/includes/signature_status_card.html`**: ```django
{% trans "Signature Status" %}
{% if document.signed_by %} {% else %} {% endif %}
``` **`templates/includes/unsigned_notification.html`**: ```django {% if unsigned_count > 0 %} {% endif %} ``` ## Testing Requirements For each implementation: 1. Test signing as provider 2. Test signing as admin 3. Test access denial for other users 4. Test re-signing prevention 5. Test unsigned notifications display 6. Test signature status indicators 7. Verify audit trail records ## Priority Order 1. **High Priority**: OT and SLP modules (most frequently used) 2. **Medium Priority**: Medical module 3. **Low Priority**: Nursing module ## Estimated Effort - Per model: ~30-45 minutes - Total: ~6-8 hours for all modules ## Notes - All implementations should follow the ABA module pattern - Maintain consistency in UI/UX across all modules - Ensure proper role-based access control - Include proper error handling and user feedback - Add appropriate translations for all user-facing text