fixing report
This commit is contained in:
parent
c24fdab770
commit
9f56d9b0a2
@ -1,431 +1,254 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
require_once __DIR__ . '/../includes/functions.php';
|
||||
require_once __DIR__ . '/../includes/lang.php';
|
||||
|
||||
// Check permission
|
||||
if (function_exists('require_permission')) {
|
||||
require_permission('reports_view');
|
||||
}
|
||||
require_login();
|
||||
require_permission('reports_view');
|
||||
|
||||
$title = t('reports_analytics');
|
||||
include __DIR__ . '/includes/header.php';
|
||||
|
||||
$pdo = db();
|
||||
$date_from = $_GET['date_from'] ?? date('Y-m-d', strtotime('-30 days'));
|
||||
$date_to = $_GET['date_to'] ?? date('Y-m-d');
|
||||
$outlet_id = $_GET['outlet_id'] ?? 'all';
|
||||
|
||||
// Date and Outlet Filter
|
||||
$startDate = $_GET['start_date'] ?? date('Y-m-d', strtotime('-7 days'));
|
||||
$endDate = $_GET['end_date'] ?? date('Y-m-d');
|
||||
$outletId = $_GET['outlet_id'] ?? '';
|
||||
|
||||
// Fetch Outlets for filter
|
||||
$outletsStmt = $pdo->query("SELECT id, name, name_ar FROM outlets WHERE is_deleted = 0 ORDER BY name ASC");
|
||||
$allOutlets = $outletsStmt->fetchAll();
|
||||
|
||||
// Base query additions
|
||||
$outletCondition = "";
|
||||
$expenseOutletCondition = "";
|
||||
$queryParams = [$startDate, $endDate];
|
||||
if (!empty($outletId)) {
|
||||
$outletCondition = " AND o.outlet_id = ? ";
|
||||
$expenseOutletCondition = " AND e.outlet_id = ? ";
|
||||
$queryParams[] = $outletId;
|
||||
$params = [':from' => $date_from . ' 00:00:00', ':to' => $date_to . ' 23:59:59'];
|
||||
$outlet_query = "";
|
||||
if ($outlet_id !== 'all') {
|
||||
$outlet_query = " AND o.outlet_id = :outlet_id";
|
||||
$params[':outlet_id'] = $outlet_id;
|
||||
}
|
||||
|
||||
// 0. Daily Sales
|
||||
$dailyStmt = $pdo->prepare("
|
||||
SELECT
|
||||
DATE(o.created_at) as sales_date,
|
||||
COUNT(o.id) as order_count,
|
||||
SUM(o.total_amount) as total_sales
|
||||
FROM orders o
|
||||
WHERE DATE(o.created_at) BETWEEN ? AND ?
|
||||
AND o.status != 'cancelled'
|
||||
$outletCondition
|
||||
GROUP BY DATE(o.created_at)
|
||||
ORDER BY DATE(o.created_at) DESC
|
||||
");
|
||||
$dailyStmt->execute($queryParams);
|
||||
$dailySales = $dailyStmt->fetchAll();
|
||||
try {
|
||||
// Outlets for filter
|
||||
$outlets = $pdo->query("SELECT id, name FROM outlets WHERE is_deleted = 0")->fetchAll();
|
||||
|
||||
// 1. Sales by Staff
|
||||
$staffStmt = $pdo->prepare("
|
||||
SELECT
|
||||
u.full_name as staff_name,
|
||||
u.full_name_ar as staff_name_ar,
|
||||
u.username,
|
||||
COUNT(o.id) as order_count,
|
||||
SUM(o.total_amount) as total_sales
|
||||
// Daily Sales
|
||||
$daily_sales = $pdo->prepare("SELECT DATE(o.created_at) as date, SUM(o.total_amount) as total
|
||||
FROM orders o
|
||||
WHERE o.created_at BETWEEN :from AND :to $outlet_query
|
||||
AND o.status = 'completed'
|
||||
GROUP BY DATE(o.created_at)
|
||||
ORDER BY date ASC");
|
||||
$daily_sales->execute($params);
|
||||
$daily_sales_data = $daily_sales->fetchAll();
|
||||
|
||||
// Staff Sales
|
||||
$staff_sales = $pdo->prepare("SELECT u.username, SUM(o.total_amount) as total
|
||||
FROM orders o
|
||||
JOIN users u ON o.user_id = u.id
|
||||
WHERE DATE(o.created_at) BETWEEN ? AND ?
|
||||
AND o.status != 'cancelled'
|
||||
$outletCondition
|
||||
GROUP BY o.user_id
|
||||
ORDER BY total_sales DESC
|
||||
");
|
||||
$staffStmt->execute($queryParams);
|
||||
$staffSales = $staffStmt->fetchAll();
|
||||
WHERE o.created_at BETWEEN :from AND :to $outlet_query
|
||||
AND o.status = 'completed'
|
||||
GROUP BY u.id
|
||||
ORDER BY total DESC");
|
||||
$staff_sales->execute($params);
|
||||
$staff_sales_data = $staff_sales->fetchAll();
|
||||
|
||||
// 2. Sales by Outlet
|
||||
$outletStmt = $pdo->prepare("
|
||||
SELECT
|
||||
ot.name as outlet_name,
|
||||
ot.name_ar as outlet_name_ar,
|
||||
COUNT(o.id) as order_count,
|
||||
SUM(o.total_amount) as total_sales
|
||||
// Outlet Sales
|
||||
$outlet_sales = $pdo->prepare("SELECT ou.name, SUM(o.total_amount) as total
|
||||
FROM orders o
|
||||
JOIN outlets ot ON o.outlet_id = ot.id
|
||||
WHERE DATE(o.created_at) BETWEEN ? AND ?
|
||||
AND o.status != 'cancelled'
|
||||
$outletCondition
|
||||
GROUP BY o.outlet_id
|
||||
ORDER BY total_sales DESC
|
||||
");
|
||||
$outletStmt->execute($queryParams);
|
||||
$outletSales = $outletStmt->fetchAll();
|
||||
JOIN outlets ou ON o.outlet_id = ou.id
|
||||
WHERE o.created_at BETWEEN :from AND :to $outlet_query
|
||||
AND o.status = 'completed'
|
||||
GROUP BY ou.id
|
||||
ORDER BY total DESC");
|
||||
$outlet_sales->execute($params);
|
||||
$outlet_sales_data = $outlet_sales->fetchAll();
|
||||
|
||||
// 3. Sales by Category
|
||||
$categoryStmt = $pdo->prepare("
|
||||
SELECT
|
||||
c.name as category_name,
|
||||
c.name_ar as category_name_ar,
|
||||
SUM(oi.quantity) as items_sold,
|
||||
SUM(oi.quantity * oi.unit_price) as total_sales
|
||||
// Category Sales
|
||||
$cat_sales = $pdo->prepare("SELECT c.name, SUM(oi.quantity * oi.unit_price) as total
|
||||
FROM order_items oi
|
||||
JOIN orders o ON oi.order_id = o.id
|
||||
JOIN products p ON oi.product_id = p.id
|
||||
JOIN categories c ON p.category_id = c.id
|
||||
WHERE DATE(o.created_at) BETWEEN ? AND ?
|
||||
AND o.status != 'cancelled'
|
||||
$outletCondition
|
||||
WHERE o.created_at BETWEEN :from AND :to $outlet_query
|
||||
AND o.status = 'completed'
|
||||
GROUP BY c.id
|
||||
ORDER BY total_sales DESC
|
||||
");
|
||||
$categoryStmt->execute($queryParams);
|
||||
$categorySales = $categoryStmt->fetchAll();
|
||||
ORDER BY total DESC");
|
||||
$cat_sales->execute($params);
|
||||
$cat_sales_data = $cat_sales->fetchAll();
|
||||
|
||||
// 4. Expenses by Category
|
||||
$expenseCatStmt = $pdo->prepare("
|
||||
SELECT
|
||||
ec.name as category_name,
|
||||
ec.name_ar as category_name_ar,
|
||||
SUM(e.amount) as total_amount
|
||||
// Expenses
|
||||
$expenses = $pdo->prepare("SELECT ec.name, SUM(e.amount) as total
|
||||
FROM expenses e
|
||||
JOIN expense_categories ec ON e.category_id = ec.id
|
||||
WHERE e.expense_date BETWEEN ? AND ?
|
||||
$expenseOutletCondition
|
||||
GROUP BY ec.id
|
||||
ORDER BY total_amount DESC
|
||||
");
|
||||
$expenseCatStmt->execute($queryParams);
|
||||
$expenseSales = $expenseCatStmt->fetchAll();
|
||||
WHERE e.expense_date BETWEEN :from AND :to
|
||||
AND (:outlet_id_all = 'all' OR e.outlet_id = :outlet_id_exp)
|
||||
GROUP BY ec.id");
|
||||
$exp_params = [':from' => $date_from, ':to' => $date_to, ':outlet_id_all' => $outlet_id, ':outlet_id_exp' => $outlet_id];
|
||||
$expenses->execute($exp_params);
|
||||
$expense_data = $expenses->fetchAll();
|
||||
|
||||
// Total Summary
|
||||
$totalStmt = $pdo->prepare("
|
||||
SELECT
|
||||
COUNT(o.id) as total_orders,
|
||||
SUM(o.total_amount) as total_revenue
|
||||
FROM orders o
|
||||
WHERE DATE(o.created_at) BETWEEN ? AND ?
|
||||
AND o.status != 'cancelled'
|
||||
$outletCondition
|
||||
");
|
||||
$totalStmt->execute($queryParams);
|
||||
$summary = $totalStmt->fetch();
|
||||
// Summary
|
||||
$total_sales = array_sum(array_column($daily_sales_data, 'total'));
|
||||
$total_expenses = array_sum(array_column($expense_data, 'total'));
|
||||
$net_profit = $total_sales - $total_expenses;
|
||||
|
||||
$totalExpStmt = $pdo->prepare("
|
||||
SELECT SUM(e.amount) as total_expenses
|
||||
FROM expenses e
|
||||
WHERE e.expense_date BETWEEN ? AND ?
|
||||
$expenseOutletCondition
|
||||
");
|
||||
$totalExpStmt->execute($queryParams);
|
||||
$totalExpenses = $totalExpStmt->fetchColumn() ?? 0;
|
||||
|
||||
$netProfit = ($summary['total_revenue'] ?? 0) - $totalExpenses;
|
||||
} catch (PDOException $e) {
|
||||
echo '<div class="alert alert-danger">Database error: ' . htmlspecialchars($e->getMessage()) . '</div>';
|
||||
include __DIR__ . '/includes/footer.php';
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="container-fluid p-0">
|
||||
<div class="container-fluid py-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap gap-3">
|
||||
<div>
|
||||
<h2 class="fw-bold mb-1">Business Reports</h2>
|
||||
<p class="text-muted mb-0">Overview of your business performance</p>
|
||||
</div>
|
||||
<form class="row g-2 align-items-center" method="GET">
|
||||
<h1 class="h3 mb-0 text-gray-800"><?php echo t('daily_reports'); ?></h1>
|
||||
<form class="row g-2 align-items-center">
|
||||
<div class="col-auto">
|
||||
<select name="outlet_id" class="form-select" style="min-width: 180px;">
|
||||
<option value="">All Outlets</option>
|
||||
<?php foreach ($allOutlets as $o): ?>
|
||||
<option value="<?= $o['id'] ?>" <?= $outletId == $o['id'] ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($o['name']) ?> <?= $o['name_ar'] ? '('.$o['name_ar'].')' : '' ?>
|
||||
<input type="date" name="date_from" class="form-control form-control-sm" value="<?php echo $date_from; ?>">
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<input type="date" name="date_to" class="form-control form-control-sm" value="<?php echo $date_to; ?>">
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select name="outlet_id" class="form-select form-select-sm">
|
||||
<option value="all"><?php echo t('all'); ?></option>
|
||||
<?php foreach ($outlets as $o): ?>
|
||||
<option value="<?php echo $o['id']; ?>" <?php echo $outlet_id == $o['id'] ? 'selected' : ''; ?>>
|
||||
<?php echo $o['name']; ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-white border-end-0 text-muted"><i class="bi bi-calendar"></i></span>
|
||||
<input type="date" name="start_date" class="form-control border-start-0" value="<?= htmlspecialchars($startDate) ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text bg-white border-end-0 text-muted"><i class="bi bi-calendar"></i></span>
|
||||
<input type="date" name="end_date" class="form-control border-start-0" value="<?= htmlspecialchars($endDate) ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<div class="d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary px-4 text-nowrap">Filter</button>
|
||||
<a href="reports.php" class="btn btn-light text-nowrap">Reset</a>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-sm"><?php echo t('filter'); ?></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Summary Cards -->
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="card border-0 shadow-sm stat-card p-3">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="icon-box bg-primary-subtle text-primary">
|
||||
<i class="bi bi-receipt"></i>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card border-0 shadow-sm h-100 py-2" style="border-left: 4px solid #4e73df !important;">
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col mr-2">
|
||||
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1"><?php echo t('total'); ?> <?php echo t('orders'); ?></div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo number_format($total_sales, 2); ?></div>
|
||||
</div>
|
||||
<div>
|
||||
<small class="text-muted d-block">Total Orders</small>
|
||||
<h4 class="fw-bold mb-0"><?= number_format((float)($summary['total_orders'] ?? 0)) ?></h4>
|
||||
<div class="col-auto">
|
||||
<i class="bi bi-cart-check fs-2 text-gray-300"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="card border-0 shadow-sm stat-card p-3">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="icon-box bg-success-subtle text-success">
|
||||
<i class="bi bi-currency-dollar"></i>
|
||||
</div>
|
||||
<div>
|
||||
<small class="text-muted d-block">Total Revenue</small>
|
||||
<h4 class="fw-bold mb-0"><?= format_currency($summary['total_revenue'] ?? 0) ?></h4>
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card border-0 shadow-sm h-100 py-2" style="border-left: 4px solid #e74a3b !important;">
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col mr-2">
|
||||
<div class="text-xs font-weight-bold text-danger text-uppercase mb-1"><?php echo t('expenses'); ?></div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo number_format($total_expenses, 2); ?></div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="bi bi-wallet2 fs-2 text-gray-300"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="card border-0 shadow-sm stat-card p-3">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="icon-box bg-danger-subtle text-danger">
|
||||
<i class="bi bi-cash-stack"></i>
|
||||
</div>
|
||||
<div>
|
||||
<small class="text-muted d-block">Total Expenses</small>
|
||||
<h4 class="fw-bold mb-0"><?= format_currency($totalExpenses) ?></h4>
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card border-0 shadow-sm h-100 py-2" style="border-left: 4px solid #1cc88a !important;">
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col mr-2">
|
||||
<div class="text-xs font-weight-bold text-success text-uppercase mb-1"><?php echo t('total'); ?></div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800"><?php echo number_format($net_profit, 2); ?></div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="bi bi-cash-stack fs-2 text-gray-300"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-3">
|
||||
<div class="card border-0 shadow-sm stat-card p-3">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="icon-box bg-info-subtle text-info">
|
||||
<i class="bi bi-piggy-bank"></i>
|
||||
</div>
|
||||
<div>
|
||||
<small class="text-muted d-block">Net Profit</small>
|
||||
<h4 class="fw-bold mb-0 <?= $netProfit < 0 ? 'text-danger' : 'text-info' ?>"><?= format_currency($netProfit) ?></h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Daily Breakdown -->
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-header bg-white py-3 border-0 d-flex justify-content-between align-items-center">
|
||||
<h5 class="fw-bold mb-0"><i class="bi bi-bar-chart me-2 text-primary"></i> Daily Sales Breakdown</h5>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-sm btn-light border dropdown-toggle" type="button" data-bs-toggle="dropdown">Export</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#" onclick="window.print()"><i class="bi bi-printer me-2"></i> Print</a></li>
|
||||
</ul>
|
||||
<div class="row">
|
||||
<div class="col-xl-8 col-lg-7">
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-header py-3 bg-white border-bottom-0">
|
||||
<h6 class="m-0 font-weight-bold text-primary"><?php echo t('daily_reports'); ?></h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-area" style="height: 320px;">
|
||||
<canvas id="dailySalesChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4 col-lg-5">
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-header py-3 bg-white border-bottom-0">
|
||||
<h6 class="m-0 font-weight-bold text-primary"><?php echo t('categories'); ?></h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-pie pt-4 pb-2" style="height: 320px;">
|
||||
<canvas id="categorySalesChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="bg-light text-muted small text-uppercase">
|
||||
<tr>
|
||||
<th class="ps-4">Date</th>
|
||||
<th class="text-center">Orders</th>
|
||||
<th class="text-end pe-4">Revenue</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($dailySales)): ?>
|
||||
<tr><td colspan="3" class="text-center py-5 text-muted">No sales found for the selected period</td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($dailySales as $day): ?>
|
||||
<tr>
|
||||
<td class="ps-4 fw-bold text-dark"><?= date('M d, Y (D)', strtotime($day['sales_date'])) ?></td>
|
||||
<td class="text-center"><?= $day['order_count'] ?></td>
|
||||
<td class="text-end pe-4 fw-bold text-primary"><?= format_currency($day['total_sales']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
<!-- Sales by Category -->
|
||||
<div class="col-md-6">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card-header bg-white py-3 border-0">
|
||||
<h5 class="fw-bold mb-0"><i class="bi bi-tags me-2 text-warning"></i> Sales by Category</h5>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 mb-4">
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-header py-3 bg-white border-bottom-0">
|
||||
<h6 class="m-0 font-weight-bold text-primary"><?php echo t('users'); ?></h6>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="bg-light">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th class="ps-3">Category</th>
|
||||
<th class="text-center">Items Sold</th>
|
||||
<th class="text-end pe-3">Total Revenue</th>
|
||||
<th><?php echo t('name'); ?></th>
|
||||
<th class="text-end"><?php echo t('total'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($categorySales)): ?>
|
||||
<tr><td colspan="3" class="text-center py-4 text-muted">No data found for this period</td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($categorySales as $cat): ?>
|
||||
<tr>
|
||||
<td class="ps-3">
|
||||
<div class="fw-bold"><?= htmlspecialchars($cat['category_name']) ?></div>
|
||||
<?php if ($cat['category_name_ar']): ?>
|
||||
<small class="text-muted"><?= htmlspecialchars($cat['category_name_ar']) ?></small>
|
||||
<?php if (empty($staff_sales_data)): ?>
|
||||
<tr><td colspan="2" class="text-center text-muted"><?php echo t('none'); ?></td></tr>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center"><?= $cat['items_sold'] ?></td>
|
||||
<td class="text-end pe-3 fw-bold text-dark"><?= format_currency($cat['total_sales']) ?></td>
|
||||
<?php foreach ($staff_sales_data as $s): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($s['username']); ?></td>
|
||||
<td class="text-end"><?php echo number_format($s['total'], 2); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Expenses by Category -->
|
||||
<div class="col-md-6">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card-header bg-white py-3 border-0">
|
||||
<h5 class="fw-bold mb-0"><i class="bi bi-cash-stack me-2 text-danger"></i> Expenses by Category</h5>
|
||||
<div class="col-lg-6 mb-4">
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-header py-3 bg-white border-bottom-0">
|
||||
<h6 class="m-0 font-weight-bold text-primary"><?php echo t('outlets'); ?></h6>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="bg-light">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th class="ps-3">Category</th>
|
||||
<th class="text-end pe-3">Total Amount</th>
|
||||
<th><?php echo t('outlet'); ?></th>
|
||||
<th class="text-end"><?php echo t('total'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($expenseSales)): ?>
|
||||
<tr><td colspan="2" class="text-center py-4 text-muted">No data found for this period</td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($expenseSales as $exp): ?>
|
||||
<tr>
|
||||
<td class="ps-3">
|
||||
<div class="fw-bold"><?= htmlspecialchars($exp['category_name']) ?></div>
|
||||
<?php if ($exp['category_name_ar']): ?>
|
||||
<small class="text-muted"><?= htmlspecialchars($exp['category_name_ar']) ?></small>
|
||||
<?php if (empty($outlet_sales_data)): ?>
|
||||
<tr><td colspan="2" class="text-center text-muted"><?php echo t('none'); ?></td></tr>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-end pe-3 fw-bold text-danger"><?= format_currency($exp['total_amount']) ?></td>
|
||||
<?php foreach ($outlet_sales_data as $o): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($o['name']); ?></td>
|
||||
<td class="text-end"><?php echo number_format($o['total'], 2); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sales by Staff -->
|
||||
<div class="col-md-6">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card-header bg-white py-3 border-0">
|
||||
<h5 class="fw-bold mb-0"><i class="bi bi-people me-2 text-primary"></i> Sales Summary by Staff</h5>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="ps-3">Staff Name</th>
|
||||
<th class="text-center">Orders</th>
|
||||
<th class="text-end pe-3">Total Sales</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($staffSales)): ?>
|
||||
<tr><td colspan="3" class="text-center py-4 text-muted">No data found for this period</td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($staffSales as $staff): ?>
|
||||
<tr>
|
||||
<td class="ps-3">
|
||||
<div class="fw-bold"><?= htmlspecialchars($staff['staff_name'] ?: $staff['username']) ?></div>
|
||||
<?php if ($staff['staff_name_ar']): ?>
|
||||
<small class="text-muted"><?= htmlspecialchars($staff['staff_name_ar']) ?></small>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center"><?= $staff['order_count'] ?></td>
|
||||
<td class="text-end pe-3 fw-bold text-primary"><?= format_currency($staff['total_sales']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sales by Outlet -->
|
||||
<div class="col-md-6">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card-header bg-white py-3 border-0">
|
||||
<h5 class="fw-bold mb-0"><i class="bi bi-shop me-2 text-success"></i> Sales by Outlet</h5>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th class="ps-3">Outlet</th>
|
||||
<th class="text-center">Orders</th>
|
||||
<th class="text-end pe-4">Total Sales</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($outletSales)): ?>
|
||||
<tr><td colspan="3" class="text-center py-4 text-muted">No data found for this period</td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($outletSales as $outlet): ?>
|
||||
<tr>
|
||||
<td class="ps-3">
|
||||
<div class="fw-bold"><?= htmlspecialchars($outlet['outlet_name']) ?></div>
|
||||
<?php if ($outlet['outlet_name_ar']): ?>
|
||||
<small class="text-muted"><?= htmlspecialchars($outlet['outlet_name_ar']) ?></small>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-center"><?= $outlet['order_count'] ?></td>
|
||||
<td class="text-end pe-4 fw-bold text-success"><?= format_currency($outlet['total_sales']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -435,4 +258,53 @@ $netProfit = ($summary['total_revenue'] ?? 0) - $totalExpenses;
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script>
|
||||
const dailyCtx = document.getElementById('dailySalesChart').getContext('2d');
|
||||
new Chart(dailyCtx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo json_encode(array_column($daily_sales_data, 'date')); ?>,
|
||||
datasets: [{
|
||||
label: '<?php echo t('total'); ?>',
|
||||
data: <?php echo json_encode(array_column($daily_sales_data, 'total')); ?>,
|
||||
borderColor: '#4e73df',
|
||||
backgroundColor: 'rgba(78, 115, 223, 0.05)',
|
||||
fill: true,
|
||||
tension: 0.3
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: { display: false }
|
||||
},
|
||||
scales: {
|
||||
y: { beginAtZero: true }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const catCtx = document.getElementById('categorySalesChart').getContext('2d');
|
||||
new Chart(catCtx, {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: <?php echo json_encode(array_column($cat_sales_data, 'name')); ?>,
|
||||
datasets: [{
|
||||
data: <?php echo json_encode(array_column($cat_sales_data, 'total')); ?>,
|
||||
backgroundColor: ['#4e73df', '#1cc88a', '#36b9cc', '#f6c23e', '#e74a3b'],
|
||||
hoverBackgroundColor: ['#2e59d9', '#17a673', '#2c9faf', '#dda20a', '#be2617'],
|
||||
hoverBorderColor: "rgba(234, 236, 244, 1)",
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: { position: 'bottom' }
|
||||
},
|
||||
cutout: '70%'
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php include __DIR__ . '/includes/footer.php'; ?>
|
||||
Loading…
x
Reference in New Issue
Block a user