agdar/CLINICAL_SIGNING_IMPLEMENTATION_PLAN.md
Marwan Alwali a04817ef6e update
2025-11-02 19:25:08 +03:00

8.4 KiB

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/<uuid:pk>/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):

# 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):

# Add sign routes
path('consults/<uuid:pk>/sign/', views.OTConsultSignView.as_view(), name='consult_sign'),
path('sessions/<uuid:pk>/sign/', views.OTSessionSignView.as_view(), name='session_sign'),
path('progress-reports/<uuid:pk>/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():

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):

class SLPConsultSignView(...)
class SLPAssessmentSignView(...)
class SLPInterventionSignView(...)
class SLPProgressReportSignView(...)

URLs (slp/urls.py):

path('consults/<uuid:pk>/sign/', ...),
path('assessments/<uuid:pk>/sign/', ...),
path('interventions/<uuid:pk>/sign/', ...),
path('progress-reports/<uuid:pk>/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):

class MedicalConsultationSignView(...)
class MedicalFollowUpSignView(...)

URLs (medical/urls.py):

path('consultations/<uuid:pk>/sign/', ...),
path('follow-ups/<uuid:pk>/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):

class NursingEncounterSignView(...)

URLs (nursing/urls.py):

path('encounters/<uuid:pk>/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:

# 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:

<div class="card mb-3">
    <div class="card-header">
        <h6 class="mb-0"><i class="fas fa-signature me-2"></i>{% trans "Signature Status" %}</h6>
    </div>
    <div class="card-body">
        {% if document.signed_by %}
            <!-- Signed content -->
        {% else %}
            <!-- Unsigned content with sign button -->
        {% endif %}
    </div>
</div>

templates/includes/unsigned_notification.html:

{% if unsigned_count > 0 %}
<div class="alert alert-warning alert-dismissible fade show mb-3" role="alert">
    <!-- Notification content -->
</div>
{% 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