Search by

karnoweb / laravel-inventory

sajadsoft1

Warehouse inventory package for Laravel: batches, FIFO/FEFO, transfers, reservations, and stock counts.

Package info

github.com/karnoweb/laravel-inventory

pkg:composer/karnoweb/laravel-inventory

Statistics

Installs: 17

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

13.4.0 2026-09-15 07:26 UTC

This package is auto-updated.

Last update: 2026-09-15 07:28:00 UTC


README

A Laravel inventory ledger for receiving, issuing, reserving, transferring, counting, and valuing stock. It tracks quantities through immutable movements instead of a mutable stock column.

Basic usage needs only a stockable Laravel model, a warehouse, a quantity, and a unit cost. Branches, locations, serials, units of measure, recipes, expiry, and costing choices are optional.

Requirements

  • PHP ^8.2
  • Laravel 11, 12, or 13

Installation

composer require karnoweb/laravel-inventory:^13.3
php artisan migrate

The package migrations are auto-discovered. Publish configuration only when changing defaults:

php artisan vendor:publish --tag=inventory-config

Five-minute quick start

Make the model whose stock is tracked inventory-aware:

use Illuminate\Database\Eloquent\Model;
use Karnoweb\Inventory\Traits\HasInventory;

class Product extends Model
{
    use HasInventory;
}

Use one product and one warehouse. branch_id is optional.

use Karnoweb\Inventory\Facades\Inventory;

$chips = Product::query()->firstOrFail();
$warehouse = Inventory::warehouses()->create([
    'name' => 'Main Warehouse',
    'branch_id' => null,
]);

Inventory::stock()->receive($chips, 10, 10_000, warehouseId: $warehouse->id);
Inventory::stock()->receive($chips, 10, 20_000, warehouseId: $warehouse->id);

Inventory::stock()->onHand($chips, $warehouse->id);    // 20 physical units
Inventory::reservations()->reserve($chips, 5, warehouseId: $warehouse->id);
Inventory::stock()->available($chips, $warehouse->id); // 15 units still issuable

Inventory::stock()->issue($chips, 3, warehouseId: $warehouse->id);

onHand is physical stock. reserved is promised stock. available is sellable stock after active reservations and expired batches are excluded.

20 on hand
- 5 reserved
= 15 available

Use a source model when an operation belongs to a business record. Usually use an item, such as OrderItem, rather than a whole Order.

Inventory::stock()->issue($chips, 3, warehouseId: $warehouse->id, sourceable: $orderItem);
Inventory::stock()->returnIssue($returnItem, $orderItem, 1);

Create and confirm a transfer separately. Creating it does not move stock.

$transfer = Inventory::transfers()->create($warehouse, $otherWarehouse, [[
    'stockable' => $chips,
    'quantity' => 3,
]]);

Inventory::transfers()->confirm($transfer);

Optional features

  • FIFO, FEFO, WAC: configure inventory.general.costing.
  • Locations: enable inventory.location.enabled to receive or issue from a shelf.
  • Serials: enable inventory.serial.enabled, then set tracks_serial for a product.
  • UOM: enable inventory.uom.enabled for integer base-unit conversions.
  • Recipes: enable inventory.recipe.enabled only for composed products.
  • Branches: provide a host-owned inventory.branch.resolver when tenant isolation is needed.

Documentation

Start with Getting started, then read the mental model. The full learning reference is in docs.

Testing

vendor/bin/phpunit