aiarmada / inventory
Multi-location inventory and warehouse management system for Laravel with allocation strategies, cart integration, and movement tracking
Requires
- php: ^8.4
- composer-runtime-api: ^2.1
- ext-intl: *
Requires (Dev)
- akaunting/laravel-money: ^6.0
- anourvalar/eloquent-serialize: ^1.2
- chillerlan/php-qrcode: ^5.0
- filament/blueprint: ^2.0
- filament/filament: ^5.0
- filament/spatie-laravel-media-library-plugin: ^5.0
- filament/support: *
- guzzlehttp/guzzle: ^7.0
- larastan/larastan: ^3.0
- laravel/boost: ^2.0
- laravel/cashier: ^16.0
- laravel/framework: ^12.0|^13.0
- laravel/pint: ^1.0
- laravel/prompts: ^0.3.5
- league/csv: ^9.27
- league/flysystem-aws-s3-v3: ^3.0
- lorisleiva/laravel-actions: ^2.9
- nunomaduro/essentials: ^1.0
- nunomaduro/termwind: ^2.0
- openspout/openspout: ^4.23
- orchestra/testbench: ^10.0|^11.0
- owen-it/laravel-auditing: ^14.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phiki/phiki: ^2.0
- phpstan/extension-installer: ^1.1
- phpstan/phpstan: ^2.1
- pragmarx/google2fa: ^8.0
- pragmarx/google2fa-qrcode: ^3.0
- rector/rector: ^2.0
- spatie/browsershot: ^5.0
- spatie/laravel-activitylog: ^4.10
- spatie/laravel-data: ^4.18
- spatie/laravel-health: ^1.34
- spatie/laravel-medialibrary: ^11.0
- spatie/laravel-model-states: ^2.8
- spatie/laravel-package-tools: ^1.92
- spatie/laravel-pdf: ^2.4
- spatie/laravel-permission: ^7.2
- spatie/laravel-ray: ^1.29
- spatie/laravel-settings: ^3.6
- spatie/laravel-sluggable: ^3.7
- spatie/laravel-tags: ^4.2
- spatie/laravel-webhook-client: ^3.4
- staudenmeir/belongs-to-through: ^2.5
- staudenmeir/eloquent-has-many-deep: ^1.7
- symplify/monorepo-builder: ^12.5
README
A comprehensive multi-location inventory and warehouse management package for Laravel with allocation strategies, cart integration, and full movement tracking.
Features
- Multi-Location Support - Manage inventory across warehouses, stores, and fulfillment centers
- Allocation Strategies - Priority-based, FIFO, least-stock, or single-location allocation
- Split Allocation - Automatically split orders across multiple locations
- Cart Integration - Seamless integration with
aiarmada/cartpackage - Movement Tracking - Full audit trail of all inventory movements
- Reservation System - Prevent overselling during checkout
- Per-Product Strategy - Override global allocation strategy per product
- Event-Driven - Dispatch events for low inventory, allocation, and more
- UUID Support - First-class UUID support for all models
Installation
composer require aiarmada/inventory
The package auto-discovers and registers itself. Run migrations:
php artisan migrate
Optionally publish the configuration:
php artisan vendor:publish --tag=inventory-config
Quick Start
1. Add Trait to Your Model
use AIArmada\Inventory\Contracts\InventoryableInterface; use AIArmada\Inventory\Traits\HasInventory; use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Model; class Product extends Model implements InventoryableInterface { use HasUuids, HasInventory; }
2. Manage Inventory
use AIArmada\Inventory\Facades\Inventory; $product = Product::find($id); $location = InventoryLocation::where('code', 'WAREHOUSE-A')->first(); // Receive inventory $product->receive($location->id, 100, 'Initial stock'); // Ship inventory $product->ship($location->id, 5, 'sale', 'ORDER-123'); // Transfer between locations $product->transfer($fromLocationId, $toLocationId, 20); // Check availability $total = $product->getTotalAvailable(); // All locations $atLocation = $product->getInventoryAtLocation($locationId); // Check if sufficient inventory exists $product->hasInventory(10); // true if >= 10 available across all locations
3. Use Facades
use AIArmada\Inventory\Facades\Inventory; use AIArmada\Inventory\Facades\InventoryAllocation; // Inventory operations Inventory::receive($product, $locationId, 100, 'Supplier delivery'); Inventory::ship($product, $locationId, 5, 'sale', 'ORDER-123'); Inventory::transfer($product, $fromId, $toId, 20); Inventory::getAvailability($product); // [locationId => available, ...] // Allocations InventoryAllocation::allocate($product, 5, 'cart-123', 30); // Returns Collection<InventoryAllocation> InventoryAllocation::release($product, 'cart-123'); InventoryAllocation::commit('cart-123', 'ORDER-456');
Allocation Strategies
The package supports multiple allocation strategies:
| Strategy | Description |
|---|---|
priority |
Allocate from highest-priority location first (default) |
fifo |
Allocate from location with oldest stock |
least_stock |
Allocate to balance inventory across locations |
single_location |
Must fulfill from one location or fail |
Global Strategy
Set in config or environment:
// config/inventory.php 'allocation_strategy' => 'priority', // Or via .env INVENTORY_ALLOCATION_STRATEGY=priority
Per-Product Strategy
Override on individual products:
// In your Product model public function getAllocationStrategy(): ?AllocationStrategy { return $this->allocation_strategy ? AllocationStrategy::from($this->allocation_strategy) : null; // null = use global config }
Or set directly on inventory levels:
$level = $product->inventoryLevels()->where('location_id', $locationId)->first(); $level->update(['allocation_strategy' => 'single_location']);
Split Allocation
When enabled (default), allocations can span multiple locations:
// Product needs 100 units, Warehouse A has 60, Warehouse B has 50 $allocations = InventoryAllocation::allocate($product, 100, 'cart-123'); // Returns 2 allocations: // - 60 from Warehouse A // - 40 from Warehouse B
Disable split allocation to require single-location fulfillment:
// config/inventory.php 'allow_split_allocation' => false,
Cart Integration
When installed with aiarmada/cart, the package automatically:
- Extends
CartManagerwith inventory methods - Releases allocations when carts are cleared
- Commits inventory on payment success
use AIArmada\Cart\Facades\Cart; // Allocate inventory for checkout $allocations = Cart::allocateAllInventory(30); // 30 min TTL // Validate availability $validation = Cart::validateInventory(); if (!$validation['available']) { foreach ($validation['issues'] as $issue) { // $issue['itemId'], $issue['requested'], $issue['available'] } } // Commit after payment Cart::commitInventory('ORDER-123'); // Release on abandon Cart::releaseAllInventory();
Events
| Event | Description |
|---|---|
InventoryReceived |
Stock received at location |
InventoryShipped |
Stock shipped from location |
InventoryTransferred |
Stock moved between locations |
InventoryAdjusted |
Stock level manually adjusted |
InventoryAllocated |
Stock allocated to cart |
InventoryReleased |
Allocation released |
LowInventoryDetected |
Stock below reorder point |
OutOfInventory |
Available stock reached zero |
Commands
# Clean up expired allocations
php artisan inventory:cleanup-allocations
Schedule in your console kernel:
$schedule->command('inventory:cleanup-allocations')->everyFiveMinutes();
Configuration
Key options in config/inventory.php:
return [ 'allocation_strategy' => 'priority', 'allocation_ttl_minutes' => 30, 'allow_split_allocation' => true, 'default_reorder_point' => 10, 'cart' => [ 'enabled' => true, ], 'payment' => [ 'auto_commit' => true, ], ];
Documentation
Testing
./vendor/bin/pest tests/src/Inventory
License
MIT License. See LICENSE for details.