557 lines
18 KiB
HTML
557 lines
18 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>Print Bill {{ bill.bill_number }} - {{ tenant.name }}</title>
|
|
|
|
<!-- Print-specific styles -->
|
|
<style>
|
|
@media print {
|
|
body { margin: 0; }
|
|
.no-print { display: none !important; }
|
|
.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: 28px;
|
|
font-weight: bold;
|
|
color: #2c5aa0;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.hospital-details {
|
|
font-size: 14px;
|
|
color: #666;
|
|
}
|
|
|
|
.bill-title {
|
|
font-size: 22px;
|
|
font-weight: bold;
|
|
margin: 20px 0;
|
|
text-transform: uppercase;
|
|
color: #2c5aa0;
|
|
}
|
|
|
|
.bill-info-section {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 30px;
|
|
border: 1px solid #ddd;
|
|
padding: 20px;
|
|
background-color: #f8f9fa;
|
|
}
|
|
|
|
.patient-info, .bill-details {
|
|
width: 48%;
|
|
}
|
|
|
|
.info-group {
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.info-label {
|
|
font-weight: bold;
|
|
color: #555;
|
|
margin-bottom: 5px;
|
|
display: block;
|
|
}
|
|
|
|
.info-value {
|
|
margin-left: 10px;
|
|
color: #333;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 18px;
|
|
font-weight: bold;
|
|
margin: 30px 0 15px 0;
|
|
color: #2c5aa0;
|
|
border-bottom: 2px solid #2c5aa0;
|
|
padding-bottom: 5px;
|
|
}
|
|
|
|
.line-items-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin: 20px 0;
|
|
border: 2px solid #333;
|
|
}
|
|
|
|
.line-items-table th,
|
|
.line-items-table td {
|
|
border: 1px solid #333;
|
|
padding: 10px;
|
|
text-align: left;
|
|
}
|
|
|
|
.line-items-table th {
|
|
background-color: #2c5aa0;
|
|
color: white;
|
|
font-weight: bold;
|
|
text-align: center;
|
|
}
|
|
|
|
.amount-column {
|
|
text-align: right;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.totals-section {
|
|
margin-top: 30px;
|
|
text-align: right;
|
|
border: 2px solid #333;
|
|
padding: 20px;
|
|
background-color: #f8f9fa;
|
|
}
|
|
|
|
.total-row {
|
|
margin: 8px 0;
|
|
padding: 5px 0;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.total-label {
|
|
font-weight: bold;
|
|
display: inline-block;
|
|
width: 200px;
|
|
}
|
|
|
|
.total-amount {
|
|
display: inline-block;
|
|
width: 120px;
|
|
text-align: right;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.grand-total {
|
|
border-top: 2px solid #333;
|
|
font-size: 18px;
|
|
font-weight: bold;
|
|
padding-top: 15px;
|
|
margin-top: 15px;
|
|
color: #2c5aa0;
|
|
}
|
|
|
|
.payment-history, .claims-history {
|
|
margin-top: 40px;
|
|
}
|
|
|
|
.payment-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 15px;
|
|
border: 1px solid #333;
|
|
}
|
|
|
|
.payment-table th,
|
|
.payment-table td {
|
|
border: 1px solid #333;
|
|
padding: 8px;
|
|
text-align: left;
|
|
}
|
|
|
|
.payment-table th {
|
|
background-color: #f8f9fa;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.print-controls {
|
|
text-align: center;
|
|
margin: 20px 0;
|
|
}
|
|
|
|
.btn {
|
|
background-color: #2c5aa0;
|
|
color: white;
|
|
padding: 12px 24px;
|
|
border: none;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
margin: 0 10px;
|
|
text-decoration: none;
|
|
display: inline-block;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.btn:hover {
|
|
background-color: #1e3d6f;
|
|
}
|
|
|
|
.btn-secondary {
|
|
background-color: #6c757d;
|
|
}
|
|
|
|
.btn-secondary:hover {
|
|
background-color: #545b62;
|
|
}
|
|
|
|
.status-badge {
|
|
padding: 6px 12px;
|
|
border-radius: 4px;
|
|
font-size: 12px;
|
|
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: 50px;
|
|
text-align: center;
|
|
font-size: 10px;
|
|
color: #666;
|
|
border-top: 1px solid #ddd;
|
|
padding-top: 20px;
|
|
}
|
|
|
|
.notes-section {
|
|
margin-top: 30px;
|
|
padding: 15px;
|
|
border: 1px solid #ddd;
|
|
background-color: #f8f9fa;
|
|
}
|
|
|
|
.notes-title {
|
|
font-weight: bold;
|
|
margin-bottom: 10px;
|
|
color: #555;
|
|
}
|
|
|
|
.watermark {
|
|
position: fixed;
|
|
top: 50%;
|
|
left: 50%;
|
|
transform: translate(-50%, -50%) rotate(-45deg);
|
|
font-size: 72px;
|
|
color: rgba(0,0,0,0.1);
|
|
z-index: -1;
|
|
pointer-events: none;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<!-- Status Watermark -->
|
|
{% if bill.status == 'paid' %}
|
|
<div class="watermark">PAID</div>
|
|
{% elif bill.status == 'cancelled' %}
|
|
<div class="watermark">CANCELLED</div>
|
|
{% elif bill.status == 'overdue' %}
|
|
<div class="watermark">OVERDUE</div>
|
|
{% endif %}
|
|
|
|
<!-- Print Controls (hidden when printing) -->
|
|
<div class="print-controls no-print">
|
|
<button onclick="window.print()" class="btn">🖨️ Print Bill</button>
|
|
<a href="{% url 'billing:bill_detail' bill.bill_id %}" class="btn btn-secondary">← Back to Bill</a>
|
|
<a href="{% url 'billing:bill_list' %}" class="btn btn-secondary">📋 All Bills</a>
|
|
</div>
|
|
|
|
<!-- Hospital Header -->
|
|
<div class="bill-header avoid-break">
|
|
<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 %}
|
|
{% if tenant.website %} | {{ tenant.website }}{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="bill-title">Medical Bill - Detailed Statement</div>
|
|
</div>
|
|
|
|
<!-- Bill Information -->
|
|
<div class="bill-info-section avoid-break">
|
|
<div class="patient-info">
|
|
<div class="info-group">
|
|
<div class="info-label">Patient Information:</div>
|
|
<div class="info-value">
|
|
<strong>{{ bill.patient.get_full_name }}</strong><br>
|
|
{% if bill.patient.patient_id %}
|
|
Patient ID: {{ bill.patient.patient_id }}<br>
|
|
{% endif %}
|
|
{% if bill.patient.date_of_birth %}
|
|
DOB: {{ bill.patient.date_of_birth|date:"M d, Y" }}<br>
|
|
{% endif %}
|
|
{% if bill.patient.phone %}
|
|
Phone: {{ bill.patient.phone }}<br>
|
|
{% endif %}
|
|
{% if bill.patient.email %}
|
|
Email: {{ bill.patient.email }}<br>
|
|
{% endif %}
|
|
{% if bill.patient.address %}
|
|
Address: {{ bill.patient.address }}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
{% if bill.encounter %}
|
|
<div class="info-group">
|
|
<div class="info-label">Encounter Details:</div>
|
|
<div class="info-value">
|
|
Type: {{ bill.encounter.encounter_type|title }}<br>
|
|
Date: {{ bill.encounter.encounter_date|date:"M d, Y" }}<br>
|
|
{% if bill.encounter.provider %}
|
|
Provider: {{ bill.encounter.provider.get_full_name }}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if bill.admission %}
|
|
<div class="info-group">
|
|
<div class="info-label">Admission Details:</div>
|
|
<div class="info-value">
|
|
Admission Date: {{ bill.admission.admission_date|date:"M d, Y" }}<br>
|
|
{% if bill.admission.discharge_date %}
|
|
Discharge Date: {{ bill.admission.discharge_date|date:"M d, Y" }}<br>
|
|
{% endif %}
|
|
Type: {{ bill.admission.admission_type|title }}
|
|
</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.bill_number }}</strong></div>
|
|
</div>
|
|
|
|
<div class="info-group">
|
|
<div class="info-label">Bill Date:</div>
|
|
<div class="info-value">{{ bill.bill_date|date:"F d, Y" }}</div>
|
|
</div>
|
|
|
|
{% if bill.due_date %}
|
|
<div class="info-group">
|
|
<div class="info-label">Due Date:</div>
|
|
<div class="info-value">{{ bill.due_date|date:"F 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.status }}">
|
|
{{ bill.get_status_display }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{% if bill.created_by %}
|
|
<div class="info-group">
|
|
<div class="info-label">Created By:</div>
|
|
<div class="info-value">{{ bill.created_by.get_full_name }}</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Line Items -->
|
|
<div class="line-items-section">
|
|
<div class="section-title">Services & Charges</div>
|
|
<table class="line-items-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Line #</th>
|
|
<th>Description</th>
|
|
<th>Service Code</th>
|
|
<th>Quantity</th>
|
|
<th>Unit Price</th>
|
|
<th>Total Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for item in line_items %}
|
|
<tr>
|
|
<td style="text-align: center;">{{ item.line_number }}</td>
|
|
<td>
|
|
<strong>{{ item.description }}</strong>
|
|
{% if item.notes %}
|
|
<br><small style="color: #666;">{{ item.notes }}</small>
|
|
{% endif %}
|
|
</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="6" style="text-align: center; color: #666; padding: 20px;">
|
|
No line items found for this bill
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- Totals -->
|
|
<div class="totals-section avoid-break">
|
|
<div class="total-row">
|
|
<span class="total-label">Subtotal:</span>
|
|
<span class="total-amount">${{ subtotal|floatformat:2 }}</span>
|
|
</div>
|
|
|
|
{% if bill.tax_amount %}
|
|
<div class="total-row">
|
|
<span class="total-label">Tax ({{ bill.tax_rate|floatformat:1 }}%):</span>
|
|
<span class="total-amount">${{ bill.tax_amount|floatformat:2 }}</span>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if bill.discount_amount %}
|
|
<div class="total-row">
|
|
<span class="total-label">Discount:</span>
|
|
<span class="total-amount">-${{ 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.total_amount|floatformat:2 }}</span>
|
|
</div>
|
|
|
|
{% if total_payments %}
|
|
<div class="total-row">
|
|
<span class="total-label">Total Payments:</span>
|
|
<span class="total-amount">${{ total_payments|floatformat:2 }}</span>
|
|
</div>
|
|
|
|
<div class="total-row" style="color: {% if bill.balance_amount > 0 %}#dc3545{% else %}#28a745{% endif %};">
|
|
<span class="total-label">Balance Due:</span>
|
|
<span class="total-amount">${{ bill.balance_amount|floatformat:2 }}</span>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Payment History -->
|
|
{% if payments %}
|
|
<div class="payment-history">
|
|
<div class="section-title">Payment History</div>
|
|
<table class="payment-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Payment Date</th>
|
|
<th>Payment Method</th>
|
|
<th>Reference Number</th>
|
|
<th>Amount</th>
|
|
<th>Notes</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for payment in 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>
|
|
<td>{{ payment.notes|default:"-" }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Insurance Claims -->
|
|
{% if claims %}
|
|
<div class="claims-history">
|
|
<div class="section-title">Insurance Claims</div>
|
|
<table class="payment-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Claim Number</th>
|
|
<th>Insurance Provider</th>
|
|
<th>Submission Date</th>
|
|
<th>Claim Amount</th>
|
|
<th>Status</th>
|
|
<th>Response Date</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for claim in 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>
|
|
<td>{{ claim.response_date|date:"M d, Y"|default:"-" }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Notes Section -->
|
|
{% if bill.notes %}
|
|
<div class="notes-section">
|
|
<div class="notes-title">Additional Notes:</div>
|
|
<div>{{ bill.notes|linebreaks }}</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Print Footer -->
|
|
<div class="print-footer">
|
|
<p><strong>{{ tenant.name }}</strong> - Medical Billing Statement</p>
|
|
<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>
|
|
{% if bill.balance_amount > 0 %}
|
|
<p style="margin-top: 15px; font-weight: bold; color: #dc3545;">
|
|
Payment is due by {{ bill.due_date|date:"F d, Y"|default:"upon receipt" }}
|
|
</p>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<script>
|
|
// Print function
|
|
function printBill() {
|
|
window.print();
|
|
}
|
|
|
|
// Keyboard shortcut for printing
|
|
document.addEventListener('keydown', function(e) {
|
|
if (e.ctrlKey && e.key === 'p') {
|
|
e.preventDefault();
|
|
window.print();
|
|
}
|
|
});
|
|
|
|
// Auto-focus for better printing experience
|
|
window.onload = function() {
|
|
document.body.focus();
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|