249 lines
10 KiB
PHP
249 lines
10 KiB
PHP
<?php
|
|
require_once __DIR__ . '/includes/app.php';
|
|
$user = require_permission('eid_orders', 'show');
|
|
ensure_sales_table();
|
|
|
|
$activeNav = 'eid_orders';
|
|
$pageTitle = tr('طباعة تجهيزات العيد', 'Print Eid Prep Summary');
|
|
$metaDescription = tr('ملخص قابل للطباعة لتجهيزات طلبات العيد حسب التاريخ والفرع والحالة.', 'Printable Eid preparation summary by date, branch, and status.');
|
|
$metaRobots = 'noindex, nofollow';
|
|
|
|
$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 = trim((string) ($_GET['q'] ?? ''));
|
|
$paymentStatus = trim((string) ($_GET['payment_status'] ?? ''));
|
|
$deliveryStatus = trim((string) ($_GET['delivery_status'] ?? ''));
|
|
$dateFrom = trim((string) ($_GET['date_from'] ?? ''));
|
|
$dateTo = trim((string) ($_GET['date_to'] ?? ''));
|
|
$allowedBranches = $user && $user['role'] !== 'owner' ? get_user_branches($user) : [];
|
|
$deliveryOptions = eid_delivery_status_options();
|
|
$dbError = null;
|
|
$orders = [];
|
|
$itemRows = [];
|
|
$summary = [
|
|
'total_orders' => 0,
|
|
'unique_items' => 0,
|
|
'total_quantity' => 0,
|
|
'total_amount' => 0,
|
|
];
|
|
|
|
try {
|
|
$params = [':order_type' => 'eid'];
|
|
$where = ' WHERE order_type = :order_type ';
|
|
|
|
if ($mode) {
|
|
$where .= ' AND sale_mode = :sale_mode ';
|
|
$params[':sale_mode'] = $mode;
|
|
}
|
|
|
|
if ($branch) {
|
|
$where .= ' AND branch_code = :branch_code ';
|
|
$params[':branch_code'] = $branch;
|
|
}
|
|
|
|
if ($user && $user['role'] !== 'owner') {
|
|
if ($allowedBranches === []) {
|
|
$where .= ' AND 1=0 ';
|
|
} else {
|
|
$namedParams = [];
|
|
foreach ($allowedBranches as $i => $allowedBranch) {
|
|
$key = ':v_branch_' . $i;
|
|
$namedParams[] = $key;
|
|
$params[$key] = $allowedBranch;
|
|
}
|
|
$where .= ' AND branch_code IN (' . implode(', ', $namedParams) . ') ';
|
|
}
|
|
}
|
|
|
|
if ($search !== '') {
|
|
$where .= ' AND (receipt_no LIKE :search OR customer_name LIKE :search OR cashier_name LIKE :search OR notes LIKE :search) ';
|
|
$params[':search'] = '%' . $search . '%';
|
|
}
|
|
|
|
if (in_array($paymentStatus, ['paid', 'partial', 'unpaid'], true)) {
|
|
$where .= ' AND payment_status = :payment_status ';
|
|
$params[':payment_status'] = $paymentStatus;
|
|
}
|
|
|
|
if (isset($deliveryOptions[$deliveryStatus])) {
|
|
$where .= ' AND delivery_status = :delivery_status ';
|
|
$params[':delivery_status'] = $deliveryStatus;
|
|
}
|
|
|
|
if ($dateFrom !== '' && preg_match('/^\d{4}-\d{2}-\d{2}$/', $dateFrom)) {
|
|
$where .= ' AND DATE(COALESCE(delivery_date, sale_date)) >= :date_from ';
|
|
$params[':date_from'] = $dateFrom;
|
|
} else {
|
|
$dateFrom = '';
|
|
}
|
|
|
|
if ($dateTo !== '' && preg_match('/^\d{4}-\d{2}-\d{2}$/', $dateTo)) {
|
|
$where .= ' AND DATE(COALESCE(delivery_date, sale_date)) <= :date_to ';
|
|
$params[':date_to'] = $dateTo;
|
|
} else {
|
|
$dateTo = '';
|
|
}
|
|
|
|
$sql = 'SELECT * FROM sales_orders' . $where . ' ORDER BY COALESCE(delivery_date, DATE(sale_date)) ASC, sale_date ASC';
|
|
$stmt = db()->prepare($sql);
|
|
foreach ($params as $key => $value) {
|
|
$stmt->bindValue($key, $value);
|
|
}
|
|
$stmt->execute();
|
|
$orders = $stmt->fetchAll();
|
|
|
|
$itemIndex = [];
|
|
foreach ($orders as &$order) {
|
|
$decodedItems = json_decode((string) ($order['items_json'] ?? '[]'), true);
|
|
$items = is_array($decodedItems) ? $decodedItems : [];
|
|
$order['items'] = $items;
|
|
|
|
foreach ($items as $item) {
|
|
$sku = trim((string) ($item['sku'] ?? ''));
|
|
$name = trim((string) ($item['name_ar'] ?? ''));
|
|
if ($name === '') {
|
|
$name = trim((string) ($item['name_en'] ?? ''));
|
|
}
|
|
if ($name === '') {
|
|
$name = $sku !== '' ? $sku : tr('صنف بدون اسم', 'Unnamed item');
|
|
}
|
|
|
|
$key = $sku !== '' ? $sku : md5($name);
|
|
$qty = max(0, (float) ($item['qty'] ?? 0));
|
|
|
|
if (!isset($itemIndex[$key])) {
|
|
$itemIndex[$key] = [
|
|
'sku' => $sku,
|
|
'name' => $name,
|
|
'qty' => 0.0,
|
|
'order_count' => 0,
|
|
];
|
|
}
|
|
|
|
$itemIndex[$key]['qty'] += $qty;
|
|
$itemIndex[$key]['order_count']++;
|
|
}
|
|
}
|
|
unset($order);
|
|
|
|
usort($orders, static function (array $a, array $b): int {
|
|
$aDate = (string) ($a['delivery_date'] ?: substr((string) ($a['sale_date'] ?? ''), 0, 10));
|
|
$bDate = (string) ($b['delivery_date'] ?: substr((string) ($b['sale_date'] ?? ''), 0, 10));
|
|
return [$aDate, (string) ($a['receipt_no'] ?? '')] <=> [$bDate, (string) ($b['receipt_no'] ?? '')];
|
|
});
|
|
|
|
$itemRows = array_values($itemIndex);
|
|
usort($itemRows, static function (array $a, array $b): int {
|
|
if ($a['qty'] === $b['qty']) {
|
|
return strcasecmp((string) $a['name'], (string) $b['name']);
|
|
}
|
|
return $b['qty'] <=> $a['qty'];
|
|
});
|
|
|
|
$summary['total_orders'] = count($orders);
|
|
$summary['unique_items'] = count($itemRows);
|
|
$summary['total_quantity'] = array_sum(array_map(static fn(array $row): float => (float) $row['qty'], $itemRows));
|
|
$summary['total_amount'] = array_sum(array_map(static fn(array $row): float => (float) ($row['total_amount'] ?? 0), $orders));
|
|
} catch (Throwable $e) {
|
|
$dbError = $e->getMessage();
|
|
}
|
|
|
|
$filterParams = array_filter([
|
|
'q' => $search,
|
|
'branch' => $branch,
|
|
'mode' => $mode,
|
|
'payment_status' => $paymentStatus,
|
|
'delivery_status' => $deliveryStatus,
|
|
'date_from' => $dateFrom,
|
|
'date_to' => $dateTo,
|
|
], static fn($value) => $value !== null && $value !== '');
|
|
|
|
$generatedAt = date('Y-m-d H:i');
|
|
require __DIR__ . '/includes/header.php';
|
|
?>
|
|
<style>
|
|
.eid-print-shell { max-width: 1180px; margin: 0 auto; }
|
|
.eid-print-card {
|
|
background: #fff;
|
|
border: 1px solid #e8ecf4;
|
|
border-radius: 16px;
|
|
box-shadow: 0 12px 40px rgba(15, 23, 42, 0.06);
|
|
}
|
|
.eid-print-card .table th { white-space: nowrap; }
|
|
|
|
@media print {
|
|
@page {
|
|
size: portrait;
|
|
margin: 1cm;
|
|
}
|
|
body { background: #fff !important; color: #000 !important; font-size: 12pt !important; }
|
|
.main-sidebar, .main-header, .footer-section, footer, .d-print-none, .alert-dismissible .btn-close { display: none !important; }
|
|
.main-content { margin: 0 !important; padding: 0 !important; }
|
|
|
|
.eid-print-shell { max-width: 100% !important; margin: 0 !important; padding: 0 !important; }
|
|
.eid-print-card { box-shadow: none !important; border: none !important; padding: 0 !important; margin: 0 !important; border-radius: 0 !important; }
|
|
|
|
.table { width: 100% !important; border-collapse: collapse !important; }
|
|
.table th, .table td {
|
|
border: 1px solid #000 !important;
|
|
padding: 6px !important;
|
|
color: #000 !important;
|
|
}
|
|
.table th { background: transparent !important; }
|
|
}
|
|
</style>
|
|
|
|
<div class="eid-print-shell py-4">
|
|
<section class="eid-print-card p-4 p-lg-5 mb-4">
|
|
<div class="d-flex justify-content-between align-items-start gap-3 flex-wrap mb-4 d-print-none">
|
|
<div>
|
|
<h1 class="h3 mb-1"><i class="bi bi-printer me-2"></i><?= h(tr("ملخص تجهيزات طلبات العيد", "Eid Order Prep Summary")) ?></h1>
|
|
<p class="text-muted mb-0"><?= h(tr("تقرير قابل للطباعة يوضح الأصناف المطلوبة وعدد الطلبات التي تحتوي كل صنف.", "Printable report showing required items and how many orders contain each item.")) ?></p>
|
|
</div>
|
|
<div class="d-flex gap-2 flex-wrap">
|
|
<a class="btn btn-outline-secondary" href="<?= h(url_for("eid_orders.php", $filterParams)) ?>"><i class="bi bi-arrow-<?= current_lang() === "ar" ? "right" : "left" ?> me-1"></i><?= h(tr("رجوع لطلبات العيد", "Back to Eid Orders")) ?></a>
|
|
<button type="button" class="btn btn-dark" onclick="window.print()"><i class="bi bi-printer me-1"></i><?= h(tr("طباعة", "Print")) ?></button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-center mb-4">
|
|
<h2 class="h4 mb-1"><?= h(tr("ملخص تجهيزات طلبات العيد", "Eid Order Prep Summary")) ?></h2>
|
|
<div class="text-muted"><?= h(tr("تاريخ الطباعة", "Printed at")) ?>: <?= h($generatedAt) ?></div>
|
|
<?php if ($dateFrom !== "" || $dateTo !== ""): ?>
|
|
<div class="text-muted mt-1"><?= h(tr("الفترة", "Period")) ?>: <?= h($dateFrom !== "" ? $dateFrom : "…") ?> → <?= h($dateTo !== "" ? $dateTo : "…") ?></div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if ($dbError): ?>
|
|
<div class="alert alert-danger"><?= h($dbError) ?></div>
|
|
<?php else: ?>
|
|
<?php if ($itemRows === []): ?>
|
|
<div class="alert alert-secondary text-center"><?= h(tr("لا توجد بيانات للطباعة.", "No data to print.")) ?></div>
|
|
<?php else: ?>
|
|
<div class="table-responsive">
|
|
<table class="table table-bordered align-middle text-center">
|
|
<thead >
|
|
<tr>
|
|
<th style="width: 60px;">#</th>
|
|
<th style="text-align: right !important;"><?= h(tr("الصنف", "Item")) ?></th>
|
|
<th style="width: 150px;"><?= h(tr("عدد الطلبات", "Orders count")) ?></th>
|
|
<th style="width: 150px;"><?= h(tr("الكمية المطلوبة", "Quantity wanted")) ?></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($itemRows as $index => $row): ?>
|
|
<tr>
|
|
<td><?= $index + 1 ?></td>
|
|
<td class="fw-bold" style="text-align: right !important;"><?= h($row["name"]) ?></td>
|
|
<td><?= (int) $row["order_count"] ?></td>
|
|
<td class="fw-bold"><?= h(rtrim(rtrim(number_format((float) $row["qty"], 3, ".", ""), "0"), ".")) ?></td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
<?php endif; ?>
|
|
</section>
|
|
</div>
|
|
<?php require __DIR__ . "/includes/footer.php"; ?>
|