328 lines
8.7 KiB
Markdown
328 lines
8.7 KiB
Markdown
# InsuranceClaim Model Merge Plan
|
|
|
|
## Overview
|
|
Merge `patients.InsuranceClaim` into `billing.InsuranceClaim` to eliminate duplication and centralize claim management.
|
|
|
|
---
|
|
|
|
## Current State Analysis
|
|
|
|
### billing.InsuranceClaim (Canonical - Keep This)
|
|
**Location:** `billing/models.py` (line 606+)
|
|
|
|
**Core Fields:**
|
|
- `medical_bill` (FK to MedicalBill)
|
|
- `claim_id`, `claim_number`
|
|
- `insurance_info` (FK to patients.InsuranceInfo)
|
|
- `claim_type` (PRIMARY, SECONDARY, TERTIARY, etc.)
|
|
- `submission_date`, `service_date_from`, `service_date_to`
|
|
- `billed_amount`, `allowed_amount`, `paid_amount`
|
|
- `patient_responsibility`, `deductible_amount`, `coinsurance_amount`, `copay_amount`
|
|
- `status` (DRAFT, SUBMITTED, PENDING, PROCESSING, PAID, DENIED, etc.)
|
|
- `clearinghouse`, `batch_number`
|
|
- `response_date`, `check_number`, `check_date`
|
|
- `denial_reason`, `denial_code`
|
|
- `prior_auth_number`
|
|
- `notes`
|
|
- `original_claim` (FK to self for resubmissions)
|
|
- `resubmission_count`
|
|
|
|
**Missing Saudi-Specific Fields:**
|
|
- ❌ `saudi_id_number`
|
|
- ❌ `insurance_card_number`
|
|
- ❌ `service_provider`, `service_provider_license`
|
|
- ❌ `facility_name`, `facility_license`
|
|
- ❌ `primary_diagnosis_code`, `primary_diagnosis_description`
|
|
- ❌ `secondary_diagnosis_codes` (JSON)
|
|
- ❌ `procedure_codes` (JSON)
|
|
- ❌ `discount_amount`
|
|
- ❌ `appeal_date`, `appeal_reason`
|
|
- ❌ `attachments` (JSON)
|
|
- ❌ `processed_date`, `payment_date`
|
|
|
|
---
|
|
|
|
### patients.InsuranceClaim (Duplicate - Remove This)
|
|
**Location:** `patients/models.py` (line 784+)
|
|
|
|
**Unique Fields Not in billing:**
|
|
- ✅ `service_provider`, `service_provider_license` - Provider details
|
|
- ✅ `facility_name`, `facility_license` - Facility details
|
|
- ✅ `primary_diagnosis_code`, `primary_diagnosis_description` - Diagnosis info
|
|
- ✅ `secondary_diagnosis_codes` (JSON) - Additional diagnoses
|
|
- ✅ `procedure_codes` (JSON) - Procedures performed
|
|
- ✅ `discount_amount` - Discounts applied
|
|
- ✅ `saudi_id_number` - Saudi National ID
|
|
- ✅ `insurance_card_number` - Insurance card number
|
|
- ✅ `appeal_date`, `appeal_reason` - Appeal information
|
|
- ✅ `attachments` (JSON) - Document attachments
|
|
- ✅ `processed_date`, `payment_date` - Additional date tracking
|
|
- ✅ `priority` (LOW, NORMAL, HIGH, URGENT, EMERGENCY)
|
|
- ✅ `claim_type` has more options (MEDICAL, DENTAL, VISION, etc.)
|
|
|
|
**Fields Already in billing:**
|
|
- `claim_number`, `patient`, `insurance_info`
|
|
- `status`, `billed_amount`, `approved_amount`, `paid_amount`
|
|
- `patient_responsibility`, `denial_reason`, `denial_code`
|
|
- `authorization_number` (same as `prior_auth_number`)
|
|
|
|
---
|
|
|
|
## Merge Strategy
|
|
|
|
### Step 1: Add Missing Fields to billing.InsuranceClaim
|
|
|
|
Add these fields to `billing/models.py` InsuranceClaim model:
|
|
|
|
```python
|
|
# Saudi-specific fields
|
|
saudi_id_number = models.CharField(
|
|
max_length=10,
|
|
blank=True,
|
|
null=True,
|
|
help_text='Saudi National ID or Iqama number'
|
|
)
|
|
|
|
insurance_card_number = models.CharField(
|
|
max_length=50,
|
|
blank=True,
|
|
null=True,
|
|
help_text='Insurance card number'
|
|
)
|
|
|
|
# Provider and Facility Information
|
|
service_provider = models.CharField(
|
|
max_length=200,
|
|
blank=True,
|
|
null=True,
|
|
help_text='Healthcare provider who provided the service'
|
|
)
|
|
|
|
service_provider_license = models.CharField(
|
|
max_length=50,
|
|
blank=True,
|
|
null=True,
|
|
help_text='Provider license number (Saudi Medical License)'
|
|
)
|
|
|
|
facility_name = models.CharField(
|
|
max_length=200,
|
|
blank=True,
|
|
null=True,
|
|
help_text='Healthcare facility name'
|
|
)
|
|
|
|
facility_license = models.CharField(
|
|
max_length=50,
|
|
blank=True,
|
|
null=True,
|
|
help_text='Facility license number (MOH License)'
|
|
)
|
|
|
|
# Medical Codes
|
|
primary_diagnosis_code = models.CharField(
|
|
max_length=20,
|
|
blank=True,
|
|
null=True,
|
|
help_text='Primary diagnosis code (ICD-10)'
|
|
)
|
|
|
|
primary_diagnosis_description = models.TextField(
|
|
blank=True,
|
|
null=True,
|
|
help_text='Primary diagnosis description'
|
|
)
|
|
|
|
secondary_diagnosis_codes = models.JSONField(
|
|
default=list,
|
|
blank=True,
|
|
help_text='Secondary diagnosis codes and descriptions'
|
|
)
|
|
|
|
procedure_codes = models.JSONField(
|
|
default=list,
|
|
blank=True,
|
|
help_text='Procedure codes (CPT/HCPCS) and descriptions'
|
|
)
|
|
|
|
# Additional Financial
|
|
discount_amount = models.DecimalField(
|
|
max_digits=12,
|
|
decimal_places=2,
|
|
default=Decimal('0.00'),
|
|
help_text='Discount applied (SAR)'
|
|
)
|
|
|
|
# Additional Dates
|
|
processed_date = models.DateTimeField(
|
|
blank=True,
|
|
null=True,
|
|
help_text='Date claim was processed'
|
|
)
|
|
|
|
payment_date = models.DateTimeField(
|
|
blank=True,
|
|
null=True,
|
|
help_text='Date payment was received'
|
|
)
|
|
|
|
# Appeal Information (already has denial_reason, denial_code)
|
|
appeal_date = models.DateTimeField(
|
|
blank=True,
|
|
null=True,
|
|
help_text='Date appeal was filed'
|
|
)
|
|
|
|
appeal_reason = models.TextField(
|
|
blank=True,
|
|
null=True,
|
|
help_text='Reason for appeal'
|
|
)
|
|
|
|
# Attachments
|
|
attachments = models.JSONField(
|
|
default=list,
|
|
blank=True,
|
|
help_text='List of attached documents'
|
|
)
|
|
|
|
# Priority (add to ClaimProcessingStatus choices)
|
|
priority = models.CharField(
|
|
max_length=10,
|
|
choices=[
|
|
('LOW', 'Low'),
|
|
('NORMAL', 'Normal'),
|
|
('HIGH', 'High'),
|
|
('URGENT', 'Urgent'),
|
|
('EMERGENCY', 'Emergency'),
|
|
],
|
|
default='NORMAL',
|
|
blank=True,
|
|
help_text='Claim priority'
|
|
)
|
|
```
|
|
|
|
### Step 2: Move Related Models to billing
|
|
|
|
#### ClaimDocument Model
|
|
**Action:** Move from `patients/models.py` to `billing/models.py`
|
|
|
|
**Changes Needed:**
|
|
- Update FK: `claim = models.ForeignKey(InsuranceClaim, ...)` (already correct)
|
|
- Update `db_table` from `patients_claim_document` to `billing_claim_document`
|
|
- Update Meta class
|
|
|
|
#### ClaimStatusHistory Model
|
|
**Action:** Already exists in billing as `ClaimStatusUpdate`
|
|
|
|
**Decision:** Keep `billing.ClaimStatusUpdate`, remove `patients.ClaimStatusHistory`
|
|
|
|
**Comparison:**
|
|
- `patients.ClaimStatusHistory` - simpler, just tracks status changes
|
|
- `billing.ClaimStatusUpdate` - more comprehensive with financial updates
|
|
|
|
**Action:** Enhance `ClaimStatusUpdate` if needed, but it's already more complete
|
|
|
|
---
|
|
|
|
### Step 3: Remove from patients app
|
|
|
|
Remove these models from `patients/models.py`:
|
|
1. `InsuranceClaim` (line 784+)
|
|
2. `ClaimDocument` (line 1121+)
|
|
3. `ClaimStatusHistory` (line 1197+)
|
|
|
|
Add import at top of file:
|
|
```python
|
|
from billing.models import InsuranceClaim, ClaimDocument
|
|
```
|
|
|
|
---
|
|
|
|
### Step 4: Update All References
|
|
|
|
**Files to Update:**
|
|
|
|
1. **patients/admin.py** - Update imports
|
|
2. **patients/views.py** - Update imports
|
|
3. **patients/forms.py** - Update imports
|
|
4. **patients/api/** - Update imports and serializers
|
|
5. **billing/admin.py** - Add ClaimDocument admin
|
|
6. **Any other files** importing from patients.models
|
|
|
|
**Search Pattern:**
|
|
```bash
|
|
grep -r "from patients.models import.*InsuranceClaim" .
|
|
grep -r "patients.InsuranceClaim" .
|
|
```
|
|
|
|
---
|
|
|
|
## Migration Strategy
|
|
|
|
### Option A: Data Migration (Recommended for Production)
|
|
1. Add new fields to billing.InsuranceClaim
|
|
2. Create data migration to copy data from patients to billing
|
|
3. Update all FK references
|
|
4. Remove old models from patients
|
|
5. Run migrations
|
|
|
|
### Option B: Drop and Reseed (Recommended for Development)
|
|
1. Backup any important data
|
|
2. Drop database
|
|
3. Make all model changes
|
|
4. Run fresh migrations
|
|
5. Reseed data
|
|
|
|
---
|
|
|
|
## Implementation Checklist
|
|
|
|
- [ ] Add missing fields to billing.InsuranceClaim
|
|
- [ ] Move ClaimDocument model to billing app
|
|
- [ ] Update ClaimDocument db_table and Meta
|
|
- [ ] Remove InsuranceClaim from patients/models.py
|
|
- [ ] Remove ClaimDocument from patients/models.py
|
|
- [ ] Remove ClaimStatusHistory from patients/models.py
|
|
- [ ] Add imports in patients/models.py
|
|
- [ ] Update patients/admin.py imports
|
|
- [ ] Update patients/views.py imports
|
|
- [ ] Update patients/forms.py imports
|
|
- [ ] Update patients/api/ imports
|
|
- [ ] Update billing/admin.py to include ClaimDocument
|
|
- [ ] Search and update all other references
|
|
- [ ] Create/run migrations
|
|
- [ ] Test thoroughly
|
|
- [ ] Update REFACTORING_PROGRESS.md
|
|
|
|
---
|
|
|
|
## Risk Assessment
|
|
|
|
**High Risk:**
|
|
- Data loss if migration not done correctly
|
|
- Broken FK references if not all updated
|
|
- Admin interface breakage
|
|
|
|
**Mitigation:**
|
|
- Comprehensive testing before deployment
|
|
- Database backup before changes
|
|
- Incremental implementation with testing at each step
|
|
- Consider drop-and-reseed for cleanest implementation
|
|
|
|
---
|
|
|
|
## Benefits After Merge
|
|
|
|
1. **Single Source of Truth:** All insurance claims in one place
|
|
2. **Consistent API:** Unified claim management interface
|
|
3. **Better Reporting:** Centralized claim analytics
|
|
4. **Reduced Confusion:** No duplicate models
|
|
5. **Easier Maintenance:** Changes in one place only
|
|
6. **Saudi Compliance:** All Saudi-specific fields included
|
|
|
|
---
|
|
|
|
**Status:** Ready for Implementation
|
|
**Next Step:** Add missing fields to billing.InsuranceClaim
|