'Purchase',
'title' => '',
'amount' => '',
'priority' => 'Standard',
'needed_by' => '',
'justification' => '',
];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$action = trim((string) ($_POST['action'] ?? ''));
if (!verify_csrf($_POST['csrf_token'] ?? null)) {
flash('danger', 'Your session expired. Please try again.');
redirect('index.php');
}
if ($action === 'login') {
$candidate = authenticate_demo_user((string) ($_POST['email'] ?? ''), (string) ($_POST['password'] ?? ''));
if ($candidate) {
set_current_user($candidate);
flash('success', 'Signed in as ' . $candidate['name'] . '.');
redirect('index.php');
}
$loginError = 'Use one of the demo accounts below and the default password Twende2026.';
} elseif ($action === 'logout') {
logout_current_user();
flash('primary', 'Signed out successfully.');
redirect('index.php');
} elseif ($action === 'create_request') {
$currentUser = require_auth();
if (!can_submit_requests($currentUser)) {
flash('warning', 'Admin / Finance accounts can review and approve requests, but submission is reserved for department staff in this first MVP slice.');
redirect('index.php#submit');
}
$result = create_request($currentUser, $_POST);
if (!empty($result['success'])) {
flash('success', 'Request ' . $result['request_code'] . ' submitted and routed to the supervisor queue.');
redirect('request.php?id=' . (int) $result['id']);
}
$formErrors = $result['errors'] ?? [];
$oldForm = array_merge($oldForm, $result['values'] ?? []);
}
}
$currentUser = current_user();
$metrics = $currentUser ? dashboard_metrics($currentUser) : null;
$visibleRequests = $currentUser ? fetch_visible_requests($currentUser, 12) : [];
$queueRequests = $currentUser ? fetch_queue_requests($currentUser, 6) : [];
$timelineSample = [
['step' => 'Level 1', 'label' => 'Supervisor review'],
['step' => 'Level 2', 'label' => 'Head of Department'],
['step' => 'Level 3', 'label' => 'Admin / Finance'],
];
render_head(
'Department Request & Approval Manager',
'Submit departmental requests, route them through supervisor and HOD review, and close them with admin/finance sign-off.'
);
?>
Internal workflow portal
Track departmental requests from submission to final decision.
This first MVP slice already covers the end-to-end flow: employees submit a request, supervisors and HODs review by department level, and Admin / Finance completes the final sign-off with a visible audit trail.
= e($sample['step']) ?>
= e($sample['label']) ?>
Workflow
Create → Approve → Track
Departments
Operations + HR demos
Demo access
Password: Twende2026
What you can test immediately
- Submit a purchase, leave, access, travel, or maintenance request.
- Switch roles using the demo accounts and approve at each department level.
- Open a request detail page to review the full audit trail and latest note.
Portal sign in
Open the workflow dashboard
Use a demo staff account to experience the employee, approver, and admin states.
= e($loginError) ?>
| User |
Role |
Department |
|
= e($demoUser['name']) ?>
= e($demoUser['email']) ?>
|
= e($demoUser['role_label']) ?> |
= e($demoUser['department']) ?> |
Signed in as = e($currentUser['role_label']) ?>
Department request workflow, ready for daily use.
Submit requests, route them through the department chain, and keep every decision visible. The current policy is fixed to Supervisor → HOD → Admin / Finance for all departments in this first release.
= e($sample['step']) ?>
= e($sample['label']) ?>
Current profile
Name
= e($currentUser['name']) ?>
Role
= e($currentUser['role_label']) ?>
Department
= e($currentUser['department']) ?>
Access
= ($currentUser['approval_level'] ?? 0) > 0 ? 'Review + approve' : 'Submit + track' ?>
= ($currentUser['approval_level'] ?? 0) > 0 || is_admin_finance($currentUser) ? 'Visible requests' : 'My requests' ?>
= (int) ($metrics['visible_total'] ?? 0) ?>
Requests in your current scope
Open
= (int) ($metrics['open'] ?? 0) ?>
Still moving through approval levels
Awaiting my action
= (int) ($metrics['awaiting_action'] ?? 0) ?>
Items currently assigned to you
Approved
= (int) ($metrics['approved'] ?? 0) ?>
Closed requests in your scope
Create / input
Submit a new department request
Capture the essentials once, then let the workflow route it automatically to each level.
Submission disabled for Admin / Finance
Why submission is hidden
This MVP keeps Admin / Finance focused on final approvals and oversight. Use an employee, supervisor, or HOD account to create a request and then switch back here to complete level 3.
Please fix the following before submitting:
Approval queue
Requests waiting on you
Queue is filtered by your department and approval level.
= (int) count($queueRequests) ?> active
No items in your queue.
When a request reaches your level, it will appear here with a direct link to approve or reject.
Routing policy
Current approval design
All departments share the same three-step ladder in this first version. Admin can see every request; department approvers only see requests in their own department.
$definition): ?>
Level = (int) $level ?>
= e($definition['label']) ?>
= $level === 3 ? 'Applies across all departments' : 'Applies inside the requester’s department' ?>
Request list
= ($currentUser['approval_level'] ?? 0) > 0 || is_admin_finance($currentUser) ? 'Requests in view' : 'My request history' ?>
Open a row to inspect the approval trail, current stage, and latest decision comment.
Showing = (int) count($visibleRequests) ?> most recent records
No requests yet.
Create your first request above and it will appear here immediately.
| Request |
Department |
Requester |
Status |
Updated |
Action |
|
= e($request['title']) ?>
= e($request['request_code']) ?> · = e($request['request_type']) ?> · = format_money($request['amount']) ?>
|
= e($request['department']) ?> |
= e($request['requester_name']) ?>
= e($request['requester_email']) ?>
|
= e($request['status']) ?>
= e(level_label((int) $request['current_stage'])) ?>
|
= e(format_datetime($request['updated_at'])) ?> |
Open
|