update sale list adding filter

This commit is contained in:
Flatlogic Bot 2026-04-26 02:37:30 +00:00
parent bf43c58e3a
commit 64c01fd51a

162
sales.php
View File

@ -4,8 +4,28 @@ $user = require_permission('sales', 'show');
$mode = isset($_GET['mode']) && in_array($_GET['mode'], ['pos', 'normal'], true) ? $_GET['mode'] : null;
$branch = isset($_GET['branch']) && array_key_exists($_GET['branch'], branches()) ? $_GET['branch'] : null;
$search = $_GET['q'] ?? '';
$statusFilter = $_GET['status'] ?? '';
$search = trim((string) ($_GET['q'] ?? ''));
$statusFilter = trim((string) ($_GET['status'] ?? ''));
$paymentStatus = trim((string) ($_GET['payment_status'] ?? ''));
$deliveryOptions = eid_delivery_status_options();
$deliveryStatus = trim((string) ($_GET['delivery_status'] ?? ''));
$dateFrom = trim((string) ($_GET['date_from'] ?? ''));
$dateTo = trim((string) ($_GET['date_to'] ?? ''));
$legacyPaymentStatuses = ['paid', 'partial', 'unpaid'];
if ($paymentStatus === '' && in_array($statusFilter, $legacyPaymentStatuses, true)) {
$paymentStatus = $statusFilter;
$statusFilter = '';
}
if (!in_array($statusFilter, ['', 'order', 'completed'], true)) {
$statusFilter = '';
}
if (!in_array($paymentStatus, array_merge([''], $legacyPaymentStatuses), true)) {
$paymentStatus = '';
}
if ($deliveryStatus !== '' && !array_key_exists($deliveryStatus, $deliveryOptions)) {
$deliveryStatus = '';
}
$allowedBranches = $user && $user['role'] !== 'owner' ? get_user_branches($user) : array_keys(branches());
$activeNav = $statusFilter === 'order' ? 'sales_orders' : 'sales';
$pageTitle = $statusFilter === 'order' ? tr('الطلبات', 'Orders') : tr('المبيعات', 'Sales Ledger');
@ -60,16 +80,28 @@ try {
}
}
if ($search) {
if ($search !== '') {
$where .= ' AND (receipt_no LIKE :search OR cashier_name LIKE :search OR customer_name LIKE :search)';
$params[':search'] = "%$search%";
}
if (in_array($statusFilter, ['paid', 'partial', 'unpaid'], true)) {
if ($paymentStatus !== '') {
$where .= ' AND payment_status = :payment_status ';
$params[':payment_status'] = $statusFilter;
$where .= " AND COALESCE(status, 'completed') <> 'order' ";
} elseif ($statusFilter === 'order') {
$params[':payment_status'] = $paymentStatus;
}
if ($deliveryStatus !== '') {
$where .= ' AND delivery_status = :delivery_status ';
$params[':delivery_status'] = $deliveryStatus;
}
if ($dateFrom !== '') {
$where .= ' AND DATE(sale_date) >= :date_from ';
$params[':date_from'] = $dateFrom;
}
if ($dateTo !== '') {
$where .= ' AND DATE(sale_date) <= :date_to ';
$params[':date_to'] = $dateTo;
}
if ($statusFilter === 'order') {
$where .= " AND status = 'order' ";
} elseif ($statusFilter === 'completed') {
$where .= " AND COALESCE(status, 'completed') = 'completed' ";
@ -102,6 +134,20 @@ try {
$dbError = $e->getMessage();
}
$queryState = static function (array $extra = []) use ($search, $branch, $mode, $statusFilter, $paymentStatus, $deliveryStatus, $dateFrom, $dateTo): array {
return array_filter(array_merge([
'q' => $search,
'branch' => $branch,
'mode' => $mode,
'status' => $statusFilter,
'payment_status' => $paymentStatus,
'delivery_status' => $deliveryStatus,
'date_from' => $dateFrom,
'date_to' => $dateTo,
], $extra), static fn ($value) => $value !== null && $value !== '');
};
$hasAdvancedFilters = $mode !== null || $paymentStatus !== '' || $branch !== null || $deliveryStatus !== '' || $dateFrom !== '' || $dateTo !== '' || $statusFilter !== '';
require __DIR__ . '/includes/header.php';
?>
<section class="mb-4">
@ -111,27 +157,87 @@ require __DIR__ . '/includes/header.php';
<div class="small text-muted"><?= h($statusFilter === 'order' ? tr('هذه القائمة تعرض طلبات البيع العادي المحفوظة بحالة طلب.', 'This list shows normal sales saved with order status.') : tr('ابحث بصرياً في أحدث المبيعات مع صلاحيات حسب الدور والفرع.', 'Scan the latest sales with role and branch scoping.')) ?></div>
</div>
<div class="d-flex gap-2 flex-wrap">
<a class="btn btn-sm <?= $mode === null ? 'btn-dark' : 'btn-outline-secondary' ?>" href="<?= h(url_for('sales.php', ['q' => $search, 'status' => $statusFilter])) ?>"><?= h(tr('الكل', 'All')) ?></a>
<a class="btn btn-sm <?= $mode === 'pos' ? 'btn-dark' : 'btn-outline-secondary' ?>" href="<?= h(url_for('sales.php', ['mode' => 'pos', 'q' => $search, 'status' => $statusFilter])) ?>">POS</a>
<a class="btn btn-sm <?= $mode === 'normal' ? 'btn-dark' : 'btn-outline-secondary' ?>" href="<?= h(url_for('sales.php', ['mode' => 'normal', 'q' => $search, 'status' => $statusFilter])) ?>"><?= h(tr('فاتورة', 'Invoice')) ?></a>
<a class="btn btn-sm <?= $mode === null ? 'btn-dark' : 'btn-outline-secondary' ?>" href="<?= h(url_for('sales.php', $queryState(['mode' => null, 'p' => null]))) ?>"><?= h(tr('الكل', 'All')) ?></a>
<a class="btn btn-sm <?= $mode === 'pos' ? 'btn-dark' : 'btn-outline-secondary' ?>" href="<?= h(url_for('sales.php', $queryState(['mode' => 'pos', 'p' => null]))) ?>">POS</a>
<a class="btn btn-sm <?= $mode === 'normal' ? 'btn-dark' : 'btn-outline-secondary' ?>" href="<?= h(url_for('sales.php', $queryState(['mode' => 'normal', 'p' => null]))) ?>"><?= h(tr('فاتورة', 'Invoice')) ?></a>
</div>
</div>
<form class="d-flex mb-3" method="GET" action="sales.php">
<?php if($mode): ?>
<input type="hidden" name="mode" value="<?= h($mode) ?>">
<?php endif; ?>
<div class="input-group" style="max-width: 600px;">
<select name="status" class="form-select" style="max-width: 150px;" onchange="this.form.submit()">
<option value=""><?= h(tr('كل الحالات', 'All Statuses')) ?></option>
<option value="paid" <?= $statusFilter === 'paid' ? 'selected' : '' ?>><?= h(tr('مدفوعة بالكامل', 'Paid')) ?></option>
<option value="partial" <?= $statusFilter === 'partial' ? 'selected' : '' ?>><?= h(tr('مدفوعة جزئياً', 'Partially Paid')) ?></option>
<option value="unpaid" <?= $statusFilter === 'unpaid' ? 'selected' : '' ?>><?= h(tr('غير مدفوعة', 'Unpaid')) ?></option>
<option value="order" <?= $statusFilter === 'order' ? 'selected' : '' ?>><?= h(tr('طلب حجز', 'Order')) ?></option>
<option value="completed" <?= $statusFilter === 'completed' ? 'selected' : '' ?>><?= h(tr('كل الفواتير المكتملة', 'Completed Invoices')) ?></option>
</select>
<input type="text" name="q" class="form-control" placeholder="<?= h(tr('بحث بالإيصال، الكاشير، العميل أو الهاتف...', 'Search receipt, cashier, customer or phone...')) ?>" value="<?= h($search) ?>">
<button class="btn btn-outline-secondary" type="submit"><i class="bi bi-search"></i></button>
<form class="mb-4" method="GET" action="sales.php">
<div class="d-flex justify-content-end align-items-center mb-3">
<details class="eid-advanced-toggle" <?= $hasAdvancedFilters ? 'open' : '' ?>>
<summary class="btn btn-sm btn-outline-secondary">
<i class="bi bi-sliders me-1"></i><?= h(tr('فلاتر إضافية', 'More filters')) ?>
</summary>
<div class="eid-advanced-panel">
<div class="row g-2">
<div class="col-12 col-md-4">
<label class="form-label mb-1" for="sales-mode"><?= h(tr('القناة', 'Channel')) ?></label>
<select id="sales-mode" class="form-select form-select-sm" name="mode">
<option value=""><?= h(tr('الكل', 'All')) ?></option>
<option value="normal" <?= $mode === 'normal' ? 'selected' : '' ?>><?= h(tr('فاتورة', 'Invoice')) ?></option>
<option value="pos" <?= $mode === 'pos' ? 'selected' : '' ?>>POS</option>
</select>
</div>
<div class="col-12 col-md-4">
<label class="form-label mb-1" for="sales-payment-status"><?= h(tr('حالة الدفع', 'Payment')) ?></label>
<select id="sales-payment-status" class="form-select form-select-sm" name="payment_status">
<option value=""><?= h(tr('كل الحالات', 'All statuses')) ?></option>
<option value="paid" <?= $paymentStatus === 'paid' ? 'selected' : '' ?>><?= h(tr('مدفوع', 'Paid')) ?></option>
<option value="partial" <?= $paymentStatus === 'partial' ? 'selected' : '' ?>><?= h(tr('جزئي', 'Partial')) ?></option>
<option value="unpaid" <?= $paymentStatus === 'unpaid' ? 'selected' : '' ?>><?= h(tr('غير مدفوع', 'Unpaid')) ?></option>
</select>
</div>
<div class="col-12 col-md-4">
<label class="form-label mb-1" for="sales-status"><?= h(tr('نوع السجل', 'Record type')) ?></label>
<select id="sales-status" class="form-select form-select-sm" name="status">
<option value=""><?= h(tr('العرض الافتراضي', 'Default view')) ?></option>
<option value="completed" <?= $statusFilter === 'completed' ? 'selected' : '' ?>><?= h(tr('كل الفواتير المكتملة', 'Completed invoices')) ?></option>
<option value="order" <?= $statusFilter === 'order' ? 'selected' : '' ?>><?= h(tr('طلبات الحجز', 'Order reservations')) ?></option>
</select>
</div>
</div>
</div>
</details>
</div>
<div class="row g-3 align-items-end">
<div class="col-12 col-md-3">
<label class="form-label mb-1" for="sales-search"><?= h(tr('بحث سريع', 'Quick search')) ?></label>
<input id="sales-search" type="text" class="form-control form-control-sm" name="q" value="<?= h($search) ?>" placeholder="<?= h(tr('بحث بالإيصال، الكاشير، العميل أو الهاتف...', 'Search receipt, cashier, customer or phone...')) ?>">
</div>
<div class="col-12 col-md-2">
<label class="form-label mb-1" for="sales-branch"><?= h(tr('الفرع', 'Branch')) ?></label>
<select id="sales-branch" class="form-select form-select-sm" name="branch">
<option value=""><?= h(tr('كل الفروع', 'All branches')) ?></option>
<?php foreach (branches() as $branchCode => $branchLabel): ?>
<?php if ($user['role'] !== 'owner' && !in_array($branchCode, $allowedBranches, true)) { continue; } ?>
<option value="<?= h($branchCode) ?>" <?= $branch === $branchCode ? 'selected' : '' ?>><?= h(branch_label($branchCode)) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-12 col-md-2">
<label class="form-label mb-1" for="sales-delivery-status"><?= h(tr('التجهيز', 'Prep')) ?></label>
<select id="sales-delivery-status" class="form-select form-select-sm" name="delivery_status">
<option value=""><?= h(tr('كل الحالات', 'All statuses')) ?></option>
<?php foreach ($deliveryOptions as $value => $label): ?>
<option value="<?= h($value) ?>" <?= $deliveryStatus === $value ? 'selected' : '' ?>><?= h($label) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-12 col-md-3">
<label class="form-label mb-1">
<?= h($statusFilter === 'order' ? tr('فترة الطلب', 'Order window') : tr('فترة البيع', 'Sale window')) ?>
</label>
<div class="d-flex gap-2">
<input id="sales-date-from" type="date" class="form-control form-control-sm" name="date_from" value="<?= h($dateFrom) ?>" aria-label="<?= h(tr('من تاريخ', 'From date')) ?>">
<input id="sales-date-to" type="date" class="form-control form-control-sm" name="date_to" value="<?= h($dateTo) ?>" aria-label="<?= h(tr('إلى تاريخ', 'To date')) ?>">
</div>
</div>
<div class="col-12 col-md-2 d-flex gap-2">
<button type="submit" class="btn btn-sm btn-dark w-50"><i class="bi bi-funnel me-1"></i><?= h(tr('تطبيق', 'Apply')) ?></button>
<a class="btn btn-sm btn-outline-secondary w-50" href="<?= h(url_for('sales.php', ['status' => $statusFilter])) ?>"><?= h(tr('إعادة ضبط', 'Reset')) ?></a>
</div>
</div>
</form>
@ -249,7 +355,7 @@ require __DIR__ . '/includes/header.php';
<ul class="pagination justify-content-center mb-0">
<?php for($i=1; $i<=$totalPages; $i++): ?>
<li class="page-item <?= $i === $page ? 'active' : '' ?>">
<a class="page-link" href="<?= h(url_for('sales.php', ['p' => $i, 'q' => $search, 'mode' => $mode, 'status' => $statusFilter])) ?>"><?= $i ?></a>
<a class="page-link" href="<?= h(url_for('sales.php', $queryState(['p' => $i]))) ?>"><?= $i ?></a>
</li>
<?php endfor; ?>
</ul>