Categories Domain
Overview
The Categories domain provides hierarchical product classification capabilities for the inventory system. It enables organizations to organize their item catalog into logical groupings that support navigation, reporting, analysis, and item management workflows. Categories use a simple self-referencing parent-child structure that can accommodate unlimited hierarchy depth.
Core Concepts
Hierarchical Classification
Categories implement a tree structure that mirrors real-world product taxonomy:
All Products (root)
├── Electronics
│ ├── Computers
│ │ ├── Laptops
│ │ ├── Desktops
│ │ └── Tablets
│ ├── Mobile Devices
│ │ ├── Smartphones
│ │ └── Accessories
│ └── Audio Equipment
├── Office Supplies
│ ├── Writing Instruments
│ ├── Paper Products
│ └── Desk Accessories
└── Raw Materials
├── Metals
├── Plastics
└── Chemicals
Classification Benefits
Navigation: Users browse items by category hierarchy Reporting: Category-based analytics and summaries Search: Filter items by category for focused results Organization: Logical grouping of related items Authorization: Future support for category-level permissions
Domain Structure
Aggregates
categories/
└── aggregates/
└── category.aggregate.md # Category aggregate documentation
Entities
categories/
└── entities/
└── category.md # Category entity (aggregate root)
Key Aggregates
Category
Aggregate Root: Category
Purpose: Represents a hierarchical classification node for organizing items.
Key Characteristics:
- Self-referencing hierarchy (parent-child)
- Unlimited depth support
- Simple tree structure
- Active/inactive status (soft delete)
- Unique code identifier
Relationships:
- Has one parent
Category(optional - root categories have no parent) - Has many child
Categoryinstances (0 to many) - Referenced by many
Iteminstances
Core Operations:
- Create category with optional parent
- Update category information
- Check if root category
- Check if has children
- Get hierarchical path for display
- Archive/unarchive category
Business Rules
Category Creation Rules
- Code Required: Category code must be unique and not empty
- Name Required: Category name cannot be empty
- Description Optional: Additional details can be provided
- Parent Optional: Categories can be root-level (no parent)
- Parent Must Be Active: Cannot create child category under inactive parent
Hierarchy Rules
- No Circular References: Category cannot be its own ancestor (validated at service level)
- Single Parent: Each category has at most one parent
- Unlimited Depth: No artificial limit on hierarchy depth
- Root Categories: Categories without parent are considered root
Update Rules
- Immutable Code: Category code cannot be changed after creation
- Name Updates: Category name can be freely updated
- Description Updates: Description can be added, updated, or cleared
- Parent Reassignment: Not supported directly (create new category instead)
Archive Rules
- Soft Delete: Categories archived via IsActive flag
- Child Impact: Archiving parent doesn't automatically archive children
- Item Reference: Items referencing archived categories retain reference
- Restoration: Archived categories can be unarchived
Integration Points
With Item Module
- Item Classification: Items reference one category
- Category Navigation: Browse items by category
- Category Filtering: Filter item lists by category
- Optional Assignment: Items can exist without category
With Reporting
- Category Reports: Summarize inventory by category
- Hierarchy Reports: Show category hierarchy with item counts
- Category Analysis: Analyze patterns at category level
- Drill-Down: Navigate from category summaries to item details
With User Interface
- Category Trees: Display hierarchy in navigation
- Breadcrumbs: Show category path in item views
- Category Selectors: Dropdown or tree picker for category assignment
- Search Filters: Category-based search filtering
Common Patterns
Creating Root Category
// Create top-level category (no parent)
var rootCategory = Category.Create(
code: "ELECTRONICS",
name: "Electronics",
description: "Electronic devices and components");
await categoryRepository.AddAsync(rootCategory);
await unitOfWork.CommitAsync();
Creating Child Category
// 1. Load parent category
var parentCategory = await categoryRepository
.GetByCodeAsync("ELECTRONICS");
// 2. Create child category
var childCategory = Category.Create(
code: "COMPUTERS",
name: "Computers",
description: "Desktop and laptop computers",
parentCategory: parentCategory);
await categoryRepository.AddAsync(childCategory);
await unitOfWork.CommitAsync();
// Result hierarchy: Electronics > Computers
Building Multi-Level Hierarchy
// Level 1: Root
var electronics = Category.Create("ELECTRONICS", "Electronics");
// Level 2: Sub-category
var computers = Category.Create("COMPUTERS", "Computers",
parentCategory: electronics);
// Level 3: Sub-sub-category
var laptops = Category.Create("LAPTOPS", "Laptops",
parentCategory: computers);
// Save all
await categoryRepository.AddAsync(electronics);
await categoryRepository.AddAsync(computers);
await categoryRepository.AddAsync(laptops);
await unitOfWork.CommitAsync();
// Result: Electronics > Computers > Laptops
Getting Category Path for Display
var category = await categoryRepository.GetByCodeAsync("LAPTOPS");
// Get full hierarchical path
string path = category.GetHierarchyPath();
// Result: "Electronics > Computers > Laptops"
// Use in UI:
// - Breadcrumbs: Home > Electronics > Computers > Laptops
// - Item display: "Category: Electronics > Computers > Laptops"
// - Reports: Group by full category path
Checking Category Status
var category = await categoryRepository.GetByCodeAsync("COMPUTERS");
// Check if root category
bool isRoot = category.IsRoot(); // false (has parent)
// Check if has children
bool hasChildren = category.HasChildren(); // true (has laptops, desktops, etc.)
// Get children
var children = category.ChildCategories; // Collection of child categories
Updating Category
var category = await categoryRepository.GetByCodeAsync("COMPUTERS");
// Update name and description
category.Update(
name: "Computer Systems",
description: "Desktop computers, laptops, and workstations");
await unitOfWork.CommitAsync();
// Note: Code cannot be changed
// Note: Parent cannot be changed (create new category instead)
Archiving Category
var category = await categoryRepository.GetByCodeAsync("OBSOLETE-CATEGORY");
// Archive category (soft delete)
categoryRepository.Archive(category);
await unitOfWork.CommitAsync();
// Category is now inactive (IsActive = false)
// Items still reference it
// Can be restored later
// Later, restore if needed
categoryRepository.UnArchive(category);
await unitOfWork.CommitAsync();
Repository Pattern
ICategoryRepository
Query Methods:
GetByIdAsync(Guid id): Get single category with related dataGetAllAsync(): Get all active categoriesGetByCodeAsync(string code): Find category by unique codeGetRootCategoriesAsync(): Get top-level categories (no parent)GetChildrenAsync(Guid parentId): Get immediate childrenGetDescendantsAsync(Guid parentId): Get all descendants (recursive)
Specialized Query Methods:
GetCategoryTreeAsync(): Load entire category treeGetCategoriesWithItemCountAsync(): Categories with item countsGetAncestorsAsync(Guid categoryId): Get all parent categories up to rootGetPathAsync(Guid categoryId): Get full path from root
Validation Methods:
ExistsByCodeAsync(string code): Check if category code existsIsCodeUniqueAsync(string code, Guid? excludeId): Validate for updatesHasChildrenAsync(Guid categoryId): Check if category has childrenHasItemsAsync(Guid categoryId): Check if items assigned to category
Command Methods:
AddAsync(Category category): Create new categoryUpdate(Category category): Update existing categoryArchive(Category category): Soft delete categoryUnArchive(Category category): Restore archived category
Domain Services
CategoryHierarchyService (Future Enhancement)
Purpose: Validates complex hierarchy operations and provides advanced hierarchy queries.
Planned Methods:
Task<bool> WouldCreateCircularReference(Guid categoryId, Guid newParentId)
Task<IEnumerable<Category>> GetAllAncestorsAsync(Category category)
Task<IEnumerable<Category>> GetAllDescendantsAsync(Category category)
Task<int> GetHierarchyDepthAsync(Category category)
Task MoveCategory(Guid categoryId, Guid? newParentId)
Testing Strategy
Unit Tests
- Factory Method Tests: Category creation with various combinations
- Hierarchy Tests: Parent-child relationship management
- Validation Tests: Business rule enforcement
- Path Tests: Hierarchy path calculation
- Status Tests: Root and children checks
Integration Tests
- Repository Tests: Database operations and query correctness
- Hierarchy Persistence: Multi-level hierarchies correctly saved/loaded
- Relationship Tests: Parent-child navigation
- Item Integration: Categories correctly associated with items
- Circular Reference Tests: Prevention at database level
Performance Considerations
Optimization Strategies
- Hierarchy Loading: Load full tree in single query for UI
- Path Caching: Cache calculated paths for performance
- Item Count Aggregation: Cached item counts per category
- Indexed Queries: Fast lookups by code and parent ID
Scalability Metrics
- Category Lookup: <5ms for code-based lookup
- Tree Loading: <50ms for full category tree (100 categories)
- Path Calculation: <10ms for path generation
- Memory Footprint: ~500 bytes per category
Database Optimization
- Clustered Index: Primary key on Category Id
- Code Index: Unique non-clustered index on Code
- Parent Index: Non-clustered index on ParentCategoryId
- Hierarchy Queries: Recursive CTE support for descendants
Future Enhancements
Planned Features
- Category Attributes: Custom attributes per category
- Category Images: Visual representation for UI
- Category Templates: Default settings for items in category
- Multi-Path Categories: Items in multiple categories
- Category Authorization: Permission control at category level
- Category Sorting: Custom sort order within parent
- Category Tags: Additional classification beyond hierarchy
Extensibility Points
-
Domain Events: Publish events for category changes
- CategoryCreated
- CategoryUpdated
- CategoryArchived
-
Hierarchy Service: Advanced hierarchy operations
-
Integration Events: Cross-module communication
- CategoryStructureChanged → Reporting
- CategoryArchived → All consuming modules
Related Documentation
Domain Documentation
- Category Aggregate - Detailed aggregate documentation
API Documentation
- Categories API - REST endpoints for category management
Concept Documentation
- Category Hierarchy Design - Hierarchy patterns
- Item Classification - Classification strategies
Last Updated: 2025-10-24 | Status: Production Ready | Version: 1.0