PHPackages                             obelaw/ium-eam - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. obelaw/ium-eam

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

obelaw/ium-eam
==============

IUM Employee Asset Management

041PHP

Since May 20Pushed 3w agoCompare

[ Source](https://github.com/obelawium/eam)[ Packagist](https://packagist.org/packages/obelaw/ium-eam)[ RSS](/packages/obelaw-ium-eam/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependenciesVersions (1)Used By (0)

Obelawium EAM � Employee Asset Management
=========================================

[](#obelawium-eam--employee-asset-management)

A Laravel package for managing physical assets across any holder type (employees, warehouses, departments, etc.) using a polymorphic "holder" pattern.

Part of the [Obelawium IUM](https://github.com/obelawium/ium) ecosystem.

---

Requirements
------------

[](#requirements)

- PHP ^8.2
- Laravel ^11.0 | ^12.0
- `obelaw/ium`

---

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

[](#installation)

```
composer require obelaw/ium-eam
```

### Publish migrations

[](#publish-migrations)

```
php artisan vendor:publish --tag=ium-eam-migrations
php artisan migrate
```

### Publish config (optional)

[](#publish-config-optional)

```
php artisan vendor:publish --tag=ium-eam-config
```

---

Configuration
-------------

[](#configuration)

`config/eam.php` maps holder class name fragments to asset statuses:

```
return [
    'holder_status_map' => [
        'Employee' => 'assigned',
        'Warehouse' => 'available',
        'Maintenance' => 'maintenance',
        'Department' => 'assigned',
    ],
];
```

When an asset is transferred to a holder, the status is resolved by matching `class_basename($holderType)` against the keys above.

### Morph map (recommended)

[](#morph-map-recommended)

Register a morph map in your `AppServiceProvider` to keep class names out of the database:

```
use Illuminate\Database\Eloquent\Relations\Relation;

Relation::morphMap([
    'employee' => \App\Models\Employee::class,
    'warehouse' => \App\Models\Warehouse::class,
    'department' => \App\Models\Department::class,
]);
```

---

Making a Model a Valid Asset Holder
-----------------------------------

[](#making-a-model-a-valid-asset-holder)

Add the `HasAssets` trait to any Eloquent model:

```
use Obelaw\Ium\Eam\Traits\HasAssets;

class Employee extends Model
{
    use HasAssets;
}
```

This provides:

MethodDescription`assets()``MorphMany` � all assets currently held`assetTransitions()``MorphMany` � all transitions involving this holder`receiveAsset(int $assetId, array $data = [])`Transfer an asset to this holder---

Asset Lifecycle
---------------

[](#asset-lifecycle)

1. **Create** � asset enters inventory with status `available`
2. **Transfer** � asset is transferred to a holder; status updates from config map
3. **Transfer again** � asset moves between holders; full history is recorded
4. **Return** � transfer with `to_holder_type = null` returns asset to pool (`available`)
5. **Retire** � asset is permanently retired; holder is cleared, status set to `retired`
6. **Report** � query assets by holder, category, status, or transition history

---

Usage
-----

[](#usage)

All functionality is accessible via `ium()->eam()`:

### Assets

[](#assets)

```
use Obelaw\Ium\Eam\Data\AssetDTO;
use Obelaw\Ium\Eam\Data\TransferAssetDTO;

// Create
$asset = ium()->eam()->assets()->create(AssetDTO::from([
    'code' => 'LPT-001',
    'name' => 'Dell Laptop',
    'description' => 'Developer laptop',
    'category_id' => 1,
    'serial_number' => 'SN123456',
    'purchase_date' => '2024-01-15',
    'purchase_value' => 1200.00,
]));

// Update
$asset = ium()->eam()->assets()->update($asset->id, AssetDTO::from([...]));

// Find
$asset = ium()->eam()->assets()->find($asset->id);

// List all
$assets = ium()->eam()->assets()->list();

// List available only
$assets = ium()->eam()->assets()->available();

// Transfer to a holder
$transition = ium()->eam()->assets()->transferTo(TransferAssetDTO::from([
    'asset_id' => $asset->id,
    'toHolder' => Employee::find(42),
    'performed_by' => 'admin',
    'condition' => 'good',
    'reason' => 'New hire equipment',
]));

// Return to pool (nullable holder)
$transition = ium()->eam()->assets()->transferTo(TransferAssetDTO::from([
    'asset_id' => $asset->id,
    'toHolder' => null,
    'performed_by' => 'admin',
    'condition' => 'good',
]));

// View transition history
$history = ium()->eam()->assets()->history($asset->id);

// Retire
$asset = ium()->eam()->assets()->retire($asset->id, 'End of life');

// Assets held by a specific holder
$assets = ium()->eam()->assets()->heldBy(\App\Models\Employee::class, 42);
```

### Using the HasAssets trait directly

[](#using-the-hasassets-trait-directly)

```
$employee = Employee::find(42);

// All assets currently held
$employee->assets;

// Receive an asset
$employee->receiveAsset($asset->id, [
    'performed_by' => 'admin',
    'condition' => 'good',
]);
```

### Categories

[](#categories)

```
use Obelaw\Ium\Eam\Data\AssetCategoryDTO;

$category = ium()->eam()->categories()->create(AssetCategoryDTO::from([
    'name' => 'Laptops',
    'slug' => 'laptops',
    'parent_id' => null,
]));

$category = ium()->eam()->categories()->find(1);
$categories = ium()->eam()->categories()->list();
```

### Reports

[](#reports)

```
// Overdue assets
$overdue = ium()->eam()->reports()->overdue();

// Assets by holder
$assets = ium()->eam()->reports()->byHolder(\App\Models\Warehouse::class, 3);

// Assets by category
$assets = ium()->eam()->reports()->byCategory(1);

// Assets by status
$assets = ium()->eam()->reports()->byStatus('maintenance');

// Transition history for an asset
$transitions = ium()->eam()->reports()->transitions($asset->id);

// Lost and damaged assets
$assets = ium()->eam()->reports()->lostAndDamaged();
```

---

Database Schema
---------------

[](#database-schema)

### `eam_asset_categories`

[](#eam_asset_categories)

ColumnTypeNotes`id`bigintPK`name`string`slug`stringunique`parent_id`bigintnullable, self-ref FK### `eam_assets`

[](#eam_assets)

ColumnTypeNotes`id`bigintPK`code`stringunique`name`string`description`textnullable`category_id`bigintFK`status`enumavailable, assigned, maintenance, lost, retired`serial_number`stringnullable`purchase_date`datenullable`purchase_value`decimal(15,2)nullable`holder_type`stringnullable (morph)`holder_id`bigintnullable (morph)### `eam_asset_transitions`

[](#eam_asset_transitions)

ColumnTypeNotes`id`bigintPK`asset_id`bigintFK ? eam\_assets`from_holder_type`stringnullable`from_holder_id`bigintnullable`to_holder_type`stringnullable`to_holder_id`bigintnullable`performed_by`string`condition`enumgood, damaged, lost (nullable)`reason`stringnullable`notes`textnullable`transitioned_at`timestamp### `eam_audit_log`

[](#eam_audit_log)

ColumnTypeNotes`id`bigintPK`asset_id`bigintFK ? eam\_assets`action`stringcreated, updated, transferred, retired`performed_by`string`payload`jsonnullable`notes`textnullable---

Events
------

[](#events)

EventPayloadFired when`AssetCreated``Asset $asset`Asset is created`AssetTransferred``AssetTransition $transition`Asset changes holder`AssetRetired``Asset $asset`Asset is retired`AssetOverdue``Asset $asset`Overdue report run (once per asset)---

Exceptions
----------

[](#exceptions)

ExceptionThrown when`AssetNotFoundException`Asset ID does not exist`AssetAlreadyRetiredException`Attempting to transfer/retire an already-retired asset`InvalidHolderException`Target holder class does not use `HasAssets` trait`InvalidTransitionException`Transition is not permitted in current state---

License
-------

[](#license)

MIT

###  Health Score

23

—

LowBetter than 26% of packages

Maintenance62

Regular maintenance activity

Popularity11

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 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.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/31162701?v=4)[komicho](/maintainers/komicho)[@komicho](https://github.com/komicho)

---

Top Contributors

[![komtcho](https://avatars.githubusercontent.com/u/12757671?v=4)](https://github.com/komtcho "komtcho (2 commits)")

### Embed Badge

![Health badge](/badges/obelaw-ium-eam/health.svg)

```
[![Health](https://phpackages.com/badges/obelaw-ium-eam/health.svg)](https://phpackages.com/packages/obelaw-ium-eam)
```

###  Alternatives

[brianhenryie/strauss

Prefixes dependencies namespaces so they are unique to your plugin

187406.5k30](/packages/brianhenryie-strauss)[oleh-ozimok/php-centrifugo

PHP client for Centrifugo real-time messaging server

39514.4k1](/packages/oleh-ozimok-php-centrifugo)[taxjar/module-taxjar

TaxJar Sales Tax Module for Magento 2

24466.7k](/packages/taxjar-module-taxjar)[zendtech/ibmitoolkit

PHP frontend to XMLSERVICE for IBM i development.

4786.6k6](/packages/zendtech-ibmitoolkit)

PHPackages © 2026

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