Marwan Alwali be70e47e22 update
2025-08-30 09:45:26 +03:00

511 lines
28 KiB
HTML

{% extends "base.html" %}
{% load static %}
{% block title %}{% if object %}Edit Payment{% else %}Record Payment{% 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 Payment{% else %}Record Payment{% 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:payment_list' %}">Payments</a></li>
<li class="breadcrumb-item active">{% if object %}Edit{% else %}Record{% endif %}</li>
</ol>
</nav>
</div>
<div class="btn-group">
<a href="{% url 'billing:payment_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:payment_detail' object.payment_id %}" class="btn btn-outline-primary">
<i class="fas fa-eye me-2"></i>View Details
</a>
{% endif %}
</div>
</div>
<form method="post" id="paymentForm" hx-post="{% if object %}{% url 'billing:payment_update' object.payment_id %}{% else %}{% url 'billing:payment_create' %}{% endif %}" hx-target="#form-container">
{% csrf_token %}
<div class="row">
<!-- Main Form -->
<div class="col-lg-8">
<div id="form-container">
<!-- Bill Information -->
<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.payment_number }}
<label for="{{ form.payment_number.id_for_label }}">Payment Number *</label>
{% if form.payment_number.errors %}
<div class="invalid-feedback d-block">
{{ form.payment_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>Paid Amount:</strong> <span id="bill-paid" class="text-primary"></span><br>
<strong>Balance:</strong> <span id="bill-balance" class="text-danger"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Payment Details -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-credit-card me-2"></i>Payment Details
</h5>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-4">
<div class="form-floating">
{{ form.payment_amount }}
<label for="{{ form.payment_amount.id_for_label }}">Payment Amount *</label>
{% if form.payment_amount.errors %}
<div class="invalid-feedback d-block">
{{ form.payment_amount.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-4">
<div class="form-floating">
{{ form.payment_date }}
<label for="{{ form.payment_date.id_for_label }}">Payment Date *</label>
{% if form.payment_date.errors %}
<div class="invalid-feedback d-block">
{{ form.payment_date.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-4">
<div class="form-floating">
{{ form.payment_method }}
<label for="{{ form.payment_method.id_for_label }}">Payment Method *</label>
{% if form.payment_method.errors %}
<div class="invalid-feedback d-block">
{{ form.payment_method.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
{{ form.reference_number }}
<label for="{{ form.reference_number.id_for_label }}">Reference Number</label>
{% if form.reference_number.errors %}
<div class="invalid-feedback d-block">
{{ form.reference_number.errors.0 }}
</div>
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
{{ form.status }}
<label for="{{ form.status.id_for_label }}">Status *</label>
{% if form.status.errors %}
<div class="invalid-feedback d-block">
{{ form.status.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>
<!-- Payment Method Specific Fields -->
<div class="card mb-4" id="payment-method-details" style="display: none;">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-info-circle me-2"></i>Additional Details
</h5>
</div>
<div class="card-body">
<!-- Credit/Debit Card Fields -->
<div id="card-fields" style="display: none;">
<div class="row g-3">
<div class="col-md-6">
<div class="form-floating">
<input type="text" class="form-control" id="card_number" name="card_number" placeholder="Card Number">
<label for="card_number">Card Number (Last 4 digits)</label>
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
<input type="text" class="form-control" id="card_holder" name="card_holder" placeholder="Card Holder">
<label for="card_holder">Card Holder Name</label>
</div>
</div>
</div>
</div>
<!-- Check Fields -->
<div id="check-fields" style="display: none;">
<div class="row g-3">
<div class="col-md-6">
<div class="form-floating">
<input type="text" class="form-control" id="check_number" name="check_number" placeholder="Check Number">
<label for="check_number">Check Number</label>
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
<input type="text" class="form-control" id="bank_name" name="bank_name" placeholder="Bank Name">
<label for="bank_name">Bank Name</label>
</div>
</div>
</div>
</div>
<!-- Bank Transfer Fields -->
<div id="transfer-fields" style="display: none;">
<div class="row g-3">
<div class="col-md-6">
<div class="form-floating">
<input type="text" class="form-control" id="transaction_id" name="transaction_id" placeholder="Transaction ID">
<label for="transaction_id">Transaction ID</label>
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
<input type="text" class="form-control" id="bank_account" name="bank_account" placeholder="Bank Account">
<label for="bank_account">Bank Account (Last 4 digits)</label>
</div>
</div>
</div>
</div>
<!-- Insurance Fields -->
<div id="insurance-fields" style="display: none;">
<div class="row g-3">
<div class="col-md-6">
<div class="form-floating">
<input type="text" class="form-control" id="insurance_company" name="insurance_company" placeholder="Insurance Company">
<label for="insurance_company">Insurance Company</label>
</div>
</div>
<div class="col-md-6">
<div class="form-floating">
<input type="text" class="form-control" id="claim_number" name="claim_number" placeholder="Claim Number">
<label for="claim_number">Claim Number</label>
</div>
</div>
</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:payment_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_process" class="btn btn-success">
<i class="fas fa-check me-2"></i>{% if object %}Update{% else %}Record{% endif %} Payment
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- Payment Summary -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">
<i class="fas fa-calculator me-2"></i>Payment Summary
</h5>
</div>
<div class="card-body">
<div class="d-flex justify-content-between mb-2">
<span>Payment Amount:</span>
<span id="payment-amount-display" class="fw-bold text-success">$0.00</span>
</div>
<div class="d-flex justify-content-between mb-2">
<span>Processing Fee:</span>
<span id="processing-fee">$0.00</span>
</div>
<hr>
<div class="d-flex justify-content-between fw-bold">
<span>Total:</span>
<span id="total-payment">$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="payFullBalance()">
<i class="fas fa-money-bill-wave me-2"></i>Pay Full Balance
</button>
<button type="button" class="btn btn-outline-secondary" onclick="calculatePartialPayment()">
<i class="fas fa-calculator me-2"></i>Calculate Partial
</button>
<button type="button" class="btn btn-outline-info" onclick="viewPaymentHistory()">
<i class="fas fa-history me-2"></i>Payment History
</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-methods">
Payment Methods
</button>
</h2>
<div id="help-methods" class="accordion-collapse collapse" data-bs-parent="#helpAccordion">
<div class="accordion-body">
<ul class="list-unstyled mb-0">
<li><i class="fas fa-credit-card text-primary me-2"></i>Credit/Debit Cards</li>
<li><i class="fas fa-money-check text-success me-2"></i>Checks</li>
<li><i class="fas fa-university text-info me-2"></i>Bank Transfers</li>
<li><i class="fas fa-shield-alt text-warning me-2"></i>Insurance Payments</li>
<li><i class="fas fa-money-bill text-secondary me-2"></i>Cash</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>Payment amount must be positive</li>
<li><i class="fas fa-check text-success me-2"></i>Cannot exceed bill balance</li>
<li><i class="fas fa-check text-success me-2"></i>Reference number required for cards</li>
<li><i class="fas fa-check text-success me-2"></i>Check number required for checks</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<script>
// Payment method change handler
document.addEventListener('DOMContentLoaded', function() {
const paymentMethodSelect = document.getElementById('{{ form.payment_method.id_for_label }}');
const paymentMethodDetails = document.getElementById('payment-method-details');
function togglePaymentMethodFields() {
const method = paymentMethodSelect.value;
// Hide all method-specific fields
document.getElementById('card-fields').style.display = 'none';
document.getElementById('check-fields').style.display = 'none';
document.getElementById('transfer-fields').style.display = 'none';
document.getElementById('insurance-fields').style.display = 'none';
// Show relevant fields based on method
if (method === 'CREDIT_CARD' || method === 'DEBIT_CARD') {
document.getElementById('card-fields').style.display = 'block';
paymentMethodDetails.style.display = 'block';
} else if (method === 'CHECK') {
document.getElementById('check-fields').style.display = 'block';
paymentMethodDetails.style.display = 'block';
} else if (method === 'BANK_TRANSFER') {
document.getElementById('transfer-fields').style.display = 'block';
paymentMethodDetails.style.display = 'block';
} else if (method === 'INSURANCE') {
document.getElementById('insurance-fields').style.display = 'block';
paymentMethodDetails.style.display = 'block';
} else {
paymentMethodDetails.style.display = 'none';
}
}
paymentMethodSelect.addEventListener('change', togglePaymentMethodFields);
togglePaymentMethodFields(); // Initialize on page load
});
// 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 HTMX or 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-paid').textContent = `$${data.paid_amount}`;#}
{# document.getElementById('bill-balance').textContent = `$${data.balance_amount}`;#}
{# document.getElementById('bill-details').style.display = 'block';#}
{# #}
{# // Set max payment amount to balance#}
{# const paymentAmountField = document.getElementById('{{ form.payment_amount.id_for_label }}');#}
{# paymentAmountField.max = data.balance_amount;#}
{# })#}
{# .catch(error => {#}
{# console.error('Error fetching bill details:', error);#}
{# });#}
{# } else {#}
{# document.getElementById('bill-details').style.display = 'none';#}
{# }#}
{# });#}
// Payment amount change handler
document.getElementById('{{ form.payment_amount.id_for_label }}').addEventListener('input', function() {
const amount = parseFloat(this.value) || 0;
const processingFee = calculateProcessingFee(amount);
const total = amount + processingFee;
document.getElementById('payment-amount-display').textContent = `$${amount.toFixed(2)}`;
document.getElementById('processing-fee').textContent = `$${processingFee.toFixed(2)}`;
document.getElementById('total-payment').textContent = `$${total.toFixed(2)}`;
});
function calculateProcessingFee(amount) {
const method = document.getElementById('{{ form.payment_method.id_for_label }}').value;
// Example processing fee calculation
if (method === 'CREDIT_CARD' || method === 'DEBIT_CARD') {
return amount * 0.029; // 2.9% for cards
} else if (method === 'BANK_TRANSFER') {
return Math.min(amount * 0.01, 5.00); // 1% up to $5
}
return 0; // No fee for cash, check, insurance
}
function payFullBalance() {
const balanceElement = document.getElementById('bill-balance');
if (balanceElement) {
const balance = balanceElement.textContent.replace('$', '');
document.getElementById('{{ form.payment_amount.id_for_label }}').value = balance;
document.getElementById('{{ form.payment_amount.id_for_label }}').dispatchEvent(new Event('input'));
}
}
function calculatePartialPayment() {
const amount = prompt('Enter partial payment amount:');
if (amount && !isNaN(amount) && amount > 0) {
document.getElementById('{{ form.payment_amount.id_for_label }}').value = amount;
document.getElementById('{{ form.payment_amount.id_for_label }}').dispatchEvent(new Event('input'));
}
}
{#function viewPaymentHistory() {#}
{# const billId = document.getElementById('{{ form.medical_bill.id_for_label }}').value;#}
{# if (billId) {#}
{# window.open(`{% url 'billing:payment_history' %}?bill_id=${billId}`, '_blank');#}
{# } else {#}
{# alert('Please select a bill first.');#}
{# }#}
{# }#}
// Form validation
document.getElementById('paymentForm').addEventListener('submit', function(e) {
const paymentAmount = parseFloat(document.getElementById('{{ form.payment_amount.id_for_label }}').value);
const billBalance = parseFloat(document.getElementById('bill-balance')?.textContent?.replace('$', '') || 0);
if (paymentAmount > billBalance) {
e.preventDefault();
alert('Payment amount cannot exceed the bill balance.');
return false;
}
if (paymentAmount <= 0) {
e.preventDefault();
alert('Payment amount must be greater than zero.');
return false;
}
});
</script>
{% endblock %}