19 KiB
Insurance Approval Integration Documentation
Overview
The Insurance Approval Request module has been successfully integrated with all relevant clinical order modules in the hospital management system. This document outlines the integration points and usage patterns.
Integrated Modules
1. Laboratory Module ✅
Model: LabOrder
File: laboratory/models.py
Integration Details:
- Added
GenericRelationto link lab orders with approval requests - Added helper methods for approval status checking
- Supports multi-tenant approval tracking
Helper Methods Added:
# Check if order has valid approval
lab_order.has_valid_approval() # Returns True/False
# Get active approval
lab_order.get_active_approval() # Returns InsuranceApprovalRequest or None
# Check if approval is required
lab_order.requires_approval() # Returns True/False
# Get approval status for display
lab_order.approval_status # Returns status string
Usage Example:
from laboratory.models import LabOrder
from insurance_approvals.models import InsuranceApprovalRequest
# Create a lab order
lab_order = LabOrder.objects.get(order_number='LAB-1-000001')
# Check if approval is needed
if lab_order.requires_approval():
# Create approval request
approval = InsuranceApprovalRequest.objects.create(
tenant=lab_order.tenant,
patient=lab_order.patient,
insurance_info=lab_order.patient.insurance_info.first(),
request_type='LABORATORY',
content_object=lab_order, # Links to lab order
service_description=f"Lab tests: {', '.join([t.test_name for t in lab_order.tests.all()])}",
procedure_codes=', '.join([t.cpt_code for t in lab_order.tests.all() if t.cpt_code]),
diagnosis_codes=lab_order.diagnosis_code or '',
clinical_justification=lab_order.clinical_indication,
requesting_provider=lab_order.ordering_provider,
service_start_date=lab_order.collection_datetime.date() if lab_order.collection_datetime else timezone.now().date(),
priority='ROUTINE',
status='PENDING_SUBMISSION',
)
# Check approval status
if lab_order.has_valid_approval():
print("Order has valid approval - proceed with processing")
else:
print(f"Approval status: {lab_order.approval_status}")
# Get all approval requests for this order
approvals = lab_order.approval_requests.all()
2. Radiology Module ✅
Model: ImagingOrder
File: radiology/models.py
Integration Details:
- Added
GenericRelationto link imaging orders with approval requests - Added identical helper methods as laboratory module
- Supports all imaging modalities (CT, MRI, X-Ray, etc.)
Helper Methods Added:
# Check if order has valid approval
imaging_order.has_valid_approval() # Returns True/False
# Get active approval
imaging_order.get_active_approval() # Returns InsuranceApprovalRequest or None
# Check if approval is required
imaging_order.requires_approval() # Returns True/False
# Get approval status for display
imaging_order.approval_status # Returns status string
Usage Example:
from radiology.models import ImagingOrder
from insurance_approvals.models import InsuranceApprovalRequest
# Create an imaging order
imaging_order = ImagingOrder.objects.get(order_number='IMG-1-000001')
# Check if approval is needed
if imaging_order.requires_approval():
# Create approval request
approval = InsuranceApprovalRequest.objects.create(
tenant=imaging_order.tenant,
patient=imaging_order.patient,
insurance_info=imaging_order.patient.insurance_info.first(),
request_type='RADIOLOGY',
content_object=imaging_order, # Links to imaging order
service_description=imaging_order.study_description,
procedure_codes=imaging_order.modality, # Could be enhanced with CPT codes
diagnosis_codes=imaging_order.diagnosis_code or '',
clinical_justification=imaging_order.clinical_indication,
requesting_provider=imaging_order.ordering_provider,
service_start_date=imaging_order.requested_datetime.date() if imaging_order.requested_datetime else timezone.now().date(),
priority='URGENT' if imaging_order.is_stat else 'ROUTINE',
status='PENDING_SUBMISSION',
)
# Access approvals
active_approval = imaging_order.get_active_approval()
if active_approval:
print(f"Authorization Number: {active_approval.authorization_number}")
print(f"Expires: {active_approval.expiration_date}")
Common Integration Patterns
Pattern 1: Pre-Order Approval Check
def create_order_with_approval_check(patient, order_type, **order_data):
"""
Create an order and check if insurance approval is required.
"""
# Create the order
if order_type == 'LAB':
order = LabOrder.objects.create(patient=patient, **order_data)
elif order_type == 'IMAGING':
order = ImagingOrder.objects.create(patient=patient, **order_data)
# Check if approval is required
if order.requires_approval():
# Redirect to approval request creation
return {
'order': order,
'requires_approval': True,
'redirect_url': f'/insurance-approvals/create/?order_type={order_type}&order_id={order.id}'
}
return {
'order': order,
'requires_approval': False
}
Pattern 2: Approval Status Display
def get_order_status_with_approval(order):
"""
Get comprehensive order status including approval information.
"""
status = {
'order_status': order.status,
'has_insurance': order.patient.insurance_info.exists(),
'requires_approval': order.requires_approval(),
'approval_status': order.approval_status,
'can_proceed': False
}
if not status['has_insurance']:
status['can_proceed'] = True # No insurance, no approval needed
elif order.has_valid_approval():
status['can_proceed'] = True
status['approval'] = order.get_active_approval()
return status
Pattern 3: Bulk Approval Status Check
def get_orders_needing_approval(tenant, order_type='LAB'):
"""
Get all orders that need insurance approval.
"""
if order_type == 'LAB':
Model = LabOrder
elif order_type == 'IMAGING':
Model = ImagingOrder
orders = Model.objects.filter(
tenant=tenant,
status__in=['PENDING', 'SCHEDULED']
)
orders_needing_approval = []
for order in orders:
if order.requires_approval():
orders_needing_approval.append({
'order': order,
'patient': order.patient,
'insurance': order.patient.insurance_info.first(),
'approval_status': order.approval_status
})
return orders_needing_approval
Approval Request Types
The system supports the following request types:
- LABORATORY - Lab tests and panels
- RADIOLOGY - Imaging studies (CT, MRI, X-Ray, etc.)
- PHARMACY - Medications (to be integrated)
- PROCEDURE - Medical procedures (to be integrated)
- SURGERY - Surgical procedures (to be integrated)
- THERAPY - Physical/Occupational therapy
- DME - Durable Medical Equipment
- HOME_HEALTH - Home health services
- HOSPICE - Hospice care
- TRANSPORTATION - Medical transportation
- OTHER - Other services
Approval Workflow States
DRAFT → PENDING_SUBMISSION → SUBMITTED → UNDER_REVIEW
↓
MORE_INFO_REQUIRED (can loop back to SUBMITTED)
↓
APPROVED / PARTIALLY_APPROVED / DENIED
↓
APPEAL_SUBMITTED → APPEAL_APPROVED / APPEAL_DENIED
↓
EXPIRED (if expiration_date passes)
Database Relationships
GenericForeignKey Pattern
# In InsuranceApprovalRequest model
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
# In LabOrder/ImagingOrder models
approval_requests = GenericRelation(
'insurance_approvals.InsuranceApprovalRequest',
content_type_field='content_type',
object_id_field='object_id',
related_query_name='lab_order' # or 'imaging_order'
)
Querying Across Relationships
# Get all lab orders with approvals
from django.contrib.contenttypes.models import ContentType
from laboratory.models import LabOrder
from insurance_approvals.models import InsuranceApprovalRequest
lab_order_ct = ContentType.objects.get_for_model(LabOrder)
approvals_for_lab_orders = InsuranceApprovalRequest.objects.filter(
content_type=lab_order_ct
)
# Get specific lab order's approvals
lab_order = LabOrder.objects.get(pk=1)
approvals = lab_order.approval_requests.all()
# Reverse query - get order from approval
approval = InsuranceApprovalRequest.objects.get(pk=1)
order = approval.content_object # Returns LabOrder or ImagingOrder instance
Template Integration Examples
Display Approval Status in Order List
{% for order in orders %}
<tr>
<td>{{ order.order_number }}</td>
<td>{{ order.patient.get_full_name }}</td>
<td>
{% if order.approval_status == 'APPROVED' %}
<span class="badge bg-success">Approved</span>
{% elif order.approval_status == 'APPROVAL_REQUIRED' %}
<span class="badge bg-warning">Approval Required</span>
<a href="{% url 'insurance_approvals:create' %}?order_id={{ order.id }}"
class="btn btn-sm btn-primary">Request Approval</a>
{% elif order.approval_status == 'NO_INSURANCE' %}
<span class="badge bg-secondary">No Insurance</span>
{% else %}
<span class="badge bg-info">{{ order.get_approval_status_display }}</span>
{% endif %}
</td>
</tr>
{% endfor %}
Display Approval Details in Order Detail
{% if order.has_valid_approval %}
<div class="alert alert-success">
<h6><i class="fa fa-check-circle"></i> Insurance Approval Active</h6>
{% with approval=order.get_active_approval %}
<p><strong>Authorization Number:</strong> {{ approval.authorization_number }}</p>
<p><strong>Expires:</strong> {{ approval.expiration_date|date:"M d, Y" }}</p>
<p><strong>Approved Quantity:</strong> {{ approval.approved_quantity }}</p>
{% endwith %}
</div>
{% elif order.requires_approval %}
<div class="alert alert-warning">
<h6><i class="fa fa-exclamation-triangle"></i> Insurance Approval Required</h6>
<p>This order requires insurance approval before processing.</p>
<a href="{% url 'insurance_approvals:create' %}?order_id={{ order.id }}"
class="btn btn-primary">Request Approval</a>
</div>
{% endif %}
API Integration (DRF)
Serializer Example
from rest_framework import serializers
from laboratory.models import LabOrder
from insurance_approvals.models import InsuranceApprovalRequest
class LabOrderSerializer(serializers.ModelSerializer):
approval_status = serializers.CharField(read_only=True)
has_valid_approval = serializers.BooleanField(read_only=True)
requires_approval = serializers.SerializerMethodField()
active_approval = serializers.SerializerMethodField()
class Meta:
model = LabOrder
fields = '__all__'
def get_requires_approval(self, obj):
return obj.requires_approval()
def get_active_approval(self, obj):
approval = obj.get_active_approval()
if approval:
return {
'id': approval.id,
'approval_number': approval.approval_number,
'authorization_number': approval.authorization_number,
'status': approval.status,
'expiration_date': approval.expiration_date
}
return None
Future Integration Points
Pharmacy Module (Pending)
- Model:
PharmacyOrderorPrescription - Request Type:
PHARMACY - Same integration pattern as Lab and Radiology
Operating Theatre Module (Pending)
- Model:
SurgeryScheduleorOperativeCase - Request Type:
SURGERYorPROCEDURE - Same integration pattern
Other Potential Integrations:
- Home Health Orders
- DME Orders
- Physical Therapy Orders
- Hospice Care Orders
Migration Notes
IMPORTANT: Migrations are NOT included in this integration. The user will handle migrations separately.
To apply changes:
- Create migrations:
python manage.py makemigrations laboratory radiology - Review migrations carefully
- Apply migrations:
python manage.py migrate
Testing Recommendations
Unit Tests
from django.test import TestCase
from laboratory.models import LabOrder
from insurance_approvals.models import InsuranceApprovalRequest
class LabOrderApprovalIntegrationTest(TestCase):
def test_order_requires_approval_with_insurance(self):
# Create patient with insurance
patient = self.create_patient_with_insurance()
order = LabOrder.objects.create(patient=patient, ...)
self.assertTrue(order.requires_approval())
def test_order_has_valid_approval(self):
order = self.create_lab_order()
approval = InsuranceApprovalRequest.objects.create(
content_object=order,
status='APPROVED',
expiration_date=timezone.now().date() + timedelta(days=30),
...
)
self.assertTrue(order.has_valid_approval())
self.assertEqual(order.get_active_approval(), approval)
3. Pharmacy Module ✅
Model: Prescription
File: pharmacy/models.py
Integration Details:
- Added
GenericRelationto link prescriptions with approval requests - Added helper methods for approval status checking
- Enhanced with prior authorization support
- Checks medication formulary status for approval requirements
Helper Methods Added:
# Check if prescription has valid approval
prescription.has_valid_approval() # Returns True/False
# Get active approval
prescription.get_active_approval() # Returns InsuranceApprovalRequest or None
# Check if approval is required
prescription.requires_approval() # Returns True/False
# Get approval status for display
prescription.approval_status # Returns status string
Special Features:
- Prior Authorization Integration: Checks both approval requests and prior authorization fields
- Formulary Status: Automatically requires approval for RESTRICTED or PRIOR_AUTH medications
- Enhanced Status: Returns specific statuses like 'PRIOR_AUTH_REQUIRED', 'PRIOR_AUTH_EXPIRED', etc.
Usage Example:
from pharmacy.models import Prescription
from insurance_approvals.models import InsuranceApprovalRequest
# Create a prescription
prescription = Prescription.objects.get(prescription_number='RX-1-000001')
# Check if approval is needed (considers formulary status)
if prescription.requires_approval():
# Create approval request
approval = InsuranceApprovalRequest.objects.create(
tenant=prescription.tenant,
patient=prescription.patient,
insurance_info=prescription.patient.insurance_info.first(),
request_type='PHARMACY',
content_object=prescription, # Links to prescription
service_description=f"{prescription.medication.display_name} - {prescription.quantity_prescribed} {prescription.quantity_unit}",
procedure_codes=prescription.medication.ndc_number or '',
diagnosis_codes=prescription.diagnosis_code or '',
clinical_justification=prescription.indication or 'As prescribed',
requesting_provider=prescription.prescriber,
service_start_date=prescription.date_written,
priority='URGENT' if prescription.medication.is_controlled_substance else 'ROUTINE',
status='PENDING_SUBMISSION',
requested_quantity=prescription.quantity_prescribed,
)
# Check prior authorization
if prescription.prior_authorization_required:
if not prescription.prior_authorization_number:
print("Prior authorization required but not obtained")
4. Operating Theatre Module ✅
Model: SurgicalCase
File: operating_theatre/models.py
Integration Details:
- Added
GenericRelationto link surgical cases with approval requests - Added helper methods for approval status checking
- Enhanced with emergency case handling
- Supports elective and emergency approval workflows
Helper Methods Added:
# Check if surgical case has valid approval
surgical_case.has_valid_approval() # Returns True/False
# Get active approval
surgical_case.get_active_approval() # Returns InsuranceApprovalRequest or None
# Check if approval is required
surgical_case.requires_approval() # Returns True/False
# Get approval status for display
surgical_case.approval_status # Returns status string
Special Features:
- Emergency Case Handling: Different approval requirements for emergency vs elective cases
- Enhanced Status: Returns 'EMERGENCY_APPROVAL_REQUIRED' for emergency cases
- Procedure Code Support: Integrates with procedure_codes JSON field
Usage Example:
from operating_theatre.models import SurgicalCase
from insurance_approvals.models import InsuranceApprovalRequest
# Create a surgical case
surgical_case = SurgicalCase.objects.get(case_number='SURG-20250103-0001')
# Check if approval is needed
if surgical_case.requires_approval():
# Determine priority based on case type
if surgical_case.is_emergency:
priority = 'STAT'
is_expedited = True
else:
priority = 'ROUTINE'
is_expedited = False
# Create approval request
approval = InsuranceApprovalRequest.objects.create(
tenant=surgical_case.tenant,
patient=surgical_case.patient,
insurance_info=surgical_case.patient.insurance_info.first(),
request_type='SURGERY',
content_object=surgical_case, # Links to surgical case
service_description=surgical_case.primary_procedure,
procedure_codes=', '.join(surgical_case.procedure_codes) if surgical_case.procedure_codes else '',
diagnosis_codes=', '.join(surgical_case.diagnosis_codes) if surgical_case.diagnosis_codes else surgical_case.diagnosis,
clinical_justification=surgical_case.clinical_notes or f"Surgical intervention required for {surgical_case.diagnosis}",
requesting_provider=surgical_case.primary_surgeon,
service_start_date=surgical_case.scheduled_start.date(),
priority=priority,
is_expedited=is_expedited,
status='PENDING_SUBMISSION',
)
Summary
✅ Laboratory Module - Fully integrated ✅ Radiology Module - Fully integrated ✅ Pharmacy Module - Fully integrated (with prior auth support) ✅ Operating Theatre Module - Fully integrated (with emergency handling)
All integrated modules now support:
- Automatic approval requirement detection
- Approval status tracking
- Multi-tenant approval management
- Complete audit trail
- Flexible workflow states
- Module-specific enhancements (prior auth, emergency cases, etc.)
The integration is backward compatible and does not affect existing functionality.