173 lines
6.5 KiB
PHP
173 lines
6.5 KiB
PHP
<?php
|
|
$title = 'Reports - Billing';
|
|
$page = 'reports';
|
|
require_once 'templates/header.php';
|
|
?>
|
|
|
|
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
|
<h1 class="h2">Reports</h1>
|
|
</div>
|
|
|
|
<?php
|
|
require_once 'db/config.php';
|
|
|
|
$pdo = db();
|
|
|
|
// Fetch stats
|
|
$total_customers = $pdo->query('SELECT COUNT(*) FROM customers')->fetchColumn();
|
|
$active_customers = $pdo->query("SELECT COUNT(*) FROM customers WHERE status = 'Active'")->fetchColumn();
|
|
$total_plans = $pdo->query('SELECT COUNT(*) FROM plans')->fetchColumn();
|
|
$total_revenue = $pdo->query("SELECT SUM(amount) FROM invoices WHERE status = 'Paid'")->fetchColumn();
|
|
|
|
$invoice_status_stmt = $pdo->query("SELECT status, COUNT(*) as count FROM invoices GROUP BY status");
|
|
$invoice_statuses = $invoice_status_stmt->fetchAll(PDO::FETCH_KEY_PAIR);
|
|
|
|
$total_invoices = array_sum($invoice_statuses);
|
|
$paid_invoices = $invoice_statuses['Paid'] ?? 0;
|
|
$pending_invoices = $invoice_statuses['Pending'] ?? 0;
|
|
$overdue_invoices = $invoice_statuses['Overdue'] ?? 0;
|
|
|
|
?>
|
|
|
|
<div class="row">
|
|
<div class="col-md-3 mb-4">
|
|
<div class="card text-white bg-primary">
|
|
<div class="card-body">
|
|
<h5 class="card-title"><i class="bi bi-people-fill"></i> Total Customers</h5>
|
|
<p class="card-text fs-4"><?php echo $total_customers; ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3 mb-4">
|
|
<div class="card text-white bg-success">
|
|
<div class="card-body">
|
|
<h5 class="card-title"><i class="bi bi-person-check-fill"></i> Active Customers</h5>
|
|
<p class="card-text fs-4"><?php echo $active_customers; ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3 mb-4">
|
|
<div class="card text-white bg-info">
|
|
<div class="card-body">
|
|
<h5 class="card-title"><i class="bi bi-tags-fill"></i> Available Plans</h5>
|
|
<p class="card-text fs-4"><?php echo $total_plans; ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3 mb-4">
|
|
<div class="card text-white bg-dark">
|
|
<div class="card-body">
|
|
<h5 class="card-title"><i class="bi bi-cash-stack"></i> Total Revenue</h5>
|
|
<p class="card-text fs-4">$<?php echo number_format($total_revenue, 2); ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mt-4">
|
|
<div class="col-md-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<i class="bi bi-journal-text"></i> Invoice Status Distribution
|
|
</div>
|
|
<div class="card-body">
|
|
<canvas id="invoiceStatusChart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mt-4">
|
|
<div class="col-md-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<i class="bi bi-journal-text"></i> Generated Reports
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Report Name</th>
|
|
<th>Type</th>
|
|
<th>Date Generated</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
$stmt = $pdo->query('SELECT * FROM reports ORDER BY created_at DESC');
|
|
$reports = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
if (empty($reports)):
|
|
?>
|
|
<tr>
|
|
<td colspan="4" class="text-center py-5">
|
|
<i class="bi bi-journal-x" style="font-size: 3rem; color: #ccc;"></i>
|
|
<h2 class="mt-3">No Reports Found</h2>
|
|
<p class="text-muted">There are no generated reports to display yet.</p>
|
|
</td>
|
|
</tr>
|
|
<?php else: ?>
|
|
<?php foreach ($reports as $report): ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars($report['name']); ?></td>
|
|
<td><span class="badge bg-secondary"><?php echo htmlspecialchars($report['type']); ?></span></td>
|
|
<td><?php echo date('M d, Y H:i A', strtotime($report['created_at'])); ?></td>
|
|
<td>
|
|
<a href="view_report.php?id=<?php echo $report['id']; ?>" class="btn btn-sm btn-outline-primary"><i class="bi bi-eye"></i> View</a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
const ctx = document.getElementById('invoiceStatusChart').getContext('2d');
|
|
new Chart(ctx, {
|
|
type: 'doughnut',
|
|
data: {
|
|
labels: ['Paid', 'Pending', 'Overdue'],
|
|
datasets: [{
|
|
label: 'Invoice Status',
|
|
data: [<?php echo $paid_invoices; ?>, <?php echo $pending_invoices; ?>, <?php echo $overdue_invoices; ?>],
|
|
backgroundColor: [
|
|
'rgba(25, 135, 84, 0.7)',
|
|
'rgba(255, 193, 7, 0.7)',
|
|
'rgba(220, 53, 69, 0.7)'
|
|
],
|
|
borderColor: [
|
|
'rgba(25, 135, 84, 1)',
|
|
'rgba(255, 193, 7, 1)',
|
|
'rgba(220, 53, 69, 1)'
|
|
],
|
|
borderWidth: 1
|
|
}]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: {
|
|
position: 'top',
|
|
},
|
|
title: {
|
|
display: false,
|
|
text: 'Invoice Status Distribution'
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
|
|
<?php
|
|
require_once 'templates/footer.php';
|
|
?>
|