Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Process Approval Laravel Package

ringlesoft/laravel-process-approval

Multi-level approval workflows for Laravel Eloquent models. Define configurable, role-based approval steps and track review status across multiple approvers before execution. Supports Laravel 10+, publishable config/migrations/views, with optional UUID support.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require ringlesoft/laravel-process-approval
    php artisan process-approval:install
    php artisan migrate
    
  2. Define an Approvable Model

    use RingleSoft\LaravelProcessApproval\Traits\Approvable;
    use RingleSoft\LaravelProcessApproval\Contracts\ApprovableModel;
    
    class FundRequest extends Model implements ApprovableModel
    {
        use Approvable;
    
        public function onApprovalCompleted(ProcessApproval $approval): bool
        {
            // Logic to execute on final approval
            return true;
        }
    }
    
  3. Create a Flow & Steps

    php artisan process-approval:flow add FundRequest
    php artisan process-approval:step add
    

    (Follow CLI prompts to configure roles/steps)

  4. Add UI Component

    <x-ringlesoft-approval-actions :model="$fundRequest" />
    

First Use Case

Scenario: A "Leave Request" model needs 3-tier approval (Manager → HR → Director).

  1. Implement ApprovableModel on LeaveRequest.
  2. Define onApprovalCompleted() to finalize the request (e.g., update status).
  3. Create a flow via CLI:
    php artisan process-approval:flow add LeaveRequest
    php artisan process-approval:step add
    
    (Select roles: manager, hr, director with actions approve/reject).
  4. Display approval buttons on the show page:
    <x-ringlesoft-approval-actions :model="$leaveRequest" />
    

Implementation Patterns

Core Workflows

  1. Model Submission

    • Auto-submit: Set $autoSubmit = true or implement enableAutoSubmit().
    • Manual submit: Add a submit button via the Approvable trait’s default UI.
    • Bypass: Implement bypassApprovalProcess() to skip workflows for specific cases.
  2. Approval Routing

    • Sequential Approval: Steps are processed in order (configurable via CLI).
    • Parallel Approval: Use multiple steps with the same role (e.g., two HR approvers).
    • Conditional Logic: Pause approvals with pauseApprovals() for custom validation.
  3. UI Integration

    • Status Summary: Use <x-ringlesoft-approval-status-summary> in lists:
      <x-ringlesoft-approval-status-summary :model="$request" />
      
    • Dynamic Actions: The <x-ringlesoft-approval-actions> component adapts to the current step (e.g., shows "Approve/Reject" only for the next approver).
  4. Event-Driven Extensions

    • Notifications: Subscribe to ProcessSubmittedEvent to notify approvers:
      public function handle(ProcessSubmittedEvent $event)
      {
          $nextApprover = $event->approvable->getNextApprover();
          Notification::send($nextApprover, new AwaitingApprovalNotification($event->approvable));
      }
      
    • Audit Logging: Listen to ProcessApprovedEvent/ProcessRejectedEvent to log actions.

Integration Tips

  • Role Management: Ensure roles (e.g., manager) exist in your roles table (e.g., Spatie’s laravel-permission).
  • Multi-Tenancy: Configure multi_tenancy_field in process_approval.php to scope approvals by tenant.
  • Custom Views: Publish and override Blade components (e.g., approval-actions.blade.php) for theming.
  • Testing: Use the Approvals facade to mock approvals in tests:
    $approval = Approvals::approve($request, $user);
    

Gotchas and Tips

Pitfalls

  1. Migration Conflicts

    • Issue: Running php artisan migrate twice if load_migrations is true in config.
    • Fix: Set load_migrations: false after publishing migrations manually or use process-approval:install.
  2. UUID Mismatches

    • Issue: Mixing UUID/non-UUID migrations breaks polymorphic relations.
    • Fix: Stick to one type (prefer UUIDs for new projects via --uuids flag).
  3. Missing Roles

    • Issue: Approval steps fail if referenced roles don’t exist.
    • Fix: Verify roles exist before creating steps:
      php artisan role:create manager --permissions=approve,reject
      
  4. Circular Dependencies

    • Issue: onApprovalCompleted() failing causes stuck approvals.
    • Fix: Use transactions or rollback logic:
      public function onApprovalCompleted(ProcessApproval $approval): bool
      {
          DB::transaction(function () use ($approval) {
              $this->update(['status' => 'approved']);
              // Other logic...
          });
          return true;
      }
      
  5. UI Styling Quirks

    • Issue: Tailwind/Bootstrap classes conflict with custom CSS.
    • Fix: Override published views or adjust css_library in config.

Debugging Tips

  • Check Approval Flow:

    php artisan process-approval:flow list
    

    Verify steps are correctly ordered and roles are assigned.

  • Inspect Model State: Use the getApprovalStatus() method to debug:

    $request->getApprovalStatus(); // Returns ['step' => 1, 'status' => 'pending']
    
  • Event Debugging: Temporarily log events in a listener:

    public function handle(ApprovalNotificationEvent $event)
    {
        Log::info('Approval Event:', $event->toArray());
    }
    
  • Database Inspection: Check the approvals and approval_steps tables for orphaned records:

    SELECT * FROM approvals WHERE model_type = 'App\Models\FundRequest';
    

Extension Points

  1. Custom Approval Actions Extend the ApproveAction class to add custom logic (e.g., auto-approve if amount < $100):

    class CustomApproveAction extends ApproveAction
    {
        public function handle(ProcessApproval $approval)
        {
            if ($approval->approvable->amount < 100) {
                return $this->approve($approval);
            }
            return parent::handle($approval);
        }
    }
    
  2. Dynamic Role Assignment Override getNextApprover() in your model:

    public function getNextApprover(): ?User
    {
        return User::where('department', $this->department)->first();
    }
    
  3. API Integration Use the Approvals facade in controllers:

    $approval = Approvals::approve($request, auth()->user());
    return response()->json(['status' => 'approved']);
    
  4. Localization Publish translations and override messages:

    php artisan vendor:publish --tag="approvals-translations"
    

    Then modify resources/lang/en/approval.php.

  5. Performance

    • Eager Load Approvers: Use with(['nextApprover']) in queries.
    • Cache Flows: Cache the approval_steps query in AppServiceProvider:
      Cache::remember('approval_flows', now()->addHours(1), function () {
          return ApprovalFlow::with('steps')->get();
      });
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony