39728-vm/reports.php
2026-04-19 09:52:55 +00:00

303 lines
16 KiB
PHP

<?php
require_once __DIR__ . '/includes/app.php';
$user = require_roles(['owner', 'manager']);
$pageTitle = tr('التقارير', 'Reports');
$activeNav = 'reports';
$tab = $_GET['tab'] ?? 'summary';
$dbError = null;
if ($tab === 'sales') {
$dateFrom = $_GET['date_from'] ?? date('Y-m-01');
$dateTo = $_GET['date_to'] ?? date('Y-m-t');
$branchFilter = $_GET['branch'] ?? '';
$params = [];
$where = base_sales_query_filters($params, null, $branchFilter ?: null);
$where .= ' AND DATE(sale_date) >= :date_from AND DATE(sale_date) <= :date_to';
$params[':date_from'] = $dateFrom;
$params[':date_to'] = $dateTo;
$sql = 'SELECT * FROM sales_orders' . $where . ' ORDER BY sale_date DESC';
try {
$stmt = db()->prepare($sql);
foreach ($params as $k => $v) {
$stmt->bindValue($k, $v);
}
$stmt->execute();
$salesReport = $stmt->fetchAll();
} catch(Throwable $e) {
$dbError = $e->getMessage();
$salesReport = [];
}
} elseif ($tab === 'orders') {
$branchFilter = $_GET['branch'] ?? '';
$params = [];
$where = base_sales_query_filters($params, null, $branchFilter ?: null);
$where .= " AND status = 'order'";
$sql = 'SELECT * FROM sales_orders' . $where . ' ORDER BY sale_date ASC';
try {
$stmt = db()->prepare($sql);
foreach ($params as $k => $v) {
$stmt->bindValue($k, $v);
}
$stmt->execute();
$followUpOrders = $stmt->fetchAll();
} catch(Throwable $e) {
$dbError = $e->getMessage();
$followUpOrders = [];
}
} else {
$report = ['gross' => 0.0, 'branch_totals' => [], 'payment_totals' => [], 'product_totals' => [], 'sales_count' => 0];
try {
$report = report_metrics();
} catch (Throwable $e) {
$dbError = $e->getMessage();
}
}
require __DIR__ . '/includes/header.php';
?>
<div class="d-flex justify-content-between align-items-center mb-4 d-print-none">
<div>
<h1 class="h3 mb-0"><?= h($pageTitle) ?></h1>
</div>
</div>
<ul class="nav nav-tabs mb-4 d-print-none">
<li class="nav-item">
<a class="nav-link <?= $tab === 'summary' ? 'active' : '' ?>" href="reports.php?tab=summary"><?= h(tr('ملخص عام', 'General Summary')) ?></a>
</li>
<li class="nav-item">
<a class="nav-link <?= $tab === 'sales' ? 'active' : '' ?>" href="reports.php?tab=sales"><?= h(tr('تقرير المبيعات', 'Sales Report')) ?></a>
</li>
<li class="nav-item">
<a class="nav-link <?= $tab === 'orders' ? 'active' : '' ?>" href="reports.php?tab=orders"><?= h(tr('طلبات للمتابعة', 'Follow-up Orders')) ?></a>
</li>
</ul>
<?php if ($dbError): ?>
<div class="alert alert-danger d-print-none"><?= h($dbError) ?></div>
<?php endif; ?>
<?php if ($tab === 'sales'): ?>
<div class="card mb-4 d-print-none">
<div class="card-body">
<form method="GET" action="reports.php" class="row g-3 align-items-end">
<input type="hidden" name="tab" value="sales">
<div class="col-md-3">
<label class="form-label"><?= h(tr('من تاريخ', 'From Date')) ?></label>
<input type="date" name="date_from" class="form-control" value="<?= h($dateFrom) ?>">
</div>
<div class="col-md-3">
<label class="form-label"><?= h(tr('إلى تاريخ', 'To Date')) ?></label>
<input type="date" name="date_to" class="form-control" value="<?= h($dateTo) ?>">
</div>
<div class="col-md-4">
<label class="form-label"><?= h(tr('الفرع', 'Branch')) ?></label>
<select name="branch" class="form-select">
<option value=""><?= h(tr('جميع الفروع', 'All Branches')) ?></option>
<?php
$availableBranches = $user['role'] === 'owner' ? branches() : [$user['branch_code'] => branches()[$user['branch_code']]];
foreach ($availableBranches as $code => $b):
?>
<option value="<?= h($code) ?>" <?= $branchFilter === $code ? 'selected' : '' ?>><?= h(branch_label($code)) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-2">
<button type="submit" class="btn btn-primary w-100"><?= h(tr('بحث', 'Search')) ?></button>
</div>
</form>
</div>
</div>
<div class="d-none d-print-block mb-4 text-center">
<h2><?= h(tr('تقرير المبيعات', 'Sales Report')) ?></h2>
<p><?= h(tr('الفترة من', 'Period from')) ?> <?= h($dateFrom) ?> <?= h(tr('إلى', 'to')) ?> <?= h($dateTo) ?></p>
<?php if ($branchFilter): ?>
<p><?= h(tr('الفرع:', 'Branch:')) ?> <?= h(branch_label($branchFilter)) ?></p>
<?php endif; ?>
</div>
<div class="surface-card">
<div class="d-flex justify-content-between align-items-center mb-3 d-print-none">
<h3 class="h5 mb-0"><?= h(tr('نتائج التقرير', 'Report Results')) ?></h3>
<button class="btn btn-outline-secondary btn-sm" onclick="window.print()"><i class="bi bi-printer"></i> <?= h(tr('طباعة', 'Print')) ?></button>
</div>
<?php if(empty($salesReport)): ?>
<p class="text-muted"><?= h(tr('لا توجد مبيعات في هذه الفترة.', 'No sales found in this period.')) ?></p>
<?php else: ?>
<div class="table-responsive">
<table class="table table-bordered table-striped align-middle">
<thead>
<tr>
<th><?= h(tr('التاريخ', 'Date')) ?></th>
<th><?= h(tr('رقم الإيصال', 'Receipt No')) ?></th>
<th><?= h(tr('الكاشير', 'Cashier')) ?></th>
<th><?= h(tr('الفرع', 'Branch')) ?></th>
<th><?= h(tr('طريقة الدفع', 'Payment Method')) ?></th>
<th><?= h(tr('الحالة', 'Status')) ?></th>
<th class="text-end"><?= h(tr('الإجمالي', 'Total')) ?></th>
</tr>
</thead>
<tbody>
<?php
$totalSum = 0;
foreach($salesReport as $sale):
$totalSum += (float) $sale['total_amount'];
?>
<tr>
<td><?= h(date('Y-m-d H:i', strtotime((string)$sale['sale_date']))) ?></td>
<td><?= h((string)$sale['receipt_no']) ?></td>
<td><?= h((string)$sale['cashier_name']) ?></td>
<td><?= h(branch_label((string)$sale['branch_code'])) ?></td>
<td><?= h(ucfirst((string)$sale['payment_method'])) ?></td>
<td>
<?php if (($sale['status'] ?? 'completed') === 'order'): ?>
<span class="badge bg-warning text-dark"><i class="bi bi-clock"></i> <?= h(tr('طلب حجز', 'Order')) ?></span>
<?php else: ?>
<span class="badge bg-success"><i class="bi bi-check-circle"></i> <?= h(tr('مدفوع', 'Paid')) ?></span>
<?php endif; ?>
</td>
<td class="text-end fw-bold"><?= h(currency((float)$sale['total_amount'])) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot class="table-dark">
<tr>
<td colspan="6" class="text-end"><?= h(tr('الإجمالي الكلي', 'Grand Total')) ?></td>
<td class="text-end fw-bold fs-5"><?= h(currency($totalSum)) ?></td>
</tr>
</tfoot>
</table>
</div>
<?php endif; ?>
</div>
<?php elseif ($tab === 'orders'): ?>
<div class="card mb-4 d-print-none">
<div class="card-body">
<form method="GET" action="reports.php" class="row g-3 align-items-end">
<input type="hidden" name="tab" value="orders">
<div class="col-md-4">
<label class="form-label"><?= h(tr('الفرع', 'Branch')) ?></label>
<select name="branch" class="form-select" onchange="this.form.submit()">
<option value=""><?= h(tr('جميع الفروع', 'All Branches')) ?></option>
<?php
$availableBranches = $user['role'] === 'owner' ? branches() : [$user['branch_code'] => branches()[$user['branch_code']]];
foreach ($availableBranches as $code => $b):
?>
<option value="<?= h($code) ?>" <?= $branchFilter === $code ? 'selected' : '' ?>><?= h(branch_label($code)) ?></option>
<?php endforeach; ?>
</select>
</div>
</form>
</div>
</div>
<div class="d-none d-print-block mb-4 text-center">
<h2><?= h(tr('طلبات للمتابعة', 'Follow-up Orders')) ?></h2>
<p><?= h(date('Y-m-d H:i')) ?></p>
<?php if ($branchFilter): ?>
<p><?= h(tr('الفرع:', 'Branch:')) ?> <?= h(branch_label($branchFilter)) ?></p>
<?php endif; ?>
</div>
<div class="surface-card">
<div class="d-flex justify-content-between align-items-center mb-3 d-print-none">
<h3 class="h5 mb-0"><?= h(tr('طلبات حجز بانتظار الدفع', 'Reservation orders pending payment')) ?></h3>
<button class="btn btn-outline-secondary btn-sm" onclick="window.print()"><i class="bi bi-printer"></i> <?= h(tr('طباعة', 'Print')) ?></button>
</div>
<?php if(empty($followUpOrders)): ?>
<p class="text-muted"><?= h(tr('لا توجد طلبات للمتابعة.', 'No follow-up orders.')) ?></p>
<?php else: ?>
<div class="table-responsive">
<table class="table table-bordered table-hover align-middle">
<thead>
<tr>
<th><?= h(tr('التاريخ', 'Date')) ?></th>
<th><?= h(tr('رقم الإيصال', 'Receipt No')) ?></th>
<th><?= h(tr('العميل', 'Customer')) ?></th>
<th><?= h(tr('هاتف العميل', 'Customer Phone')) ?></th>
<th><?= h(tr('الفرع', 'Branch')) ?></th>
<th class="text-end"><?= h(tr('المبلغ المستحق', 'Due Amount')) ?></th>
<th class="d-print-none text-end"><?= h(tr('إجراءات', 'Actions')) ?></th>
</tr>
</thead>
<tbody>
<?php foreach($followUpOrders as $sale): ?>
<tr>
<td><?= h(date('Y-m-d H:i', strtotime((string)$sale['sale_date']))) ?></td>
<td><?= h((string)$sale['receipt_no']) ?></td>
<td><?= h((string)($sale['customer_name'] ?: '-')) ?></td>
<td><?= h((string)($sale['customer_phone'] ?: '-')) ?></td>
<td><?= h(branch_label((string)$sale['branch_code'])) ?></td>
<td class="text-end fw-bold text-danger"><?= h(currency((float)$sale['total_amount'])) ?></td>
<td class="d-print-none text-end">
<a class="btn btn-sm btn-light border" href="<?= h(url_for('sale.php', ['id' => $sale['id']])) ?>"><?= h(tr('عرض', 'View')) ?></a>
<button class="btn btn-sm btn-success" onclick="markPaidFromReports(<?= $sale['id'] ?>)"><i class="bi bi-check-lg"></i> <?= h(tr('دفع', 'Pay')) ?></button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<script>
function markPaidFromReports(id) {
if(confirm("<?= h(tr('هل أنت متأكد من تأكيد دفع هذا الطلب؟', 'Are you sure you want to confirm payment for this order?')) ?>")) {
window.location.href = 'sales.php?mark_paid=' + id + '&redirect=reports.php?tab=orders';
}
}
</script>
<?php endif; ?>
</div>
<?php else: ?>
<section class="row g-3 mb-4 d-print-none">
<div class="col-md-4"><article class="metric-card"><div class="eyebrow"><?= h(tr('إجمالي المبيعات', 'Gross sales')) ?></div><div class="metric-value"><?= h(currency((float) $report['gross'])) ?></div><div class="small text-muted"><?= h(tr('حسب نطاق صلاحية المستخدم الحالي', 'Scoped to the current viewer permissions')) ?></div></article></div>
<div class="col-md-4"><article class="metric-card"><div class="eyebrow"><?= h(tr('عدد الفواتير', 'Invoices')) ?></div><div class="metric-value"><?= h((string) $report['sales_count']) ?></div><div class="small text-muted"><?= h(tr('إجمالي الفواتير المسجلة', 'Total logged invoices')) ?></div></article></div>
<div class="col-md-4"><article class="metric-card"><div class="eyebrow"><?= h(tr('أفضل صنف', 'Top product')) ?></div><div class="metric-value small-metric"><?= h($report['product_totals'] ? product_label((string) array_key_first($report['product_totals'])) : tr('لا يوجد', 'None yet')) ?></div><div class="small text-muted"><?= h(tr('الأكثر مبيعاً حتى الآن', 'Most sold item so far')) ?></div></article></div>
</section>
<section class="row g-4 d-print-none">
<div class="col-lg-6">
<div class="surface-card h-100">
<h3 class="h5 mb-3"><?= h(tr('المبيعات حسب الفرع', 'Sales by branch')) ?></h3>
<?php if (!$report['branch_totals']): ?>
<div class="empty-state compact"><h4><?= h(tr('لا توجد بيانات', 'No data')) ?></h4><p><?= h(tr('أضف عملية بيع أولاً لبدء التقارير.', 'Add a first sale to activate reports.')) ?></p></div>
<?php else: ?>
<div class="d-grid gap-2">
<?php foreach ($report['branch_totals'] as $branchCode => $amount): ?>
<div class="report-row"><span><?= h(branch_label((string) $branchCode)) ?></span><strong><?= h(currency((float) $amount)) ?></strong></div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
<div class="col-lg-6">
<div class="surface-card h-100">
<h3 class="h5 mb-3"><?= h(tr('المبيعات حسب الدفع', 'Sales by payment')) ?></h3>
<?php if (!$report['payment_totals']): ?>
<div class="empty-state compact"><h4><?= h(tr('بانتظار البيانات', 'Waiting for data')) ?></h4><p><?= h(tr('عند تسجيل عمليات بيع ستظهر هنا طرق الدفع.', 'Payment mix will appear here once sales are logged.')) ?></p></div>
<?php else: ?>
<div class="d-grid gap-2">
<?php foreach ($report['payment_totals'] as $payment => $amount): ?>
<div class="report-row"><span><?= h(ucfirst((string) $payment)) ?></span><strong><?= h(currency((float) $amount)) ?></strong></div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
</section>
<?php endif; ?>
<?php require __DIR__ . '/includes/footer.php'; ?>