hospital-management/insurance_approvals_data.py
2025-10-06 15:25:37 +03:00

459 lines
21 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import django
# Set up Django environment
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'hospital_management.settings')
django.setup()
import random
from datetime import datetime, timedelta, date
from django.utils import timezone as django_timezone
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from core.models import Tenant
from patients.models import PatientProfile, InsuranceInfo
from insurance_approvals.models import (
InsuranceApprovalRequest,
ApprovalDocument,
ApprovalStatusHistory,
ApprovalCommunicationLog,
ApprovalTemplate
)
User = get_user_model()
# Sample data for insurance approvals
PROCEDURE_CODES = [
'99213', '99214', '99215', # Office visits
'80053', '80061', '85025', # Lab tests
'70450', '70553', '71020', # Radiology
'99281', '99282', '99283', # Emergency
'J1100', 'J2001', 'J3301', # Medications
]
DIAGNOSIS_CODES = [
'E11.9', 'I10', 'J44.9', # Diabetes, Hypertension, COPD
'M79.3', 'K21.9', 'F41.9', # Pain, GERD, Anxiety
'N18.3', 'J45.909', 'E78.5', # CKD, Asthma, Hyperlipidemia
]
SERVICE_DESCRIPTIONS = [
'Comprehensive metabolic panel and lipid panel',
'MRI of lumbar spine without contrast',
'CT scan of abdomen and pelvis with contrast',
'Echocardiogram with Doppler',
'Physical therapy - 12 sessions',
'Home health nursing services',
'Durable medical equipment - wheelchair',
'Specialty medication - Humira',
'Sleep study - polysomnography',
'Cardiac stress test',
]
CLINICAL_JUSTIFICATIONS = [
'Patient presents with chronic lower back pain unresponsive to conservative treatment. MRI needed to rule out disc herniation.',
'Patient has uncontrolled diabetes with HbA1c of 9.2%. Comprehensive metabolic panel needed to assess kidney function.',
'Patient with history of hypertension presenting with chest pain. Cardiac workup necessary to rule out MI.',
'Patient requires physical therapy following knee replacement surgery to regain mobility and strength.',
'Patient with severe rheumatoid arthritis requiring biologic therapy after failure of conventional DMARDs.',
]
MEDICAL_NECESSITY_STATEMENTS = [
'This service is medically necessary to diagnose and treat the patient\'s condition. Conservative treatments have been attempted without success.',
'Patient\'s condition requires this intervention to prevent further deterioration and complications.',
'This treatment is the standard of care for the patient\'s diagnosed condition and is essential for optimal outcomes.',
]
DENIAL_REASONS = [
'Service not covered under current plan',
'Medical necessity not established',
'Prior authorization required but not obtained',
'Service considered experimental/investigational',
'Frequency limits exceeded',
]
DENIAL_CODES = [
'D001', 'D002', 'D003', 'D004', 'D005'
]
COMMUNICATION_SUBJECTS = [
'Status inquiry for pending authorization',
'Additional documentation submitted',
'Appeal of denied claim',
'Verification of coverage',
'Request for expedited review',
]
COMMUNICATION_MESSAGES = [
'Called insurance company to check on status of pending authorization request.',
'Submitted additional clinical documentation to support medical necessity.',
'Discussed denial reason with insurance representative and initiated appeal process.',
'Verified patient coverage and benefits for requested service.',
]
COMMUNICATION_RESPONSES = [
'Authorization is under review, expect decision within 48-72 hours.',
'Additional documentation received and added to file.',
'Appeal has been escalated to medical review team.',
'Coverage confirmed, authorization number provided.',
]
def create_approval_templates():
"""Create approval request templates"""
print("Creating insurance approval templates...")
tenants = list(Tenant.objects.all())
if not tenants:
print("No tenants found. Please create tenants first.")
return []
templates_created = 0
created_templates = []
template_data = [
{
'name': 'MRI Authorization Template',
'request_type': 'RADIOLOGY',
'insurance_company': 'Bupa Arabia',
'clinical_justification': 'Patient presents with [symptoms]. Conservative treatment including [treatments] has been attempted without relief. MRI is necessary to [diagnostic purpose].',
'medical_necessity': 'Imaging is medically necessary to establish accurate diagnosis and guide treatment plan.',
'required_documents': 'Clinical notes, Previous imaging reports, Treatment history',
'required_codes': 'ICD-10 diagnosis code, CPT procedure code',
},
{
'name': 'Physical Therapy Authorization',
'request_type': 'THERAPY',
'insurance_company': 'Tawuniya',
'clinical_justification': 'Patient requires physical therapy following [condition/surgery]. Therapy is essential for recovery and return to function.',
'medical_necessity': 'Physical therapy is medically necessary to restore mobility, strength, and prevent complications.',
'required_documents': 'Physician referral, Surgical report (if applicable), Functional assessment',
'required_codes': 'ICD-10 diagnosis code, CPT therapy codes',
},
{
'name': 'Specialty Medication Prior Auth',
'request_type': 'PHARMACY',
'insurance_company': 'Saudi Enaya',
'clinical_justification': 'Patient has failed conventional therapy with [medications]. Specialty medication is required for disease control.',
'medical_necessity': 'Specialty medication is medically necessary as patient has not responded to standard treatments.',
'required_documents': 'Medication history, Lab results, Treatment failure documentation',
'required_codes': 'ICD-10 diagnosis code, NDC code, J-code',
},
{
'name': 'Laboratory Testing Authorization',
'request_type': 'LABORATORY',
'insurance_company': 'Malath Insurance',
'clinical_justification': 'Laboratory testing is required to [diagnostic purpose] for patient with [condition].',
'medical_necessity': 'Testing is medically necessary to monitor disease progression and guide treatment decisions.',
'required_documents': 'Clinical notes, Previous lab results',
'required_codes': 'ICD-10 diagnosis code, CPT lab codes',
},
{
'name': 'DME Authorization Template',
'request_type': 'DME',
'insurance_company': 'Walaa Insurance',
'clinical_justification': 'Patient requires durable medical equipment due to [condition]. Equipment is necessary for [functional purpose].',
'medical_necessity': 'DME is medically necessary to maintain patient safety and independence.',
'required_documents': 'Physician prescription, Medical evaluation, Functional assessment',
'required_codes': 'ICD-10 diagnosis code, HCPCS code',
},
]
for tenant in tenants:
for template_info in template_data:
try:
template = ApprovalTemplate.objects.create(
tenant=tenant,
name=template_info['name'],
description=f"Standard template for {template_info['request_type']} authorization requests",
request_type=template_info['request_type'],
insurance_company=template_info['insurance_company'],
clinical_justification_template=template_info['clinical_justification'],
medical_necessity_template=template_info['medical_necessity'],
required_documents=template_info['required_documents'],
required_codes=template_info['required_codes'],
is_active=True,
usage_count=0,
)
created_templates.append(template)
templates_created += 1
except Exception as e:
print(f"Error creating template '{template_info['name']}': {str(e)}")
continue
print(f"Successfully created {templates_created} approval templates.")
return created_templates
def create_approval_requests():
"""Create insurance approval requests"""
print("Creating insurance approval requests...")
tenants = list(Tenant.objects.all())
if not tenants:
print("No tenants found.")
return []
patients = list(PatientProfile.objects.all())
if not patients:
print("No patients found. Please run patients_data.py first.")
return []
users = list(User.objects.filter(is_active=True))
if not users:
print("No users found.")
return []
requests_created = 0
created_requests = []
# Create 100 approval requests
for i in range(100):
try:
patient = random.choice(patients)
tenant = patient.tenant
# Get patient's insurance
insurance = InsuranceInfo.objects.filter(patient=patient).first()
if not insurance:
continue
# Random request type
request_type = random.choice([
'LABORATORY', 'RADIOLOGY', 'PHARMACY', 'PROCEDURE',
'SURGERY', 'THERAPY', 'DME', 'HOME_HEALTH'
])
# Random status with weighted distribution
status_weights = [
('DRAFT', 5),
('PENDING_SUBMISSION', 10),
('SUBMITTED', 15),
('UNDER_REVIEW', 20),
('MORE_INFO_REQUIRED', 10),
('APPROVED', 25),
('PARTIALLY_APPROVED', 5),
('DENIED', 7),
('APPEAL_SUBMITTED', 2),
('APPEAL_APPROVED', 1),
]
statuses, weights = zip(*status_weights)
status = random.choices(statuses, weights=weights)[0]
# Random priority
priority = random.choices(
['ROUTINE', 'URGENT', 'STAT', 'EMERGENCY'],
weights=[70, 20, 7, 3]
)[0]
# Create dates
created_date = django_timezone.now() - timedelta(days=random.randint(1, 90))
# Create approval request
approval = InsuranceApprovalRequest.objects.create(
tenant=tenant,
patient=patient,
insurance_info=insurance,
request_type=request_type,
service_description=random.choice(SERVICE_DESCRIPTIONS),
procedure_codes=', '.join(random.sample(PROCEDURE_CODES, random.randint(1, 3))),
diagnosis_codes=', '.join(random.sample(DIAGNOSIS_CODES, random.randint(1, 2))),
clinical_justification=random.choice(CLINICAL_JUSTIFICATIONS),
medical_necessity=random.choice(MEDICAL_NECESSITY_STATEMENTS) if random.choice([True, False]) else None,
alternative_treatments_tried='Conservative management including medication and physical therapy' if random.choice([True, False]) else None,
requested_quantity=random.randint(1, 10),
requested_visits=random.randint(1, 20) if request_type == 'THERAPY' else None,
requested_units=random.randint(1, 30) if request_type == 'PHARMACY' else None,
service_start_date=created_date.date() + timedelta(days=random.randint(1, 30)),
service_end_date=created_date.date() + timedelta(days=random.randint(31, 180)) if random.choice([True, False]) else None,
status=status,
priority=priority,
submission_method=random.choice(['PHONE', 'FAX', 'EMAIL', 'PORTAL']) if status not in ['DRAFT', 'PENDING_SUBMISSION'] else None,
submitted_date=created_date + timedelta(days=1) if status not in ['DRAFT', 'PENDING_SUBMISSION'] else None,
decision_date=created_date + timedelta(days=random.randint(3, 14)) if status in ['APPROVED', 'PARTIALLY_APPROVED', 'DENIED'] else None,
authorization_number=f"AUTH{random.randint(100000, 999999)}" if status in ['APPROVED', 'PARTIALLY_APPROVED'] else None,
reference_number=f"REF{random.randint(100000, 999999)}" if status not in ['DRAFT'] else None,
approved_quantity=random.randint(1, 10) if status in ['APPROVED', 'PARTIALLY_APPROVED'] else None,
approved_visits=random.randint(1, 15) if status in ['APPROVED', 'PARTIALLY_APPROVED'] and request_type == 'THERAPY' else None,
approved_amount=random.uniform(500, 5000) if status in ['APPROVED', 'PARTIALLY_APPROVED'] else None,
effective_date=created_date.date() if status in ['APPROVED', 'PARTIALLY_APPROVED'] else None,
expiration_date=created_date.date() + timedelta(days=random.randint(30, 180)) if status in ['APPROVED', 'PARTIALLY_APPROVED'] else None,
denial_reason=random.choice(DENIAL_REASONS) if status == 'DENIED' else None,
denial_code=random.choice(DENIAL_CODES) if status == 'DENIED' else None,
appeal_date=created_date + timedelta(days=random.randint(15, 30)) if status in ['APPEAL_SUBMITTED', 'APPEAL_APPROVED'] else None,
appeal_reason='Medical necessity clearly established by clinical documentation' if status in ['APPEAL_SUBMITTED', 'APPEAL_APPROVED'] else None,
is_urgent=priority in ['URGENT', 'STAT', 'EMERGENCY'],
is_expedited=priority in ['STAT', 'EMERGENCY'],
requires_peer_review=random.choice([True, False]) if random.random() < 0.2 else False,
requesting_provider=random.choice(users),
assigned_to=random.choice(users) if random.choice([True, False]) else None,
submitted_by=random.choice(users) if status not in ['DRAFT', 'PENDING_SUBMISSION'] else None,
created_by=random.choice(users),
created_at=created_date,
updated_at=created_date + timedelta(days=random.randint(0, 5)),
)
created_requests.append(approval)
requests_created += 1
if requests_created % 20 == 0:
print(f"Created {requests_created} approval requests...")
except Exception as e:
print(f"Error creating approval request {i}: {str(e)}")
continue
print(f"Successfully created {requests_created} approval requests.")
return created_requests
def create_status_history(approvals):
"""Create status history for approvals"""
print("Creating status history...")
users = list(User.objects.filter(is_active=True))
history_created = 0
for approval in approvals:
try:
# Create 1-3 status changes per approval
num_changes = random.randint(1, 3)
statuses = ['DRAFT', 'PENDING_SUBMISSION', 'SUBMITTED', 'UNDER_REVIEW']
if approval.status in ['APPROVED', 'PARTIALLY_APPROVED']:
statuses.append(approval.status)
elif approval.status == 'DENIED':
statuses.extend(['MORE_INFO_REQUIRED', 'DENIED'])
for i in range(min(num_changes, len(statuses) - 1)):
ApprovalStatusHistory.objects.create(
approval_request=approval,
from_status=statuses[i] if i > 0 else None,
to_status=statuses[i + 1],
reason=random.choice([
'Status updated per workflow',
'Additional information received',
'Insurance company decision',
'Routine processing'
]),
notes=random.choice([
'Processing normally',
'No issues noted',
'Awaiting insurance response',
None
]),
changed_by=random.choice(users) if users else None,
changed_at=approval.created_at + timedelta(days=i + 1),
)
history_created += 1
except Exception as e:
print(f"Error creating status history for approval {approval.approval_number}: {str(e)}")
continue
print(f"Successfully created {history_created} status history records.")
return history_created
def create_communications(approvals):
"""Create communication logs"""
print("Creating communication logs...")
users = list(User.objects.filter(is_active=True))
comms_created = 0
for approval in approvals:
# 60% of approvals have communications
if random.random() < 0.6:
try:
# Create 1-3 communications per approval
num_comms = random.randint(1, 3)
for i in range(num_comms):
comm_type = random.choice(['PHONE', 'FAX', 'EMAIL', 'PORTAL'])
ApprovalCommunicationLog.objects.create(
approval_request=approval,
communication_type=comm_type,
contact_person=f"{random.choice(['Sarah', 'Ahmed', 'Fatima', 'Mohammed'])} - Insurance Rep",
contact_number=f"+966{random.randint(11, 17)}{random.randint(1000000, 9999999)}" if comm_type == 'PHONE' else None,
subject=random.choice(COMMUNICATION_SUBJECTS),
message=random.choice(COMMUNICATION_MESSAGES),
response=random.choice(COMMUNICATION_RESPONSES) if random.choice([True, False]) else None,
outcome=random.choice([
'Authorization approved',
'Pending additional review',
'Request for more information',
'Claim denied'
]) if random.choice([True, False]) else None,
follow_up_required=random.choice([True, False]),
follow_up_date=approval.created_at.date() + timedelta(days=random.randint(3, 14)) if random.choice([True, False]) else None,
communicated_by=random.choice(users) if users else None,
communicated_at=approval.created_at + timedelta(days=random.randint(1, 10)),
)
comms_created += 1
except Exception as e:
print(f"Error creating communication for approval {approval.approval_number}: {str(e)}")
continue
print(f"Successfully created {comms_created} communication logs.")
return comms_created
def main():
"""Main function to create all insurance approval data"""
print("🏥 Creating Insurance Approval Data")
try:
# Check if tenants exist
tenants = list(Tenant.objects.all())
if not tenants:
print("❌ No tenants found. Please run core_data.py first.")
return
print(f"📋 Found {len(tenants)} tenants")
# Check if patients exist
patients = list(PatientProfile.objects.all())
if not patients:
print("❌ No patients found. Please run patients_data.py first.")
return
print(f"👥 Found {len(patients)} patients")
# Create approval templates
print("\n1⃣ Creating Approval Templates...")
templates = create_approval_templates()
# Create approval requests
print("\n2⃣ Creating Approval Requests...")
approvals = create_approval_requests()
if not approvals:
print("❌ No approvals created. Stopping.")
return
# Create status history
print("\n3⃣ Creating Status History...")
history_count = create_status_history(approvals)
# Create communications
print("\n4⃣ Creating Communication Logs...")
comms_count = create_communications(approvals)
print("\n🎉 Insurance Approval Data Creation Complete!")
print(f"📊 Summary:")
print(f" - Approval Templates: {len(templates)}")
print(f" - Approval Requests: {len(approvals)}")
print(f" - Status History Records: {history_count}")
print(f" - Communication Logs: {comms_count}")
except Exception as e:
print(f"❌ Error in main execution: {str(e)}")
if __name__ == '__main__':
main()