2025-08-12 13:33:25 +03:00

665 lines
34 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}{% if object %}Edit Claim{% else %}Submit Insurance Claim{% endif %} - {{ block.super }}{% endblock %}
{% block content %}
<div class="container-fluid">
<!-- Page Header -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h1 class="h3 mb-1">{% if object %}Edit Insurance Claim{% else %}Submit Insurance Claim{% endif %}</h1>
<nav aria-label="breadcrumb">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="{% url 'billing:dashboard' %}">Billing</a></li>
<li class="breadcrumb-item"><a href="{% url 'billing:claim_list' %}">Insurance Claims</a></li>
<li class="breadcrumb-item active">{% if object %}Edit{% else %}Submit{% endif %}</li>
</ol>
</nav>
</div>
<div class="btn-group">
<a href="{% url 'billing:claim_list' %}" class="btn btn-outline-secondary">
<i class="fas fa-arrow-left me-2"></i>Back to List
</a>
{% if object %}
<a href="{% url 'billing:claim_detail' object.claim_id %}" class="btn btn-outline-primary">
<i class="fas fa-eye me-2"></i>View Details
</a>
{% endif %}
</div>
</div>
<form method="post" id="claimForm" hx-post="{% if object %}{% url 'billing:claim_update' object.claim_id %}{% else %}{% url 'billing:claim_create' %}{% endif %}" hx-target="#form-container">
{% csrf_token %}
<div class="row">
<!-- Main Form -->
<div class="col-lg-8">
<div id="form-container">
<!-- Bill Selection -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-file-invoice me-2"></i>Bill Information
</h5>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-6">
<div class="form-floating">
{{ form.medical_bill }}
<label for="{{ form.medical_bill.id_for_label }}">Medical Bill *</label>
{% if form.medical_bill.errors %}
<div class="invalid-feedback d-block">
{{ form.medical_bill.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
{{ form.claim_number }}
<label for="{{ form.claim_number.id_for_label }}">Claim Number *</label>
{% if form.claim_number.errors %}
<div class="invalid-feedback d-block">
{{ form.claim_number.errors.0 }}
</div>
{% endif %}
</div>
</div>
</div>
<!-- Bill Details Display -->
<div id="bill-details" class="mt-3" style="display: none;">
<div class="alert alert-info">
<h6 class="alert-heading">Bill Details</h6>
<div class="row">
<div class="col-md-6">
<strong>Patient:</strong> <span id="bill-patient"></span><br>
<strong>Bill Number:</strong> <span id="bill-number"></span><br>
<strong>Bill Date:</strong> <span id="bill-date"></span>
</div>
<div class="col-md-6">
<strong>Total Amount:</strong> <span id="bill-total" class="text-success"></span><br>
<strong>Service Date:</strong> <span id="bill-service-date"></span><br>
<strong>Provider:</strong> <span id="bill-provider"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Insurance Information -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-shield-alt me-2"></i>Insurance Information
</h5>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-6">
<div class="form-floating">
{{ form.insurance_info }}
<label for="{{ form.insurance_info.id_for_label }}">Insurance Information *</label>
{% if form.insurance_info.errors %}
<div class="invalid-feedback d-block">
{{ form.insurance_info.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
{{ form.service_date }}
<label for="{{ form.service_date.id_for_label }}">Service Date *</label>
{% if form.service_date.errors %}
<div class="invalid-feedback d-block">
{{ form.service_date.errors.0 }}
</div>
{% endif %}
</div>
</div>
</div>
<!-- Insurance Details Display -->
<div id="insurance-details" class="mt-3" style="display: none;">
<div class="alert alert-light">
<h6 class="alert-heading">Insurance Details</h6>
<div class="row">
<div class="col-md-6">
<strong>Company:</strong> <span id="insurance-company"></span><br>
<strong>Policy Number:</strong> <span id="insurance-policy"></span><br>
<strong>Group Number:</strong> <span id="insurance-group"></span>
</div>
<div class="col-md-6">
<strong>Member ID:</strong> <span id="insurance-member"></span><br>
<strong>Plan Type:</strong> <span id="insurance-plan"></span><br>
<strong>Copay:</strong> <span id="insurance-copay"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Claim Details -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-file-medical me-2"></i>Claim Details
</h5>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-4">
<div class="form-floating">
{{ form.billed_amount }}
<label for="{{ form.billed_amount.id_for_label }}">Billed Amount *</label>
{% if form.billed_amount.errors %}
<div class="invalid-feedback d-block">
{{ form.billed_amount.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-4">
<div class="form-floating">
{{ form.diagnosis_code }}
<label for="{{ form.diagnosis_code.id_for_label }}">Primary Diagnosis Code *</label>
{% if form.diagnosis_code.errors %}
<div class="invalid-feedback d-block">
{{ form.diagnosis_code.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-4">
<div class="form-floating">
{{ form.procedure_code }}
<label for="{{ form.procedure_code.id_for_label }}">Primary Procedure Code</label>
{% if form.procedure_code.errors %}
<div class="invalid-feedback d-block">
{{ form.procedure_code.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
{{ form.place_of_service }}
<label for="{{ form.place_of_service.id_for_label }}">Place of Service *</label>
{% if form.place_of_service.errors %}
<div class="invalid-feedback d-block">
{{ form.place_of_service.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
{{ form.referring_provider }}
<label for="{{ form.referring_provider.id_for_label }}">Referring Provider</label>
{% if form.referring_provider.errors %}
<div class="invalid-feedback d-block">
{{ form.referring_provider.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-12">
<div class="form-floating">
{{ form.notes }}
<label for="{{ form.notes.id_for_label }}">Notes</label>
{% if form.notes.errors %}
<div class="invalid-feedback d-block">
{{ form.notes.errors.0 }}
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<!-- Claim Line Items -->
<div class="card mb-4">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">
<i class="fas fa-list me-2"></i>Claim Line Items
</h5>
<button type="button" class="btn btn-sm btn-outline-primary" onclick="addLineItem()">
<i class="fas fa-plus me-1"></i>Add Line Item
</button>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0" id="line-items-table">
<thead class="table-light">
<tr>
<th>Service Code *</th>
<th>Description *</th>
<th>Service Date *</th>
<th width="100">Quantity *</th>
<th width="120">Billed Amount *</th>
<th width="80">Actions</th>
</tr>
</thead>
<tbody id="line-items-body">
<!-- Line items will be dynamically added here -->
</tbody>
</table>
</div>
<div class="p-3 bg-light">
<div class="d-flex justify-content-between">
<span class="fw-bold">Total Billed Amount:</span>
<span class="fw-bold text-primary" id="total-billed-amount">$0.00</span>
</div>
</div>
</div>
</div>
<!-- Form Actions -->
<div class="card">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<a href="{% url 'billing:claim_list' %}" class="btn btn-outline-secondary">
<i class="fas fa-times me-2"></i>Cancel
</a>
</div>
<div class="btn-group">
<button type="submit" name="action" value="save_draft" class="btn btn-outline-primary">
<i class="fas fa-save me-2"></i>Save as Draft
</button>
<button type="submit" name="action" value="save_and_submit" class="btn btn-success">
<i class="fas fa-paper-plane me-2"></i>{% if object %}Update{% else %}Submit{% endif %} Claim
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- Claim Summary -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-calculator me-2"></i>Claim Summary
</h5>
</div>
<div class="card-body">
<div class="d-flex justify-content-between mb-2">
<span>Total Billed:</span>
<span id="summary-billed" class="fw-bold text-primary">$0.00</span>
</div>
<div class="d-flex justify-content-between mb-2">
<span>Line Items:</span>
<span id="summary-items">0</span>
</div>
<div class="d-flex justify-content-between mb-2">
<span>Expected Copay:</span>
<span id="summary-copay" class="text-warning">$0.00</span>
</div>
<hr>
<div class="d-flex justify-content-between fw-bold">
<span>Expected Payment:</span>
<span id="summary-expected" class="text-success">$0.00</span>
</div>
</div>
</div>
<!-- Quick Actions -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-bolt me-2"></i>Quick Actions
</h5>
</div>
<div class="card-body">
<div class="d-grid gap-2">
<button type="button" class="btn btn-outline-primary" onclick="copyFromBill()">
<i class="fas fa-copy me-2"></i>Copy from Bill
</button>
<button type="button" class="btn btn-outline-secondary" onclick="validateClaim()">
<i class="fas fa-check-circle me-2"></i>Validate Claim
</button>
<button type="button" class="btn btn-outline-info" onclick="previewClaim()">
<i class="fas fa-eye me-2"></i>Preview Claim
</button>
<button type="button" class="btn btn-outline-warning" onclick="checkEligibility()">
<i class="fas fa-shield-alt me-2"></i>Check Eligibility
</button>
</div>
</div>
</div>
<!-- Help Panel -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-question-circle me-2"></i>Help & Guidelines
</h5>
</div>
<div class="card-body">
<div class="accordion accordion-flush" id="helpAccordion">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#help-codes">
Diagnosis & Procedure Codes
</button>
</h2>
<div id="help-codes" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
<div class="accordion-body">
<ul class="list-unstyled mb-0">
<li><i class="fas fa-code text-primary me-2"></i>Use ICD-10 for diagnosis codes</li>
<li><i class="fas fa-code text-success me-2"></i>Use CPT/HCPCS for procedure codes</li>
<li><i class="fas fa-search text-info me-2"></i>Verify codes are current</li>
<li><i class="fas fa-check text-warning me-2"></i>Ensure medical necessity</li>
</ul>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#help-validation">
Validation Rules
</button>
</h2>
<div id="help-validation" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
<div class="accordion-body">
<ul class="list-unstyled mb-0">
<li><i class="fas fa-check text-success me-2"></i>Service date within coverage period</li>
<li><i class="fas fa-check text-success me-2"></i>Valid diagnosis and procedure codes</li>
<li><i class="fas fa-check text-success me-2"></i>Correct place of service</li>
<li><i class="fas fa-check text-success me-2"></i>Provider credentials verified</li>
</ul>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#help-submission">
Submission Tips
</button>
</h2>
<div id="help-submission" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
<div class="accordion-body">
<ul class="list-unstyled mb-0">
<li><i class="fas fa-clock text-primary me-2"></i>Submit within timely filing limits</li>
<li><i class="fas fa-file-alt text-success me-2"></i>Include all required documentation</li>
<li><i class="fas fa-double-check text-info me-2"></i>Review for accuracy before submission</li>
<li><i class="fas fa-history text-warning me-2"></i>Track claim status regularly</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<script>
let lineItemCounter = 0;
// Bill selection change handler
document.getElementById('{{ form.medical_bill.id_for_label }}').addEventListener('change', function() {
const billId = this.value;
if (billId) {
// Fetch bill details via AJAX
fetch(`{% url 'billing:bill_details_api' %}?bill_id=${billId}`)
.then(response => response.json())
.then(data => {
document.getElementById('bill-patient').textContent = data.patient_name;
document.getElementById('bill-number').textContent = data.bill_number;
document.getElementById('bill-date').textContent = data.bill_date;
document.getElementById('bill-total').textContent = `$${data.total_amount}`;
document.getElementById('bill-service-date').textContent = data.service_date;
document.getElementById('bill-provider').textContent = data.provider;
document.getElementById('bill-details').style.display = 'block';
// Auto-populate billed amount
document.getElementById('{{ form.billed_amount.id_for_label }}').value = data.total_amount;
// Auto-populate service date
document.getElementById('{{ form.service_date.id_for_label }}').value = data.service_date;
updateSummary();
})
.catch(error => {
console.error('Error fetching bill details:', error);
});
} else {
document.getElementById('bill-details').style.display = 'none';
}
});
// Insurance selection change handler
document.getElementById('{{ form.insurance_info.id_for_label }}').addEventListener('change', function() {
const insuranceId = this.value;
if (insuranceId) {
// Fetch insurance details via AJAX
fetch(`{% url 'billing:insurance_details_api' %}?insurance_id=${insuranceId}`)
.then(response => response.json())
.then(data => {
document.getElementById('insurance-company').textContent = data.company;
document.getElementById('insurance-policy').textContent = data.policy_number;
document.getElementById('insurance-group').textContent = data.group_number || '-';
document.getElementById('insurance-member').textContent = data.member_id || '-';
document.getElementById('insurance-plan').textContent = data.plan_type || '-';
document.getElementById('insurance-copay').textContent = data.copay_amount ? `$${data.copay_amount}` : '-';
document.getElementById('insurance-details').style.display = 'block';
updateSummary();
})
.catch(error => {
console.error('Error fetching insurance details:', error);
});
} else {
document.getElementById('insurance-details').style.display = 'none';
}
});
// Add line item function
function addLineItem() {
lineItemCounter++;
const tbody = document.getElementById('line-items-body');
const row = document.createElement('tr');
row.innerHTML = `
<td>
<input type="text" class="form-control form-control-sm" name="line_item_${lineItemCounter}_service_code" placeholder="CPT/HCPCS Code" required>
</td>
<td>
<input type="text" class="form-control form-control-sm" name="line_item_${lineItemCounter}_description" placeholder="Service Description" required>
</td>
<td>
<input type="date" class="form-control form-control-sm" name="line_item_${lineItemCounter}_service_date" required>
</td>
<td>
<input type="number" class="form-control form-control-sm" name="line_item_${lineItemCounter}_quantity" value="1" min="1" required>
</td>
<td>
<input type="number" class="form-control form-control-sm line-item-amount" name="line_item_${lineItemCounter}_amount" step="0.01" min="0" placeholder="0.00" required>
</td>
<td>
<button type="button" class="btn btn-sm btn-outline-danger" onclick="removeLineItem(this)">
<i class="fas fa-trash"></i>
</button>
</td>
`;
tbody.appendChild(row);
// Add event listener for amount changes
row.querySelector('.line-item-amount').addEventListener('input', updateSummary);
updateSummary();
}
// Remove line item function
function removeLineItem(button) {
button.closest('tr').remove();
updateSummary();
}
// Update summary function
function updateSummary() {
const lineItemAmounts = document.querySelectorAll('.line-item-amount');
let totalBilled = 0;
let itemCount = 0;
lineItemAmounts.forEach(input => {
const amount = parseFloat(input.value) || 0;
totalBilled += amount;
if (amount > 0) itemCount++;
});
// Update main billed amount if line items exist
if (lineItemAmounts.length > 0) {
document.getElementById('{{ form.billed_amount.id_for_label }}').value = totalBilled.toFixed(2);
}
// Update summary displays
document.getElementById('total-billed-amount').textContent = `$${totalBilled.toFixed(2)}`;
document.getElementById('summary-billed').textContent = `$${totalBilled.toFixed(2)}`;
document.getElementById('summary-items').textContent = itemCount;
// Calculate expected payment (simplified)
const copayText = document.getElementById('insurance-copay')?.textContent || '$0';
const copay = parseFloat(copayText.replace('$', '')) || 0;
const expectedPayment = Math.max(0, totalBilled - copay);
document.getElementById('summary-copay').textContent = `$${copay.toFixed(2)}`;
document.getElementById('summary-expected').textContent = `$${expectedPayment.toFixed(2)}`;
}
// Quick action functions
function copyFromBill() {
const billSelect = document.getElementById('{{ form.medical_bill.id_for_label }}');
if (!billSelect.value) {
alert('Please select a bill first.');
return;
}
// Fetch bill line items and copy them
fetch(`{% url 'billing:bill_line_items_api' %}?bill_id=${billSelect.value}`)
.then(response => response.json())
.then(data => {
// Clear existing line items
document.getElementById('line-items-body').innerHTML = '';
lineItemCounter = 0;
// Add line items from bill
data.line_items.forEach(item => {
addLineItem();
const lastRow = document.getElementById('line-items-body').lastElementChild;
lastRow.querySelector(`[name="line_item_${lineItemCounter}_service_code"]`).value = item.service_code;
lastRow.querySelector(`[name="line_item_${lineItemCounter}_description"]`).value = item.description;
lastRow.querySelector(`[name="line_item_${lineItemCounter}_service_date"]`).value = item.service_date;
lastRow.querySelector(`[name="line_item_${lineItemCounter}_quantity"]`).value = item.quantity;
lastRow.querySelector(`[name="line_item_${lineItemCounter}_amount"]`).value = item.unit_price;
});
updateSummary();
})
.catch(error => {
console.error('Error copying from bill:', error);
alert('Error copying line items from bill.');
});
}
function validateClaim() {
// Basic client-side validation
const requiredFields = document.querySelectorAll('[required]');
let isValid = true;
requiredFields.forEach(field => {
if (!field.value.trim()) {
field.classList.add('is-invalid');
isValid = false;
} else {
field.classList.remove('is-invalid');
}
});
if (isValid) {
alert('Claim validation passed! All required fields are completed.');
} else {
alert('Claim validation failed. Please complete all required fields.');
}
}
function previewClaim() {
const claimData = new FormData(document.getElementById('claimForm'));
// Open preview in new window
const previewWindow = window.open('', '_blank', 'width=800,height=600');
previewWindow.document.write('<h3>Claim Preview</h3><p>Loading...</p>');
fetch('{% url "billing:claim_preview" %}', {
method: 'POST',
body: claimData
})
.then(response => response.text())
.then(html => {
previewWindow.document.open();
previewWindow.document.write(html);
previewWindow.document.close();
})
.catch(error => {
console.error('Error generating preview:', error);
previewWindow.document.write('<p>Error generating preview.</p>');
});
}
function checkEligibility() {
const insuranceSelect = document.getElementById('{{ form.insurance_info.id_for_label }}');
const serviceDate = document.getElementById('{{ form.service_date.id_for_label }}').value;
if (!insuranceSelect.value || !serviceDate) {
alert('Please select insurance information and service date first.');
return;
}
// Simulate eligibility check
alert('Eligibility check initiated. Results will be available in a few moments.');
// In a real implementation, this would make an API call to check eligibility
setTimeout(() => {
alert('Eligibility verified: Patient is eligible for services on the specified date.');
}, 2000);
}
// Initialize with one line item if creating new claim
{% if not object %}
document.addEventListener('DOMContentLoaded', function() {
addLineItem();
});
{% endif %}
// Form validation
document.getElementById('claimForm').addEventListener('submit', function(e) {
const lineItems = document.querySelectorAll('#line-items-body tr');
if (lineItems.length === 0) {
e.preventDefault();
alert('Please add at least one line item to the claim.');
return false;
}
const billedAmount = parseFloat(document.getElementById('{{ form.billed_amount.id_for_label }}').value);
if (billedAmount <= 0) {
e.preventDefault();
alert('Billed amount must be greater than zero.');
return false;
}
});
</script>
{% endblock %}