update timezone
This commit is contained in:
parent
106c5dab28
commit
2d79f6ac5f
@ -12,7 +12,7 @@ if (!in_array($user['role'], ['owner', 'manager'])) {
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$pdo = db();
|
||||
$keys = [
|
||||
'company_name_ar', 'company_name_en', 'vat_percentage',
|
||||
'timezone', 'company_name_ar', 'company_name_en', 'vat_percentage',
|
||||
'company_vat_number', 'company_phone', 'company_email', 'company_address',
|
||||
'smtp_host', 'smtp_port', 'smtp_user', 'smtp_pass', 'smtp_secure', 'mail_from', 'mail_from_name'
|
||||
];
|
||||
@ -54,4 +54,4 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$referer = $_SERVER['HTTP_REFERER'] ?? '../index.php';
|
||||
header('Location: ' . $referer);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
date_default_timezone_set('UTC');
|
||||
|
||||
|
||||
function get_settings(): array
|
||||
{
|
||||
@ -33,6 +33,15 @@ function get_setting(string $key, $default = '')
|
||||
return $settings[$key] ?? $default;
|
||||
}
|
||||
|
||||
$app_tz = get_setting('timezone', 'UTC');
|
||||
if (empty($app_tz)) {
|
||||
$app_tz = 'UTC';
|
||||
}
|
||||
date_default_timezone_set($app_tz);
|
||||
try {
|
||||
db()->exec("SET time_zone = '" . date('P') . "'");
|
||||
} catch (Throwable $e) {}
|
||||
|
||||
|
||||
|
||||
function app_name(): string
|
||||
|
||||
@ -10,6 +10,17 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-12">
|
||||
<label class="form-label"><?= h(tr('المنطقة الزمنية (Timezone)', 'Timezone')) ?></label>
|
||||
<select class="form-select" name="timezone" required>
|
||||
<?php
|
||||
$zones = timezone_identifiers_list();
|
||||
$current_tz = get_setting('timezone', 'UTC');
|
||||
foreach($zones as $z): ?>
|
||||
<option value="<?= h($z) ?>" <?= $z === $current_tz ? 'selected' : '' ?>><?= h($z) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label"><?= h(tr('اسم الشركة (عربي)', 'Company Name (AR)')) ?></label>
|
||||
<input type="text" class="form-control" name="company_name_ar" value="<?= h(get_setting('company_name_ar')) ?>" required>
|
||||
|
||||
284
reports.php
284
reports.php
@ -44,9 +44,14 @@ if ($tab === 'sales') {
|
||||
}
|
||||
$stmt->execute();
|
||||
$followUpOrders = $stmt->fetchAll();
|
||||
|
||||
$onlineStmt = db()->query("SELECT * FROM online_orders WHERE status IN ('pending', 'accepted') ORDER BY created_at ASC");
|
||||
$onlineOrders = $onlineStmt->fetchAll();
|
||||
|
||||
} catch(Throwable $e) {
|
||||
$dbError = $e->getMessage();
|
||||
$followUpOrders = [];
|
||||
$onlineOrders = [];
|
||||
}
|
||||
} elseif ($tab === 'daily') {
|
||||
$reportDate = $_GET['date'] ?? date('Y-m-d');
|
||||
@ -92,6 +97,65 @@ if ($tab === 'sales') {
|
||||
} catch(Throwable $e) {
|
||||
$dbError = $e->getMessage();
|
||||
}
|
||||
} elseif ($tab === 'expenses') {
|
||||
$dateFrom = $_GET['date_from'] ?? date('Y-m-01');
|
||||
$dateTo = $_GET['date_to'] ?? date('Y-m-t');
|
||||
$branchFilter = $_GET['branch'] ?? '';
|
||||
$categoryFilter = $_GET['category_id'] ?? '';
|
||||
|
||||
$params = [];
|
||||
$whereConditions = ["DATE(e.expense_date) >= :date_from", "DATE(e.expense_date) <= :date_to"];
|
||||
$params[':date_from'] = $dateFrom;
|
||||
$params[':date_to'] = $dateTo;
|
||||
|
||||
if ($user['role'] !== 'owner') {
|
||||
$whereConditions[] = "(e.branch_code = :ubranch OR e.branch_code IS NULL)";
|
||||
$params[':ubranch'] = $user['branch_code'];
|
||||
if ($branchFilter && $branchFilter === $user['branch_code']) {
|
||||
$whereConditions[] = "e.branch_code = :branch";
|
||||
$params[':branch'] = $branchFilter;
|
||||
} elseif ($branchFilter && $branchFilter === 'general') {
|
||||
$whereConditions[] = "e.branch_code IS NULL";
|
||||
}
|
||||
} else {
|
||||
if ($branchFilter) {
|
||||
if ($branchFilter === 'general') {
|
||||
$whereConditions[] = "e.branch_code IS NULL";
|
||||
} else {
|
||||
$whereConditions[] = "e.branch_code = :branch";
|
||||
$params[':branch'] = $branchFilter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($categoryFilter) {
|
||||
$whereConditions[] = "e.category_id = :category_id";
|
||||
$params[':category_id'] = $categoryFilter;
|
||||
}
|
||||
|
||||
$where = " WHERE " . implode(" AND ", $whereConditions);
|
||||
|
||||
$sql = "SELECT e.*, c.name_ar as category_name_ar, c.name_en as category_name_en, u.username as created_by_name
|
||||
FROM expenses e
|
||||
LEFT JOIN expense_categories c ON e.category_id = c.id
|
||||
LEFT JOIN users u ON e.created_by = u.id
|
||||
" . $where . "
|
||||
ORDER BY e.expense_date DESC";
|
||||
try {
|
||||
$stmt = db()->prepare($sql);
|
||||
foreach ($params as $k => $v) {
|
||||
$stmt->bindValue($k, $v);
|
||||
}
|
||||
$stmt->execute();
|
||||
$expensesReport = $stmt->fetchAll();
|
||||
|
||||
$catStmt = db()->query("SELECT id, name_ar, name_en FROM expense_categories ORDER BY name_ar");
|
||||
$expenseCategories = $catStmt->fetchAll();
|
||||
} catch(Throwable $e) {
|
||||
$dbError = $e->getMessage();
|
||||
$expensesReport = [];
|
||||
$expenseCategories = [];
|
||||
}
|
||||
} else {
|
||||
$report = ['gross' => 0.0, 'branch_totals' => [], 'payment_totals' => [], 'product_totals' => [], 'sales_count' => 0];
|
||||
try {
|
||||
@ -123,6 +187,9 @@ require __DIR__ . '/includes/header.php';
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?= $tab === 'orders' ? 'active' : '' ?>" href="reports.php?tab=orders"><?= h(tr('طلبات للمتابعة', 'Follow-up Orders')) ?></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link<?= $tab === 'expenses' ? 'active' : '' ?>" href="reports.php?tab=expenses"><?= h(tr('تقرير المصروفات', 'Expenses Report')) ?></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<?php if ($dbError): ?>
|
||||
@ -240,6 +307,176 @@ require __DIR__ . '/includes/header.php';
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php elseif ($tab === 'expenses'): ?>
|
||||
|
||||
<style>
|
||||
@media print {
|
||||
body { font-size: 13pt !important; background: #fff; }
|
||||
.table-bordered th, .table-bordered td { border: 1px solid #000 !important; padding: 6px; }
|
||||
.table th { background-color: #f0f0f0 !important; -webkit-print-color-adjust: exact; color: #000; }
|
||||
.d-print-none { display: none !important; }
|
||||
.surface-card { box-shadow: none !important; border: none !important; padding: 0 !important; }
|
||||
.print-header { display: block !important; margin-bottom: 30px; }
|
||||
.page-break-inside-avoid { page-break-inside: avoid; }
|
||||
}
|
||||
.print-header { display: none; }
|
||||
</style>
|
||||
|
||||
<!-- Filters (Hidden on Print) -->
|
||||
<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="expenses">
|
||||
<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-2">
|
||||
<label class="form-label"><?= h(tr('التصنيف', 'Category')) ?></label>
|
||||
<select name="category_id" class="form-select">
|
||||
<option value=""><?= h(tr('الكل', 'All')) ?></option>
|
||||
<?php foreach($expenseCategories as $cat):
|
||||
if ($cat['id'] == $categoryFilter) {
|
||||
$catName = $cat['name_ar'] . ' / ' . $cat['name_en'];
|
||||
break;
|
||||
}
|
||||
?>
|
||||
<option value="<?= $cat['id'] ?>" <?= $categoryFilter == $cat['id'] ? 'selected' : '' ?> >
|
||||
<?= h($cat['name_ar'] . ' / ' . $cat['name_en']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label"><?= h(tr('الفرع', 'Branch')) ?></label>
|
||||
<select name="branch" class="form-select">
|
||||
<option value=""><?= h(tr('جميع الفروع', 'All Branches')) ?></option>
|
||||
<option value="general" <?= $branchFilter === 'general' ? 'selected' : '' ?>><?= h(tr('مصروفات عامة', 'General Expenses')) ?></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>
|
||||
|
||||
<!-- Formal Print Header -->
|
||||
<div class="print-header">
|
||||
<div class="text-center mb-4" style="border-bottom: 2px solid #000; padding-bottom: 15px;">
|
||||
<h2 style="font-weight: bold; margin:0;"><?= h(tr('تقرير المصروفات التفصيلي', 'Detailed Expenses Report')) ?></h2>
|
||||
<p style="margin: 5px 0 0; color: #555;"><?= h(tr('تاريخ الإصدار:', 'Generated on:')) ?> <?= date('Y-m-d H:i') ?></p>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4" style="border: 1px solid #000; padding: 15px; margin: 0;">
|
||||
<div class="col-8">
|
||||
<div style="margin-bottom: 5px;"><strong><?= h(tr('الفترة:', 'Period:')) ?></strong> <?= h($dateFrom) ?> <?= h(tr('إلى', 'to')) ?> <?= h($dateTo) ?></div>
|
||||
<?php if ($categoryFilter):
|
||||
$catName = '';
|
||||
foreach ($expenseCategories as $c) {
|
||||
if ($c['id'] == $categoryFilter) {
|
||||
$catName = $c['name_ar'] . ' / ' . $c['name_en'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<div style="margin-bottom: 5px;"><strong><?= h(tr('التصنيف:', 'Category:')) ?></strong> <?= h($catName) ?></div>
|
||||
<?php endif; ?>
|
||||
<div><strong><?= h(tr('الفرع:', 'Branch:')) ?></strong> <?= h($branchFilter ? ($branchFilter === 'general' ? tr('مصروفات عامة', 'General Expenses') : branch_label($branchFilter)) : tr('جميع الفروع', 'All Branches')) ?></div>
|
||||
</div>
|
||||
<div class="col-4 text-end">
|
||||
<div><strong><?= h(tr('بواسطة:', 'Requested By:')) ?></strong> <?= h($user['username']) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Results Table -->
|
||||
<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('طباعة رسمية', 'Formal Print')) ?></button>
|
||||
</div>
|
||||
|
||||
<?php if(empty($expensesReport)): ?>
|
||||
<p class="text-muted d-print-none"><?= h(tr('لا توجد مصروفات في هذه الفترة.', 'No expenses found in this period.')) ?></p>
|
||||
<div class="print-header text-center py-5">
|
||||
<h4><?= h(tr('لا توجد بيانات لهذه الفترة', 'No data for this period')) ?></h4>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-striped align-middle" style="width: 100%;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?= h(tr('التاريخ', 'Date')) ?></th>
|
||||
<th><?= h(tr('الفرع', 'Branch')) ?></th>
|
||||
<th><?= h(tr('التصنيف', 'Category')) ?></th>
|
||||
<th><?= h(tr('الوصف', 'Description')) ?></th>
|
||||
<th><?= h(tr('المسجل', 'Logged By')) ?></th>
|
||||
<th class="text-end"><?= h(tr('المبلغ', 'Amount')) ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$totalSum = 0;
|
||||
foreach($expensesReport as $exp):
|
||||
$totalSum += (float) $exp['amount'];
|
||||
?>
|
||||
<tr>
|
||||
<td><?= h(date('Y-m-d', strtotime((string)$exp['expense_date']))) ?></td>
|
||||
<td>
|
||||
<?php if (empty($exp['branch_code'])): ?>
|
||||
<?= h(tr('عام', 'General')) ?>
|
||||
<?php else:
|
||||
echo h(branch_label((string)$exp['branch_code']));
|
||||
endif; ?>
|
||||
</td>
|
||||
<td><?= h($exp['category_name_ar'] . ' / ' . $exp['category_name_en']) ?></td>
|
||||
<td><?= h((string)$exp['description']) ?></td>
|
||||
<td><?= h((string)$exp['created_by_name']) ?></td>
|
||||
<td class="text-end fw-bold"><?= h(currency((float)$exp['amount'])) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<tfoot class="table-dark">
|
||||
<tr>
|
||||
<td colspan="5" class="text-end"><strong><?= h(tr('الإجمالي الكلي', 'Grand Total')) ?></strong></td>
|
||||
<td class="text-end fw-bold fs-5"><strong><?= h(currency($totalSum)) ?></strong></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Signatures (Print Only) -->
|
||||
<div class="print-header mt-5 pt-5 page-break-inside-avoid">
|
||||
<div class="row text-center mt-5">
|
||||
<div class="col-4">
|
||||
<p><strong><?= h(tr('المحاسب / المُعد', 'Prepared by / Accountant')) ?></strong></p>
|
||||
<hr style="width: 60%; margin: 40px auto 0; border-top: 1px solid #000;">
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<p><strong><?= h(tr('المراجع', 'Checked by')) ?></strong></p>
|
||||
<hr style="width: 60%; margin: 40px auto 0; border-top: 1px solid #000;">
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<p><strong><?= h(tr('المدير العام', 'General Manager')) ?></strong></p>
|
||||
<hr style="width: 60%; margin: 40px auto 0; border-top: 1px solid #000;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php elseif ($tab === 'orders'): ?>
|
||||
|
||||
<div class="card mb-4 d-print-none">
|
||||
@ -321,6 +558,53 @@ require __DIR__ . '/includes/header.php';
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<!-- Online Orders Section -->
|
||||
<div class="surface-card mt-4 mb-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3 d-print-none">
|
||||
<h3 class="h5 mb-0"><i class="bi bi-globe me-2 text-primary"></i><?= h(tr('طلبات المتجر الإلكتروني (نشطة)', 'Active Online Store Orders')) ?></h3>
|
||||
<a class="btn btn-outline-primary btn-sm" href="online_orders.php"><i class="bi bi-box-arrow-up-right"></i> <?= h(tr('إدارة الطلبات', 'Manage Orders')) ?></a>
|
||||
</div>
|
||||
|
||||
<?php if(empty($onlineOrders)): ?>
|
||||
<p class="text-muted"><?= h(tr('لا توجد طلبات متجر نشطة حالياً.', 'No active online orders currently.')) ?></p>
|
||||
<?php else: ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-hover align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th><?= h(tr('التاريخ', 'Date')) ?></th>
|
||||
<th><?= h(tr('رقم الطلب', 'Order ID')) ?></th>
|
||||
<th><?= h(tr('العميل', 'Customer')) ?></th>
|
||||
<th><?= h(tr('هاتف العميل', 'Customer Phone')) ?></th>
|
||||
<th><?= h(tr('العنوان', 'Address')) ?></th>
|
||||
<th><?= h(tr('الحالة', 'Status')) ?></th>
|
||||
<th class="text-end"><?= h(tr('الإجمالي', 'Total')) ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach($onlineOrders as $order): ?>
|
||||
<tr>
|
||||
<td><?= h(date('Y-m-d H:i', strtotime((string)$order['created_at']))) ?></td>
|
||||
<td>#<?= h((string)$order['id']) ?></td>
|
||||
<td><?= h((string)($order['customer_name'] ?: '-')) ?></td>
|
||||
<td><?= h((string)($order['customer_phone'] ?: '-')) ?></td>
|
||||
<td><?= h((string)($order['customer_address'] ?: '-')) ?></td>
|
||||
<td>
|
||||
<?php if ($order['status'] === 'pending'): ?>
|
||||
<span class="badge bg-warning text-dark"><?= h(tr('قيد الانتظار', 'Pending')) ?></span>
|
||||
<?php elseif ($order['status'] === 'accepted'): ?>
|
||||
<span class="badge bg-info text-dark"><?= h(tr('مقبول', 'Accepted')) ?></span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td class="text-end fw-bold text-primary"><?= h(currency((float)$order['total_amount'])) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php elseif ($tab === 'daily'): ?>
|
||||
|
||||
<div class="card mb-4 d-print-none">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user