Stock Movement Tracking Guide
Overview
Stock movements provide an immutable audit trail of all inventory transactions for regulatory compliance, reconciliation, and dispute resolution. Every stock change is recorded with timestamp, user, reason, and reference to source transaction.
Movement Types
Inbound Movements (Increase Stock)
Purchase - Goods received from suppliers
type: PURCHASE
increases_stock: true
affects_financials: true
required_docs: ['purchase_order', 'receipt']Return - Customer returns
type: RETURN
increases_stock: true
affects_financials: true
required_docs: ['return_authorization', 'return_receipt']Release - Reservation released
type: RELEASE
increases_stock: false (but increases available)
affects_financials: falseManufacturing - Produced/assembled items
type: MANUFACTURING
increases_stock: true
affects_financials: true
required_docs: ['production_order', 'bom']Outbound Movements (Decrease Stock)
Sale - Goods sold/shipped
type: SALE
decreases_stock: true
affects_financials: true
required_docs: ['sales_order', 'shipping_label']Reservation - Stock reserved for orders
type: RESERVATION
decreases_stock: false (but decreases available)
affects_financials: falseLoss Movements
Damage - Damaged goods
type: DAMAGE
decreases_stock: true
requires_approval: true
affects_financials: true
required_docs: ['damage_report', 'approval']Theft - Theft/shrinkage
type: THEFT
decreases_stock: true
requires_approval: true
affects_financials: true
required_docs: ['incident_report', 'police_report']Expiry - Expired/spoiled items
type: EXPIRY
decreases_stock: true
requires_approval: true
affects_financials: true
required_docs: ['expiry_report', 'disposal_certificate']Adjustment Movements
Adjustment - Manual corrections
type: ADJUSTMENT
requires_approval: true
can_increase_or_decrease: trueTransfer - Inter-warehouse movements
type: TRANSFER
can_increase_or_decrease: true (depends on perspective)
category: 'transfer'Recount - Physical count adjustments
type: RECOUNT
can_increase_or_decrease: true
category: 'adjustment'
required_docs: ['recount_report', 'variance_analysis']Stock Movement Structure
[
'id' => 789,
'product_id' => 42,
'warehouse_id' => 1,
'type' => 'purchase', // Movement type enum
'quantity' => 50, // Positive or negative
'balance_after' => 150, // Running balance
// Reference to source transaction
'reference_type' => 'purchase_order', // Model type
'reference_id' => 123, // PO ID
// Audit information
'created_by' => 5, // User ID
'created_at' => '2025-01-15 10:00:00', // Timestamp (immutable)
'reason' => 'Purchase Order #PO-123 received',
// Additional context
'cost_per_unit' => 750.00, // Unit cost at time
'total_cost' => 37500.00, // Total value
'bin_location' => 'A-12-3', // Storage location
]Viewing Stock Movements
By Product
View all movements for a product:
curl -X GET "https://api.crm.test/api/v1/operations/stock-movements?product_id=42&warehouse_id=1" \
-H "Authorization: Bearer {token}"Response:
{
"data": [
{
"id": 789,
"type": "purchase",
"type_label": "Purchase/Receiving",
"quantity": 50,
"balance_after": 150,
"created_at": "2025-01-15T10:00:00Z",
"user": {
"id": 5,
"name": "Warehouse Staff"
},
"reason": "Purchase Order #PO-123 received",
"reference": {
"type": "purchase_order",
"id": 123,
"display": "PO-20250115-123"
},
"cost_per_unit": 750.00,
"total_cost": 37500.00
},
{
"id": 788,
"type": "sale",
"type_label": "Sale/Shipment",
"quantity": -5,
"balance_after": 100,
"created_at": "2025-01-14T15:30:00Z",
"user": {
"id": 8,
"name": "Sales System"
},
"reason": "Sales Order #SO-5678",
"reference": {
"type": "sales_order",
"id": 5678
}
},
{
"id": 787,
"type": "adjustment",
"type_label": "Manual Adjustment",
"quantity": -3,
"balance_after": 105,
"created_at": "2025-01-13T09:15:00Z",
"user": {
"id": 5,
"name": "Warehouse Manager"
},
"reason": "Damaged units found during inspection",
"approved_by": {
"id": 3,
"name": "Operations Manager"
}
}
],
"meta": {
"current_balance": 150,
"total_movements": 45,
"total_in": 550,
"total_out": 400
}
}By Date Range
curl -X GET "https://api.crm.test/api/v1/operations/stock-movements?start_date=2025-01-01&end_date=2025-01-31" \
-H "Authorization: Bearer {token}"By Movement Type
curl -X GET "https://api.crm.test/api/v1/operations/stock-movements?type=adjustment" \
-H "Authorization: Bearer {token}"By User
curl -X GET "https://api.crm.test/api/v1/operations/stock-movements?user_id=5" \
-H "Authorization: Bearer {token}"Movement Categories
Stock movements are grouped into categories:
Inbound
- Purchase
- Manufacturing
- (Increases stock from external sources)
Outbound
- Sale
- (Decreases stock for external consumption)
Return
- Return
- (Customer returns)
Transfer
- Transfer
- (Between warehouses)
Adjustment
- Adjustment
- Recount
- (Manual corrections)
Loss
- Damage
- Theft
- Expiry
- (Inventory shrinkage)
Reservation
- Reservation
- Release
- (Affects availability, not stock)
Immutability and Compliance
Immutable Records
Stock movements cannot be edited or deleted:
- ✅ Created once
- ❌ Cannot update
- ❌ Cannot delete
- ✅ Corrections via new adjustment movements
Why Immutable?
- Regulatory compliance (SOX, GAAP)
- Audit trail integrity
- Fraud prevention
- Dispute resolution
Corrections
To fix errors, create offsetting adjustments:
Example: Recorded wrong quantity
Original Movement:
- Type: PURCHASE
- Quantity: +50 (should have been +30)
Correction:
- Type: ADJUSTMENT
- Quantity: -20
- Reason: "Correction - actual receipt was 30 units, not 50"Reconciliation
Variance Analysis
Compare system balance vs physical count:
curl -X GET "https://api.crm.test/api/v1/operations/stock-movements/variance?product_id=42&warehouse_id=1" \
-H "Authorization: Bearer {token}"Response:
{
"data": {
"product_id": 42,
"warehouse_id": 1,
"system_balance": 150,
"physical_count": 148,
"variance": -2,
"variance_percentage": -1.33,
"last_count_date": "2025-01-10",
"movements_since_count": 5,
"suggested_action": "Perform recount to verify discrepancy"
}
}Movement Audit
Audit trail for compliance:
curl -X GET "https://api.crm.test/api/v1/operations/stock-movements/audit?product_id=42&start_date=2025-01-01" \
-H "Authorization: Bearer {token}"Export Format (CSV):
ID,Date,Type,Product,SKU,Quantity,Balance,User,Reason,Reference
789,2025-01-15,PURCHASE,Laptop,DELL-XPS13-001,50,150,Warehouse Staff,PO-123 received,PO-123
788,2025-01-14,SALE,Laptop,DELL-XPS13-001,-5,100,Sales System,SO-5678,SO-5678API Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /stock-movements | List movements with filters |
| GET | /stock-movements/{id} | Get movement details |
| GET | /stock-movements/audit | Audit trail export |
| GET | /stock-movements/variance | Variance analysis |
| GET | /stock-movements/summary | Movement statistics |
Note: No POST/PUT/DELETE endpoints (immutable records)
Related Guides
- Multi-Warehouse Inventory - Inventory operations that create movements
- Purchase Orders - Purchase movements
- Warehouse Management - Warehouse context
- Domain Events - Events from movements