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

434 lines
23 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}Payments - {{ 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">Payments</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">Payments</li>
</ol>
</nav>
</div>
<div class="btn-group">
<a href="{% url 'billing:payment_create' %}" class="btn btn-success">
<i class="fas fa-plus me-2"></i>Record Payment
</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="">
<i class="fas fa-download me-2"></i>Export Payments
</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:payment_stats' %}" hx-trigger="load, every 60s">#}
{# <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 Payments</h6>#}
{# <h3 class="mb-0">{{ stats.total_payments|default:0 }}</h3>#}
{# </div>#}
{# <div class="text-white-50">#}
{# <i class="fas fa-credit-card fa-2x"></i>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# <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 Amount</h6>#}
{# <h3 class="mb-0">${{ stats.total_amount|default:0|floatformat:2 }}</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">Today's Payments</h6>#}
{# <h3 class="mb-0">${{ stats.today_amount|default:0|floatformat:2 }}</h3>#}
{# </div>#}
{# <div class="text-white-50">#}
{# <i class="fas fa-calendar-day 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">Pending</h6>#}
{# <h3 class="mb-0">{{ stats.pending_count|default:0 }}</h3>#}
{# </div>#}
{# <div class="text-white-50">#}
{# <i class="fas fa-clock 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:payment_list' %}" hx-target="#payment-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 payments...">
<label for="search">Search Payments</label>
</div>
</div>
<div class="col-md-2">
<div class="form-floating">
<select class="form-select" id="payment_method" name="payment_method">
<option value="">All Methods</option>
<option value="CASH" {% if request.GET.payment_method == 'CASH' %}selected{% endif %}>Cash</option>
<option value="CHECK" {% if request.GET.payment_method == 'CHECK' %}selected{% endif %}>Check</option>
<option value="CREDIT_CARD" {% if request.GET.payment_method == 'CREDIT_CARD' %}selected{% endif %}>Credit Card</option>
<option value="DEBIT_CARD" {% if request.GET.payment_method == 'DEBIT_CARD' %}selected{% endif %}>Debit Card</option>
<option value="BANK_TRANSFER" {% if request.GET.payment_method == 'BANK_TRANSFER' %}selected{% endif %}>Bank Transfer</option>
<option value="INSURANCE" {% if request.GET.payment_method == 'INSURANCE' %}selected{% endif %}>Insurance</option>
<option value="OTHER" {% if request.GET.payment_method == 'OTHER' %}selected{% endif %}>Other</option>
</select>
<label for="payment_method">Payment Method</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="PENDING" {% if request.GET.status == 'PENDING' %}selected{% endif %}>Pending</option>
<option value="PROCESSING" {% if request.GET.status == 'PROCESSING' %}selected{% endif %}>Processing</option>
<option value="COMPLETED" {% if request.GET.status == 'COMPLETED' %}selected{% endif %}>Completed</option>
<option value="FAILED" {% if request.GET.status == 'FAILED' %}selected{% endif %}>Failed</option>
<option value="REFUNDED" {% if request.GET.status == 'REFUNDED' %}selected{% endif %}>Refunded</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-1">
<button type="submit" class="btn btn-primary h-100 w-100">
<i class="fas fa-search"></i>
</button>
</div>
</form>
</div>
</div>
<!-- Payments 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-credit-card me-2"></i>Payments
<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>
</ul>
</div>
</div>
</div>
<div class="card-body p-0">
<div id="payment-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>Payment Number</th>
<th>Patient</th>
<th>Bill Number</th>
<th>Payment Date</th>
<th>Amount</th>
<th>Method</th>
<th>Status</th>
<th>Reference</th>
<th width="120">Actions</th>
</tr>
</thead>
<tbody>
{% for payment in page_obj %}
<tr>
<td>
<div class="form-check">
<input class="form-check-input payment-checkbox" type="checkbox" value="{{ payment.payment_id }}">
</div>
</td>
<td>
<a href="{% url 'billing:payment_detail' payment.payment_id %}" class="text-decoration-none fw-bold">
{{ payment.payment_number }}
</a>
</td>
<td>
<div>
<strong>{{ payment.medical_bill.patient.get_full_name }}</strong>
<br><small class="text-muted">MRN: {{ payment.medical_bill.patient.mrn }}</small>
</div>
</td>
<td>
<a href="{% url 'billing:bill_detail' payment.medical_bill.bill_id %}" class="text-decoration-none">
{{ payment.medical_bill.bill_number }}
</a>
</td>
<td>{{ payment.payment_date|date:"M d, Y" }}</td>
<td class="text-end fw-bold text-success">${{ payment.payment_amount|floatformat:2 }}</td>
<td>
<span class="badge bg-light text-dark">
{{ payment.get_payment_method_display }}
</span>
</td>
<td>
{% if payment.status == 'PENDING' %}
<span class="badge bg-warning">Pending</span>
{% elif payment.status == 'PROCESSING' %}
<span class="badge bg-info">Processing</span>
{% elif payment.status == 'COMPLETED' %}
<span class="badge bg-success">Completed</span>
{% elif payment.status == 'FAILED' %}
<span class="badge bg-danger">Failed</span>
{% elif payment.status == 'REFUNDED' %}
<span class="badge bg-secondary">Refunded</span>
{% endif %}
</td>
<td>
{% if payment.reference_number %}
<small class="text-muted">{{ payment.reference_number }}</small>
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
<td>
<div class="btn-group btn-group-sm">
<a href="{% url 'billing:payment_detail' payment.payment_id %}" class="btn btn-outline-primary btn-sm" title="View Details">
<i class="fas fa-eye"></i>
</a>
{% if payment.status == 'PENDING' %}
<a href="{% url 'billing:payment_update' payment.payment_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="{% url 'billing:payment_receipt' payment.payment_id %}">
<i class="fas fa-receipt me-2"></i>Print Receipt
</a></li>
<li><a class="dropdown-item" href="{% url 'billing:payment_email' payment.payment_id %}">
<i class="fas fa-envelope me-2"></i>Email Receipt
</a></li>
{% if payment.status == 'COMPLETED' %}
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-warning" href="{% url 'billing:payment_refund' payment.payment_id %}">
<i class="fas fa-undo me-2"></i>Process Refund
</a></li>
{% endif %}
{% if payment.status == 'PENDING' %}
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item text-danger" href="{% url 'billing:payment_delete' payment.payment_id %}">
<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-credit-card fa-3x mb-3 opacity-50"></i>
<h5>No payments found</h5>
<p>No payments match your current filters.</p>
<a href="{% url 'billing:payment_create' %}" class="btn btn-success">
<i class="fas fa-plus me-2"></i>Record First Payment
</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 }} payments
</div>
<nav aria-label="Payments 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 paymentCheckboxes = document.querySelectorAll('.payment-checkbox');
paymentCheckboxes.forEach(checkbox => {
checkbox.checked = selectAllCheckbox.checked;
});
}
function selectAll() {
const paymentCheckboxes = document.querySelectorAll('.payment-checkbox');
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
paymentCheckboxes.forEach(checkbox => {
checkbox.checked = true;
});
selectAllCheckbox.checked = true;
}
function clearSelection() {
const paymentCheckboxes = document.querySelectorAll('.payment-checkbox');
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
paymentCheckboxes.forEach(checkbox => {
checkbox.checked = false;
});
selectAllCheckbox.checked = false;
}
{#function bulkAction(action) {#}
{# const selectedPayments = Array.from(document.querySelectorAll('.payment-checkbox:checked')).map(cb => cb.value);#}
{# #}
{# if (selectedPayments.length === 0) {#}
{# alert('Please select at least one payment.');#}
{# return;#}
{# }#}
{# #}
{# switch(action) {#}
{# case 'export':#}
{# window.location.href = `{% url 'billing:export_payments' %}?payments=${selectedPayments.join(',')}`;#}
{# break;#}
{# case 'print':#}
{# window.open(`{% url 'billing:print_payments' %}?payments=${selectedPayments.join(',')}`, '_blank');#}
{# break;#}
{# }#}
{# }#}
// Update select all checkbox based on individual selections
document.addEventListener('change', function(e) {
if (e.target.classList.contains('payment-checkbox')) {
const paymentCheckboxes = document.querySelectorAll('.payment-checkbox');
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
const checkedCount = document.querySelectorAll('.payment-checkbox:checked').length;
selectAllCheckbox.checked = checkedCount === paymentCheckboxes.length;
selectAllCheckbox.indeterminate = checkedCount > 0 && checkedCount < paymentCheckboxes.length;
}
});
</script>
{% endblock %}