update orders

This commit is contained in:
Flatlogic Bot 2026-03-02 13:26:09 +00:00
parent 268b4cc1cf
commit 2807096c56
3 changed files with 253 additions and 67 deletions

View File

@ -137,7 +137,17 @@ $translations = [
'lab' => 'Lab Module',
'outlet' => 'Outlet',
'view_items' => 'View Items',
'initial_letters' => 'Initial letters (3 letters)'
'initial_letters' => 'Initial letters (3 letters)',
'from_date' => 'From Date',
'to_date' => 'To Date',
'order_no' => 'Order No',
'all_status' => 'All Status',
'all_payments' => 'All Payments',
'search_placeholder' => 'Search by Phone, Order No, Name...',
'previous' => 'Previous',
'next' => 'Next',
'page' => 'Page',
'of' => 'of'
],
'ar' => [
'dashboard' => 'لوحة القيادة',
@ -268,7 +278,17 @@ $translations = [
'lab' => 'وحدة المختبر',
'outlet' => 'المنفذ',
'view_items' => 'عرض الأصناف',
'initial_letters' => 'الحروف الأولى (3 حروف)'
'initial_letters' => 'الحروف الأولى (3 حروف)',
'from_date' => 'من تاريخ',
'to_date' => 'إلى تاريخ',
'order_no' => 'رقم الطلب',
'all_status' => 'جميع الحالات',
'all_payments' => 'جميع المدفوعات',
'search_placeholder' => 'بحث بالهاتف، رقم الطلب، الاسم...',
'previous' => 'السابق',
'next' => 'التالي',
'page' => 'صفحة',
'of' => 'من'
]
];
@ -297,4 +317,4 @@ function decimals() {
function format_amount($amount) {
return number_format((float)$amount, decimals()) . ' ' . currency();
}
}

127
lab.php
View File

@ -4,27 +4,60 @@ require_once __DIR__ . '/includes/header.php';
$current_role = $_SESSION['role'] ?? 'cashier';
// Filters
$status_filter = $_GET['status'] ?? '';
$branch_filter = $_GET['branch_id'] ?? '';
$from_date = $_GET['from_date'] ?? '';
$to_date = $_GET['to_date'] ?? '';
$search = $_GET['search'] ?? '';
$sql = "SELECT o.*, c.name_en as customer_name_en, c.name_ar as customer_name_ar,
b.name_en as branch_name_en, b.name_ar as branch_name_ar
FROM orders o
LEFT JOIN customers c ON o.customer_id = c.id
LEFT JOIN branches b ON o.branch_id = b.id
WHERE 1=1";
// Pagination
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
if ($page < 1) $page = 1;
$limit = 10;
$offset = ($page - 1) * $limit;
$sql_base = " FROM orders o
LEFT JOIN customers c ON o.customer_id = c.id
LEFT JOIN branches b ON o.branch_id = b.id
WHERE 1=1";
$params = [];
if ($status_filter) {
$sql .= " AND o.status = ?";
$sql_base .= " AND o.status = ?";
$params[] = $status_filter;
}
if ($branch_filter) {
$sql .= " AND o.branch_id = ?";
$sql_base .= " AND o.branch_id = ?";
$params[] = $branch_filter;
}
if ($from_date) {
$sql_base .= " AND DATE(o.created_at) >= ?";
$params[] = $from_date;
}
if ($to_date) {
$sql_base .= " AND DATE(o.created_at) <= ?";
$params[] = $to_date;
}
if ($search) {
$sql_base .= " AND (o.order_number LIKE ? OR c.phone LIKE ? OR c.name_en LIKE ? OR c.name_ar LIKE ?)";
$search_param = "%$search%";
$params[] = $search_param;
$params[] = $search_param;
$params[] = $search_param;
$params[] = $search_param;
}
$sql .= " ORDER BY o.created_at DESC";
// Total count for pagination
$count_sql = "SELECT COUNT(*) " . $sql_base;
$stmt_count = db()->prepare($count_sql);
$stmt_count->execute($params);
$total_items = $stmt_count->fetchColumn();
$total_pages = ceil($total_items / $limit);
// Final data query
$sql = "SELECT o.*, c.name_en as customer_name_en, c.name_ar as customer_name_ar, c.phone as customer_phone,
b.name_en as branch_name_en, b.name_ar as branch_name_ar " . $sql_base . " ORDER BY o.created_at DESC LIMIT $limit OFFSET $offset";
$stmt = db()->prepare($sql);
$stmt->execute($params);
$orders = $stmt->fetchAll();
@ -39,28 +72,40 @@ $branches = db()->query("SELECT id, name_en, name_ar FROM branches")->fetchAll()
<h5 class="fw-bold mb-0"><?= __('lab') ?? 'Lab Module' ?></h5>
<p class="text-muted small mb-0"><?= __('manage_orders_across_outlets') ?? 'Manage orders across all outlets' ?></p>
</div>
<div class="d-flex gap-2">
<form action="" method="GET" class="d-flex gap-2 flex-wrap">
<select name="branch_id" class="form-select border-radius-12" style="border-radius: 12px; width: auto;" onchange="this.form.submit()">
<option value=""><?= __('all_branches') ?? 'All Branches' ?></option>
<?php foreach($branches as $b): ?>
<option value="<?= $b['id'] ?>" <?= $branch_filter == $b['id'] ? 'selected' : '' ?>>
<?= $lang === 'ar' ? ($b['name_ar'] ?: $b['name_en']) : $b['name_en'] ?>
</option>
<?php endforeach; ?>
</select>
<select name="status" class="form-select border-radius-12" style="border-radius: 12px; width: auto;" onchange="this.form.submit()">
<option value=""><?= __('all_status') ?? 'All Status' ?></option>
<option value="received" <?= $status_filter == 'received' ? 'selected' : '' ?>><?= __('received') ?></option>
<option value="processing" <?= $status_filter == 'processing' ? 'selected' : '' ?>><?= __('processing') ?></option>
<option value="ready" <?= $status_filter == 'ready' ? 'selected' : '' ?>><?= __('ready') ?></option>
<option value="delivered" <?= $status_filter == 'delivered' ? 'selected' : '' ?>><?= __('delivered') ?></option>
<option value="cancelled" <?= $status_filter == 'cancelled' ? 'selected' : '' ?>><?= __('cancelled') ?></option>
</select>
</form>
</div>
</div>
<!-- Filters -->
<form action="" method="GET" class="row g-3 mb-4">
<div class="col-md-3">
<input type="text" name="search" class="form-control" placeholder="<?= __('search_placeholder') ?>" value="<?= htmlspecialchars($search) ?>" style="border-radius: 12px;">
</div>
<div class="col-md-2">
<select name="branch_id" class="form-select border-radius-12" style="border-radius: 12px;" onchange="this.form.submit()">
<option value=""><?= __('all_branches') ?? 'All Branches' ?></option>
<?php foreach($branches as $b): ?>
<option value="<?= $b['id'] ?>" <?= $branch_filter == $b['id'] ? 'selected' : '' ?>>
<?= $lang === 'ar' ? ($b['name_ar'] ?: $b['name_en']) : $b['name_en'] ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-2">
<select name="status" class="form-select border-radius-12" style="border-radius: 12px;" onchange="this.form.submit()">
<option value=""><?= __('all_status') ?? 'All Status' ?></option>
<option value="received" <?= $status_filter == 'received' ? 'selected' : '' ?>><?= __('received') ?></option>
<option value="processing" <?= $status_filter == 'processing' ? 'selected' : '' ?>><?= __('processing') ?></option>
<option value="ready" <?= $status_filter == 'ready' ? 'selected' : '' ?>><?= __('ready') ?></option>
<option value="delivered" <?= $status_filter == 'delivered' ? 'selected' : '' ?>><?= __('delivered') ?></option>
<option value="cancelled" <?= $status_filter == 'cancelled' ? 'selected' : '' ?>><?= __('cancelled') ?></option>
</select>
</div>
<div class="col-md-5 d-flex gap-2">
<input type="date" name="from_date" class="form-control" value="<?= $from_date ?>" style="border-radius: 12px;" title="<?= __('from_date') ?>">
<input type="date" name="to_date" class="form-control" value="<?= $to_date ?>" style="border-radius: 12px;" title="<?= __('to_date') ?>">
<button type="submit" class="btn btn-light" style="border-radius: 12px;"><i class="bi bi-search"></i></button>
</div>
</form>
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead class="bg-light">
@ -86,6 +131,7 @@ $branches = db()->query("SELECT id, name_en, name_ar FROM branches")->fetchAll()
</td>
<td>
<div class="fw-bold"><?= $lang === 'ar' ? ($order['customer_name_ar'] ?: $order['customer_name_en']) : $order['customer_name_en'] ?></div>
<div class="small text-muted"><?= $order['customer_phone'] ?></div>
</td>
<td><span class="badge bg-<?= getStatusColor($order['status']) ?> rounded-pill px-3 py-2"><?= __($order['status']) ?></span></td>
<td class="small text-muted"><?= date('d/m/Y H:i', strtotime($order['created_at'])) ?></td>
@ -112,6 +158,25 @@ $branches = db()->query("SELECT id, name_en, name_ar FROM branches")->fetchAll()
</tbody>
</table>
</div>
<!-- Pagination -->
<?php if ($total_pages > 1): ?>
<nav class="mt-4">
<ul class="pagination justify-content-center">
<li class="page-item <?= $page <= 1 ? 'disabled' : '' ?>">
<a class="page-link" href="?<?= http_build_query(array_merge($_GET, ['page' => $page - 1])) ?>" style="border-radius: 8px 0 0 8px;"><?= __('previous') ?></a>
</li>
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
<li class="page-item <?= $page == $i ? 'active' : '' ?>">
<a class="page-link" href="?<?= http_build_query(array_merge($_GET, ['page' => $i])) ?>"><?= $i ?></a>
</li>
<?php endfor; ?>
<li class="page-item <?= $page >= $total_pages ? 'disabled' : '' ?>">
<a class="page-link" href="?<?= http_build_query(array_merge($_GET, ['page' => $page + 1])) ?>" style="border-radius: 0 8px 8px 0;"><?= __('next') ?></a>
</li>
</ul>
</nav>
<?php endif; ?>
</div>
<!-- View Items Modal -->
@ -136,7 +201,7 @@ $branches = db()->query("SELECT id, name_en, name_ar FROM branches")->fetchAll()
</div>
</div>
<!-- Status Update Modal (Reused from orders.php) -->
<!-- Status Update Modal -->
<div class="modal fade" id="statusModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content border-0 rounded-4 shadow-lg">
@ -272,4 +337,4 @@ function getStatusColor($status) {
][$status] ?? 'info';
}
require_once __DIR__ . '/includes/footer.php';
?>
?>

View File

@ -2,64 +2,143 @@
$title = 'orders';
require_once __DIR__ . '/includes/header.php';
$branch_id = $_SESSION['branch_id'];
$current_role = $_SESSION['role'] ?? 'cashier';
$session_branch_id = $_SESSION['branch_id'];
// Filters
$status_filter = $_GET['status'] ?? '';
$payment_filter = $_GET['payment_status'] ?? '';
$branch_filter = $_GET['branch_id'] ?? '';
$from_date = $_GET['from_date'] ?? '';
$to_date = $_GET['to_date'] ?? '';
$search = $_GET['search'] ?? '';
$sql = "SELECT o.*, c.name_en as customer_name_en, c.name_ar as customer_name_ar, c.phone as customer_phone
FROM orders o
LEFT JOIN customers c ON o.customer_id = c.id
WHERE o.branch_id = ?";
$params = [$branch_id];
// Pagination
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
if ($page < 1) $page = 1;
$limit = 10;
$offset = ($page - 1) * $limit;
$sql_base = " FROM orders o
LEFT JOIN customers c ON o.customer_id = c.id
LEFT JOIN branches b ON o.branch_id = b.id
WHERE 1=1";
$params = [];
// Branch restriction
if ($current_role !== 'super_admin') {
$sql_base .= " AND o.branch_id = ?";
$params[] = $session_branch_id;
} elseif ($branch_filter) {
$sql_base .= " AND o.branch_id = ?";
$params[] = $branch_filter;
}
if ($status_filter) {
$sql .= " AND o.status = ?";
$sql_base .= " AND o.status = ?";
$params[] = $status_filter;
}
if ($payment_filter) {
$sql .= " AND o.payment_status = ?";
$sql_base .= " AND o.payment_status = ?";
$params[] = $payment_filter;
}
if ($from_date) {
$sql_base .= " AND DATE(o.created_at) >= ?";
$params[] = $from_date;
}
if ($to_date) {
$sql_base .= " AND DATE(o.created_at) <= ?";
$params[] = $to_date;
}
if ($search) {
$sql_base .= " AND (o.order_number LIKE ? OR c.phone LIKE ? OR c.name_en LIKE ? OR c.name_ar LIKE ?)";
$search_param = "%$search%";
$params[] = $search_param;
$params[] = $search_param;
$params[] = $search_param;
$params[] = $search_param;
}
$sql .= " ORDER BY o.created_at DESC";
// Total count for pagination
$count_sql = "SELECT COUNT(*) " . $sql_base;
$stmt_count = db()->prepare($count_sql);
$stmt_count->execute($params);
$total_items = $stmt_count->fetchColumn();
$total_pages = ceil($total_items / $limit);
// Final data query
$sql = "SELECT o.*, c.name_en as customer_name_en, c.name_ar as customer_name_ar, c.phone as customer_phone,
b.name_en as branch_name_en, b.name_ar as branch_name_ar " . $sql_base . " ORDER BY o.created_at DESC LIMIT $limit OFFSET $offset";
$stmt = db()->prepare($sql);
$stmt->execute($params);
$orders = $stmt->fetchAll();
$branches = [];
if ($current_role === 'super_admin') {
$branches = db()->query("SELECT id, name_en, name_ar FROM branches")->fetchAll();
}
?>
<div class="card p-4">
<div class="card p-4 border-0 shadow-sm" style="border-radius: 20px;">
<div class="d-flex flex-wrap justify-content-between align-items-center mb-4">
<h5 class="fw-bold mb-3 mb-md-0"><?= __('orders_list') ?? 'Orders List' ?></h5>
<div class="d-flex gap-2">
<form action="" method="GET" class="d-flex gap-2">
<select name="status" class="form-select border-radius-12" style="border-radius: 12px; width: auto;" onchange="this.form.submit()">
<option value=""><?= __('all_status') ?? 'All Status' ?></option>
<option value="received" <?= $status_filter == 'received' ? 'selected' : '' ?>><?= __('received') ?></option>
<option value="processing" <?= $status_filter == 'processing' ? 'selected' : '' ?>><?= __('processing') ?></option>
<option value="ready" <?= $status_filter == 'ready' ? 'selected' : '' ?>><?= __('ready') ?></option>
<option value="delivered" <?= $status_filter == 'delivered' ? 'selected' : '' ?>><?= __('delivered') ?></option>
<option value="cancelled" <?= $status_filter == 'cancelled' ? 'selected' : '' ?>><?= __('cancelled') ?></option>
</select>
<select name="payment_status" class="form-select border-radius-12" style="border-radius: 12px; width: auto;" onchange="this.form.submit()">
<option value=""><?= __('all_payments') ?? 'All Payments' ?></option>
<option value="unpaid" <?= $payment_filter == 'unpaid' ? 'selected' : '' ?>><?= __('unpaid') ?></option>
<option value="partially_paid" <?= $payment_filter == 'partially_paid' ? 'selected' : '' ?>><?= __('partially_paid') ?></option>
<option value="paid" <?= $payment_filter == 'paid' ? 'selected' : '' ?>><?= __('paid') ?></option>
</select>
</form>
<a href="pos.php" class="btn btn-primary px-4" style="border-radius: 12px;">
<i class="bi bi-plus-lg me-1"></i> <?= __('new_order') ?>
</a>
</div>
<a href="pos.php" class="btn btn-primary px-4" style="border-radius: 12px;">
<i class="bi bi-plus-lg me-1"></i> <?= __('new_order') ?>
</a>
</div>
<!-- Filters -->
<form action="" method="GET" class="row g-3 mb-4">
<div class="col-md-3">
<input type="text" name="search" class="form-control" placeholder="<?= __('search_placeholder') ?>" value="<?= htmlspecialchars($search) ?>" style="border-radius: 12px;">
</div>
<?php if ($current_role === 'super_admin'): ?>
<div class="col-md-2">
<select name="branch_id" class="form-select" style="border-radius: 12px;" onchange="this.form.submit()">
<option value=""><?= __('all_branches') ?></option>
<?php foreach($branches as $b): ?>
<option value="<?= $b['id'] ?>" <?= $branch_filter == $b['id'] ? 'selected' : '' ?>>
<?= $lang === 'ar' ? ($b['name_ar'] ?: $b['name_en']) : $b['name_en'] ?>
</option>
<?php endforeach; ?>
</select>
</div>
<?php endif; ?>
<div class="col-md-2">
<select name="status" class="form-select" style="border-radius: 12px;" onchange="this.form.submit()">
<option value=""><?= __('all_status') ?></option>
<option value="received" <?= $status_filter == 'received' ? 'selected' : '' ?>><?= __('received') ?></option>
<option value="processing" <?= $status_filter == 'processing' ? 'selected' : '' ?>><?= __('processing') ?></option>
<option value="ready" <?= $status_filter == 'ready' ? 'selected' : '' ?>><?= __('ready') ?></option>
<option value="delivered" <?= $status_filter == 'delivered' ? 'selected' : '' ?>><?= __('delivered') ?></option>
<option value="cancelled" <?= $status_filter == 'cancelled' ? 'selected' : '' ?>><?= __('cancelled') ?></option>
</select>
</div>
<div class="col-md-2">
<select name="payment_status" class="form-select" style="border-radius: 12px;" onchange="this.form.submit()">
<option value=""><?= __('all_payments') ?></option>
<option value="unpaid" <?= $payment_filter == 'unpaid' ? 'selected' : '' ?>><?= __('unpaid') ?></option>
<option value="partially_paid" <?= $payment_filter == 'partially_paid' ? 'selected' : '' ?>><?= __('partially_paid') ?></option>
<option value="paid" <?= $payment_filter == 'paid' ? 'selected' : '' ?>><?= __('paid') ?></option>
</select>
</div>
<div class="col-md-3 d-flex gap-2">
<input type="date" name="from_date" class="form-control" value="<?= $from_date ?>" style="border-radius: 12px;" title="<?= __('from_date') ?>">
<input type="date" name="to_date" class="form-control" value="<?= $to_date ?>" style="border-radius: 12px;" title="<?= __('to_date') ?>">
<button type="submit" class="btn btn-light" style="border-radius: 12px;"><i class="bi bi-search"></i></button>
</div>
</form>
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead class="table-light">
<tr>
<th>#</th>
<th><?= __('order_number') ?? 'Order #' ?></th>
<?php if ($current_role === 'super_admin'): ?>
<th><?= __('branch') ?></th>
<?php endif; ?>
<th><?= __('customer') ?></th>
<th><?= __('total') ?></th>
<th><?= __('status') ?></th>
@ -73,6 +152,9 @@ $orders = $stmt->fetchAll();
<tr>
<td><?= $order['id'] ?></td>
<td class="fw-bold"><?= $order['order_number'] ?></td>
<?php if ($current_role === 'super_admin'): ?>
<td><span class="small text-muted"><?= $lang === 'ar' ? ($order['branch_name_ar'] ?: $order['branch_name_en']) : $order['branch_name_en'] ?></span></td>
<?php endif; ?>
<td>
<div class="fw-bold"><?= $lang === 'ar' ? ($order['customer_name_ar'] ?: $order['customer_name_en']) : $order['customer_name_en'] ?></div>
<div class="small text-muted"><?= $order['customer_phone'] ?></div>
@ -101,7 +183,7 @@ $orders = $stmt->fetchAll();
<?php endforeach; ?>
<?php if (empty($orders)): ?>
<tr>
<td colspan="8" class="text-center py-5 text-muted">
<td colspan="<?= $current_role === 'super_admin' ? 9 : 8 ?>" class="text-center py-5 text-muted">
<i class="bi bi-inbox fs-1 d-block mb-3 opacity-25"></i>
<?= __('no_orders_found') ?? 'No orders found' ?>
</td>
@ -110,6 +192,25 @@ $orders = $stmt->fetchAll();
</tbody>
</table>
</div>
<!-- Pagination -->
<?php if ($total_pages > 1): ?>
<nav class="mt-4">
<ul class="pagination justify-content-center">
<li class="page-item <?= $page <= 1 ? 'disabled' : '' ?>">
<a class="page-link" href="?<?= http_build_query(array_merge($_GET, ['page' => $page - 1])) ?>" style="border-radius: 8px 0 0 8px;"><?= __('previous') ?></a>
</li>
<?php for ($i = 1; $i <= $total_pages; $i++): ?>
<li class="page-item <?= $page == $i ? 'active' : '' ?>">
<a class="page-link" href="?<?= http_build_query(array_merge($_GET, ['page' => $i])) ?>"><?= $i ?></a>
</li>
<?php endfor; ?>
<li class="page-item <?= $page >= $total_pages ? 'disabled' : '' ?>">
<a class="page-link" href="?<?= http_build_query(array_merge($_GET, ['page' => $page + 1])) ?>" style="border-radius: 0 8px 8px 0;"><?= __('next') ?></a>
</li>
</ul>
</nav>
<?php endif; ?>
</div>
<!-- Status Update Modal -->
@ -244,4 +345,4 @@ function getPaymentStatusColor($status) {
][$status] ?? 'info';
}
require_once __DIR__ . '/includes/footer.php';
?>
?>