Skip to content

Warehouse Context ​

Warehouse Context manages inventory tracking, stock movements, product catalog, and warehouse locations with automated order-inventory integration.

Overview ​

The Warehouse Context is a critical bounded context responsible for:

  • Product Catalog - SKU-based product management with categories and brands
  • Inventory Tracking - Real-time stock levels with multiple quantity states
  • Stock Movements - Immutable audit trail for all inventory changes
  • Warehouse Locations - Hierarchical location management (warehouses, zones, bins)
  • Order Integration - Automated synchronization with Order Management via Event Bus

Aggregates ​

Product Aggregate ​

Purpose: Product catalog management with SKUs, categories, and physical properties

Entity:

go
type Product struct {
    ID              uuid.UUID
    SKU             string  // Unique product identifier
    Name            string
    Description     string
    Category        string
    Brand           string
    UnitPrice       int     // Cents (Money value object)
    Currency        string
    Weight          float64 // Grams
    Dimensions      Dimensions // Length, Width, Height in cm
    Status          ProductStatus // active, discontinued
    CreatedAt       time.Time
    UpdatedAt       time.Time
}

Use Cases:

  • CreateProduct(sku, name, category, brand, price) - Add new product
  • UpdateProduct(id, ...) - Update product details
  • DiscontinueProduct(id) - Mark product as discontinued
  • GetProductBySKU(sku) - Find product by SKU
  • ListProducts(filters) - Search and filter products

Domain Events:

  • product.created
  • product.updated
  • product.discontinued

Tests: 139 (25 entity + 83 usecase + 10 smoke + 21 integration)


Inventory Aggregate ​

Purpose: Real-time stock level tracking with reservation management

Entity:

go
type Inventory struct {
    ID                  uuid.UUID
    ProductID           uuid.UUID
    LocationID          uuid.UUID
    QuantityOnHand      int  // Physical stock in warehouse
    QuantityReserved    int  // Reserved for orders
    QuantityAvailable   int  // Available for new orders (OnHand - Reserved)
    QuantityCommitted   int  // Shipped/delivered
    ReorderPoint        int  // Threshold for reordering
    MinStock            int  // Minimum stock level
    MaxStock            int  // Maximum stock level
    UnitCost            int  // Cents (Money value object)
    TotalCost           int  // Cents (QuantityOnHand * UnitCost)
    Currency            string
    LastStockDate       time.Time
    CreatedAt           time.Time
    UpdatedAt           time.Time
}

Stock Operations:

  • ReceiveStock(quantity, unitCost) - Receive stock from supplier
  • ReserveStock(quantity, orderID) - Reserve for order
  • ReleaseReservation(quantity, orderID) - Cancel reservation
  • CommitStock(quantity, orderID) - Ship/deliver stock

Business Rules:

  • QuantityAvailable = QuantityOnHand - QuantityReserved
  • Cannot reserve more than available stock
  • Weighted average cost calculation on receipt
  • Auto-update TotalCost on stock movements

Domain Events:

  • inventory.created
  • inventory.received
  • inventory.reserved
  • inventory.released
  • inventory.committed

Tests: 141 (97 entity + ? usecase + 21 smoke + 23 integration)


StockMovement Aggregate ​

Purpose: Immutable audit trail for all inventory changes

Entity:

go
type StockMovement struct {
    ID                  uuid.UUID
    InventoryID         uuid.UUID
    Type                MovementType // Receipt, Reservation, Release, Commit, etc.
    Quantity            int          // Positive or negative
    QuantityBeforeMove  int          // Snapshot before
    QuantityAfterMove   int          // Snapshot after
    FromWarehouseID     *uuid.UUID
    ToWarehouseID       *uuid.UUID
    ReferenceType       string       // "order", "po", "adjustment"
    ReferenceID         *uuid.UUID
    Reason              string       // Required for adjustments
    UnitCostCents       int
    TotalCostCents      int
    CurrencyCode        string
    CreatedBy           uuid.UUID
    MovementDate        time.Time
    CreatedAt           time.Time
}

Movement Types:

  • Receipt: Stock received from supplier
  • Reservation: Stock reserved for order
  • ReservationRelease: Reservation cancelled
  • Commit: Stock shipped/delivered
  • Adjustment: Manual correction
  • Transfer: Between warehouses
  • Damage: Damaged goods
  • Return: Customer return

Key Features:

  • Immutable records (append-only)
  • Before/After snapshots for auditability
  • Cost tracking per movement
  • Reference to orders/POs/adjustments
  • Compliance-ready audit trail

Domain Events:

  • stock_movement.created

Tests: 45 (11 entity + 10 usecase + 9 smoke + 15 integration)


Location Aggregate ​

Purpose: Hierarchical warehouse location management

Entity:

go
type Location struct {
    ID          uuid.UUID
    Name        string
    Code        string       // Unique location code
    Type        LocationType // warehouse, retail, dropship, virtual
    Address     valueobject.Address
    CountryCode string
    Capacity    int          // Storage capacity
    IsActive    bool
    ParentID    *uuid.UUID   // For hierarchical structure
    CreatedAt   time.Time
    UpdatedAt   time.Time
}

Location Types:

  • Warehouse: Main facility
  • Retail: Store location
  • Dropship: Supplier warehouse
  • Virtual: Digital products

Use Cases:

  • CreateLocation(name, code, type, address) - Add warehouse/store
  • UpdateLocation(id, ...) - Update details
  • ActivateLocation(id) / DeactivateLocation(id) - Enable/disable
  • GetLocationsByType(type) - Filter by type
  • GetActiveLocations() - List active locations

Domain Events:

  • location.created
  • location.updated
  • location.activated
  • location.deactivated

Tests: 74 (48 entity + 17 integration + 9 smoke)


Warehouse Integration ​

The most powerful feature - automated order-inventory synchronization via Event Bus.

Architecture ​

Order Management          Event Bus          Warehouse Context
              
 Order.Confirm()      ReservationService 
                                    .ReserveForOrder() 
              

              
 Order.Cancel()       ReservationService 
                                    .ReleaseForOrder() 
              

              
 Order.Fulfill()      ReservationService 
                                    .CommitForOrder()

Components ​

1. ReservationService (230 lines)

Business logic for stock operations:

go
type ReservationService struct {
    inventoryUC inventory.IUseCase
}

func (s *ReservationService) ReserveForOrder(ctx context.Context, orderID uuid.UUID, items []OrderItem) error {
    // For each order line item:
    // 1. Validate inventory availability
    // 2. Reserve stock via Inventory.ReserveStock()
    // 3. Create StockMovement record (type: Reservation)
}

func (s *ReservationService) ReleaseForOrder(ctx context.Context, orderID uuid.UUID) error {
    // Find all reservations for order
    // Release stock back to available pool
    // Create StockMovement records (type: ReservationRelease)
}

func (s *ReservationService) CommitForOrder(ctx context.Context, orderID uuid.UUID) error {
    // Find all reservations for order
    // Commit stock (permanent removal from inventory)
    // Create StockMovement records (type: Commit)
}

2. OrderEventHandler (230 lines)

Event handlers for order lifecycle:

go
type OrderEventHandler struct {
    reservationService *ReservationService
}

func (h *OrderEventHandler) HandleOrderConfirmed(ctx context.Context, event bus.Event) error {
    // Extract order data from event
    // Call ReservationService.ReserveForOrder()
}

func (h *OrderEventHandler) HandleOrderCancelled(ctx context.Context, event bus.Event) error {
    // Extract order ID from event
    // Call ReservationService.ReleaseForOrder()
}

func (h *OrderEventHandler) HandleOrderFulfilled(ctx context.Context, event bus.Event) error {
    // Extract order ID from event
    // Call ReservationService.CommitForOrder()
}

3. Bootstrap Integration

Initialized in cmd/api/bootstrap.go:

go
func initWarehouseIntegration(db *sqlx.DB, eventBus bus.IBus) (*integration.OrderEventHandler, error) {
    invRepo := inventoryRepo.NewInventoryRepository(db)
    inventoryUC := inventory.NewUseCase(invRepo)
    reservationService := integration.NewReservationService(inventoryUC)
    orderEventHandler := integration.NewOrderEventHandler(reservationService)
    
    if err := orderEventHandler.RegisterHandlers(eventBus); err != nil {
        return nil, err
    }
    
    return orderEventHandler, nil
}

Event Flows ​

Order Confirmation (order.confirmed):

  1. Order Management: Order.Confirm() publishes order.confirmed event
  2. Event Bus: Routes event to Warehouse Context
  3. Warehouse: OrderEventHandler.HandleOrderConfirmed()
  4. Warehouse: ReservationService.ReserveForOrder()
  5. Result: Stock reserved, order can proceed to fulfillment

Order Cancellation (order.cancelled):

  1. Order Management: Order.Cancel() publishes order.cancelled event
  2. Event Bus: Routes event to Warehouse Context
  3. Warehouse: OrderEventHandler.HandleOrderCancelled()
  4. Warehouse: ReservationService.ReleaseForOrder()
  5. Result: Stock returned to available pool

Order Fulfillment (order.fulfilled):

  1. Order Management: Order.MarkFulfilled() publishes order.fulfilled event
  2. Event Bus: Routes event to Warehouse Context
  3. Warehouse: OrderEventHandler.HandleOrderFulfilled()
  4. Warehouse: ReservationService.CommitForOrder()
  5. Result: Stock permanently removed from inventory

API Endpoints ​

Product (16 endpoints) ​

  • POST /products - Create product
  • GET /products/:id - Get by ID
  • GET /products - List products
  • PUT /products/:id - Update product
  • DELETE /products/:id - Soft delete
  • GET /products/sku/:sku - Get by SKU
  • GET /products/:id/inventory - Get inventory for product

Inventory (14 endpoints) ​

  • POST /inventory - Create inventory
  • GET /inventory/:id - Get by ID
  • PUT /inventory/:id - Update inventory
  • DELETE /inventory/:id - Soft delete
  • POST /inventory/:id/receive - Receive stock
  • POST /inventory/:id/reserve - Reserve stock
  • POST /inventory/:id/release - Release reservation
  • POST /inventory/:id/commit - Commit stock

StockMovement (7 endpoints) ​

  • POST /stock-movements - Create movement
  • GET /stock-movements/:id - Get by ID
  • GET /stock-movements - List movements
  • GET /stock-movements/inventory/:id - By inventory
  • GET /stock-movements/recent - Recent movements

Location (14 endpoints) ​

  • POST /locations - Create location
  • GET /locations/:id - Get by ID
  • GET /locations - List locations
  • PUT /locations/:id - Update location
  • DELETE /locations/:id - Soft delete

Total: 58 endpoints


Testing ​

Test Coverage ​

ComponentTestsType
Product139Entity (25) + UseCase (83) + Smoke (10) + Integration (21)
Inventory141Entity (97) + Integration (23) + Smoke (21)
StockMovement45Entity (11) + UseCase (10) + Smoke (9) + Integration (15)
Location74Entity (48) + Integration (17) + Smoke (9)
Integration34E2E order-warehouse flows
Total433100% passing (~4.2s)

Integration Tests (34) ​

End-to-end testing of order-warehouse synchronization:

  1. Order Confirmation Flow - Verify stock reservation
  2. Order Cancellation Flow - Verify reservation release
  3. Order Fulfillment Flow - Verify stock commit
  4. Edge Cases - Insufficient inventory, concurrent reservations, retries

Database Schema ​

7 Tables:

  1. warehouse_products - Product catalog (SKU, name, category, brand, price, dimensions)
  2. warehouse_inventory - Stock levels (on hand, reserved, available, committed)
  3. warehouse_stock_movements - Audit trail (immutable, all changes recorded)
  4. warehouse_locations - Warehouse/store locations (address, capacity, type)

Key Indexes:

  • idx_products_sku - Unique SKU lookup
  • idx_inventory_product_location - Composite for stock queries
  • idx_stock_movements_inventory_id - Audit trail queries
  • idx_locations_code - Unique location code

Audit Columns:

  • All tables have created_at, updated_at, deleted_at (soft delete)
  • StockMovement has created_by for user tracking
  • Before/After snapshots in StockMovement for auditability

Configuration ​

Event Bus Configuration ​

Required in config/app.{driver}-{env}.yaml:

yaml
bus:
  adapter: "redis"           # Use redis for distributed systems
  worker_pool_size: 50       # Concurrent event processing
  buffer_size: 10000         # Event queue capacity
  retry_attempts: 5          # Retry failed event handlers
  retry_delay: 1s            # Initial retry delay

No Additional Configuration: Warehouse Integration uses existing database and Event Bus connections.



Status: Production Ready (100% complete)
Last Updated: January 7, 2026
Aggregates: 4 (Product, Inventory, StockMovement, Location)
Endpoints: 58
Tests: 433 (100% passing)
Main Feature: Automated order-inventory synchronization via Event Bus

Built with Domain-Driven Design and Go