PHPackages                             aldeebhasan/inventorix - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. aldeebhasan/inventorix

ActiveLibrary[Database &amp; ORM](/categories/database)

aldeebhasan/inventorix
======================

Modern inventory control for Laravel applications. Features include stock tracking, movement history, low stock alerts, and seamless integration with your existing models

1.0.0(1mo ago)025[2 PRs](https://github.com/aldeebhasan/Inventorix/pulls)MITPHPPHP ^8.3CI passing

Since Apr 20Pushed 2w agoCompare

[ Source](https://github.com/aldeebhasan/Inventorix)[ Packagist](https://packagist.org/packages/aldeebhasan/inventorix)[ Docs](https://github.com/aldeebhasan/inventorix)[ GitHub Sponsors]()[ RSS](/packages/aldeebhasan-inventorix/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (11)Versions (4)Used By (0)

Inventorix — Modern Inventory Control for Laravel
=================================================

[](#inventorix--modern-inventory-control-for-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/3aab31e6bdae082fa0447d9ffcf6d9db08c0a8eda2866941a13d200f0c32d5ac/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f616c64656562686173616e2f696e76656e746f7269782e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/aldeebhasan/inventorix)[![GitHub Tests Action Status](https://camo.githubusercontent.com/cdf94b57ad2b1f4d5950977d72fabd30a1b124999c5d0ca4dab5a1353b619411/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f616c64656562686173616e2f696e76656e746f7269782f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/aldeebhasan/inventorix/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/40e896f19f08db647d53bc0d5ce4545530442168c6588c8e91539178bbe82c94/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f616c64656562686173616e2f696e76656e746f7269782f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/aldeebhasan/inventorix/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Codacy Badge](https://camo.githubusercontent.com/3c06c13b96c138427eebbcf697eebf1e09d05d3790fd8e1ca2940a31d9f0bec9/68747470733a2f2f6170702e636f646163792e636f6d2f70726f6a6563742f62616467652f47726164652f6466613533316465313737323461633738376232333633346663363532303531)](https://app.codacy.com/gh/aldeebhasan/Inventorix/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)[![Total Downloads](https://camo.githubusercontent.com/11c658a5f0fbfd00c4d0e1afe28d584ae3493a7be57777f4b95c13e1eb73fe61/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f616c64656562686173616e2f696e76656e746f7269782e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/aldeebhasan/inventorix)

Inventorix is a Laravel package that adds full inventory control to any Eloquent model. It handles stock tracking, movement history, reservations, FIFO/LIFO/Average costing, threshold alerts, serial number tracking, transaction rollback, and demand velocity — all without changing your existing models.

Installation
------------

[](#installation)

```
composer require aldeebhasan/inventorix
```

Publish and run the migrations:

```
php artisan vendor:publish --tag="inventorix-migrations"
php artisan migrate
```

Publish the config file:

```
php artisan vendor:publish --tag="inventorix-config"
```

Setup
-----

[](#setup)

Add the `HasInventory` trait to any Eloquent model you want to track:

```
use Aldeebhasan\Inventorix\Traits\HasInventory;

class Product extends Model
{
    use HasInventory;
}
```

You must have at least one `Location` record in the database before performing stock operations. Locations represent warehouses, bins, or any physical storage unit and support parent/child hierarchies via `parent_id`.

Basic Usage
-----------

[](#basic-usage)

You can use the `HasInventory` trait methods directly on the model, or the `Inventorix` facade for lower-level control.

### Stock Operations

[](#stock-operations)

```
use Aldeebhasan\Inventorix\DTOs\StockOperationDto;

// Add stock
$product->addStock(quantity: 100, location: $location);

// Deduct stock
$product->deductStock(quantity: 10, location: $location);

// Set stock to an absolute quantity (reconciliation)
$product->adjustStock(newQuantity: 50, location: $location);

// Transfer between locations
$product->transfer(quantity: 20, from: $warehouseA, to: $warehouseB);
```

### StockOperationDto

[](#stockoperationdto)

Pass a `StockOperationDto` as the last argument to any operation to control its behaviour:

```
$options = new StockOperationDto(
    transaction: $existingTransaction,   // attach to an open bulk transaction
    causable: $order,                    // the model that caused this operation
    cost: 9.99,                          // explicit cost per unit (null = no cost, false = use model's cost_price)
    note: 'Purchase order #123',
    createdBy: auth()->id(),
    allowNegative: true,                 // allow stock to go below zero for this call
    expiresAt: now()->addHours(2),       // reservation TTL
    serials: ['SN-001', 'SN-002'],       // explicit serial numbers
    lotReference: 'LOT-2024-01',
    externalReference: 'PO-9876',
    reasonCode: 'purchase',
);

$product->addStock(100, $location, $options);
```

### Bulk / Grouped Transactions

[](#bulk--grouped-transactions)

Group multiple operations into a single atomic transaction:

```
use Aldeebhasan\Inventorix\Facades\Inventorix;

$transaction = Inventorix::bulk(function ($transaction) use ($product, $location) {
    $options = new StockOperationDto(transaction: $transaction);

    $product->addStock(50, $location, $options);
    $anotherProduct->deductStock(5, $location, $options);
});
```

If any operation inside the callback throws, the transaction is marked `RolledBack` and the exception propagates.

### Transaction Rollback

[](#transaction-rollback)

Reverse a committed transaction by creating a compensating reversal:

```
$reversalTransaction = Inventorix::rollback($transaction);
```

This replays every movement in reverse (adds become deducts and vice-versa), handles serial number compensation automatically, and fires a `TransactionRolledBack` event.

Reservations
------------

[](#reservations)

Reservations hold stock aside without permanently deducting it:

```
// Reserve stock
$reservation = $product->reserve(quantity: 5, location: $location);

// Release the reservation (stock returns to available)
$product->releaseReservation($reservation);

// Fulfill the reservation (converts reserved stock to a real deduction)
$product->fulfillReservation($reservation);
```

Reservations can have a TTL set via config (`reservation_ttl_minutes`) or per-call via `StockOperationDto::$expiresAt`. Run the scheduled command to expire stale reservations:

```
php artisan inventorix:expire-reservations
```

Querying Stock
--------------

[](#querying-stock)

```
// Stock record at a specific location
$stock = $product->stockAt($location);

// Totals (optionally scoped to a location, with or without child locations)
$product->totalStock();
$product->totalStock($location, includeChildren: true);
$product->availableStock($location);   // total - reserved
$product->reservedStock($location);

// Is stock below the configured low-stock threshold?
$product->isLowStock($location);

// Full summary array
$product->stockSummary($location);
// Returns: total_quantity, reserved_quantity, available_quantity, locations[], is_low_stock, last_movement_at
```

Valuation
---------

[](#valuation)

```
// Value of on-hand stock for this product (uses configured costing strategy)
$product->stockValuation($location);

// Total valuation across all stockables or scoped to a location
Inventorix::totalValuation($location);

// Valuation of movements caused by a specific model
Inventorix::valuationByCausable($order);
```

Costing strategy is set in config (`fifo`, `lifo`, or `average`). Movements must carry a `cost_per_unit` value (set via `StockOperationDto::$cost`) for movement-based costing to apply.

Demand Velocity
---------------

[](#demand-velocity)

```
// Average units deducted per day over the last N days
$product->stockVelocity($location, days: 30);

// How many days until stock runs out at current velocity
$product->daysOfStock($location, velocityDays: 30);

// The calendar day with the highest deductions in the last N days
$product->peakDemandDay($location, days: 90);
```

Thresholds &amp; Alerts
-----------------------

[](#thresholds--alerts)

```
// Set a low-stock threshold for a product at a location
$product->setStockThreshold(location: $location, minQuantity: 10, maxQuantity: 500);

// Manually trigger threshold evaluation
$product->checkThresholds($location);
```

Threshold checks run automatically after every `addStock`, `deductStock`, and `adjustStock` call. When stock crosses a boundary the package fires `LowStockReached` or `OverstockReached`. To find all items currently below threshold:

```
Inventorix::lowStockItems($location);          // scoped to a location
Inventorix::lowStockItems(stockableType: Product::class); // all products
```

Alert events can optionally be dispatched on a queue (`queue_alerts` / `alert_queue` in config). Threshold records are cached in-memory (configurable TTL via `threshold_cache`) to avoid a DB hit on every stock write.

Serial Number Tracking
----------------------

[](#serial-number-tracking)

Enable in config:

```
// config/inventorix.php
'serial_tracking' => [
    'enabled' => true,
],
```

When enabled, every `addStock` auto-generates a ULID serial number per unit, and every `deductStock` auto-consumes the oldest available serials at that location (FIFO). You can also supply explicit serial numbers:

```
$product->addStock(2, $location, new StockOperationDto(serials: ['SN-A1', 'SN-A2']));
$product->deductStock(1, $location, new StockOperationDto(serials: ['SN-A1']));
```

Reservations also lock specific serials:

```
$reservation = $product->reserve(1, $location, new StockOperationDto(serials: ['SN-A2']));
```

Lifecycle Hooks
---------------

[](#lifecycle-hooks)

Register callbacks that fire before/after add and deduct operations:

```
use Aldeebhasan\Inventorix\Facades\Inventorix;

Inventorix::beforeAdd(function ($stockable, $quantity, $location, $dto) {
    // called before every addStock
});

Inventorix::afterAdd(function ($stock, $movement) {
    // called after every addStock
});

Inventorix::beforeDeduct(function ($stockable, $quantity, $location, $dto) { });
Inventorix::afterDeduct(function ($stock, $movement) { });
```

Custom Costing Strategy Per Model
---------------------------------

[](#custom-costing-strategy-per-model)

Override the costing strategy for a specific model by implementing `inventorixCostingStrategy()`:

```
use Aldeebhasan\Inventorix\Enums\CostingStrategy;

class Product extends Model
{
    use HasInventory;

    public function inventorixCostingStrategy(): CostingStrategy
    {
        return CostingStrategy::Average;
    }
}
```

Events
------

[](#events)

All events live in `Aldeebhasan\Inventorix\Events\`. Disable all events or specific ones in config:

```
'events' => [
    'enabled' => true,
    'disable' => ['StockAdded', 'StockDeducted'],
],
```

EventFired when`StockAdded`Stock is added`StockDeducted`Stock is deducted`StockAdjusted`Stock is adjusted`StockTransferred`A transfer completes`StockReserved`A reservation is created`ReservationReleased`A reservation is released`ReservationFulfilled`A reservation is fulfilled`ReservationExpired`A reservation is expired by the command`LowStockReached`Stock falls at or below a min threshold`OverstockReached`Stock rises at or above a max threshold`TransactionRolledBack`A transaction is reversedArtisan Commands
----------------

[](#artisan-commands)

CommandDescription`inventorix:expire-reservations`Release all reservations past their TTL`inventorix:prune-movements`Delete movements older than `movement_prune_after_days``inventorix:stock-report`Generate a stock reportSchedule the expiry command in your application's scheduler:

```
// routes/console.php (Laravel 11+)
Schedule::command('inventorix:expire-reservations')->hourly();
Schedule::command('inventorix:prune-movements')->daily();
```

Configuration Reference
-----------------------

[](#configuration-reference)

```
// config/inventorix.php
return [
    'default_location_id'       => env('INVENTORIX_DEFAULT_LOCATION', null),
    'allow_negative_stock'       => env('INVENTORIX_ALLOW_NEGATIVE', false),
    'reservation_ttl_minutes'    => env('INVENTORIX_RESERVATION_TTL', null),
    'movement_prune_after_days'  => env('INVENTORIX_PRUNE_DAYS', null),
    'costing_strategy'           => env('INVENTORIX_COSTING', 'fifo'), // fifo | lifo | average
    'queue_alerts'               => env('INVENTORIX_QUEUE_ALERTS', false),
    'alert_queue'                => env('INVENTORIX_ALERT_QUEUE', 'default'),
    'events' => [
        'enabled' => true,
        'disable' => [], // short class names, e.g. ['StockAdded']
    ],
    'threshold_cache' => [
        'enabled' => env('INVENTORIX_THRESHOLD_CACHE', true),
        'ttl'     => env('INVENTORIX_THRESHOLD_TTL', 300),
        'store'   => env('INVENTORIX_THRESHOLD_CACHE_STORE', null),
    ],
    'serial_tracking' => [
        'enabled' => env('INVENTORIX_SERIAL_TRACKING', false),
    ],
    // All table names and model classes are swappable via 'tables' and 'models' keys.
];
```

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Hasan Deeb](https://github.com/aldeebhasan)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance95

Actively maintained with recent releases

Popularity10

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

38d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/74e7b9d93b0f666f462ad0be43dde05991e9d141f9fe840009775808107d440e?d=identicon)[aldeebhasan](/maintainers/aldeebhasan)

---

Top Contributors

[![aldeebhasan](https://avatars.githubusercontent.com/u/62222392?v=4)](https://github.com/aldeebhasan "aldeebhasan (5 commits)")

---

Tags

invenotry-managementlaravelstockslaravelHasan Deebinventorix

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/aldeebhasan-inventorix/health.svg)

```
[![Health](https://phpackages.com/badges/aldeebhasan-inventorix/health.svg)](https://phpackages.com/packages/aldeebhasan-inventorix)
```

###  Alternatives

[illuminate/database

The Illuminate Database package.

2.8k54.1M11.0k](/packages/illuminate-database)[laravel-doctrine/orm

An integration library for Laravel and Doctrine ORM

8455.5M96](/packages/laravel-doctrine-orm)[watson/validating

Eloquent model validating trait.

9743.4M53](/packages/watson-validating)[spatie/laravel-model-flags

Add flags to Eloquent models

4341.2M4](/packages/spatie-laravel-model-flags)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

436834.4k1](/packages/clickbar-laravel-magellan)[wnx/laravel-backup-restore

A package to restore database backups made with spatie/laravel-backup.

210389.8k2](/packages/wnx-laravel-backup-restore)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
