Locations Domain
Overview
The Locations domain manages the hierarchical structure of warehouse facilities, storage areas, and inventory locations within the organization. It provides a flexible, multi-level location hierarchy that supports various warehouse management scenarios from simple single-warehouse operations to complex multi-facility, multi-zone warehouse networks.
Core Concepts
Hierarchical Location Structure
The Locations domain implements a parent-child hierarchy that mirrors real-world warehouse organization:
Main Warehouse
├── Receiving Zone
│ ├── Dock 1
│ └── Dock 2
├── Storage Zone A
│ ├── Aisle A1
│ │ ├── Shelf A1-1
│ │ └── Shelf A1-2
│ └── Aisle A2
└── Shipping Zone
├── Staging Area 1
└── Staging Area 2
Location Classification
Locations are classified using two independent dimensions:
-
Location Type: Physical characteristics and structure
- Warehouse
- Zone
- Aisle
- Shelf/Bin
- Storage Unit
- Dock
- Yard
-
Location Purpose: Functional role in operations
- General Storage
- Receiving
- Shipping
- Quarantine
- Returns
- Production
- Scrap/Damaged
This dual-classification system allows flexible organization while maintaining clear operational purpose.
Operational Status
Each location has an operational status that controls its availability:
- Operational: Location is active and can be used for inventory transactions
- Non-Operational: Location is inactive (maintenance, closed, etc.)
Non-operational locations:
- Cannot receive new inventory
- Cannot be used as transaction destinations
- Retain existing inventory (read-only)
- Can be reactivated when needed
Domain Structure
Aggregates
locations/
├── aggregates/
│ └── location.aggregate.md # Core Location aggregate documentation
Entities
locations/
└── entities/
└── location.md # Location entity (aggregate root)
Lookup Entities
locations/
└── lookup-entities/
├── location-type.md # Location type classifications
└── location-purpose.md # Location purpose definitions
Value Objects
locations/
└── value-objects/
└── address.md # Physical address value object
Domain Services
locations/
└── services/
└── location-hierarchy-service.md # Hierarchy validation and management
Key Aggregates
Location
Aggregate Root: Location
Purpose: Represents a physical or logical storage location within the warehouse hierarchy.
Key Characteristics:
- Supports unlimited hierarchy depth
- Dual classification (Type + Purpose)
- Optional physical address
- Operational status control
- Parent-child relationship management
Relationships:
- Has one
LocationType(required) - Has one
LocationPurpose(required) - Has one parent
Location(optional) - Has many child
Locationinstances (0 to many) - Has one
Addressvalue object (optional)
Core Operations:
- Create location with type and purpose
- Update location information
- Set operational status
- Manage parent-child relationships
- Calculate full hierarchical path
Business Rules
Location Creation Rules
- Code Required: Location code must be unique and not empty
- Name Required: Location name cannot be empty
- Type Required: Every location must have a LocationType
- Purpose Required: Every location must have a LocationPurpose
- Code Normalization: Location codes are automatically uppercased
- Parent Optional: Locations can be created without parent (root locations)
Hierarchy Rules
- No Circular References: Location cannot be its own ancestor
- Operational Parent Requirement: Child locations can only be added to operational parent locations
- Single Parent: Each location has at most one parent
- Unlimited Depth: No artificial limit on hierarchy depth
- Hierarchy Validation: LocationHierarchyService validates complex hierarchy operations
Update Rules
- Immutable Code: Location code cannot be changed after creation
- Name Updates: Location name can be updated freely
- Purpose Changes: Location purpose can be changed at any time
- Type Immutability: Location type cannot be changed (create new location instead)
- Address Updates: Physical address can be added, updated, or removed
Operational Status Rules
- Status Transitions: Locations can be set operational or non-operational
- Child Impact: Making parent non-operational doesn't affect children (they can remain operational)
- Transaction Validation: Inventory transactions validate location is operational
- Inventory Retention: Non-operational locations retain existing inventory (read-only)
Integration Points
With Transaction Module
- Location Validation: Transactions validate source/destination locations are operational
- Movement Operations: Stock movements require valid source and destination locations
- Adjustment Operations: Stock adjustments require valid location
- Assembly Operations: Assembly transactions require valid production location
- Location Tracking: Transactions create location-based inventory records
With Inventory Module
- Location-Based Tracking: Inventory records maintain per-location quantities
- Stock Queries: Inventory lookups filter by location and hierarchy
- Available Stock: Location hierarchy supports roll-up inventory queries
- Location Transfers: Inventory updates track location movements
With Item Module
- TrackByLocation Setting: Item StockableBehavior determines location requirement
- Location Validation: Items with TrackByLocation=true require location specification
- Simplified Tracking: Items with TrackByLocation=false use default location
Common Patterns
Creating Root Location (Warehouse)
// Create main warehouse (no parent)
var warehouse = Location.Create(
code: "WH-MAIN",
name: "Main Distribution Center",
locationType: warehouseType,
locationPurpose: generalStoragePurpose,
description: "Primary distribution facility - North Region",
parentLocation: null, // Root location
physicalAddress: new Address(
street: "123 Industrial Parkway",
city: "Springfield",
state: "IL",
postalCode: "62701",
country: "USA"));
await locationRepository.AddAsync(warehouse);
await unitOfWork.CommitAsync();
Creating Child Location with Hierarchy
// 1. Load parent location
var warehouse = await locationRepository.GetByCodeAsync("WH-MAIN");
// 2. Create child zone with hierarchy validation
var receivingZone = Location.Create(
code: "RCV-ZONE-A",
name: "Receiving Zone A",
locationType: zoneType,
locationPurpose: receivingPurpose,
description: "Primary receiving area for inbound shipments",
parentLocation: warehouse,
hierarchyService: locationHierarchyService); // Validates hierarchy
// 3. Parent automatically includes child in collection
await unitOfWork.CommitAsync();
// At this point:
// - Parent: WH-MAIN
// - Child: RCV-ZONE-A
// - Hierarchy: WH-MAIN / RCV-ZONE-A
Building Multi-Level Hierarchy
// Level 1: Warehouse (root)
var warehouse = Location.Create("WH-01", "Main Warehouse", warehouseType, generalPurpose);
// Level 2: Zone
var storageZone = Location.Create("ZONE-A", "Storage Zone A", zoneType, generalPurpose,
parentLocation: warehouse);
// Level 3: Aisle
var aisle = Location.Create("AISLE-A1", "Aisle A1", aisleType, generalPurpose,
parentLocation: storageZone);
// Level 4: Shelf
var shelf = Location.Create("SHELF-A1-1", "Shelf A1-1", shelfType, generalPurpose,
parentLocation: aisle);
// Result hierarchy: WH-01 / ZONE-A / AISLE-A1 / SHELF-A1-1
Location Status Management
// Make location non-operational (e.g., for maintenance)
var location = await locationRepository.GetByCodeAsync("AISLE-A1");
location.SetNonOperational();
await unitOfWork.CommitAsync();
// Location is now unavailable for new transactions
// Existing inventory remains (read-only access)
// Later, reactivate location
location.SetOperational();
await unitOfWork.CommitAsync();
Getting Full Hierarchical Path
var shelf = await locationRepository.GetByCodeAsync("SHELF-A1-1");
// Get display path
string fullPath = shelf.GetFullPath();
// Result: "Main Warehouse / Storage Zone A / Aisle A1 / Shelf A1-1"
// Useful for:
// - UI breadcrumbs
// - Transaction displays
// - Reports
// - Pick lists
Repository Pattern
ILocationRepository
Query Methods:
GetByIdAsync(Guid id): Get location with all related dataGetAllAsync(): Get all operational locationsGetByCodeAsync(string code): Find location by unique codeGetRootLocationsAsync(): Get top-level locations (no parent)GetChildrenAsync(Guid parentId): Get immediate children of a locationGetDescendantsAsync(Guid parentId): Get all descendants (recursive)
Specialized Query Methods:
GetByTypeAsync(int locationTypeId): Find locations by typeGetByPurposeAsync(int locationPurposeId): Find locations by purposeGetOperationalLocationsAsync(): Get only operational locationsGetNonOperationalLocationsAsync(): Get only non-operational locations
Hierarchy Methods:
GetAncestorsAsync(Guid locationId): Get all parent locations up to rootGetPathAsync(Guid locationId): Get full path from root to locationGetSubtreeAsync(Guid rootId): Get location and all descendants
Validation Methods:
ExistsByCodeAsync(string code): Check if location code existsIsCodeUniqueAsync(string code, Guid? excludeId): Validate for updatesHasChildrenAsync(Guid locationId): Check if location has children
Command Methods:
AddAsync(Location location): Create new locationUpdate(Location location): Update existing locationArchive(Location location): Soft delete locationUnArchive(Location location): Restore archived location
Domain Services
LocationHierarchyService
Purpose: Validates complex hierarchy operations and prevents invalid location structures.
Key Methods:
Hierarchy Validation:
void ValidateParentAssignment(Location parent, Location child)
- Prevents circular references
- Validates parent is operational
- Ensures no ancestor loops
Hierarchy Queries:
Task<IEnumerable<Location>> GetAllAncestorsAsync(Location location)
Task<IEnumerable<Location>> GetAllDescendantsAsync(Location location)
Task<int> GetHierarchyDepthAsync(Location location)
Task<bool> IsAncestorOfAsync(Location potential Ancestor, Location descendant)
Business Logic:
- Circular reference prevention
- Depth calculations
- Ancestor validation
- Subtree operations
Testing Strategy
Unit Tests
- Factory Method Tests: Location creation with various combinations
- Hierarchy Tests: Parent-child relationship management
- Validation Tests: Business rule enforcement
- Status Tests: Operational status transitions
- Path Tests: Full path calculation
Integration Tests
- Repository Tests: Database operations and query correctness
- Hierarchy Persistence: Multi-level hierarchies correctly saved/loaded
- Lookup Integration: LocationType and LocationPurpose relationships
- Address Persistence: Value object correctly stored
- Circular Reference Tests: Database constraints prevent invalid hierarchies
Domain Service Tests
- Hierarchy Validation: Service correctly validates hierarchy operations
- Ancestor Queries: Correctly retrieves all ancestors
- Descendant Queries: Correctly retrieves all descendants
- Circular Detection: Prevents circular parent references
Future Enhancements
Planned Features
- Location Capacity: Track capacity limits (volume, weight, pallet count)
- Location Dimensions: Physical dimensions (length, width, height)
- Location Attributes: Flexible attribute system (temperature controlled, hazmat, etc.)
- Pick Path Optimization: Define optimal picking sequences within locations
- Zone Management: Enhanced zone-level operations and reporting
- Location Reservations: Reserve locations for specific orders or operations
Extensibility Points
-
Additional Location Types: System can accommodate new location types via lookup tables
-
Custom Purposes: New location purposes can be added without code changes
-
Integration Events: Publish events for cross-module integration
- LocationCreated
- LocationStatusChanged
- LocationHierarchyModified
-
Warehouse Management Integration: Foundation for advanced WMS features
- Directed putaway
- Wave picking
- Cross-docking
- Slotting optimization
Related Documentation
Domain Documentation
- Location Aggregate - Detailed aggregate documentation
- Location Hierarchy Service - Hierarchy management
API Documentation
- Locations API - REST endpoints for location management
Concept Documentation
- Location Hierarchy Design - Hierarchy architecture
- Warehouse Organization Patterns - Common patterns
Architecture Documentation
- Location Domain Architecture - Architectural decisions
Last Updated: 2025-10-24 | Status: Active Development | Version: 1.0