154 lines
5.9 KiB
PHP
154 lines
5.9 KiB
PHP
<?php
|
|
require_once 'auth.php';
|
|
require_once 'db/config.php';
|
|
|
|
$visit_id = $_GET['visit_id'] ?? null;
|
|
|
|
if (!$visit_id) {
|
|
die("Visit ID is required.");
|
|
}
|
|
|
|
// Fetch visit details
|
|
try {
|
|
$pdo = db();
|
|
$stmt = $pdo->prepare(
|
|
"SELECT
|
|
pv.*,
|
|
p.patient_name,
|
|
p.address,
|
|
p.phone_number,
|
|
u.username as doctor_name
|
|
FROM patient_visits pv
|
|
JOIN patients p ON pv.patient_id = p.id
|
|
JOIN users u ON pv.doctor_id = u.id
|
|
WHERE pv.visit_id = ?"
|
|
);
|
|
$stmt->execute([$visit_id]);
|
|
$visit = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
// Fetch ordered tests for the visit
|
|
$tests_stmt = $pdo->prepare(
|
|
"SELECT
|
|
ot.test_type,
|
|
CASE
|
|
WHEN ot.test_type = 'lab' THEN lt.test_name
|
|
WHEN ot.test_type = 'imaging' THEN it.test_name
|
|
END as test_name,
|
|
CASE
|
|
WHEN ot.test_type = 'lab' THEN lt.cost
|
|
WHEN ot.test_type = 'imaging' THEN it.cost
|
|
END as cost
|
|
FROM ordered_tests ot
|
|
LEFT JOIN lab_tests lt ON ot.test_type = 'lab' AND ot.test_id = lt.test_id
|
|
LEFT JOIN imaging_tests it ON ot.test_type = 'imaging' AND ot.test_id = it.test_id
|
|
WHERE ot.visit_id = ?"
|
|
);
|
|
$tests_stmt->execute([$visit_id]);
|
|
$ordered_tests = $tests_stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
} catch (PDOException $e) {
|
|
$visit = null;
|
|
$ordered_tests = [];
|
|
// In a real app, you would log this error
|
|
}
|
|
|
|
if (!$visit) {
|
|
die("No completed visit found for this ID or an error occurred.");
|
|
}
|
|
|
|
// Calculate total bill
|
|
$total_bill = $visit['cost'];
|
|
foreach ($ordered_tests as $test) {
|
|
$total_bill += $test['cost'];
|
|
}
|
|
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Invoice - Visit #<?php echo htmlspecialchars($visit['visit_id']); ?></title>
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap" rel="stylesheet">
|
|
<style>
|
|
body { font-family: 'Poppins', sans-serif; background-color: #f8f9fa; }
|
|
.invoice-container { max-width: 800px; margin: 40px auto; padding: 40px; background: #fff; border-radius: 15px; box-shadow: 0 4px 20px rgba(0,0,0,0.05); }
|
|
.invoice-header { text-align: center; margin-bottom: 40px; }
|
|
.invoice-header h1 { font-weight: 600; color: #343a40; }
|
|
.invoice-header .brand { font-size: 1.5rem; font-weight: 600; color: #0d6efd; }
|
|
.invoice-details, .billing-details { margin-bottom: 30px; }
|
|
.invoice-details h5, .billing-details h5 { font-weight: 600; margin-bottom: 15px; }
|
|
.invoice-details p, .billing-details p { margin-bottom: 5px; }
|
|
.table thead { background-color: #e9ecef; }
|
|
.total-section { text-align: right; margin-top: 30px; }
|
|
.total-section h4 { font-weight: 600; }
|
|
.print-btn { display: block; width: 150px; margin: 30px auto 0; }
|
|
@media print {
|
|
body { background-color: #fff; }
|
|
.invoice-container { margin: 0; box-shadow: none; border-radius: 0; }
|
|
.print-btn, .btn-back { display: none; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="invoice-container">
|
|
<div class="invoice-header">
|
|
<div class="brand"><i class="bi bi-heart-pulse-fill"></i> ClinicFlow</div>
|
|
<h1>Invoice</h1>
|
|
</div>
|
|
|
|
<div class="row justify-content-between invoice-details">
|
|
<div class="col-md-6">
|
|
<h5>Billed To:</h5>
|
|
<p><strong><?php echo htmlspecialchars($visit['patient_name']); ?></strong></p>
|
|
<p><?php echo htmlspecialchars($visit['address']); ?></p>
|
|
<p><?php echo htmlspecialchars($visit['phone_number']); ?></p>
|
|
</div>
|
|
<div class="col-md-5 text-md-end">
|
|
<p><strong>Invoice #:</strong> INV-<?php echo htmlspecialchars($visit['visit_id']); ?></p>
|
|
<p><strong>Date:</strong> <?php echo date("F j, Y", strtotime($visit['visit_time'])); ?></p>
|
|
<p><strong>Status:</strong> <span class="badge bg-<?php echo $visit['payment_status'] === 'paid' ? 'success' : 'danger'; ?>"><?php echo ucfirst(htmlspecialchars($visit['payment_status'])); ?></span></p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="billing-details">
|
|
<h5>Consultation Details:</h5>
|
|
<p><strong>Consulting Doctor:</strong> Dr. <?php echo htmlspecialchars($visit['doctor_name']); ?></p>
|
|
</div>
|
|
|
|
<table class="table table-bordered">
|
|
<thead class="table-dark">
|
|
<tr>
|
|
<th>Item</th>
|
|
<th class="text-end">Cost</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars($visit['service_rendered']); ?> (Consultation)</td>
|
|
<td class="text-end">$<?php echo htmlspecialchars(number_format($visit['cost'], 2)); ?></td>
|
|
</tr>
|
|
<?php foreach ($ordered_tests as $test): ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars($test['test_name']); ?> (<?php echo ucfirst(htmlspecialchars($test['test_type'])); ?> Test)</td>
|
|
<td class="text-end">$<?php echo htmlspecialchars(number_format($test['cost'], 2)); ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr class="fw-bold">
|
|
<td class="text-end">Total:</td>
|
|
<td class="text-end">$<?php echo htmlspecialchars(number_format($total_bill, 2)); ?></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
|
|
<button onclick="window.print();" class="btn btn-primary print-btn"><i class="bi bi-printer"></i> Print Invoice</button>
|
|
<a href="billing.php" class="btn btn-secondary btn-back d-print-none" style="display: block; width: 150px; margin: 10px auto 0;">Back to Billing</a>
|
|
|
|
</div>
|
|
|
|
</body>
|
|
</html>
|