459 lines
15 KiB
HTML
459 lines
15 KiB
HTML
{% load static %}
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>{% if is_bulk_print %}Print Bills{% else %}Print Bill{% endif %} - {{ tenant.name }}</title>
|
|
|
|
<!-- Print-specific styles -->
|
|
<style>
|
|
@media print {
|
|
body { margin: 0; }
|
|
.no-print { display: none !important; }
|
|
.page-break { page-break-before: always; }
|
|
.avoid-break { page-break-inside: avoid; }
|
|
}
|
|
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
font-size: 12px;
|
|
line-height: 1.4;
|
|
color: #333;
|
|
margin: 20px;
|
|
}
|
|
|
|
.bill-header {
|
|
text-align: center;
|
|
margin-bottom: 30px;
|
|
border-bottom: 2px solid #333;
|
|
padding-bottom: 20px;
|
|
}
|
|
|
|
.hospital-info {
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.hospital-name {
|
|
font-size: 24px;
|
|
font-weight: bold;
|
|
color: #2c5aa0;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.hospital-details {
|
|
font-size: 14px;
|
|
color: #666;
|
|
}
|
|
|
|
.bill-title {
|
|
font-size: 20px;
|
|
font-weight: bold;
|
|
margin: 20px 0;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.bill-container {
|
|
margin-bottom: 40px;
|
|
border: 1px solid #ddd;
|
|
padding: 20px;
|
|
}
|
|
|
|
.bill-info-section {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 25px;
|
|
}
|
|
|
|
.patient-info, .bill-details {
|
|
width: 48%;
|
|
}
|
|
|
|
.info-group {
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.info-label {
|
|
font-weight: bold;
|
|
color: #555;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.info-value {
|
|
margin-left: 10px;
|
|
}
|
|
|
|
.line-items-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin: 20px 0;
|
|
}
|
|
|
|
.line-items-table th,
|
|
.line-items-table td {
|
|
border: 1px solid #ddd;
|
|
padding: 8px;
|
|
text-align: left;
|
|
}
|
|
|
|
.line-items-table th {
|
|
background-color: #f8f9fa;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.amount-column {
|
|
text-align: right;
|
|
}
|
|
|
|
.totals-section {
|
|
margin-top: 20px;
|
|
text-align: right;
|
|
}
|
|
|
|
.total-row {
|
|
margin: 5px 0;
|
|
padding: 5px 0;
|
|
}
|
|
|
|
.total-label {
|
|
font-weight: bold;
|
|
display: inline-block;
|
|
width: 150px;
|
|
}
|
|
|
|
.total-amount {
|
|
display: inline-block;
|
|
width: 100px;
|
|
text-align: right;
|
|
}
|
|
|
|
.grand-total {
|
|
border-top: 2px solid #333;
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
padding-top: 10px;
|
|
}
|
|
|
|
.payment-history {
|
|
margin-top: 30px;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
margin-bottom: 15px;
|
|
color: #2c5aa0;
|
|
border-bottom: 1px solid #ddd;
|
|
padding-bottom: 5px;
|
|
}
|
|
|
|
.payment-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.payment-table th,
|
|
.payment-table td {
|
|
border: 1px solid #ddd;
|
|
padding: 6px;
|
|
text-align: left;
|
|
}
|
|
|
|
.payment-table th {
|
|
background-color: #f8f9fa;
|
|
}
|
|
|
|
.print-controls {
|
|
text-align: center;
|
|
margin: 20px 0;
|
|
}
|
|
|
|
.btn {
|
|
background-color: #2c5aa0;
|
|
color: white;
|
|
padding: 10px 20px;
|
|
border: none;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
margin: 0 10px;
|
|
text-decoration: none;
|
|
display: inline-block;
|
|
}
|
|
|
|
.btn:hover {
|
|
background-color: #1e3d6f;
|
|
}
|
|
|
|
.btn-secondary {
|
|
background-color: #6c757d;
|
|
}
|
|
|
|
.btn-secondary:hover {
|
|
background-color: #545b62;
|
|
}
|
|
|
|
.status-badge {
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
font-size: 11px;
|
|
font-weight: bold;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.status-draft { background-color: #ffc107; color: #000; }
|
|
.status-submitted { background-color: #17a2b8; color: #fff; }
|
|
.status-paid { background-color: #28a745; color: #fff; }
|
|
.status-overdue { background-color: #dc3545; color: #fff; }
|
|
.status-cancelled { background-color: #6c757d; color: #fff; }
|
|
|
|
.print-footer {
|
|
margin-top: 40px;
|
|
text-align: center;
|
|
font-size: 10px;
|
|
color: #666;
|
|
border-top: 1px solid #ddd;
|
|
padding-top: 15px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<!-- Print Controls (hidden when printing) -->
|
|
<div class="print-controls no-print">
|
|
<button onclick="window.print()" class="btn">🖨️ Print Bills</button>
|
|
<a href="{% url 'billing:bill_list' %}" class="btn btn-secondary">← Back to Bills</a>
|
|
</div>
|
|
|
|
{% for bill_data in bills_data %}
|
|
{% if not forloop.first %}
|
|
<div class="page-break"></div>
|
|
{% endif %}
|
|
|
|
<div class="bill-container avoid-break">
|
|
<!-- Hospital Header -->
|
|
<div class="bill-header">
|
|
<div class="hospital-info">
|
|
<div class="hospital-name">{{ tenant.name }}</div>
|
|
<div class="hospital-details">
|
|
{% if tenant.address %}{{ tenant.address }}<br>{% endif %}
|
|
{% if tenant.phone %}Phone: {{ tenant.phone }}{% endif %}
|
|
{% if tenant.email %} | Email: {{ tenant.email }}{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="bill-title">Medical Bill</div>
|
|
</div>
|
|
|
|
<!-- Bill Information -->
|
|
<div class="bill-info-section">
|
|
<div class="patient-info">
|
|
<div class="info-group">
|
|
<div class="info-label">Patient Information:</div>
|
|
<div class="info-value">
|
|
<strong>{{ bill_data.bill.patient.get_full_name }}</strong><br>
|
|
{% if bill_data.bill.patient.date_of_birth %}
|
|
DOB: {{ bill_data.bill.patient.date_of_birth|date:"M d, Y" }}<br>
|
|
{% endif %}
|
|
{% if bill_data.bill.patient.phone %}
|
|
Phone: {{ bill_data.bill.patient.phone }}<br>
|
|
{% endif %}
|
|
{% if bill_data.bill.patient.address %}
|
|
{{ bill_data.bill.patient.address }}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
{% if bill_data.bill.encounter %}
|
|
<div class="info-group">
|
|
<div class="info-label">Encounter:</div>
|
|
<div class="info-value">
|
|
{{ bill_data.bill.encounter.encounter_type|title }}<br>
|
|
Date: {{ bill_data.bill.encounter.encounter_date|date:"M d, Y" }}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<div class="bill-details">
|
|
<div class="info-group">
|
|
<div class="info-label">Bill Number:</div>
|
|
<div class="info-value"><strong>{{ bill_data.bill.bill_number }}</strong></div>
|
|
</div>
|
|
|
|
<div class="info-group">
|
|
<div class="info-label">Bill Date:</div>
|
|
<div class="info-value">{{ bill_data.bill.bill_date|date:"M d, Y" }}</div>
|
|
</div>
|
|
|
|
{% if bill_data.bill.due_date %}
|
|
<div class="info-group">
|
|
<div class="info-label">Due Date:</div>
|
|
<div class="info-value">{{ bill_data.bill.due_date|date:"M d, Y" }}</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="info-group">
|
|
<div class="info-label">Status:</div>
|
|
<div class="info-value">
|
|
<span class="status-badge status-{{ bill_data.bill.status }}">
|
|
{{ bill_data.bill.get_status_display }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Line Items -->
|
|
<div class="line-items-section">
|
|
<div class="section-title">Services & Charges</div>
|
|
<table class="line-items-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Description</th>
|
|
<th>Code</th>
|
|
<th>Quantity</th>
|
|
<th>Unit Price</th>
|
|
<th>Total</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for item in bill_data.line_items %}
|
|
<tr>
|
|
<td>{{ item.description }}</td>
|
|
<td>{{ item.service_code|default:"-" }}</td>
|
|
<td class="amount-column">{{ item.quantity }}</td>
|
|
<td class="amount-column">${{ item.unit_price|floatformat:2 }}</td>
|
|
<td class="amount-column">${{ item.total_amount|floatformat:2 }}</td>
|
|
</tr>
|
|
{% empty %}
|
|
<tr>
|
|
<td colspan="5" style="text-align: center; color: #666;">No line items found</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Totals -->
|
|
<div class="totals-section">
|
|
<div class="total-row">
|
|
<span class="total-label">Subtotal:</span>
|
|
<span class="total-amount">${{ bill_data.subtotal|floatformat:2 }}</span>
|
|
</div>
|
|
|
|
{% if bill_data.bill.tax_amount %}
|
|
<div class="total-row">
|
|
<span class="total-label">Tax:</span>
|
|
<span class="total-amount">${{ bill_data.bill.tax_amount|floatformat:2 }}</span>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if bill_data.bill.discount_amount %}
|
|
<div class="total-row">
|
|
<span class="total-label">Discount:</span>
|
|
<span class="total-amount">-${{ bill_data.bill.discount_amount|floatformat:2 }}</span>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="total-row grand-total">
|
|
<span class="total-label">Total Amount:</span>
|
|
<span class="total-amount">${{ bill_data.bill.total_amount|floatformat:2 }}</span>
|
|
</div>
|
|
|
|
{% if bill_data.total_payments %}
|
|
<div class="total-row">
|
|
<span class="total-label">Paid Amount:</span>
|
|
<span class="total-amount">${{ bill_data.total_payments|floatformat:2 }}</span>
|
|
</div>
|
|
|
|
<div class="total-row">
|
|
<span class="total-label">Balance Due:</span>
|
|
<span class="total-amount">${{ bill_data.bill.balance_amount|floatformat:2 }}</span>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Payment History -->
|
|
{% if bill_data.payments %}
|
|
<div class="payment-history">
|
|
<div class="section-title">Payment History</div>
|
|
<table class="payment-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Date</th>
|
|
<th>Method</th>
|
|
<th>Reference</th>
|
|
<th>Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for payment in bill_data.payments %}
|
|
<tr>
|
|
<td>{{ payment.payment_date|date:"M d, Y" }}</td>
|
|
<td>{{ payment.get_payment_method_display }}</td>
|
|
<td>{{ payment.reference_number|default:"-" }}</td>
|
|
<td class="amount-column">${{ payment.amount|floatformat:2 }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Insurance Claims -->
|
|
{% if bill_data.claims %}
|
|
<div class="payment-history">
|
|
<div class="section-title">Insurance Claims</div>
|
|
<table class="payment-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Claim Number</th>
|
|
<th>Insurance</th>
|
|
<th>Submitted</th>
|
|
<th>Amount</th>
|
|
<th>Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for claim in bill_data.claims %}
|
|
<tr>
|
|
<td>{{ claim.claim_number }}</td>
|
|
<td>{{ claim.insurance_provider.name }}</td>
|
|
<td>{{ claim.submission_date|date:"M d, Y" }}</td>
|
|
<td class="amount-column">${{ claim.claim_amount|floatformat:2 }}</td>
|
|
<td>{{ claim.get_status_display }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
|
|
<!-- Print Footer -->
|
|
<div class="print-footer no-print">
|
|
<p>Printed on {{ print_date|date:"F d, Y \a\t g:i A" }}</p>
|
|
<p>This is a computer-generated document. No signature required.</p>
|
|
</div>
|
|
|
|
<script>
|
|
// Auto-print when page loads (optional)
|
|
// window.onload = function() { window.print(); }
|
|
|
|
// Print function
|
|
function printBills() {
|
|
window.print();
|
|
}
|
|
|
|
// Keyboard shortcut for printing
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.ctrlKey && e.key === 'p') {
|
|
e.preventDefault();
|
|
window.print();
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|