Approval Workflow System
Multi-step approval workflows with role-based and user-specific verification.
Overview
The Approval Workflow System enables you to create multi-step approval processes for any entity in your application (e.g., leave requests, expenses, purchase orders). Each step can be verified by a specific role or user.
Key Features
- Multi-Step Workflows - Define sequential approval steps
- Role-Based Verification - Assign steps to roles (e.g., "Manager", "HR")
- User-Specific Verification - Assign steps to specific users
- Polymorphic Association - Attach workflows to any entity type
- Audit Trail - Full history of approvals and rejections
Database Schema
| Table | Purpose |
|---|---|
approval_definitions | Workflow templates (name, entity_type, description) |
approval_definition_steps | Steps within a workflow (order, verifier_type, verifier_id, label) |
approval_requests | Active workflow instances (status, current_step, entity reference) |
approval_interactions | Audit log of all actions (approve/reject with comments) |
Setup Multi-Level Verification
To establish a multi-level approval process (e.g., User -> Manager -> HR), you need to define Approval Rules. The system uses these rules to generate the required steps when a workflow starts.
Configuration via Admin UI (Web GUI)
You can configure approval workflows directly from the Admin Panel without writing code. The system allows you to define multi-step processes dynamically.
- Navigate to Admin > Workflows > Create Workflow (
/admin/workflows/create). - Select the Entity Type (e.g., "Leave Request") and give it a name.
- Use the "Add Step" button to define the approval hierarchy:
- Step 1: Select "Role" -> "Manager". Label it "Manager Approval".
- Step 2: Select "Role" -> "HR". Label it "HR Verification".
- Step 3: Select "User" -> "CEO" (optional). Label it "Final Sign-off".
- Click Create Workflow to save.
The system automatically saves these definitions to the approval_definitions table and uses them whenever a new request is started for that entity type. You can view and manage existing workflows at /admin/workflows.
How it works
- When
startWorkflow()is called, the system fetches all rules for the given `permissionId`. - It creates Approval Steps for each rule, ordered by `sortOrder`.
- Step 1 becomes
PENDING. Steps 2+ map toBLOCKEDor waiting status. - When Level 1 approves, Level 2 becomes
PENDINGautomatically.
Usage
1. Create a Workflow Definition (Admin UI)
Navigate to /admin/workflows/create and define:
- Workflow Name (e.g., "Leave Request Approval")
- Entity Type (e.g., "leave_request")
- Steps with verifiers (Role or User) and labels
2. Start a Workflow (Code)
use App\Domain\Approval\Services\ApprovalService;
$approvalService = new ApprovalService();
// When a leave request is submitted
$requestId = $approvalService->startWorkflow(
entityType: 'leave_request',
entityId: $leaveRequest->id,
requesterId: auth()->id()
);
if ($requestId) {
// Workflow started, request is now pending
}3. View Pending Approvals
Users can view items waiting for their approval at /admin/approvals
// Get pending items for current user
$pending = $approvalService->getPendingItems($userId, $roleIds);4. Approve or Reject
// Approve (moves to next step or marks as approved)
$approvalService->approve($requestId, $userId, 'Looks good!');
// Reject (marks entire request as rejected)
$approvalService->reject($requestId, $userId, 'Budget exceeded');Service Methods
| Method | Description |
|---|---|
startWorkflow($entityType, $entityId, $requesterId) | Initiates a new approval request based on the workflow definition for the entity type |
getPendingItems($userId, $roleIds) | Returns pending requests where the user (or their roles) is the current step verifier |
approve($requestId, $userId, $comment) | Approves the current step. Advances to next step or marks as fully approved. |
reject($requestId, $userId, $comment) | Rejects the request. Marks status as 'rejected'. |
Admin Routes
| Route | Description | Permission |
|---|---|---|
/admin/workflows | List all workflow definitions | workflows.manage |
/admin/workflows/create | Create new workflow | workflows.manage |
/admin/workflows/test | Create test workflow and request | workflows.manage |
/admin/approvals | View pending approvals for current user | approvals.view |
/admin/approvals/action | Approve/Reject action endpoint | approvals.view |
Integration Example
To integrate with an existing entity (e.g., Leave Request):
// In LeaveRequestService or Controller after creating a leave request:
class LeaveRequestService
{
private ApprovalService $approvalService;
public function submitLeaveRequest(LeaveRequest $request): int
{
// Save the leave request
$leaveId = $this->leaveRepo->save($request);
// Start approval workflow
$this->approvalService->startWorkflow(
entityType: 'leave_request',
entityId: $leaveId,
requesterId: $request->userId
);
return $leaveId;
}
}