Skip to content

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

php
type: PURCHASE
increases_stock: true
affects_financials: true
required_docs: ['purchase_order', 'receipt']

Return - Customer returns

php
type: RETURN
increases_stock: true
affects_financials: true
required_docs: ['return_authorization', 'return_receipt']

Release - Reservation released

php
type: RELEASE
increases_stock: false (but increases available)
affects_financials: false

Manufacturing - Produced/assembled items

php
type: MANUFACTURING
increases_stock: true
affects_financials: true
required_docs: ['production_order', 'bom']

Outbound Movements (Decrease Stock)

Sale - Goods sold/shipped

php
type: SALE
decreases_stock: true
affects_financials: true
required_docs: ['sales_order', 'shipping_label']

Reservation - Stock reserved for orders

php
type: RESERVATION
decreases_stock: false (but decreases available)
affects_financials: false

Loss Movements

Damage - Damaged goods

php
type: DAMAGE
decreases_stock: true
requires_approval: true
affects_financials: true
required_docs: ['damage_report', 'approval']

Theft - Theft/shrinkage

php
type: THEFT
decreases_stock: true
requires_approval: true
affects_financials: true
required_docs: ['incident_report', 'police_report']

Expiry - Expired/spoiled items

php
type: EXPIRY
decreases_stock: true
requires_approval: true
affects_financials: true
required_docs: ['expiry_report', 'disposal_certificate']

Adjustment Movements

Adjustment - Manual corrections

php
type: ADJUSTMENT
requires_approval: true
can_increase_or_decrease: true

Transfer - Inter-warehouse movements

php
type: TRANSFER
can_increase_or_decrease: true (depends on perspective)
category: 'transfer'

Recount - Physical count adjustments

php
type: RECOUNT
can_increase_or_decrease: true
category: 'adjustment'
required_docs: ['recount_report', 'variance_analysis']

Stock Movement Structure

php
[
    '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:

bash
curl -X GET "https://api.crm.test/api/v1/operations/stock-movements?product_id=42&warehouse_id=1" \
  -H "Authorization: Bearer {token}"

Response:

json
{
  "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

bash
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

bash
curl -X GET "https://api.crm.test/api/v1/operations/stock-movements?type=adjustment" \
  -H "Authorization: Bearer {token}"

By User

bash
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:

bash
curl -X GET "https://api.crm.test/api/v1/operations/stock-movements/variance?product_id=42&warehouse_id=1" \
  -H "Authorization: Bearer {token}"

Response:

json
{
  "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:

bash
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-5678

API Endpoints

MethodEndpointDescription
GET/stock-movementsList movements with filters
GET/stock-movements/{id}Get movement details
GET/stock-movements/auditAudit trail export
GET/stock-movements/varianceVariance analysis
GET/stock-movements/summaryMovement statistics

Note: No POST/PUT/DELETE endpoints (immutable records)

Documentation for SynthesQ CRM/ERP Platform