Stock History
First-Pass Node Dossier
This page is an example of the node-level documentation format generated from the domain hierarchy and questionnaire work.
What It Is
StockHistory is a supporting audit record, not a primary business object. It stores quantity changes over time using:
stock_beforestock_afterstock_difference- timestamps
- a polymorphic
causer
In the inspected codebase, the practical source of StockHistory rows is ProductInventoryItem changes.
Parent hierarchy:
Inventory & Vendor SupplyInventory StateStock History
Primary implementation paths:
packages/framework/src/Models/StockHistory.phppackages/framework/src/Models/Traits/StockHistoriesTrait.phppackages/framework/src/Actions/StockHistory/LogStockHistory.phppackages/framework/src/Observers/ProductInventoryItemObserver.php
What Users Can Do With It
Direct capabilities
Users can directly:
- list stock-history rows through the admin API
- filter by
id,causer_type, andcauser_id - sort by
created_at,stock_after, andstock_difference
Things users cannot do directly
In the inspected packaged UI and API, users cannot directly:
- create a stock-history row
- edit a stock-history row
- delete a stock-history row
- open a dedicated stock-history detail screen
Source:
packages/framework/src/Http/Controllers/Api/Admin/StockHistoriesController.php
Where It Is Managed
| Channel | Role | Notes |
|---|---|---|
| Admin API | Direct read-only | stock_histories route only exposes index |
| Admin UI | Indirect | Inventory screens show current stock state, not stock-history rows |
| Storefront | Indirect | Uses current inventory state only |
| ERP / feeds / fulfillment | Indirect upstream inputs | These flows mutate inventory items, which may create stock-history rows |
| Excel import/export | Indirect upstream inputs | No inspected sheet directly imports or exports StockHistory |
Creation Model
StockHistory is system-generated.
The effective write path is:
- a
ProductInventoryItemchanges ProductInventoryItemObserverseesavailableas dirty- the observer calls
logStockHistory() LogStockHistorycompares the new value to the latest prior history row- a new row is created only if the quantity actually changed
Sources:
packages/framework/src/Observers/ProductInventoryItemObserver.phppackages/framework/src/Models/Traits/StockHistoriesTrait.phppackages/framework/src/Actions/StockHistory/LogStockHistory.php
Configuration And Data Model
Key model characteristics:
- plain Eloquent model
- polymorphic
causer - integer casts for stock values
- no soft deletes
- no explicit status/state machine
Important caveat:
- if there is no prior stock-history row,
LogStockHistorystarts fromstock_before = 0 - initial inventory-item creation does not seed a first history row
That means the first logged change after creation may not reflect the true original quantity.
Sources:
packages/framework/src/Models/StockHistory.phppackages/framework/database/migrations/2022_11_26_132348_create_stock_histories_table.phppackages/framework/src/Actions/StockHistory/LogStockHistory.phppackages/framework/src/Observers/ProductInventoryItemObserver.php
Relationships
Direct relationship:
causer()
Practical owner in the inspected framework:
ProductInventoryItem
Trait-based accessors added to the owning model:
stockHistories()latestStockHistory()oldestStockHistory()
Sources:
packages/framework/src/Models/StockHistory.phppackages/framework/src/Models/Traits/StockHistoriesTrait.phppackages/framework/src/Models/ProductInventoryItem.php
Rules And Downstream Effects
Logging rules
A history row is created only when:
ProductInventoryItem.availablechanges
It is not created when only:
backorder_allowedchangesdiscontinuedchanges
Additional side effects on the same inventory update
When inventory-item state changes, the observer also queues product stock recalculation. That recalculation can update:
- product
stock_level - product
stock_status - product
stock_purchasable - product discontinuation-driven stock behavior
Sources:
packages/framework/src/Observers/ProductInventoryItemObserver.phppackages/framework/src/Actions/Product/CalculateStock.php
Where It Appears In The Product
StockHistory is mostly invisible to end users.
What appears in packaged UIs instead:
- current availability badges
- current inventory tables
- current stock status on storefront product views
The inspected admin and storefront resources do not nest stock_histories inside their inventory-item payloads.
Sources:
packages/admin/resources/views/components/product-inventory-item/availability-field.blade.phppackages/admin/resources/views/components/product-inventory-item/availability-dialog.blade.phppackages/admin/resources/views/components/inventory/data-table.blade.phppackages/framework/src/Http/Resources/Admin/ProductInventoryItemResource.phppackages/framework/src/Http/Resources/Storefront/ProductInventoryItemResource.phppackages/storefront/resources/views/components/product/stock-status.blade.php
Integrations And Automation
StockHistory itself is not the sync object for ERP, feeds, or Excel.
Instead, those upstream systems modify ProductInventoryItem, and that can indirectly create stock-history rows.
Examples of upstream inputs:
- ERP inventory sync
- vendor feed inventory sync
- fulfillment debit from inventory
Sources:
packages/framework/src/Actions/ErpBridge/ProductInventoryItem/UpdateOrCreateModelFromDTO.phppackages/framework/src/Actions/ProductInventoryItem/SyncInventoryItem.phppackages/framework/src/Actions/Fulfillment/DebitFulfilledItemsFromInventory.phppackages/erp-bridge/src/Requests/ProductInventoryItems/GetProductInventoryItemsRequest.php
Current Documentation Takeaways
The three most important operator-level facts are:
StockHistoryis an audit artifact, not something operators manage directly.- The real place to understand or influence it is
ProductInventoryItem. - Quantity changes can create both a history row and a queued product stock recalculation, but only some field changes generate history.
Open Questions
- The concrete generated bindings config that wires the observer is not committed in this repo snapshot, so observer registration is inferred from framework boot logic and the observer class itself.
- The
stock_historiesAPI route exists, but no packaged admin Livewire screen currently appears to consume it directly.