459 lines
21 KiB
Python
459 lines
21 KiB
Python
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()
|