Skip to content

Inventory Module Documentation

Overview

The Inventory Module is a robust stock management system designed for hospitality needs. It handles end-to-end supply chain tracking, from purchasing to consumption, with precise costing methods and full General Ledger integration.

Key Features

  • Multi-Location Management: Track stock across unlimited physical locations (Main Store, Kitchens, Bars, Housekeeping).
  • Advanced Costing: Supports FIFO (First-In, First-Out) and Weighted Average costing methods.
  • Lot Tracking: Trace individual batches for expiry dates and specific cost layers.
  • Accounting Integration: Automatic, real-time journal postings for all financial transactions.
  • Stock Audit: Complete history of every movement (Purchase, Issue, Transfer, Adjust, Write-off).
  • Reorder Management: Low stock alerts and reorder level tracking (Planned).

Architecture

Domain Layer (app/Domain/Inventory)

Models (7 Models)

InventoryItem (InventoryItem.php)
  • Table: inventory_items
  • Description: Master record for a product/SKU.
  • Key Fields:
    • sku: Stock Keeping Unit (Unique).
    • name: Product name.
    • description: Extended details.
    • unit_of_measure: Base unit (e.g., KG, PCS, LTR).
    • category_id: Link to InventoryCategory.
    • current_quantity: Total stock across all locations.
    • average_cost: Current weighted average cost (updated on purchase).
    • last_purchase_cost: Cost of most recent purchase.
    • last_purchase_date: Timestamp of last purchase.
    • inventory_account_id: Specific asset account (optional override).
    • cogs_account_id: Specific expense account (optional override).
    • reorder_level: Minimum quantity trigger.
  • Relationships:
    • category(): Belongs to Category.
    • lots(): Has many InventoryLots.
    • transactions(): Has many InventoryTransactions.
    • locationStocks(): Has many InventoryLocationStocks.
InventoryLocation (InventoryLocation.php)
  • Table: inventory_locations
  • Description: Physical storage location.
  • Key Fields:
    • name: Location name (e.g., "Main Kitchen").
    • type: STORE | KITCHEN | BAR | HOUSEKEEPING.
    • is_active: Boolean status.
InventoryLot (InventoryLot.php)
  • Table: inventory_lots
  • Description: Tracks a specific batch of items received together. Critical for FIFO.
  • Key Fields:
    • lot_number: Batch/Lot number (e.g., from vendor).
    • purchase_date: Date received.
    • expiry_date: Expiration date (optional).
    • original_quantity: Initial qty received.
    • remaining_quantity: Current qty available in lot.
    • unit_cost: Cost per unit for this specific batch.
InventoryTransaction (InventoryTransaction.php)
  • Table: inventory_transactions
  • Description: Immutable ledger of stock movements.
  • Key Fields:
    • transaction_type: PURCHASE | ISSUE_OUT | TRANSFER | ADJUSTMENT | WRITE_OFF.
    • quantity: Net change in quantity (positive or negative).
    • unit_cost: Cost applied to this transaction.
    • total_cost: quantity * unit_cost.
    • running_quantity: Snapshot of item quantity after transaction.
    • running_average_cost: Snapshot of item average cost.
    • reference_type: Morph link to source (e.g., App\Models\PurchaseOrder).
    • reference_id: Morph ID.
    • journal_entry_id: Link to Accounting Entry.
InventoryLocationStock (InventoryLocationStock.php)
  • Table: inventory_location_stocks
  • Description: Pivot tracking quantity of Item X at Location Y.
  • Key Fields:
    • quantity: Current stock at this location.

Services

InventoryService (InventoryService.php)

Purpose: Central logic for all stock movements and financial postings.

Key Methods:

purchaseIn(...)

Records receipt of goods.

  • Logic:
    1. Calculates new weighted average cost (if method = weighted_average).
    2. Creates InventoryTransaction (Type: PURCHASE).
    3. Creates InventoryLot for FIFO tracking.
    4. Updates InventoryItem (qty, avg_cost).
    5. Updates InventoryLocationStock.
    6. Accounting: Dr Inventory Asset, Cr Accounts Payable (or Cash).
issueOut(...)

Records consumption/sale of goods.

  • Logic:
    1. Validates sufficient stock.
    2. FIFO Logic: Iterates through oldest available lots (consumeFifoLots).
      • Consumes from Lot A, then Lot B, etc.
      • Calculates weighted cost based on specific lots consumed.
    3. records InventoryLotConsumption for traceability.
    4. Creates InventoryTransaction (Type: ISSUE_OUT).
    5. Updates InventoryItem and InventoryLocationStock.
    6. Accounting: Dr COGS/Expense, Cr Inventory Asset.
transferStock(...)

Moves items between locations.

  • Logic:
    1. Validates source location has stock.
    2. Decrements Source Location Stock.
    3. Increments Destination Location Stock.
    4. Creates InventoryTransaction (Type: TRANSFER).
    5. Accounting: None (Asset remains an asset).
adjustStock(...)

Corrections for stocktakes or discrepancies.

  • Logic:
    1. Calculates difference (newQty - oldQty).
    2. Creates InventoryTransaction (Type: ADJUSTMENT).
    3. Accounting:
      • Gain: Dr Inventory, Cr COGS/Gain Account.
      • Loss: Dr COGS/Loss Account, Cr Inventory.
writeOff(...)

Removes damaged or expired stock.

  • Logic:
    1. Creates InventoryTransaction (Type: WRITE_OFF).
    2. Accounting: Dr Spoilage Expense (COGS), Cr Inventory.

Accounting Integration

The module is tightly coupled with AccountingPoster.

Account Configuration

Accounts are resolved in this order of precedence:

  1. Item-Level Override: inventory_item.inventory_account_id
  2. Category-Level Override: inventory_category.inventory_account_id (Planned)
  3. System Default: Config inventory.default_inventory_account_code (Default: 104)

Journal Entries

1. Purchase (Stock In)

AccountDr/CrAmountMemo
Inventory Asset (104)DebitTotal Cost50 KG @ $2.00
Accounts Payable (201)CreditTotal CostPurchase: Tomatoes

2. Issue (Stock Out / Consumption)

AccountDr/CrAmountMemo
COGS / Expense (604)DebitCost of GoodsCOGS: 10 KG
Inventory Asset (104)CreditCost of GoodsIssue: Tomatoes

3. Adjustment (Loss)

AccountDr/CrAmountMemo
COGS / Inventory LossDebitVariance CostAdjustment loss
Inventory Asset (104)CreditVariance CostReason: Spillage

Database Schema

mermaid
erDiagram
    InventoryItem ||--o{ InventoryLot : "has batches"
    InventoryItem ||--o{ InventoryTransaction : "history"
    InventoryItem ||--o{ InventoryLocationStock : "at location"

    InventoryTransaction ||--o{ InventoryLotConsumption : "consumes"
    InventoryTransaction ||--|| JournalEntry : "posts financial"

    InventoryLocation ||--o{ InventoryLocationStock : "stores"

    inventory_items {
        bigint id PK
        string sku
        string name
        decimal current_quantity
        decimal average_cost
        enum costing_method "FIFO, AVG"
    }

    inventory_lots {
        bigint id PK
        string lot_number
        date purchase_date
        decimal remaining_quantity
        decimal unit_cost
    }

    inventory_transactions {
        bigint id PK
        enum type "PURCHASE, ISSUE, TRANSFER"
        decimal quantity
        decimal unit_cost
        decimal total_cost
        bigint journal_entry_id FK
    }

Common Workflows

1. Receiving Goods (Purchase)

  1. Navigate to Inventory > Receive Stock.
  2. Select Item, Location, and Vendor.
  3. Enter Quantity, Unit Cost, and Lot Number (optional).
  4. Submit.
  5. System: Increases stock, creates Lot, posts Debit Inventory / Credit AP.

2. Issuing to Kitchen

  1. Navigate to Inventory > Issue Stock.
  2. Select Item and Source Location (Main Store).
  3. Enter Quantity and Reason (e.g., "Kitchen Requistion").
  4. Submit.
  5. System: Decreases stock (FIFO from oldest lot), posts Debit Food Cost / Credit Inventory.

3. Stock Transfer

  1. Navigate to Inventory > Transfer.
  2. Select Item, From Location, and To Location.
  3. Enter Quantity.
  4. Submit.
  5. System: Moves stock count between locations. No financial impact.

Audit Findings & Improvements

Strengths

  • FIFO Implementation: The consumeFifoLots method correctly handles multi-lot consumption in a single transaction, providing accurate COGS.
  • Transactional Integrity: All inventory operations are wrapped in DB transactions, ensuring stock levels and accounting entries never drift.
  • Granular History: Every single unit change is recorded in inventory_transactions.

Issues Identified

Major

  • N+1 Performance: InventoryService queries for default account IDs inside transaction blocks. If doing bulk operations, this should be cached.
  • Account Resolution: Currently falls back to hardcoded strings ('104', '604') in config lookups. Should use the AccountingMapService proposed in Phase 4.

Minor

  • Soft Deletes: Missing on InventoryItem. Deletion could orphaned transaction history.
  • Unit Conversions: No support for purchasing in Cases and issuing in Units.

Configuration

Config File: config/inventory.php

php
return [
    'costing_method' => 'fifo', // 'fifo' or 'weighted_average'
    'default_inventory_account_code' => '104',
    'default_cogs_account_code' => '604',
];

Module Version: 1.0 Status: Production Ready