> For the complete documentation index, see [llms.txt](https://docs.flexbase.in/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flexbase.in/thinking-in-flexbase/modules-and-features.md).

# Features and Modules

## 🎯 Understanding Modules and Features

**Flexbase** organizes enterprise applications into **Modules** and **Features** - a clear, business-focused approach that maps directly to your requirements and user interface actions.

***

## 📦 What is a Module?

A **Module** represents a complete business domain or functional area of your application. Think of it as a self-contained unit that handles all operations related to a specific business concept.

### **Examples of Modules:**

* 🛒 **Orders Module** - Complete order management
* 📦 **Products Module** - Product catalog and inventory
* 💳 **Payments Module** - Payment processing
* 👥 **Customers Module** - Customer management
* 📊 **Reports Module** - Analytics and reporting

***

## ⚡ What is a Feature?

A **Feature** represents a single business action or operation within a module. Every button click, form submission, or user action in your application typically maps to one feature.

### **Feature Examples:**

* **Insert (POST)**: `AddOrder`, `CreateProduct`, `RegisterCustomer`
* **Query (GET)**: `GetOrders`, `SearchProducts`, `GetCustomerDetails`
* **Update (PUT)**: `UpdateOrder`, `ModifyProduct`, `EditCustomer`
* **Delete (DELETE)**: `CancelOrder`, `RemoveProduct`, `DeactivateCustomer`

***

## 🔄 Business Requirements → Technical Mapping

### **The Mapping Process:**

1. **Identify Business Domains** → Create **Modules**
2. **Identify User Actions** → Create **Features**
3. **Define Data Requirements** → Create **DTOs**
4. **Specify Business Rules** → Create **Domain Logic**

***

## 📋 Real-World Example: E-Commerce Application

Let's walk through a complete example of how business requirements translate to Flexbase modules and features.

### **Business Requirements:**

> *"We need an e-commerce system where customers can browse products, place orders, and make payments. Administrators should be able to manage products and view order reports."*

***

## 🛒 Module 1: Orders Module

### **Business Domain:** Order Management

### **Purpose:** Handle all order-related operations

### **Features in Orders Module:**

#### **1. AddOrder Feature (POST)**

**Business Requirement:** *"Customer clicks 'Place Order' button"*

**Screen Action:** Customer fills order form and clicks "Place Order"

**Technical Implementation:**

```csharp
// Generated Controller Action
[HttpPost]
[Route("AddOrder")]
public async Task<IActionResult> AddOrder([FromBody] AddOrderDto dto)
{
    return await RunService(201, dto, _processOrdersService.AddOrder);
}

// Generated DTO
public partial class AddOrderDto : DtoBridge
{
    [Required]
    public string CustomerId { get; set; }
    
    [Required]
    public List<OrderItemDto> OrderItems { get; set; }
    
    [Range(0.01, double.MaxValue)]
    public decimal TotalAmount { get; set; }
    
    public string? Notes { get; set; }
}

// Generated Command Handler
public partial class AddOrderHandler : IAddOrderHandler
{
    public virtual async Task Execute(AddOrderCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        _model = _flexHost.GetDomainModel<Order>().AddOrder(cmd);
        _repoFactory.GetRepo().InsertOrUpdate(_model);
        await _repoFactory.GetRepo().SaveAsync();
        await this.Fire(EventCondition, serviceBusContext);
    }
}

// Domain Logic (You Write This)
public partial class Order : DomainModelBridge
{
    public virtual Order AddOrder(AddOrderCommand cmd)
    {
        // Business validation
        if (cmd.Dto.TotalAmount <= 0)
            throw new BusinessException("Order total must be greater than zero");
        
        // Business rules
        if (cmd.Dto.OrderItems.Count == 0)
            throw new BusinessException("Order must contain at least one item");
        
        // Apply business logic
        this.Convert(cmd.Dto);
        this.SetAdded(cmd.Dto.GetGeneratedId());
        this.CalculateTotal();
        this.SetOrderStatus("Pending");
        
        return this;
    }
}
```

**API Endpoint:** `POST /api/Orders/AddOrder`

#### **2. GetOrders Feature (GET)**

**Business Requirement:** *"Admin clicks 'View Orders' to see all orders"*

**Screen Action:** Admin navigates to Orders page

**Technical Implementation:**

```csharp
// Generated Controller Action
[HttpGet]
[Route("GetOrders")]
public async Task<IActionResult> GetOrders([FromQuery] GetOrdersQuery query)
{
    return await RunService(200, query, _processOrdersService.GetOrders);
}

// Generated Query DTO
public partial class GetOrdersDto : DtoBridge
{
    public Guid Id { get; set; }
    public string CustomerId { get; set; }
    public string CustomerName { get; set; }
    public decimal TotalAmount { get; set; }
    public string Status { get; set; }
    public DateTime OrderDate { get; set; }
    public int ItemCount { get; set; }
}

// Generated Query Handler
public class GetOrders : FlexiQueryEnumerableBridge<GetOrdersDto>
{
    public override IEnumerable<GetOrdersDto> Fetch()
    {
        return _repoFactory.GetRepo()
            .FindAll<Order>()
            .Include(o => o.Customer)
            .SelectTo<GetOrdersDto>()
            .ToList();
    }
}

// Custom Query with Filters (You Can Extend)
public class GetOrdersByStatus : FlexiQueryEnumerableBridge<GetOrdersDto>
{
    public string Status { get; set; }
    
    public override IEnumerable<GetOrdersDto> Fetch()
    {
        return _repoFactory.GetRepo()
            .FindAll<Order>()
            .Where(o => o.Status == Status)
            .Include(o => o.Customer)
            .SelectTo<GetOrdersDto>()
            .ToList();
    }
}
```

### **🚀 Database Optimization Magic - No Complex SQL Required!**

**The beauty of Flexbase queries is that you don't write complex SELECT statements!** Here's what happens automatically:

#### **1. Automatic Projection to Output Model**

```csharp
// You define what you want in the output DTO
public partial class GetOrdersDto : DtoBridge
{
    public Guid Id { get; set; }           // Only these fields
    public string CustomerName { get; set; } // are fetched from DB
    public decimal TotalAmount { get; set; } // automatically!
    public string Status { get; set; }
    public DateTime OrderDate { get; set; }
    // Note: No complex SELECT statements needed!
}
```

#### **2. Database-Level Optimization**

**What Flexbase generates automatically:**

```sql
-- Instead of: SELECT * FROM Orders (fetches ALL columns)
-- Flexbase generates: SELECT only the fields you need
SELECT 
    o.Id,
    c.Name AS CustomerName,  -- From joined Customer table
    o.TotalAmount,
    o.Status,
    o.OrderDate
FROM Orders o
LEFT JOIN Customers c ON o.CustomerId = c.Id
WHERE o.Status = @Status
```

#### **3. Performance Benefits**

* ✅ **Only Required Fields** - Database fetches only what's in your DTO
* ✅ **Automatic Joins** - Include() statements become optimized SQL JOINs
* ✅ **No N+1 Queries** - Single query with proper joins
* ✅ **Memory Efficient** - No unnecessary data loaded into memory
* ✅ **Network Optimized** - Less data transferred over the network

#### **4. Complex Projections Made Simple**

```csharp
// You can add calculated fields without complex SQL
public partial class GetOrdersDto : DtoBridge
{
    public Guid Id { get; set; }
    public string CustomerName { get; set; }
    public decimal TotalAmount { get; set; }
    public string Status { get; set; }
    public DateTime OrderDate { get; set; }
    
    // Calculated fields - Flexbase handles the SQL automatically
    public int DaysSinceOrder { get; set; }
    public string StatusDisplay { get; set; }
    public bool IsHighValue { get; set; }
}

// AutoMapper configuration (generated automatically)
CreateMap<Order, GetOrdersDto>()
    .ForMember(dest => dest.CustomerName, opt => opt.MapFrom(src => src.Customer.Name))
    .ForMember(dest => dest.DaysSinceOrder, opt => opt.MapFrom(src => (DateTime.UtcNow - src.OrderDate).Days))
    .ForMember(dest => dest.StatusDisplay, opt => opt.MapFrom(src => GetStatusDisplay(src.Status)))
    .ForMember(dest => dest.IsHighValue, opt => opt.MapFrom(src => src.TotalAmount > 1000));
```

#### **5. What You DON'T Have to Write**

```sql
-- ❌ You DON'T write this complex SQL:
SELECT 
    o.Id,
    c.Name AS CustomerName,
    o.TotalAmount,
    o.Status,
    o.OrderDate,
    CASE 
        WHEN o.Status = 'Pending' THEN 'Awaiting Processing'
        WHEN o.Status = 'Processing' THEN 'Being Processed'
        WHEN o.Status = 'Shipped' THEN 'On the Way'
        ELSE 'Unknown'
    END AS StatusDisplay,
    DATEDIFF(day, o.OrderDate, GETDATE()) AS DaysSinceOrder,
    CASE 
        WHEN o.TotalAmount > 1000 THEN 1 
        ELSE 0 
    END AS IsHighValue
FROM Orders o
LEFT JOIN Customers c ON o.CustomerId = c.Id
WHERE o.Status = @Status
ORDER BY o.OrderDate DESC
```

#### **6. What You DO Write (Simple and Clean)**

```csharp
// ✅ You write this simple, readable code:
public class GetOrdersByStatus : FlexiQueryEnumerableBridge<GetOrdersDto>
{
    public string Status { get; set; }
    
    public override IEnumerable<GetOrdersDto> Fetch()
    {
        return _repoFactory.GetRepo()
            .FindAll<Order>()
            .Where(o => o.Status == Status)
            .Include(o => o.Customer)
            .SelectTo<GetOrdersDto>()  // Magic happens here!
            .ToList();
    }
}
```

### **🎯 Key Benefits:**

1. **No SQL Knowledge Required** - Write C# LINQ, get optimized SQL
2. **Automatic Optimization** - Only fetch what you need
3. **Type Safety** - Compile-time validation of all projections
4. **Maintainable** - Changes to DTO automatically update SQL
5. **Performance** - Database-level optimization without complexity
6. **Readable** - Business logic is clear and understandable

### **💡 The Magic of SelectTo()**

The `SelectTo<GetOrdersDto>()` method:

* ✅ **Analyzes your DTO** - Sees what fields you need
* ✅ **Generates optimized SQL** - Only selects required columns
* ✅ **Handles joins automatically** - Based on Include() statements
* ✅ **Applies projections** - Maps complex calculations
* ✅ **Optimizes performance** - Database-level efficiency

**Result:** You focus on business logic while Flexbase handles all the complex SQL optimization automatically!

**API Endpoint:** `GET /api/Orders/GetOrders`

***

## 📦 Module 2: Products Module

### **Business Domain:** Product Catalog Management

### **Purpose:** Handle all product-related operations

### **Features in Products Module:**

#### **1. AddProduct Feature (POST)**

**Business Requirement:** *"Admin clicks 'Add New Product' button"*

**Screen Action:** Admin fills product form and clicks "Save Product"

**Technical Implementation:**

```csharp
// Generated Controller Action
[HttpPost]
[Route("AddProduct")]
public async Task<IActionResult> AddProduct([FromBody] AddProductDto dto)
{
    return await RunService(201, dto, _processProductsService.AddProduct);
}

// Generated DTO
public partial class AddProductDto : DtoBridge
{
    [Required]
    [StringLength(100)]
    public string Name { get; set; }
    
    [Required]
    [StringLength(500)]
    public string Description { get; set; }
    
    [Range(0.01, double.MaxValue)]
    public decimal Price { get; set; }
    
    [Range(0, int.MaxValue)]
    public int StockQuantity { get; set; }
    
    [Required]
    public string Category { get; set; }
    
    public string? ImageUrl { get; set; }
}

// Domain Logic (You Write This)
public partial class Product : DomainModelBridge
{
    public virtual Product AddProduct(AddProductCommand cmd)
    {
        // Business validation
        if (cmd.Dto.Price <= 0)
            throw new BusinessException("Product price must be greater than zero");
        
        if (cmd.Dto.StockQuantity < 0)
            throw new BusinessException("Stock quantity cannot be negative");
        
        // Apply business logic
        this.Convert(cmd.Dto);
        this.SetAdded(cmd.Dto.GetGeneratedId());
        this.SetProductStatus("Active");
        this.GenerateSku();
        
        return this;
    }
}
```

**API Endpoint:** `POST /api/Products/AddProduct`

#### **2. GetProducts Feature (GET)**

**Business Requirement:** *"Customer clicks 'Browse Products' to see available products"*

**Screen Action:** Customer navigates to Products page

**Technical Implementation:**

```csharp
// Generated Controller Action
[HttpGet]
[Route("GetProducts")]
public async Task<IActionResult> GetProducts([FromQuery] GetProductsQuery query)
{
    return await RunService(200, query, _processProductsService.GetProducts);
}

// Generated Query DTO
public partial class GetProductsDto : DtoBridge
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public int StockQuantity { get; set; }
    public string Category { get; set; }
    public string Status { get; set; }
    public string Sku { get; set; }
    public string? ImageUrl { get; set; }
}

// Generated Query Handler
public class GetProducts : FlexiQueryEnumerableBridge<GetProductsDto>
{
    public override IEnumerable<GetProductsDto> Fetch()
    {
        return _repoFactory.GetRepo()
            .FindAll<Product>()
            .Where(p => p.Status == "Active")
            .SelectTo<GetProductsDto>()
            .ToList();
    }
}

// Custom Search Query (You Can Extend)
public class SearchProducts : FlexiQueryEnumerableBridge<GetProductsDto>
{
    public string SearchTerm { get; set; }
    public string Category { get; set; }
    public decimal? MinPrice { get; set; }
    public decimal? MaxPrice { get; set; }
    
    public override IEnumerable<GetProductsDto> Fetch()
    {
        var query = _repoFactory.GetRepo().FindAll<Product>()
            .Where(p => p.Status == "Active");
        
        if (!string.IsNullOrEmpty(SearchTerm))
            query = query.Where(p => p.Name.Contains(SearchTerm) || p.Description.Contains(SearchTerm));
        
        if (!string.IsNullOrEmpty(Category))
            query = query.Where(p => p.Category == Category);
        
        if (MinPrice.HasValue)
            query = query.Where(p => p.Price >= MinPrice.Value);
        
        if (MaxPrice.HasValue)
            query = query.Where(p => p.Price <= MaxPrice.Value);
        
        return query.SelectTo<GetProductsDto>().ToList();
    }
}
```

**API Endpoint:** `GET /api/Products/GetProducts`

***

## 🎯 Screen-to-Feature Mapping Examples

### **Example 1: Customer Order Screen**

| Screen Element        | User Action | Feature           | HTTP Method | Endpoint                        |
| --------------------- | ----------- | ----------------- | ----------- | ------------------------------- |
| "Place Order" Button  | Click       | AddOrder          | POST        | `/api/Orders/AddOrder`          |
| "View My Orders" Link | Click       | GetCustomerOrders | GET         | `/api/Orders/GetCustomerOrders` |
| "Order Details" Link  | Click       | GetOrderDetails   | GET         | `/api/Orders/GetOrderDetails`   |
| "Cancel Order" Button | Click       | CancelOrder       | PUT         | `/api/Orders/CancelOrder`       |

### **Example 2: Admin Product Management Screen**

| Screen Element                | User Action  | Feature               | HTTP Method | Endpoint                              |
| ----------------------------- | ------------ | --------------------- | ----------- | ------------------------------------- |
| "Add Product" Button          | Click        | AddProduct            | POST        | `/api/Products/AddProduct`            |
| "Edit Product" Button         | Click        | UpdateProduct         | PUT         | `/api/Products/UpdateProduct`         |
| "Delete Product" Button       | Click        | DeleteProduct         | DELETE      | `/api/Products/DeleteProduct`         |
| "Search Products" Input       | Type + Enter | SearchProducts        | GET         | `/api/Products/SearchProducts`        |
| "Filter by Category" Dropdown | Select       | GetProductsByCategory | GET         | `/api/Products/GetProductsByCategory` |

### **Example 3: Customer Dashboard Screen**

| Screen Element        | User Action | Feature               | HTTP Method | Endpoint                               |
| --------------------- | ----------- | --------------------- | ----------- | -------------------------------------- |
| "View Profile" Link   | Click       | GetCustomerProfile    | GET         | `/api/Customers/GetCustomerProfile`    |
| "Edit Profile" Button | Click       | UpdateCustomerProfile | PUT         | `/api/Customers/UpdateCustomerProfile` |
| "Order History" Tab   | Click       | GetOrderHistory       | GET         | `/api/Orders/GetOrderHistory`          |
| "Wishlist" Tab        | Click       | GetWishlist           | GET         | `/api/Products/GetWishlist`            |

***

## 🏗️ Complete Module Structure

### **Typical Module Contains:**

```
📦 OrdersModule/
├── 🎯 Domain/
│   ├── Order.cs (Domain Model)
│   ├── AddOrder.cs (Business Logic)
│   └── Order_SeedData.cs (Test Data)
├── 🌐 Controllers/
│   └── OrdersController.cs (REST API)
├── 📝 DTOs/
│   ├── AddOrderDto.cs (Input)
│   ├── GetOrdersDto.cs (Output)
│   └── OrderDto.cs (Domain)
├── 🔧 Handlers/
│   ├── AddOrderHandler.cs (Command)
│   └── GetOrdersHandler.cs (Query)
├── 📡 Events/
│   ├── OrderCreatedEvent.cs
│   └── OrderUpdatedEvent.cs
└── 🧪 Tests/
    ├── AddOrderTests.cs
    └── GetOrdersTests.cs
```

***

## 🎯 Feature Development Workflow

### **Step 1: Identify Business Requirement**

> *"Customer needs to be able to place an order"*

### **Step 2: Map to Screen Action**

> *"Customer clicks 'Place Order' button on order form"*

### **Step 3: Define Feature**

> *"AddOrder feature in Orders module"*

### **Step 4: Generate Code**

```bash
dotnet run --generate-feature Orders AddOrder
```

### **Step 5: Add Business Logic**

```csharp
public virtual Order AddOrder(AddOrderCommand cmd)
{
    // Your business rules here
    ValidateOrder(cmd.Dto);
    ApplyBusinessRules(cmd.Dto);
    return this;
}
```

### **Step 6: Test and Deploy**

* ✅ Unit tests generated automatically
* ✅ Integration tests ready
* ✅ API documentation generated
* ✅ Ready for deployment

***

## 📊 Module Planning Template

### **For Each Business Domain, Ask:**

1. **What is the main business concept?** → Module Name
2. **What actions can users perform?** → Features
3. **What data is needed for each action?** → DTOs
4. **What business rules apply?** → Domain Logic
5. **What events should be published?** → Domain Events

### **Example: Customer Management Module**

| Question                  | Answer                                                        |
| ------------------------- | ------------------------------------------------------------- |
| **Main Business Concept** | Customer Management                                           |
| **User Actions**          | Register, Login, Update Profile, View Profile, Deactivate     |
| **Data Requirements**     | Name, Email, Phone, Address, Preferences                      |
| **Business Rules**        | Email validation, Password requirements, Profile completeness |
| **Events**                | CustomerRegistered, ProfileUpdated, CustomerDeactivated       |

***

## 🚀 Best Practices

### **Module Design:**

* ✅ **Single Responsibility** - One business domain per module
* ✅ **Clear Boundaries** - Minimal coupling between modules
* ✅ **Consistent Naming** - Follow business terminology
* ✅ **Complete Coverage** - All related features in one module

### **Feature Design:**

* ✅ **One Action Per Feature** - Each feature does one thing
* ✅ **Clear Input/Output** - Well-defined DTOs
* ✅ **Business Logic in Domain** - Keep controllers thin
* ✅ **Proper Validation** - Validate at multiple levels

### **Naming Conventions:**

* **Modules:** `OrdersModule`, `ProductsModule`, `CustomersModule`
* **Features:** `AddOrder`, `GetOrders`, `UpdateProduct`, `DeleteCustomer`
* **DTOs:** `AddOrderDto`, `GetOrdersDto`, `OrderDto`
* **Handlers:** `AddOrderHandler`, `GetOrdersHandler`

***

## 🎉 Summary

**Flexbase Modules and Features provide a clear, business-focused approach to enterprise application development:**

* **Modules** = Business domains (Orders, Products, Customers)
* **Features** = User actions (AddOrder, GetProducts, UpdateCustomer)
* **Screen Actions** = Direct mapping to features
* **Business Requirements** = Clear path to technical implementation

**The result:** A maintainable, scalable application that directly reflects your business needs and user interface requirements.

***

*Start mapping your business requirements to Flexbase modules and features today. Transform your ideas into working enterprise applications in minutes, not months.*
