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

447 lines
24 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}Medical Bills - {{ 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">Medical Bills</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 active">Medical Bills</li>
</ol>
</nav>
</div>
<div class="btn-group">
<a href="{% url 'billing:bill_create' %}" class="btn btn-primary">
<i class="fas fa-plus me-2"></i>Create Bill
</a>
<button type="button" class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown">
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="{% url 'billing:export_bills' %}">
<i class="fas fa-download me-2"></i>Export Bills
</a></li>
<li><a class="dropdown-item" href="#" onclick="window.print()">
<i class="fas fa-print me-2"></i>Print List
</a></li>
</ul>
</div>
</div>
<!-- Statistics Cards -->
<div class="row mb-4" hx-get="{% url 'billing:billing_stats' %}" hx-trigger="load, every 60s">
<div class="col-md-3 mb-3">
<div class="card bg-gradient-primary text-white">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="card-title mb-1 opacity-75">Total Bills</h6>
<h3 class="mb-0">{{ stats.total_bills|default:0 }}</h3>
</div>
<div class="text-white-50">
<i class="fas fa-file-invoice fa-2x"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3 mb-3">
<div class="card bg-gradient-success text-white">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="card-title mb-1 opacity-75">Total Amount</h6>
<h3 class="mb-0"><span class="symbol">&#xea;</span>{{ stats.total_amount|default:0|floatformat:'2g' }}</h3>
</div>
<div class="text-white-50">
<i class="fas fa-dollar-sign fa-2x"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3 mb-3">
<div class="card bg-gradient-info text-white">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="card-title mb-1 opacity-75">Total Paid</h6>
<h3 class="mb-0"><span class="symbol">&#xea;</span>{{ stats.total_paid|default:0|floatformat:'2g' }}</h3>
</div>
<div class="text-white-50">
<i class="fas fa-check-circle fa-2x"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3 mb-3">
<div class="card bg-gradient-warning text-white">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center">
<div>
<h6 class="card-title mb-1 opacity-75">Outstanding</h6>
<h3 class="mb-0"><span class="symbol">&#xea;</span>{{ stats.outstanding_amount|default:0|floatformat:'2g' }}</h3>
</div>
<div class="text-white-50">
<i class="fas fa-exclamation-triangle fa-2x"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Search and Filter Card -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-search me-2"></i>Search & Filter
</h5>
</div>
<div class="card-body">
<form method="get" class="row g-3" hx-get="{% url 'billing:bill_list' %}" hx-target="#bill-list-container" hx-trigger="submit, change delay:500ms">
<div class="col-md-3">
<div class="form-floating">
<input type="text" class="form-control" id="search" name="search" value="{{ request.GET.search }}" placeholder="Search bills...">
<label for="search">Search Bills</label>
</div>
</div>
<div class="col-md-2">
<div class="form-floating">
<select class="form-select" id="status" name="status">
<option value="">All Statuses</option>
<option value="DRAFT" {% if request.GET.status == 'DRAFT' %}selected{% endif %}>Draft</option>
<option value="PENDING" {% if request.GET.status == 'PENDING' %}selected{% endif %}>Pending</option>
<option value="SUBMITTED" {% if request.GET.status == 'SUBMITTED' %}selected{% endif %}>Submitted</option>
<option value="PARTIAL_PAID" {% if request.GET.status == 'PARTIAL_PAID' %}selected{% endif %}>Partially Paid</option>
<option value="PAID" {% if request.GET.status == 'PAID' %}selected{% endif %}>Paid</option>
<option value="OVERDUE" {% if request.GET.status == 'OVERDUE' %}selected{% endif %}>Overdue</option>
<option value="COLLECTIONS" {% if request.GET.status == 'COLLECTIONS' %}selected{% endif %}>Collections</option>
<option value="WRITTEN_OFF" {% if request.GET.status == 'WRITTEN_OFF' %}selected{% endif %}>Written Off</option>
<option value="CANCELLED" {% if request.GET.status == 'CANCELLED' %}selected{% endif %}>Cancelled</option>
</select>
<label for="status">Status</label>
</div>
</div>
<div class="col-md-2">
<div class="form-floating">
<input type="date" class="form-control" id="date_from" name="date_from" value="{{ request.GET.date_from }}">
<label for="date_from">From Date</label>
</div>
</div>
<div class="col-md-2">
<div class="form-floating">
<input type="date" class="form-control" id="date_to" name="date_to" value="{{ request.GET.date_to }}">
<label for="date_to">To Date</label>
</div>
</div>
<div class="col-md-2">
<div class="form-floating">
<input type="number" class="form-control" id="min_amount" name="min_amount" value="{{ request.GET.min_amount }}" step="0.01" placeholder="Min Amount">
<label for="min_amount">Min Amount</label>
</div>
</div>
<div class="col-md-1">
<button type="submit" class="btn btn-primary h-100 w-100">
<i class="fas fa-search"></i>
</button>
</div>
</form>
</div>
</div>
<!-- Bills List Card -->
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">
<i class="fas fa-file-invoice me-2"></i>Medical Bills
<span class="badge bg-secondary ms-2">{{ page_obj.paginator.count }} total</span>
</h5>
<div class="btn-group btn-group-sm">
<button type="button" class="btn btn-outline-secondary" onclick="selectAll()">
<i class="fas fa-check-square me-1"></i>Select All
</button>
<button type="button" class="btn btn-outline-secondary" onclick="clearSelection()">
<i class="fas fa-square me-1"></i>Clear
</button>
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown">
<i class="fas fa-cog me-1"></i>Bulk Actions
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="bulkAction('export')">
<i class="fas fa-download me-2"></i>Export Selected
</a></li>
<li><a class="dropdown-item" href="#" onclick="bulkAction('print')">
<i class="fas fa-print me-2"></i>Print Selected
</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-warning" href="#" onclick="bulkAction('submit')">
<i class="fas fa-paper-plane me-2"></i>Submit Selected
</a></li>
</ul>
</div>
</div>
</div>
<div class="card-body p-0">
<div id="bill-list-container">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th width="40">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="selectAllCheckbox" onchange="toggleSelectAll()">
</div>
</th>
<th>Bill Number</th>
<th>Patient</th>
<th>Date</th>
<th>Total Amount</th>
<th>Paid Amount</th>
<th>Balance</th>
<th>Status</th>
<th>Due Date</th>
<th width="120">Actions</th>
</tr>
</thead>
<tbody>
{% for bill in page_obj %}
<tr>
<td>
<div class="form-check">
<input class="form-check-input bill-checkbox" type="checkbox" value="{{ bill.bill_id }}">
</div>
</td>
<td>
<a href="{% url 'billing:bill_detail' bill.bill_id %}" class="text-decoration-none fw-bold">
{{ bill.bill_number }}
</a>
</td>
<td>
<div>
<strong>{{ bill.patient.get_full_name }}</strong>
<br><small class="text-muted">MRN: {{ bill.patient.mrn }}</small>
</div>
</td>
<td>{{ bill.bill_date|date:"M d, Y" }}</td>
<td class="text-end"><span class="symbol">&#xea;</span>{{ bill.total_amount|floatformat:2 }}</td>
<td class="text-end"><span class="symbol">&#xea;</span>{{ bill.paid_amount|floatformat:2 }}</td>
<td class="text-end">
<span class="{% if bill.balance_amount > 0 %}text-danger fw-bold{% else %}text-success{% endif %}">
<span class="symbol">&#xea;</span>{{ bill.balance_amount|floatformat:2 }}
</span>
</td>
<td>
{% if bill.status == 'DRAFT' %}
<span class="badge bg-secondary">Draft</span>
{% elif bill.status == 'PENDING' %}
<span class="badge bg-warning">Pending</span>
{% elif bill.status == 'SUBMITTED' %}
<span class="badge bg-info">Submitted</span>
{% elif bill.status == 'PARTIAL_PAID' %}
<span class="badge bg-primary">Partially Paid</span>
{% elif bill.status == 'PAID' %}
<span class="badge bg-success">Paid</span>
{% elif bill.status == 'OVERDUE' %}
<span class="badge bg-danger">Overdue</span>
{% elif bill.status == 'COLLECTIONS' %}
<span class="badge bg-dark">Collections</span>
{% elif bill.status == 'WRITTEN_OFF' %}
<span class="badge bg-secondary">Written Off</span>
{% elif bill.status == 'CANCELLED' %}
<span class="badge bg-secondary">Cancelled</span>
{% endif %}
</td>
<td>
{% if bill.due_date %}
<span class="{% if bill.is_overdue %}text-danger{% elif bill.days_until_due <= 7 %}text-warning{% endif %}">
{{ bill.due_date|date:"M d, Y" }}
</span>
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
<td>
<div class="btn-group btn-group-sm">
<a href="{% url 'billing:bill_detail' bill.bill_id %}" class="btn btn-outline-primary btn-sm" title="View Details">
<i class="fas fa-eye"></i>
</a>
{% if bill.status == 'DRAFT' %}
<a href="{% url 'billing:bill_update' bill.bill_id %}" class="btn btn-outline-secondary btn-sm" title="Edit">
<i class="fas fa-edit"></i>
</a>
{% endif %}
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown">
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="">
<i class="fas fa-print me-2"></i>Print
</a></li>
<li><a class="dropdown-item" href="">
<i class="fas fa-envelope me-2"></i>Email
</a></li>
{% if bill.status == 'DRAFT' %}
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-warning" href="">
<i class="fas fa-paper-plane me-2"></i>Submit
</a></li>
{% endif %}
{% if bill.status in 'DRAFT,PENDING' %}
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-danger" href="">
<i class="fas fa-trash me-2"></i>Delete
</a></li>
{% endif %}
</ul>
</div>
</div>
</td>
</tr>
{% empty %}
<tr>
<td colspan="10" class="text-center py-5">
<div class="text-muted">
<i class="fas fa-file-invoice fa-3x mb-3 opacity-50"></i>
<h5>No bills found</h5>
<p>No medical bills match your current filters.</p>
<a href="{% url 'billing:bill_create' %}" class="btn btn-primary">
<i class="fas fa-plus me-2"></i>Create First Bill
</a>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<!-- Pagination -->
{% if page_obj.has_other_pages %}
<div class="card-footer">
<div class="d-flex justify-content-between align-items-center">
<div class="text-muted">
Showing {{ page_obj.start_index }} to {{ page_obj.end_index }} of {{ page_obj.paginator.count }} bills
</div>
<nav aria-label="Bills pagination">
<ul class="pagination pagination-sm mb-0">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?{% for key, value in request.GET.items %}{% if key != 'page' %}{{ key }}={{ value }}&{% endif %}{% endfor %}page=1">First</a>
</li>
<li class="page-item">
<a class="page-link" href="?{% for key, value in request.GET.items %}{% if key != 'page' %}{{ key }}={{ value }}&{% endif %}{% endfor %}page={{ page_obj.previous_page_number }}">Previous</a>
</li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<li class="page-item active">
<span class="page-link">{{ num }}</span>
</li>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<li class="page-item">
<a class="page-link" href="?{% for key, value in request.GET.items %}{% if key != 'page' %}{{ key }}={{ value }}&{% endif %}{% endfor %}page={{ num }}">{{ num }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?{% for key, value in request.GET.items %}{% if key != 'page' %}{{ key }}={{ value }}&{% endif %}{% endfor %}page={{ page_obj.next_page_number }}">Next</a>
</li>
<li class="page-item">
<a class="page-link" href="?{% for key, value in request.GET.items %}{% if key != 'page' %}{{ key }}={{ value }}&{% endif %}{% endfor %}page={{ page_obj.paginator.num_pages }}">Last</a>
</li>
{% endif %}
</ul>
</nav>
</div>
</div>
{% endif %}
</div>
</div>
<script>
// Bulk selection functionality
function toggleSelectAll() {
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
const billCheckboxes = document.querySelectorAll('.bill-checkbox');
billCheckboxes.forEach(checkbox => {
checkbox.checked = selectAllCheckbox.checked;
});
}
function selectAll() {
const billCheckboxes = document.querySelectorAll('.bill-checkbox');
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
billCheckboxes.forEach(checkbox => {
checkbox.checked = true;
});
selectAllCheckbox.checked = true;
}
function clearSelection() {
const billCheckboxes = document.querySelectorAll('.bill-checkbox');
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
billCheckboxes.forEach(checkbox => {
checkbox.checked = false;
});
selectAllCheckbox.checked = false;
}
function bulkAction(action) {
const selectedBills = Array.from(document.querySelectorAll('.bill-checkbox:checked')).map(cb => cb.value);
if (selectedBills.length === 0) {
alert('Please select at least one bill.');
return;
}
switch(action) {
case 'export':
window.location.href = `{% url 'billing:export_bills' %}?bills=${selectedBills.join(',')}`;
break;
case 'print':
window.open(`{% url 'billing:print_bills' %}?bills=${selectedBills.join(',')}`, '_blank');
break;
case 'submit':
if (confirm(`Submit ${selectedBills.length} selected bills?`)) {
// Submit via HTMX or form
htmx.ajax('POST', '{% url "billing:bulk_submit_bills" %}', {
values: {bills: selectedBills, csrfmiddlewaretoken: '{{ csrf_token }}'}
});
}
break;
}
}
// Update select all checkbox based on individual selections
document.addEventListener('change', function(e) {
if (e.target.classList.contains('bill-checkbox')) {
const billCheckboxes = document.querySelectorAll('.bill-checkbox');
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
const checkedCount = document.querySelectorAll('.bill-checkbox:checked').length;
selectAllCheckbox.checked = checkedCount === billCheckboxes.length;
selectAllCheckbox.indeterminate = checkedCount > 0 && checkedCount < billCheckboxes.length;
}
});
</script>
{% endblock %}