matjeninstudio / laravel-contact-approvable
A Laravel package for managing contacts and approval workflows with polymorphic relationships, audit trails, and a Telescope-like admin interface.
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/matjeninstudio/laravel-contact-approvable
Requires
- php: ^8.4
- illuminate/contracts: ^12.0
- illuminate/database: ^12.0
- illuminate/notifications: ^12.0
- illuminate/support: ^12.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^10.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
This package is auto-updated.
Last update: 2025-10-31 03:44:24 UTC
README
A powerful Laravel package that brings enterprise-grade approval workflows to your application. Manage contacts, approval requests, and audit trails with polymorphic relationships, real-time notifications, and a beautiful admin interface inspired by Laravel Telescope.
โจ Features
- ๐ Polymorphic Approval Workflows - Attach approval workflows to any Eloquent model
- ๐ฅ Contact Management - Create and manage contacts with user relationships
- ๐ Approval Records & Audit Trails - Track every approval decision with comments
- ๐ Multi-Channel Notifications - Email, database, and custom notification channels
- โก Auto-Approval Support - Configure threshold-based or percentage-based auto-approvals
- โฐ Deadline Management - Set approval deadlines with automated reminders
- ๐จ Admin Interface - Telescope-like UI for monitoring approval workflows
- ๐ฏ Event-Driven Architecture - Comprehensive events for all approval lifecycle stages
- ๐ง Highly Configurable - Extensive configuration options for every feature
- ๐งช Fully Tested - Comprehensive test coverage with Pest PHP
๐ Requirements
- PHP 8.4 or higher
- Laravel 12.0 or higher
๐ฆ Installation
Install the package via Composer:
composer require matjeninstudio/laravel-contact-approvable
Publish the configuration file:
php artisan vendor:publish --provider="MatJeninStudio\ContactApprovable\ContactApprovableServiceProvider" --tag="config"
Publish and run the migrations:
php artisan vendor:publish --provider="MatJeninStudio\ContactApprovable\ContactApprovableServiceProvider" --tag="migrations" php artisan migrate
๐ Quick Start
1. Add the Trait to Your Model
use Illuminate\Database\Eloquent\Model; use MatJeninStudio\ContactApprovable\Traits\Approvable; class Document extends Model { use Approvable; // Your model code... }
2. Create a Contact and Request Approval
// Create a contact with approvers $contact = $document->createContact( name: 'Legal Department', users: [$legalUser1, $legalUser2], markAsApprover: true ); // Request approval $approval = $document->requestApproval($contact);
3. Approve or Reject
use MatJeninStudio\ContactApprovable\Models\ApprovalRecord; // Approve with comment ApprovalRecord::create([ 'approval_id' => $approval->id, 'user_id' => $legalUser1->id, 'is_approved' => true, 'comment' => 'Document reviewed and approved.', ]); // Check approval status $status = $document->getApprovalStatus(); // 'pending', 'approved', or 'rejected'
๐ Usage Guide
Working with Contacts
Contacts are groups of users that can approve requests. Each contact can have multiple users, and users can be designated as approvers.
Create a Contact
// Simple contact creation $contact = $model->createContact('Finance Team'); // With users and approvers $contact = $model->createContact( name: 'Executive Board', users: [$ceo, $cfo, $cto], isActive: true, markAsApprover: true ); // With mixed user types $contact = $model->createContact( name: 'HR Department', users: [1, 2, $userModel], // User IDs or models markAsApprover: true );
Manage Contact Users
// Attach users to existing contact $contact = $model->attachUsersToContact($contact, [$user1, $user2], markAsApprover: true); // Sync users (removes users not in the list) $contact = $model->syncContactUsers($contact, [$user1, $user3]); // Detach specific users $contact = $model->detachUsersFromContact($contact, [$user1]); // Detach all users $contact = $model->detachUsersFromContact($contact); // Update approver status $contact = $model->updateContactUserApproverStatus($contact, $user1, isApprover: true);
Approval Workflows
Request Approval
// Request approval from a contact $approval = $document->requestApproval($contact); // Request with contact ID $approval = $document->requestApproval(contactId: 1); // Check for pending approvals (prevents duplicates) $pendingApproval = $document->hasPendingApproval();
Process Approvals
use MatJeninStudio\ContactApprovable\Models\ApprovalRecord; // Approve ApprovalRecord::create([ 'approval_id' => $approval->id, 'user_id' => auth()->id(), 'is_approved' => true, 'comment' => 'Looks good to me!', ]); // Reject ApprovalRecord::create([ 'approval_id' => $approval->id, 'user_id' => auth()->id(), 'is_approved' => false, 'comment' => 'Please revise section 3.', ]);
Query Approval Status
// Get latest approval $latestApproval = $document->latestApproval(); // Get approval status $status = $document->getApprovalStatus(); // 'pending', 'approved', or 'rejected' // Check specific states $isPending = $approval->isPending(); $isApproved = $approval->isApproved(); $isRejected = $approval->isRejected(); // Query scopes use MatJeninStudio\ContactApprovable\Models\Approval; $pendingApprovals = Approval::pending()->get(); $approvedApprovals = Approval::approved()->get(); $rejectedApprovals = Approval::rejected()->get();
Events
The package dispatches events for all key actions, allowing you to hook into the approval lifecycle:
// Listen to approval events Event::listen(ApprovalRequestedEvent::class, function ($event) { // $event->approval Log::info('Approval requested', ['approval_id' => $event->approval->id]); }); Event::listen(ApprovalApprovedEvent::class, function ($event) { // $event->approvalRecord // Send custom notification, update related models, etc. }); Event::listen(ApprovalRejectedEvent::class, function ($event) { // $event->approvalRecord // Handle rejection logic });
Available Events:
- ApprovalRequestedEvent- When approval is requested
- ApprovalApprovedEvent- When approval is approved
- ApprovalRejectedEvent- When approval is rejected
- ContactCreatedEvent- When a contact is created
- ContactUpdatedEvent- When a contact is updated
- ContactDeletedEvent- When a contact is deleted
Notifications
The package includes built-in notifications that can be sent via multiple channels:
// Configure in config/contact-approvable.php 'notifications' => [ 'enabled' => true, 'channels' => ['mail', 'database'], 'queue' => true, 'queue_name' => 'default', ],
Built-in Notifications:
- ApprovalRequestedNotification- Sent to approvers when approval is requested
- ApprovalApprovedNotification- Sent when approval is approved
- ApprovalRejectedNotification- Sent when approval is rejected
Auto-Approval
Configure automatic approval based on threshold or percentage:
// In config/contact-approvable.php 'auto_approve' => [ 'enabled' => true, // Approve after 2 approvals 'threshold' => 2, // OR approve after 50% of approvers approve 'percentage' => 50, // Set to null to use threshold instead ],
Deadline Management
Set approval deadlines with automated reminders:
'deadline' => [ 'enabled' => true, 'default_days' => 7, // Approval expires in 7 days 'reminder_days' => 2, // Send reminder 2 days before deadline ],
โ๏ธ Configuration
The package is highly configurable. Here are some key configuration options:
// config/contact-approvable.php return [ // Admin interface route 'route' => 'contact-approvable', // Middleware for admin routes 'middleware' => ['web', 'auth'], // Customize table names 'table_names' => [ 'contacts' => 'contacts', 'contact_user' => 'contact_user', 'approvals' => 'approvals', 'approval_records' => 'approval_records', ], // Your User model 'user_model' => 'App\\Models\\User', // Enable/disable specific events 'events' => [ 'enabled' => true, 'dispatch' => [ 'approval_requested' => true, 'approval_approved' => true, 'approval_rejected' => true, ], ], // Admin interface settings 'admin' => [ 'per_page' => 15, 'real_time' => false, 'brand' => 'Contact Approvable', ], ];
๐ง Advanced Usage
Custom Polymorphic Relationships
The approval system works with any Eloquent model:
class Invoice extends Model { use Approvable; } class PurchaseOrder extends Model { use Approvable; } class Contract extends Model { use Approvable; } // All can use the same approval workflow $invoice->requestApproval($financeContact); $purchaseOrder->requestApproval($procurementContact); $contract->requestApproval($legalContact);
Relationship Access
// Get all approvals for a model $approvals = $document->approvals; // Get approval records through relationship $approval->records; // Get the approvable model from approval $model = $approval->approvable; // Get contact and users $contact = $approval->contact; $users = $contact->users; $approvers = $contact->approvers; // Only users marked as approvers
๐งช Testing
The package includes comprehensive tests using Pest PHP:
# Run all tests composer test # Run with coverage composer test-coverage # Run architecture tests composer test-arch # Run static analysis composer analyse # Format code composer format # Run linting (format + analyse) composer lint
๐ Use Cases
This package is perfect for:
- Document Approval Systems - Route documents through approval chains
- Purchase Order Management - Multi-level approval for procurement
- Contract Review Workflows - Legal and executive approvals
- Time-off Requests - HR approval workflows
- Expense Approvals - Finance department sign-offs
- Content Publishing - Editorial approval pipelines
- Change Request Management - IT change approval boards
- Quality Assurance - QA sign-off processes
๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (git checkout -b feature/amazing-feature)
- Commit your changes (git commit -m 'Add some amazing feature')
- Push to the branch (git push origin feature/amazing-feature)
- Open a Pull Request
๐ Security
If you discover any security-related issues, please email nuzulfikrie@gmail.com instead of using the issue tracker.
๐ License
The MIT License (MIT). Please see License File for more information.
๐จโ๐ป Credits
๐ Acknowledgments
- Inspired by Laravel Telescope's elegant UI design
- Built with Spatie's Laravel Package Tools
- Tested with Pest PHP
Made with โค๏ธ by MatJenin Studio