Add Asset Management app
Assets from purchase invoice lines, straight-line depreciation/amortization with salvage value, disposals, and [Asset Mgmt] sources in Batch GL Entries. Green third workspace with an app access guard.
This commit is contained in:
+87
-69
@@ -29,34 +29,58 @@ $topbar_avatar_src = $topbar_picture
|
||||
: htmlspecialchars($server_url . 'assets/images/avatar-1.jpg', ENT_QUOTES, 'UTF-8');
|
||||
|
||||
// ── App switcher ──────────────────────────────────────────────────────────────
|
||||
require_once __DIR__ . '/assets/utils/app_registry.php';
|
||||
$topbar_app_access = $_SESSION['login_app_access'] ?? 'wms';
|
||||
|
||||
// Detect which app this page belongs to.
|
||||
// Master-data pages (/accounting/, /inventory/, /contact/, /setting/) are neutral — don't change the session.
|
||||
$_wms_paths = ['/dashboard/', '/ics/', '/order/', '/po/', '/reports/'];
|
||||
$_ac_paths = ['/ac_dashboard/', '/revenue/', '/expense/', '/finance/', '/journal/'];
|
||||
// '/asset_dashboard/' and '/ac_dashboard/' do not match '/dashboard/' (no slash before "dashboard").
|
||||
$_app_paths = [
|
||||
'wms' => ['/dashboard/', '/ics/', '/order/', '/po/', '/reports/'],
|
||||
'accounting' => ['/ac_dashboard/', '/revenue/', '/expense/', '/finance/', '/journal/'],
|
||||
'asset' => ['/asset_dashboard/', '/asset/'],
|
||||
];
|
||||
|
||||
$topbar_current_app = null; // null = neutral page (master data / setting)
|
||||
foreach ($_wms_paths as $_p) {
|
||||
if (str_contains($_SERVER['PHP_SELF'], $_p)) { $topbar_current_app = 'wms'; break; }
|
||||
}
|
||||
if (!$topbar_current_app) {
|
||||
foreach ($_ac_paths as $_p) {
|
||||
if (str_contains($_SERVER['PHP_SELF'], $_p)) { $topbar_current_app = 'accounting'; break; }
|
||||
foreach ($_app_paths as $_app_key => $_paths) {
|
||||
foreach ($_paths as $_p) {
|
||||
if (str_contains($_SERVER['PHP_SELF'], $_p)) { $topbar_current_app = $_app_key; break 2; }
|
||||
}
|
||||
}
|
||||
|
||||
// Asset Management pages are only for users given that app.
|
||||
if ($topbar_current_app === 'asset' && !app_can_access($topbar_app_access, 'asset')) {
|
||||
while (ob_get_level() > 0) {
|
||||
ob_end_clean();
|
||||
}
|
||||
header('Location: ' . $server_url . app_home_path($app_registry, app_default_for_access($app_registry, $topbar_app_access)));
|
||||
exit;
|
||||
}
|
||||
|
||||
// Only persist to session when on a definitive app page
|
||||
if ($topbar_current_app) {
|
||||
$_SESSION['login_current_app'] = $topbar_current_app;
|
||||
}
|
||||
// Default session on first visit or neutral pages
|
||||
if (empty($_SESSION['login_current_app'])) {
|
||||
$_SESSION['login_current_app'] = ($topbar_app_access === 'accounting') ? 'accounting' : 'wms';
|
||||
$_SESSION['login_current_app'] = app_default_for_access($app_registry, $topbar_app_access);
|
||||
}
|
||||
|
||||
$topbar_show_wms = in_array($topbar_app_access, ['all', 'wms']);
|
||||
$topbar_show_accounting = in_array($topbar_app_access, ['all', 'accounting']);
|
||||
$topbar_show_wms = app_can_access($topbar_app_access, 'wms');
|
||||
$topbar_show_accounting = app_can_access($topbar_app_access, 'accounting');
|
||||
$topbar_switch_apps = array_filter(
|
||||
$app_registry,
|
||||
fn($key) => app_can_access($topbar_app_access, $key),
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
|
||||
// Per-app colour. WMS keeps the compiled orange theme (#E66239); the others override it.
|
||||
$_app_themes = [
|
||||
'accounting' => ['main' => '#0284c7', 'rgb' => '2, 132, 199', 'dark' => '#0369a1', 'subtle' => '#e0f2fe', 'border' => '#bae6fd'],
|
||||
'asset' => ['main' => '#16a34a', 'rgb' => '22, 163, 74', 'dark' => '#15803d', 'subtle' => '#dcfce7', 'border' => '#bbf7d0'],
|
||||
];
|
||||
$_theme_app = $_SESSION['login_current_app'] ?? 'wms';
|
||||
$_theme = $_app_themes[$_theme_app] ?? null;
|
||||
|
||||
$_usage = (new UsageGuard($pdo1, (int)$_SESSION['login_company_id'], $packages))->getStatus();
|
||||
$_usage_max_pct = max($_usage['daily_pct'], $_usage['weekly_pct']);
|
||||
@@ -64,67 +88,67 @@ $_usage_warn = $_usage_max_pct >= 80 && $_usage_max_pct < 100;
|
||||
$_usage_full = $_usage_max_pct >= 100;
|
||||
?>
|
||||
|
||||
<?php if (($_SESSION['login_current_app'] ?? 'wms') === 'accounting'): ?>
|
||||
<style id="theme-accounting">
|
||||
<?php if ($_theme): ?>
|
||||
<style id="theme-<?php echo $_theme_app; ?>">
|
||||
:root {
|
||||
--bs-primary: #0284c7;
|
||||
--bs-primary-rgb: 2, 132, 199;
|
||||
--bs-primary-bg-subtle: #e0f2fe;
|
||||
--bs-primary-border-subtle: #bae6fd;
|
||||
--bs-primary-text-emphasis: #0369a1;
|
||||
--bs-focus-ring-color: rgba(2, 132, 199, .25);
|
||||
--bs-primary: <?php echo $_theme['main']; ?>;
|
||||
--bs-primary-rgb: <?php echo $_theme['rgb']; ?>;
|
||||
--bs-primary-bg-subtle: <?php echo $_theme['subtle']; ?>;
|
||||
--bs-primary-border-subtle: <?php echo $_theme['border']; ?>;
|
||||
--bs-primary-text-emphasis: <?php echo $_theme['dark']; ?>;
|
||||
--bs-focus-ring-color: rgba(<?php echo $_theme['rgb']; ?>, .25);
|
||||
}
|
||||
/* Sidebar active/hover — hardcoded in theme */
|
||||
.sidebar .nav-link:hover,
|
||||
.sidebar .nav-link.active {
|
||||
color: #0284c7 !important;
|
||||
background-color: rgba(2, 132, 199, 0.09) !important;
|
||||
color: <?php echo $_theme['main']; ?> !important;
|
||||
background-color: rgba(<?php echo $_theme['rgb']; ?>, 0.09) !important;
|
||||
}
|
||||
/* Buttons */
|
||||
.btn-primary {
|
||||
--bs-btn-bg: #0284c7;
|
||||
--bs-btn-border-color: #0284c7;
|
||||
--bs-btn-hover-bg: #0369a1;
|
||||
--bs-btn-hover-border-color: #0369a1;
|
||||
--bs-btn-active-bg: #0369a1;
|
||||
--bs-btn-active-border-color: #0369a1;
|
||||
--bs-btn-disabled-bg: #0284c7;
|
||||
--bs-btn-disabled-border-color: #0284c7;
|
||||
--bs-btn-focus-shadow-rgb: 2, 132, 199;
|
||||
--bs-btn-bg: <?php echo $_theme['main']; ?>;
|
||||
--bs-btn-border-color: <?php echo $_theme['main']; ?>;
|
||||
--bs-btn-hover-bg: <?php echo $_theme['dark']; ?>;
|
||||
--bs-btn-hover-border-color: <?php echo $_theme['dark']; ?>;
|
||||
--bs-btn-active-bg: <?php echo $_theme['dark']; ?>;
|
||||
--bs-btn-active-border-color: <?php echo $_theme['dark']; ?>;
|
||||
--bs-btn-disabled-bg: <?php echo $_theme['main']; ?>;
|
||||
--bs-btn-disabled-border-color: <?php echo $_theme['main']; ?>;
|
||||
--bs-btn-focus-shadow-rgb: <?php echo $_theme['rgb']; ?>;
|
||||
}
|
||||
.btn-outline-primary {
|
||||
--bs-btn-color: #0284c7;
|
||||
--bs-btn-border-color: #0284c7;
|
||||
--bs-btn-hover-bg: #0284c7;
|
||||
--bs-btn-hover-border-color: #0284c7;
|
||||
--bs-btn-active-bg: #0284c7;
|
||||
--bs-btn-active-border-color: #0284c7;
|
||||
--bs-btn-disabled-color: #0284c7;
|
||||
--bs-btn-disabled-border-color: #0284c7;
|
||||
--bs-btn-color: <?php echo $_theme['main']; ?>;
|
||||
--bs-btn-border-color: <?php echo $_theme['main']; ?>;
|
||||
--bs-btn-hover-bg: <?php echo $_theme['main']; ?>;
|
||||
--bs-btn-hover-border-color: <?php echo $_theme['main']; ?>;
|
||||
--bs-btn-active-bg: <?php echo $_theme['main']; ?>;
|
||||
--bs-btn-active-border-color: <?php echo $_theme['main']; ?>;
|
||||
--bs-btn-disabled-color: <?php echo $_theme['main']; ?>;
|
||||
--bs-btn-disabled-border-color: <?php echo $_theme['main']; ?>;
|
||||
}
|
||||
.pagination {
|
||||
--bs-pagination-active-bg: #0284c7;
|
||||
--bs-pagination-active-border-color: #0284c7;
|
||||
--bs-pagination-active-bg: <?php echo $_theme['main']; ?>;
|
||||
--bs-pagination-active-border-color: <?php echo $_theme['main']; ?>;
|
||||
}
|
||||
.nav-pills { --bs-nav-pills-link-active-bg: #0284c7; }
|
||||
.dropdown-menu { --bs-dropdown-link-active-bg: #0284c7; }
|
||||
.nav-pills { --bs-nav-pills-link-active-bg: <?php echo $_theme['main']; ?>; }
|
||||
.dropdown-menu { --bs-dropdown-link-active-bg: <?php echo $_theme['main']; ?>; }
|
||||
.list-group {
|
||||
--bs-list-group-active-bg: #0284c7;
|
||||
--bs-list-group-active-border-color: #0284c7;
|
||||
--bs-list-group-active-bg: <?php echo $_theme['main']; ?>;
|
||||
--bs-list-group-active-border-color: <?php echo $_theme['main']; ?>;
|
||||
}
|
||||
.progress, .progress-stacked { --bs-progress-bar-bg: #0284c7; }
|
||||
.progress, .progress-stacked { --bs-progress-bar-bg: <?php echo $_theme['main']; ?>; }
|
||||
.table-primary {
|
||||
--bs-table-color: #0284c7;
|
||||
--bs-table-bg: rgba(2, 132, 199, 0.09);
|
||||
--bs-table-border-color: rgba(2, 132, 199, 0.15);
|
||||
--bs-table-striped-bg: rgba(2, 132, 199, 0.12);
|
||||
--bs-table-active-bg: rgba(2, 132, 199, 0.15);
|
||||
--bs-table-hover-bg: rgba(2, 132, 199, 0.12);
|
||||
--bs-table-color: <?php echo $_theme['main']; ?>;
|
||||
--bs-table-bg: rgba(<?php echo $_theme['rgb']; ?>, 0.09);
|
||||
--bs-table-border-color: rgba(<?php echo $_theme['rgb']; ?>, 0.15);
|
||||
--bs-table-striped-bg: rgba(<?php echo $_theme['rgb']; ?>, 0.12);
|
||||
--bs-table-active-bg: rgba(<?php echo $_theme['rgb']; ?>, 0.15);
|
||||
--bs-table-hover-bg: rgba(<?php echo $_theme['rgb']; ?>, 0.12);
|
||||
}
|
||||
thead.border-light th {
|
||||
background-color: rgba(2, 132, 199, 0.09) !important;
|
||||
color: #0284c7 !important;
|
||||
border-color: rgba(2, 132, 199, 0.15) !important;
|
||||
background-color: rgba(<?php echo $_theme['rgb']; ?>, 0.09) !important;
|
||||
color: <?php echo $_theme['main']; ?> !important;
|
||||
border-color: rgba(<?php echo $_theme['rgb']; ?>, 0.15) !important;
|
||||
}
|
||||
</style>
|
||||
<?php endif; ?>
|
||||
@@ -171,30 +195,24 @@ $_usage_full = $_usage_max_pct >= 100;
|
||||
<ul class="list-unstyled d-flex align-items-center mb-0 gap-1">
|
||||
|
||||
<!-- App switcher -->
|
||||
<?php if ($topbar_show_wms && $topbar_show_accounting): ?>
|
||||
<?php if (count($topbar_switch_apps) > 1): ?>
|
||||
<li class="dropdown">
|
||||
<a class="position-relative btn-icon btn-sm btn-light btn rounded-circle" data-bs-toggle="dropdown"
|
||||
aria-expanded="false" href="#" role="button" title="Switch App">
|
||||
<i class="ti ti-layout-grid" style="font-size:18px;"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-end p-2" style="min-width:170px;">
|
||||
<div class="dropdown-menu dropdown-menu-end p-2" style="min-width:210px;">
|
||||
<?php $_sess_app = $_SESSION['login_current_app'] ?? 'wms'; ?>
|
||||
<a href="<?php echo $server_url?>dashboard/index.php"
|
||||
class="dropdown-item rounded d-flex align-items-center gap-2 py-2 <?php echo $_sess_app === 'wms' ? 'active' : ''; ?>">
|
||||
<i class="ti ti-box"></i>
|
||||
<span>WMS</span>
|
||||
<?php if ($_sess_app === 'wms'): ?>
|
||||
<i class="ti ti-check ms-auto text-success"></i>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
<a href="<?php echo $server_url?>ac_dashboard/index.php"
|
||||
class="dropdown-item rounded d-flex align-items-center gap-2 py-2 <?php echo $_sess_app === 'accounting' ? 'active' : ''; ?>">
|
||||
<i class="ti ti-calculator"></i>
|
||||
<span>Accounting</span>
|
||||
<?php if ($_sess_app === 'accounting'): ?>
|
||||
<?php foreach ($topbar_switch_apps as $_app_key => $_app): ?>
|
||||
<a href="<?php echo $server_url . app_home_path($app_registry, $_app_key); ?>"
|
||||
class="dropdown-item rounded d-flex align-items-center gap-2 py-2 <?php echo $_sess_app === $_app_key ? 'active' : ''; ?>">
|
||||
<i class="ti <?php echo htmlspecialchars($_app['icon'] ?? 'ti-apps', ENT_QUOTES, 'UTF-8'); ?>"></i>
|
||||
<span><?php echo htmlspecialchars($_app['label'] ?? $_app_key, ENT_QUOTES, 'UTF-8'); ?></span>
|
||||
<?php if ($_sess_app === $_app_key): ?>
|
||||
<i class="ti ti-check ms-auto text-success"></i>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
|
||||
Reference in New Issue
Block a user