Skip to main content

Item Aggregate

Purpose

The Item aggregate serves as the central master data entity for the inventory management system, representing any product, material, component, or service that can be tracked, transacted, or referenced within the organization. It implements a composition-based architecture that provides unprecedented flexibility compared to traditional inheritance-based item hierarchies.

This aggregate is fundamentally responsible for maintaining item identity, classification, measurement specifications, and optional inventory tracking capabilities through behavior composition. The Item aggregate ensures that all transactions, assemblies, and inventory operations reference valid, properly configured items that conform to the organization's catalog standards.

The Item aggregate acts as the cornerstone of inventory operations, providing the foundational master data that enables accurate inventory tracking, transaction processing, assembly operations, and financial integration.

Business Rules & Invariants

Core Business Rules

  1. Unique Item Identification: Each item must have a unique ItemNumber that serves as the primary business identifier, distinct from the system-generated ID. Item numbers are immutable after creation.

  2. Composition-Based Behaviors: Items use composition instead of inheritance for capabilities. Behaviors (like StockableBehavior) can be added, removed, or modified independently from the core item entity.

  3. Stockable vs Non-Stockable: Items without StockableBehavior are non-stockable (e.g., services, labor). Only items with StockableBehavior can participate in inventory transactions and have stock levels tracked.

  4. Unit Class Flexibility: Items reference a UnitClass (e.g., "Weight", "Volume") rather than a specific UnitOfMeasure, allowing transactions to use any compatible unit within that class at runtime.

  5. Category Classification: Items can optionally belong to a hierarchical category structure for organization, reporting, and search purposes. Category assignment can be changed or cleared at any time.

  6. Tax Integration: Items can reference a TaxGroup for integration with finance module tax calculations on purchase and sales transactions.

Domain Invariants

  • Item Number Required: ItemNumber cannot be null or empty
  • Item Name Required: Name cannot be null or empty
  • Behavior Uniqueness: An item can have at most one StockableBehavior instance
  • No Self-Reference: Items cannot reference themselves in relationships
  • Active Status Control: Soft delete via IsActive flag instead of hard delete
  • Immutable Identifier: ItemNumber cannot be modified after creation

State Management

Item Lifecycle States

[Creation] → [Configuration] → [Active Use] → [Archive]

[Behavior Management]

[Stockable/Non-Stockable Transitions]

Behavior Lifecycle

[Item Created (No Behavior)] → [Add Stockable Behavior] → [Active Stockable Item]

[Update Behavior Settings]

[Remove Behavior] → [Non-Stockable Item]

Status Transitions

[Active] ←→ [Archived]

[Used in Transactions] → [Cannot Delete]

Aggregate Components

1. Item (Aggregate Root)

Properties:

Core Identification:

  • ItemNumber: Unique business identifier (immutable, user-defined)
  • Name: Display name for the item
  • Description: Detailed description or specifications

Classification:

  • CategoryId: Optional foreign key to Category aggregate
  • Category: Navigation property to hierarchical category structure

Measurement:

  • DefaultUnitClassId: Optional foreign key to UnitClass aggregate
  • DefaultUnitClass: Navigation property specifying the class of units (Weight, Volume, etc.)

Tax Integration:

  • TaxGroupId: Optional foreign key for tax calculation integration with finance module

Behavior Composition:

  • StockableBehavior: Optional owned entity enabling inventory tracking capabilities

Computed Properties:

  • IsStockable: Boolean indicator derived from presence of StockableBehavior

Base Properties (from AggregateRoot):

  • Id: System-generated unique identifier
  • CreatedDate: Timestamp of creation
  • ModifiedDate: Timestamp of last modification
  • IsActive: Soft delete flag

Key Behaviors:

  • Create(): Static factory method creating new item with validation
  • UpdateBaseInfo(): Modifies name and description with validation
  • UpdateCategory(): Assigns or clears category relationship
  • UpdateDefaultUnitClass(): Changes unit class specification
  • UpdateTaxGroup(): Modifies tax group assignment
  • AddStockableBehavior(): Adds inventory tracking capability
  • RemoveStockableBehavior(): Removes inventory tracking capability
  • UpdateStockableBehavior(): Modifies existing stockable behavior settings
  • AddOrUpdateBehavior(): Smart method that adds, updates, or removes behavior based on inputs

Validation Logic:

The Item aggregate enforces validation at multiple levels:

  • Construction Validation: Factory method validates required fields
  • Update Validation: Update methods validate state transitions
  • Behavior Validation: Ensures behavior can be added/removed safely
  • Business Rule Enforcement: Prevents invalid configurations

Central Master Data Role:

The Item serves as the single source of truth for:

  • Product Catalog: Complete catalog of all items in the organization
  • Transaction Reference: All inventory transactions reference items
  • BOM Components: Items serve as both parent items and components in BOMs
  • Inventory Tracking: Stockable items enable inventory record creation
  • Financial Integration: Item tax groups drive GL posting and tax calculations

2. StockableBehavior (Owned Entity)

Purpose: Composition-based behavior that enables inventory tracking capabilities for an item. When present, the item can participate in inventory transactions and have stock levels maintained.

Properties:

  • ItemId: Foreign key reference to parent Item (aggregate root)
  • AllowNegativeStock: Boolean controlling whether inventory can go negative
  • TrackByLocation: Boolean controlling whether location-specific tracking is required
  • Item: Navigation property back to parent Item

Key Behaviors:

  • Create(): Static factory method for creating behavior
  • UpdateInventoryRules(): Modifies tracking settings

Business Significance:

This composition pattern provides critical flexibility:

  • Dynamic Capabilities: Items can transition between stockable and non-stockable
  • Configuration Control: Each item has independent inventory tracking rules
  • Transaction Validation: Stockable behavior settings control transaction processing
  • Inventory Impact: Only items with this behavior create inventory records

Inventory Tracking Rules:

  1. AllowNegativeStock = false:

    • Transactions that would result in negative inventory are rejected
    • Used for items requiring strict physical inventory control
    • Prevents over-commitment of inventory
  2. AllowNegativeStock = true:

    • Inventory can go negative (backorder scenarios)
    • Used for high-velocity items or when backorders are acceptable
    • Enables flexibility in transaction processing
  3. TrackByLocation = true:

    • Inventory maintained separately for each location
    • All transactions must specify source/destination locations
    • Enables detailed location-based inventory management
  4. TrackByLocation = false:

    • Inventory tracked at organization level only
    • Location specification optional on transactions
    • Simplified tracking for non-warehouse items

Domain Events

Item Lifecycle Events (Future Enhancement)

  • ItemCreatedDomainEvent: Raised when new item is created

    • Contains ItemId, ItemNumber, Name for integration tracking
    • Enables cache invalidation and search index updates
    • Supports audit trail maintenance
  • ItemArchivedDomainEvent: Raised when item is archived

    • Triggers impact analysis for existing transactions and BOMs
    • Enables workflow automation for archive procedures
    • Supports compliance and audit requirements

Behavior Management Events (Future Enhancement)

  • ItemStockableBehaviorAddedDomainEvent: Raised when stockable behavior is added

    • Contains ItemId and behavior configuration
    • Triggers initialization of inventory records
    • Enables integration with warehouse management systems
  • ItemStockableBehaviorRemovedDomainEvent: Raised when stockable behavior is removed

    • Requires validation that no inventory exists
    • Triggers cleanup of inventory records
    • Supports audit trail for significant configuration changes
  • ItemStockableBehaviorUpdatedDomainEvent: Raised when behavior settings change

    • Contains old and new configuration for comparison
    • Enables impact analysis for transaction validation
    • Supports workflow automation for approval processes

Integration and Audit Events

These events enable:

  • Compliance Tracking: Complete audit trail of item changes
  • Impact Analysis: Understanding downstream effects of configuration changes
  • Cache Management: Intelligent invalidation of performance optimizations
  • Workflow Automation: Triggering approval processes for critical changes
  • Search Index Updates: Keeping search systems synchronized

Repository Contract

IItemRepository

Core Query Methods:

  • GetByIdAsync(Guid id): Retrieves single item with all related data
  • GetAllAsync(): Retrieves all active items with related entities
  • GetByItemNumberAsync(string itemNumber): Finds item by business identifier
  • GetArchivedAsync(): Retrieves archived (inactive) items

Specialized Query Methods:

  • GetStockableItemsAsync(): Returns only items with StockableBehavior
  • GetNonStockableItemsAsync(): Returns items without StockableBehavior
  • GetByCategoryAsync(Guid categoryId): Finds all items in specific category
  • GetByUnitClassAsync(Guid unitClassId): Finds items using specific unit class
  • GetByTaxGroupAsync(Guid taxGroupId): Finds items with specific tax group

Validation Methods:

  • ExistsByItemNumberAsync(string itemNumber): Checks if item number already exists
  • IsItemNumberUniqueAsync(string itemNumber, Guid? excludeId): Validates uniqueness for updates
  • CanBeArchivedAsync(Guid itemId): Validates if item can be safely archived

Command Methods:

  • AddAsync(Item item): Persists new item with validation
  • Update(Item item): Updates existing item
  • Archive(Item item): Soft delete (sets IsActive = false)
  • UnArchive(Item item): Restores archived item

Performance Optimization:

  • Eager Loading: Include related entities in single query
  • Selective Loading: Load only required relationships based on use case
  • Caching Support: Query patterns support caching strategies
  • Indexed Queries: Optimized queries on ItemNumber and Category

Domain Services

IItemService

Purpose: Provides cross-aggregate coordination and complex validation logic involving items and related entities.

Key Methods:

Transaction Validation:

Task<bool> CanUseInTransactionAsync(Guid itemId, TransactionType transactionType)
  • Validates item can be used in specific transaction type
  • Checks stockable status for inventory transactions
  • Verifies item is active and not archived

Unit Compatibility:

Task<IEnumerable<UnitOfMeasure>> GetCompatibleUnitsAsync(Guid itemId)
  • Returns all units compatible with item's UnitClass
  • Used for transaction unit dropdowns
  • Validates unit compatibility for conversions

Behavior Conversion:

Task<Result> ConvertToStockableAsync(Guid itemId, bool allowNegativeStock, bool trackByLocation)
  • Safely converts non-stockable item to stockable
  • Validates prerequisites (no conflicting transactions)
  • Initializes inventory records if needed
Task<Result> ConvertToNonStockableAsync(Guid itemId)
  • Safely converts stockable item to non-stockable
  • Validates no inventory exists
  • Cleans up related inventory records

Business Logic Integration:

  • Coordinates with Transaction aggregate for validation
  • Coordinates with Inventory aggregate for record management
  • Coordinates with BOM aggregate for component validation

Usage Patterns

Creating Basic Item

// 1. Create item with required properties
var item = Item.Create(
itemNumber: "WIDGET-100",
name: "Standard Widget",
description: "General purpose widget for assembly operations");

// 2. Optional: Assign category
item.UpdateCategory(widgetCategoryId);

// 3. Optional: Assign unit class
item.UpdateDefaultUnitClass(weightUnitClassId);

// 4. Optional: Assign tax group
item.UpdateTaxGroup(standardTaxGroupId);

// 5. Save via repository
await itemRepository.AddAsync(item);
await unitOfWork.CommitAsync();

Creating Stockable Item

// 1. Create base item
var item = Item.Create(
itemNumber: "RM-STEEL-001",
name: "Steel Plate 1/4 inch",
description: "Cold rolled steel plate, 1/4 inch thickness",
categoryId: rawMaterialsCategoryId,
defaultUnitClassId: weightUnitClassId,
taxGroupId: rawMaterialsTaxGroupId);

// 2. Add stockable behavior for inventory tracking
item.AddStockableBehavior(
allowNegativeStock: false, // Prevent negative inventory
trackByLocation: true); // Require location tracking

// 3. Persist
await itemRepository.AddAsync(item);
await unitOfWork.CommitAsync();

// At this point:
// - Item can be used in inventory transactions
// - Inventory records will be created for this item
// - All transactions must specify locations
// - Negative stock is prevented

Creating Non-Stockable Item (Service)

// Create service item without stockable behavior
var serviceItem = Item.Create(
itemNumber: "SRV-CONSULTING",
name: "Consulting Services",
description: "Professional consulting services - hourly rate",
categoryId: servicesCategoryId);

// No stockable behavior added
// Service items don't track inventory

await itemRepository.AddAsync(serviceItem);
await unitOfWork.CommitAsync();

// Service item can be:
// - Referenced in documents
// - Used for billing
// - Tracked for revenue
// But will NOT:
// - Create inventory records
// - Participate in stock transactions
// - Have stock quantities

Modifying Stockable Behavior

// 1. Retrieve item
var item = await itemRepository.GetByIdAsync(itemId);

// 2. Update stockable behavior settings
if (item.IsStockable)
{
item.UpdateStockableBehavior(
allowNegativeStock: true, // Now allow backorders
trackByLocation: false); // Simplify to org-level tracking
}
else
{
// Convert to stockable
item.AddStockableBehavior(
allowNegativeStock: false,
trackByLocation: true);
}

// 3. Save changes
await unitOfWork.CommitAsync();

Using AddOrUpdateBehavior (Smart Method)

// Smart method handles all scenarios
item.AddOrUpdateBehavior(
allowNegativeStock: true,
trackByLocation: false);

// If behavior exists: updates settings
// If behavior doesn't exist: creates it
// If both params are null: removes behavior

Performance Considerations

Optimization Strategies

  • Repository Patterns: Specialized queries for different use cases reduce over-fetching
  • Eager Loading: Load related entities in single query to avoid N+1 problems
  • Behavior Caching: StockableBehavior loaded with item to avoid separate queries
  • Index Strategy: Clustered index on Id, non-clustered on ItemNumber for lookups

Scalability Metrics

  • Item Lookup by Number: <5ms for indexed item number queries
  • Category-Based Queries: <20ms for category-filtered item lists
  • Stockable Item Queries: <10ms with filtered index on behavior presence
  • Memory Footprint: ~2KB per item entity in memory

Database Optimization

  • Primary Key: Clustered index on Id (Guid) for entity framework
  • Item Number Index: Unique non-clustered index for business key lookups
  • Category Index: Non-clustered index for category-based queries
  • Foreign Keys: Indexed foreign keys for join performance
  • Behavior Storage: Owned entity table with 1:1 relationship to items

Caching Strategies

  • Item Catalog Cache: Cache entire item catalog for read-heavy scenarios
  • Lookup Cache: Cache item number to ID mappings
  • Category Cache: Cache items by category for navigation
  • Invalidation: Cache invalidation on item updates via domain events (future)

Integration with Other Aggregates

Category Aggregate

  • Hierarchical Classification: Items reference categories for organization
  • Multi-Level Hierarchy: Categories support parent-child relationships
  • Flexible Assignment: Category can be changed or cleared on items
  • Reporting Integration: Category-based reports and analytics

UnitClass Aggregate

  • Measurement Flexibility: Item references UnitClass, not specific units
  • Transaction Compatibility: Transactions can use any unit in the class
  • Conversion Support: UnitClass enables runtime unit conversions
  • Display Preferences: Default unit class guides UI presentation

Transaction Aggregate

  • Stockable Validation: Transactions validate item has StockableBehavior
  • Negative Stock Control: Transaction processing checks AllowNegativeStock
  • Location Requirements: TrackByLocation setting enforces location specification
  • Item Reference: All transaction lines reference Item aggregate

Inventory Aggregate

  • Record Creation: Only stockable items generate inventory records
  • Location Granularity: TrackByLocation determines inventory record structure
  • Quantity Updates: Inventory reacts to transaction domain events
  • Stock Queries: Inventory lookups filter by stockable items

BOM Aggregate

  • Parent Items: Items serve as parent items in BOMs (finished goods)
  • Component Items: Items serve as components in BOMs (raw materials)
  • Circular Reference Prevention: BOMs validate item isn't its own component
  • Unit Compatibility: BOM component units must be compatible with item's unit class

Finance Module Integration

  • Tax Calculation: Item TaxGroup drives tax calculations on purchase/sales
  • GL Account Determination: Item properties help determine posting accounts
  • Revenue Recognition: Item type influences revenue accounting
  • Cost of Goods Sold: Stockable items impact COGS calculations

Design Patterns Applied

Domain-Driven Design Patterns

  • Aggregate Pattern: Item maintains consistency boundary for item data
  • Repository Pattern: Specialized data access with performance optimization
  • Factory Method Pattern: Static Create() method enforces invariants
  • Composition Pattern: Behaviors composed rather than inherited
  • Domain Events Pattern: Future enhancement for change notification (planned)

Behavioral Patterns

  • Strategy Pattern: StockableBehavior represents different inventory strategies
  • Null Object Pattern: Missing StockableBehavior implies non-stockable strategy
  • Template Method Pattern: Base item provides template, behaviors customize

Structural Patterns

  • Composite Pattern: Used in Category relationships
  • Owned Entity Pattern: StockableBehavior owned by Item aggregate
  • Value Object Pattern: Planned for pricing, dimensions, identifiers

Security and Compliance Considerations

Access Control

  • Item Creation: Restricted to authorized catalog management roles
  • Behavior Changes: Stockable status changes require elevated privileges
  • Archive Operations: Item archival controlled through authorized workflows

Audit and Compliance

  • Complete Audit Trail: All item changes tracked via timestamps (future: domain events)
  • Soft Delete: Archived items retained for historical reporting
  • Change Tracking: ModifiedDate tracks last update timestamp
  • Behavior History: StockableBehavior changes will be tracked via events (planned)

Data Integrity

  • Referential Integrity: Foreign keys prevent orphaned relationships
  • Constraint Validation: Comprehensive validation prevents inconsistent state
  • Transaction Consistency: Unit of Work ensures atomic changes
  • Uniqueness Enforcement: Unique index on ItemNumber prevents duplicates

Future Evolution

Planned Enhancements

  1. Domain Events: Full event-driven architecture for item changes
  2. Item Variants: Support size/color/style variants of base items
  3. Item Attributes: Flexible attribute system for specifications
  4. Pricing Integration: Built-in price lists and pricing tiers
  5. Supplier Relationships: Link items to preferred suppliers
  6. Digital Assets: Support for images, documents, specifications
  7. Serial/Lot Tracking: Enhanced StockableBehavior for serialized items

Extensibility Points

  1. Additional Behaviors:

    • PurchasableBehavior: Purchase-specific rules and lead times
    • SellableBehavior: Sales-specific rules and pricing
    • ManufacturableBehavior: Production-specific settings
    • SerializableBehavior: Serial number tracking
  2. Custom Validation: Domain service extensible for business-specific rules

  3. Integration Events: Cross-module communication

    • ItemCreated → Finance module
    • ItemStockableStatusChanged → Warehouse module
    • ItemArchived → All consuming modules
  4. Reporting Extensions: Item-based reports and analytics

    • Catalog reports
    • Inventory valuation
    • Movement analysis
    • ABC classification

Architecture Decisions

Why Composition Over Inheritance?

Decision: Use composition (StockableBehavior) instead of inheritance (StockableItem : Item).

Rationale:

  • Items need to transition between stockable and non-stockable states
  • No rigid type hierarchy to manage
  • Easy to add new behaviors without modifying base class
  • Behaviors are self-contained and independently testable
  • Aligns with modern DDD practices

Trade-offs:

  • Slightly more complex queries (left join for behavior)
  • Null checks required for optional behavior
  • Benefits far outweigh minor complexity increase

Why UnitClass Instead of UnitOfMeasure?

Decision: Items reference UnitClass (e.g., "Weight") not specific UnitOfMeasure (e.g., "kg").

Rationale:

  • Maximum flexibility at transaction time
  • Different users/locations can use preferred units
  • Supports international operations with different measurement systems
  • Reduces item proliferation (one item, many transaction units)

Example:

  • Item uses "Weight" class
  • Transactions can use: kg, lb, g, oz, tons, etc.
  • System handles conversions automatically

Why Soft Delete Instead of Hard Delete?

Decision: Use Archive/UnArchive (IsActive flag) instead of database delete.

Rationale:

  • Preserve historical transaction references
  • Audit trail requirements
  • Enable restoration if archived by mistake
  • Prevent referential integrity issues
  • Support compliance and regulatory needs

Last Updated: 2025-10-24 | Status: Production | Version: 1.0