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

600 lines
26 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}{% if object %}Edit{% else %}Add{% endif %} Insurance - Patients{% endblock %}
{% block css %}
<link href="{% static 'assets/plugins/bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css' %}" rel="stylesheet" />
{% endblock %}
{% block content %}
<!-- BEGIN breadcrumb -->
<ol class="breadcrumb float-xl-end">
<li class="breadcrumb-item"><a href="{% url 'core:dashboard' %}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{% url 'patients:patient_list' %}">Patients</a></li>
{% if object %}
<li class="breadcrumb-item"><a href="{% url 'patients:patient_detail' object.patient.pk %}">{{ object.patient.get_full_name }}</a></li>
<li class="breadcrumb-item"><a href="{% url 'patients:insurance_detail' object.pk %}">{{ object.insurance_provider }}</a></li>
<li class="breadcrumb-item active">Edit</li>
{% else %}
<li class="breadcrumb-item"><a href="{% url 'patients:insurance_list' %}">Insurance</a></li>
<li class="breadcrumb-item active">Add Insurance</li>
{% endif %}
</ol>
<!-- END breadcrumb -->
<!-- BEGIN page-header -->
<h1 class="page-header">
{% if object %}Edit Insurance{% else %}Add Insurance{% endif %}
<small>{% if object %}{{ object.insurance_provider }}{% else %}New Insurance Policy{% endif %}</small>
</h1>
<!-- END page-header -->
<div class="row">
<div class="col-xl-8">
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Insurance Information</h4>
<div class="panel-heading-btn">
<button type="button" class="btn btn-xs btn-info me-2" onclick="saveDraft()">
<i class="fa fa-save"></i> Save Draft
</button>
<a href="javascript:;" class="btn btn-xs btn-icon btn-default" data-toggle="panel-expand"><i class="fa fa-expand"></i></a>
</div>
</div>
<div class="panel-body">
<form method="post" id="insurance-form" novalidate>
{% csrf_token %}
<div class="row mb-3">
<div class="col-md-6">
<div class="form-floating">
{{ form.patient }}
<label for="{{ form.patient.id_for_label }}">Patient <span class="text-danger">*</span></label>
{% if form.patient.errors %}
<div class="invalid-feedback d-block">{{ form.patient.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
{{ form.insurance_type }}
<label for="{{ form.insurance_type.id_for_label }}">Insurance Type <span class="text-danger">*</span></label>
{% if form.insurance_type.errors %}
<div class="invalid-feedback d-block">{{ form.insurance_type.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<div class="form-floating">
{{ form.insurance_provider }}
<label for="{{ form.insurance_provider.id_for_label }}">Insurance Provider <span class="text-danger">*</span></label>
{% if form.insurance_provider.errors %}
<div class="invalid-feedback d-block">{{ form.insurance_provider.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
{{ form.policy_number }}
<label for="{{ form.policy_number.id_for_label }}">Policy Number <span class="text-danger">*</span></label>
{% if form.policy_number.errors %}
<div class="invalid-feedback d-block">{{ form.policy_number.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<div class="form-floating">
{{ form.member_id }}
<label for="{{ form.member_id.id_for_label }}">Member ID</label>
{% if form.member_id.errors %}
<div class="invalid-feedback d-block">{{ form.member_id.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
{{ form.group_number }}
<label for="{{ form.group_number.id_for_label }}">Group Number</label>
{% if form.group_number.errors %}
<div class="invalid-feedback d-block">{{ form.group_number.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<div class="form-floating">
{{ form.effective_date }}
<label for="{{ form.effective_date.id_for_label }}">Effective Date</label>
{% if form.effective_date.errors %}
<div class="invalid-feedback d-block">{{ form.effective_date.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
{{ form.expiration_date }}
<label for="{{ form.expiration_date.id_for_label }}">Expiration Date</label>
{% if form.expiration_date.errors %}
<div class="invalid-feedback d-block">{{ form.expiration_date.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<div class="form-floating">
{{ form.copay }}
<label for="{{ form.copay.id_for_label }}">Copay Amount ($)</label>
{% if form.copay.errors %}
<div class="invalid-feedback d-block">{{ form.copay.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
{{ form.deductible }}
<label for="{{ form.deductible.id_for_label }}">Deductible Amount ($)</label>
{% if form.deductible.errors %}
<div class="invalid-feedback d-block">{{ form.deductible.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<div class="form-floating">
{{ form.status }}
<label for="{{ form.status.id_for_label }}">Status <span class="text-danger">*</span></label>
{% if form.status.errors %}
<div class="invalid-feedback d-block">{{ form.status.errors.0 }}</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-check mt-3">
{{ form.is_primary }}
<label class="form-check-label" for="{{ form.is_primary.id_for_label }}">
Primary Insurance
</label>
{% if form.is_primary.errors %}
<div class="invalid-feedback d-block">{{ form.is_primary.errors.0 }}</div>
{% endif %}
</div>
</div>
</div>
<div class="mb-3">
<label for="{{ form.coverage_details.id_for_label }}" class="form-label">Coverage Details</label>
{{ form.coverage_details }}
{% if form.coverage_details.errors %}
<div class="invalid-feedback d-block">{{ form.coverage_details.errors.0 }}</div>
{% endif %}
<div class="form-text">Describe what services are covered, limitations, and special requirements.</div>
</div>
<div class="mb-3">
<label for="{{ form.notes.id_for_label }}" class="form-label">Additional Notes</label>
{{ form.notes }}
{% if form.notes.errors %}
<div class="invalid-feedback d-block">{{ form.notes.errors.0 }}</div>
{% endif %}
<div class="form-text">Any additional information about this insurance policy.</div>
</div>
<!-- Form Actions -->
<div class="d-flex justify-content-between">
<div>
<a href="{% if object %}{% url 'patients:insurance_detail' object.pk %}{% else %}{% url 'patients:insurance_list' %}{% endif %}" class="btn btn-secondary">
<i class="fa fa-arrow-left me-2"></i>Cancel
</a>
</div>
<div>
<button type="button" class="btn btn-info me-2" onclick="saveDraft()">
<i class="fa fa-save me-2"></i>Save Draft
</button>
<button type="submit" class="btn btn-primary">
<i class="fa fa-check me-2"></i>{% if object %}Update{% else %}Create{% endif %} Insurance
</button>
</div>
</div>
</form>
</div>
</div>
<!-- END panel -->
</div>
<div class="col-xl-4">
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Help & Guidelines</h4>
</div>
<div class="panel-body">
<div class="alert alert-info">
<h6 class="alert-heading">Insurance Information Tips</h6>
<ul class="mb-0 small">
<li>Verify all information with the insurance card</li>
<li>Primary insurance should be billed first</li>
<li>Check effective and expiration dates carefully</li>
<li>Include group number if available</li>
<li>Document any special coverage requirements</li>
</ul>
</div>
<div class="card border-primary mb-3">
<div class="card-header bg-primary text-white">
<h6 class="card-title mb-0">Required Fields</h6>
</div>
<div class="card-body">
<ul class="list-unstyled mb-0 small">
<li><i class="fa fa-check text-success me-2"></i>Patient</li>
<li><i class="fa fa-check text-success me-2"></i>Insurance Provider</li>
<li><i class="fa fa-check text-success me-2"></i>Policy Number</li>
<li><i class="fa fa-check text-success me-2"></i>Insurance Type</li>
<li><i class="fa fa-check text-success me-2"></i>Status</li>
</ul>
</div>
</div>
<div class="card border-warning mb-3">
<div class="card-header bg-warning text-dark">
<h6 class="card-title mb-0">Validation Rules</h6>
</div>
<div class="card-body">
<ul class="list-unstyled mb-0 small">
<li><i class="fa fa-exclamation-triangle text-warning me-2"></i>Only one primary insurance per patient</li>
<li><i class="fa fa-exclamation-triangle text-warning me-2"></i>Effective date cannot be in the future</li>
<li><i class="fa fa-exclamation-triangle text-warning me-2"></i>Expiration date must be after effective date</li>
<li><i class="fa fa-exclamation-triangle text-warning me-2"></i>Policy number must be unique per provider</li>
</ul>
</div>
</div>
<div class="card border-success">
<div class="card-header bg-success text-white">
<h6 class="card-title mb-0">Quick Actions</h6>
</div>
<div class="card-body">
<div class="d-grid gap-2">
<button type="button" class="btn btn-outline-primary btn-sm" onclick="verifyWithProvider()">
<i class="fa fa-check-circle me-2"></i>Verify with Provider
</button>
<button type="button" class="btn btn-outline-info btn-sm" onclick="checkEligibility()">
<i class="fa fa-search me-2"></i>Check Eligibility
</button>
<button type="button" class="btn btn-outline-secondary btn-sm" onclick="scanInsuranceCard()">
<i class="fa fa-camera me-2"></i>Scan Insurance Card
</button>
</div>
</div>
</div>
</div>
</div>
<!-- END panel -->
{% if object %}
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Current Patient</h4>
</div>
<div class="panel-body">
<div class="text-center mb-3">
<div class="w-60px h-60px bg-primary rounded-circle d-flex align-items-center justify-content-center mx-auto mb-2">
<i class="fa fa-user text-white"></i>
</div>
<h6 class="mb-1">{{ object.patient.get_full_name }}</h6>
<small class="text-muted">{{ object.patient.patient_id }}</small>
</div>
<table class="table table-borderless table-sm">
<tr>
<td class="fw-bold" width="60">DOB:</td>
<td>{{ object.patient.date_of_birth|date:"M d, Y" }}</td>
</tr>
<tr>
<td class="fw-bold">Age:</td>
<td>{{ object.patient.age }} years</td>
</tr>
<tr>
<td class="fw-bold">Gender:</td>
<td>{{ object.patient.get_gender_display }}</td>
</tr>
</table>
<div class="d-grid">
<a href="{% url 'patients:patient_detail' object.patient.pk %}" class="btn btn-outline-primary btn-sm">
<i class="fa fa-user me-2"></i>View Patient
</a>
</div>
</div>
</div>
<!-- END panel -->
{% endif %}
<!-- BEGIN panel -->
<div class="panel panel-inverse">
<div class="panel-heading">
<h4 class="panel-title">Form Status</h4>
</div>
<div class="panel-body">
<div id="form-status">
<div class="alert alert-secondary">
<i class="fa fa-info-circle me-2"></i>
<span id="status-text">Form not saved</span>
</div>
</div>
<div class="small text-muted">
<div>Last saved: <span id="last-saved">Never</span></div>
<div>Auto-save: <span class="text-success">Enabled</span></div>
</div>
</div>
</div>
<!-- END panel -->
</div>
</div>
<!-- Verification Modal -->
<div class="modal fade" id="verificationModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Verify Insurance</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div id="verification-results">
<!-- Verification results will be loaded here -->
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script src="{% static 'assets/plugins/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js' %}"></script>
<script>
$(document).ready(function() {
// Initialize date pickers
$('#{{ form.effective_date.id_for_label }}, #{{ form.expiration_date.id_for_label }}').datepicker({
format: 'yyyy-mm-dd',
autoclose: true,
todayHighlight: true
});
// Form validation
$('#insurance-form').on('submit', function(e) {
if (!validateForm()) {
e.preventDefault();
}
});
// Auto-save functionality
var autoSaveTimer;
$('#insurance-form input, #insurance-form select, #insurance-form textarea').on('change input', function() {
clearTimeout(autoSaveTimer);
autoSaveTimer = setTimeout(function() {
saveDraft();
}, 5000); // Auto-save after 5 seconds of inactivity
});
// Insurance type change handler
$('#{{ form.insurance_type.id_for_label }}').on('change', function() {
var type = $(this).val();
if (type === 'PRIMARY') {
$('#{{ form.is_primary.id_for_label }}').prop('checked', true);
checkPrimaryInsurance();
}
});
// Primary insurance checkbox handler
$('#{{ form.is_primary.id_for_label }}').on('change', function() {
if ($(this).is(':checked')) {
checkPrimaryInsurance();
}
});
// Policy number validation
$('#{{ form.policy_number.id_for_label }}').on('blur', function() {
validatePolicyNumber();
});
// Date validation
$('#{{ form.effective_date.id_for_label }}, #{{ form.expiration_date.id_for_label }}').on('change', function() {
validateDates();
});
});
function validateForm() {
var isValid = true;
var errors = [];
// Required field validation
var requiredFields = ['{{ form.patient.id_for_label }}', '{{ form.insurance_provider.id_for_label }}', '{{ form.policy_number.id_for_label }}', '{{ form.insurance_type.id_for_label }}', '{{ form.status.id_for_label }}'];
requiredFields.forEach(function(fieldId) {
var field = $('#' + fieldId);
if (!field.val()) {
field.addClass('is-invalid');
errors.push(field.closest('.form-floating').find('label').text().replace(' *', '') + ' is required');
isValid = false;
} else {
field.removeClass('is-invalid');
}
});
// Date validation
if (!validateDates()) {
isValid = false;
}
if (!isValid) {
toastr.error('Please fix the following errors:\n' + errors.join('\n'));
}
return isValid;
}
function validateDates() {
var effectiveDate = $('#{{ form.effective_date.id_for_label }}').val();
var expirationDate = $('#{{ form.expiration_date.id_for_label }}').val();
if (effectiveDate && expirationDate) {
var effective = new Date(effectiveDate);
var expiration = new Date(expirationDate);
if (expiration <= effective) {
$('#{{ form.expiration_date.id_for_label }}').addClass('is-invalid');
toastr.error('Expiration date must be after effective date');
return false;
} else {
$('#{{ form.expiration_date.id_for_label }}').removeClass('is-invalid');
}
}
return true;
}
function checkPrimaryInsurance() {
var patientId = $('#{{ form.patient.id_for_label }}').val();
if (!patientId) return;
$.ajax({
url: '{% url "patients:check_primary_insurance" %}',
method: 'POST',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}',
'patient_id': patientId,
'current_insurance_id': {% if object %}'{{ object.pk }}'{% else %}null{% endif %}
},
success: function(response) {
if (response.has_primary) {
toastr.warning('Patient already has a primary insurance. This will replace the existing primary insurance.');
}
}
});
}
function validatePolicyNumber() {
var policyNumber = $('#{{ form.policy_number.id_for_label }}').val();
var provider = $('#{{ form.insurance_provider.id_for_label }}').val();
if (policyNumber && provider) {
$.ajax({
url: '{% url "patients:validate_policy_number" %}',
method: 'POST',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}',
'policy_number': policyNumber,
'provider': provider,
'current_insurance_id': {% if object %}'{{ object.pk }}'{% else %}null{% endif %}
},
success: function(response) {
if (!response.is_valid) {
$('#{{ form.policy_number.id_for_label }}').addClass('is-invalid');
toastr.error('Policy number already exists for this provider');
} else {
$('#{{ form.policy_number.id_for_label }}').removeClass('is-invalid');
}
}
});
}
}
function saveDraft() {
var formData = $('#insurance-form').serialize();
$.ajax({
url: '{% url "patients:save_insurance_draft" %}',
method: 'POST',
data: formData,
success: function(response) {
updateFormStatus('Draft saved', 'success');
$('#last-saved').text(new Date().toLocaleTimeString());
},
error: function() {
updateFormStatus('Failed to save draft', 'danger');
}
});
}
function updateFormStatus(message, type) {
var alertClass = 'alert-' + type;
$('#form-status').html('<div class="alert ' + alertClass + '"><i class="fa fa-info-circle me-2"></i>' + message + '</div>');
}
function verifyWithProvider() {
var provider = $('#{{ form.insurance_provider.id_for_label }}').val();
var policyNumber = $('#{{ form.policy_number.id_for_label }}').val();
if (!provider || !policyNumber) {
toastr.error('Please enter insurance provider and policy number first');
return;
}
$.ajax({
url: '{% url "patients:verify_with_provider" %}',
method: 'POST',
data: {
'csrfmiddlewaretoken': '{{ csrf_token }}',
'provider': provider,
'policy_number': policyNumber
},
beforeSend: function() {
$('#verification-results').html('<div class="text-center"><i class="fa fa-spinner fa-spin fa-2x"></i><br>Verifying with provider...</div>');
$('#verificationModal').modal('show');
},
success: function(response) {
$('#verification-results').html(response.html);
},
error: function() {
$('#verification-results').html('<div class="alert alert-danger">Failed to verify with provider. Please try again.</div>');
}
});
}
function checkEligibility() {
var formData = $('#insurance-form').serialize();
$.ajax({
url: '{% url "patients:check_insurance_eligibility" %}',
method: 'POST',
data: formData,
beforeSend: function() {
$('#verification-results').html('<div class="text-center"><i class="fa fa-spinner fa-spin fa-2x"></i><br>Checking eligibility...</div>');
$('#verificationModal').modal('show');
},
success: function(response) {
$('#verification-results').html(response.html);
},
error: function() {
$('#verification-results').html('<div class="alert alert-danger">Failed to check eligibility. Please try again.</div>');
}
});
}
function scanInsuranceCard() {
toastr.info('Insurance card scanning feature coming soon!');
}
</script>
{% endblock %}