Overview
TheInventoryMovementService manages all inventory movements including inputs (purchases/production), outputs (sales), adjustments (corrections/returns), and transfers between warehouses. It automatically updates stock levels and generates corresponding accounting journal entries.
Namespace: App\Services\Inventory\InventoryMovementService
Location: app/Services/Inventory/InventoryMovementService.php
Methods
register()
Registers a new inventory movement, updates stock levels, and creates accounting entries.Movement data array with the following structure:
Returns the created InventoryMovement model instance
- Stock Initialization - Creates stock record if it doesn’t exist (quantity 0, min_stock 0)
- Stock Calculation:
- Input: Increases stock by absolute quantity
- Output/Transfer: Decreases stock by absolute quantity
- Adjustment: Applies raw quantity (can be positive or negative)
- Validation - Throws exception if resulting stock would be negative
- Movement Creation - Creates inventory movement record with previous and current stock
- Stock Update - Updates the warehouse stock quantity
- Accounting Entry - Generates appropriate journal entry based on movement type
- Transfer Mirror - For transfers, creates corresponding entry movement in destination warehouse
Movement Types
Input
Increases inventory (purchases, production)
- Quantity stored as positive
- Increases warehouse stock
Output
Decreases inventory (sales, consumption)
- Quantity stored as negative
- Decreases warehouse stock
Adjustment
Corrections, returns, losses
- Quantity can be positive or negative
- Adds raw quantity to stock
Transfer
Between warehouses
- Quantity stored as negative in source
- Creates mirror positive entry in destination
Example Usage
Protected Methods
generateAccountingEntry()
Generates the appropriate journal entry based on movement type and context.The created inventory movement record
Product model instance (used to calculate cost)
Absolute quantity value
TYPE_INPUT - Purchase or Production
TYPE_INPUT - Purchase or Production
Calculation:
totalValue = quantity × product.costIf reference is Production:- Debit: Warehouse Account (inventory asset increase)
- Credit: Production Account 5.2 (cost of internal production)
- Debit: Warehouse Account (inventory asset increase)
- Credit: Cash Account 1.1.01 (payment for purchase)
TYPE_OUTPUT - Sale or Consumption
TYPE_OUTPUT - Sale or Consumption
Note: This records the cost of goods sold, not the sale price.Calculation:
totalValue = quantity × product.cost- Debit: Cost of Sales Account 5.1 (expense recognition)
- Credit: Warehouse Account (inventory asset decrease)
TYPE_TRANSFER - Between Warehouses
TYPE_TRANSFER - Between Warehouses
Reclassification between inventory asset accounts
- Debit: Destination Warehouse Account (asset increase)
- Credit: Source Warehouse Account (asset decrease)
TYPE_ADJUSTMENT - Corrections/Returns
TYPE_ADJUSTMENT - Corrections/Returns
Positive Adjustment (quantity > 0):If reference is Sale (reversal):
- Debit: Warehouse Account (inventory restored)
- Credit: Cost of Sales Account 5.1 (cost reversal)
- Debit: Warehouse Account (inventory increase)
- Credit: Production Account 5.2 (internal adjustment)
- Debit: Cost of Sales Account 5.1 (loss/shrinkage expense)
- Credit: Warehouse Account (inventory reduction)
InventoryMovementService.php:75-133
createItem()
Helper method to create individual journal entry items.The journal entry instance
Accounting account ID. Throws exception if null.
Debit amount
Credit amount
Line item description
InventoryMovementService.php:135-145
registerTransferEntry()
Creates the mirror inventory movement in the destination warehouse for transfers.The source warehouse movement record
Original movement data including
to_warehouse_id- Initializes or retrieves destination warehouse stock
- Calculates new destination stock (increases by quantity)
- Creates positive entry movement in destination
- Updates destination stock quantity
- Links to parent movement via polymorphic reference
InventoryMovementService.php:147-172
InventoryMovement Model Constants
Exception Handling
Insufficient Stock
Insufficient Stock
Exception:
"Stock insuficiente en el almacén de origen."Cause: Attempting to reduce stock below zeroResolution: Verify available stock before creating output or adjustment movementsMissing Accounting Configuration
Missing Accounting Configuration
Exception:
"Error Contable: Almacén o Contrapartida no tiene cuenta asignada."Cause: Warehouse doesn’t have an accounting account assigned, or system accounts are missingResolution:- Ensure each warehouse has an
accounting_account_idassigned - Verify required accounts exist: Cash (1.1.01), Cost of Sales (5.1), Production (5.2)
Accounting Accounts Reference
The service uses these standard accounting accounts:| Account Code | Description | Usage |
|---|---|---|
| 1.1.01 | Cash | Credited on purchases |
| 1.2.xx | Warehouse Accounts | Each warehouse has its own inventory asset account |
| 5.1 | Cost of Sales | Debited on outputs, adjusted on returns |
| 5.2 | Production Cost | Credited on internal production inputs |
Database Transaction Safety
Theregister() method wraps all operations in a database transaction using DB::transaction(). This ensures:
- Stock updates are atomic
- Accounting entries are created only if stock update succeeds
- Transfer mirror entries are created together
- All changes are rolled back on any failure
Integration Points
Used By
- SaleService - Creates output movements on sales, adjustment movements on cancellations
- PurchaseService - Creates input movements for inventory purchases
- ProductionService - Creates input movements for manufactured goods
- TransferController - Direct usage for warehouse transfers
Uses
- JournalEntry Model - Creates accounting entries
- InventoryStock Model - Updates stock levels
- Product Model - Retrieves product cost for accounting calculations
Related Models
- InventoryMovement Model - Movement records
- InventoryStock Model - Stock levels per warehouse
- Warehouse Model - Warehouse configuration
- Product Model - Product cost information
- JournalEntry Model - Accounting entries