# Insert Example

## Overview

This document demonstrates the complete **Insert flow** using the **AddToShipping** feature from the EBusiness application. The flow starts with a POST request to the controller and ends with event publishing and subscriber processing.

## Complete Flow Architecture

```
POST Request → Controller → Service → PreBus Plugins → Command Handler → RESTClient → External System
                                                                                    ↓
Response ← Controller ← Service ← Command Handler ← RESTClient ← External System
```

### **Detailed Flow Breakdown**

```
1. POST Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. PreBus Processing (Validation Pipeline)
   ├── AddToShippingSequence (Plugin Registration)
   ├── AddToShippingDataPacket (Validation Context)
   └── ValidateShipping Plugin (Business Rules)
   ↓
5. Command Handler (RESTClient Integration)
   ├── Internal DTO → Request DTO Mapping
   ├── RESTClient Call to External System
   └── Response DTO Processing
   ↓
6. Event Publishing (Asynchronous Processing)
   ↓
7. Subscribers (Side Effects)
```

## Step-by-Step Implementation

### 1. **API Controller** - The Entry Point

**File**: `ShippingController_AddToShipping.cs`

```csharp
[HttpPost]
[Route("AddToShipping")]
[ProducesResponseType(typeof(BadRequestResult), 400)]
[ProducesResponseType(typeof(string), 201)]
public async Task<IActionResult> AddToShipping([FromBody]AddToShippingDto dto)
{
    return await RunService(201, dto, _processShippingService.AddToShipping);
}
```

**What Happens:**

* **HTTP Method**: `POST /api/Shipping/AddToShipping`
* **Input**: `AddToShippingDto` from request body
* **Action**: Calls the service layer to process the shipping
* **Response**: HTTP 201 Created with shipping ID

### 2. **Service Layer** - Business Orchestration

**File**: `ProcessShippingService_AddToShipping.cs`

```csharp
public async Task<CommandResult> AddToShipping(AddToShippingDto dto)
{
    var packet = await ProcessBusinessRuleSequence<AddToShippingDataPacket, AddToShippingSequence, AddToShippingDto, FlexAppContextBridge>(dto);

    if (packet.HasError)
    {
        return new CommandResult(Status.Failed, packet.Errors());
    }
    else
    {
        dto.SetGeneratedId(_pkGenerator.GenerateKey());
        AddToShippingCommand cmd = new AddToShippingCommand
        {
             Dto = dto,
        };

        await ProcessCommand(cmd);

        CommandResult cmdResult = new CommandResult(Status.Success);

        AddToShippingResultModel outputResult = new AddToShippingResultModel();
        outputResult.Id = dto.GetGeneratedId();
        cmdResult.result = outputResult;

        return cmdResult;
    }
}
```

**What Happens:**

* **PreBus Processing**: Executes business rule sequences (plugins)
* **Validation**: Processes business rule sequences
* **ID Generation**: Generates unique shipping ID
* **Command Creation**: Creates `AddToShippingCommand` with DTO
* **Command Processing**: Calls the command handler
* **Result**: Returns success with generated shipping ID

### 2.1. **PreBus Business Rule Sequence** - Validation Pipeline

**File**: `AddToShippingSequence.cs`

```csharp
public class AddToShippingSequence : FlexiBusinessRuleSequenceBase<AddToShippingDataPacket>
{
    public AddToShippingSequence()
    {
        this.Add<ValidateShipping>(); 
    }
}
```

**What Happens:**

* **Plugin Registration**: Registers validation plugins in execution order
* **Sequential Processing**: Executes plugins one by one
* **Error Collection**: Collects validation errors from all plugins
* **Early Exit**: Stops processing if any plugin fails

### 2.2. **PreBus Data Packet** - Validation Context

**File**: `AddToShippingDataPacket.cs`

```csharp
public partial class AddToShippingDataPacket : FlexiFlowDataPacketWithDtoBridge<AddToShippingDto, FlexAppContextBridge>
{
    protected readonly ILogger<AddToShippingDataPacket> _logger;

    public AddToShippingDataPacket(ILogger<AddToShippingDataPacket> logger)
    {
        _logger = logger;
    }

    #region "Properties
    //Models and other properties goes here
    #endregion
}
```

**What Happens:**

* **Context Container**: Holds DTO and application context
* **Error Collection**: Collects validation errors from plugins
* **Data Sharing**: Allows plugins to share data during validation
* **Logging**: Provides logging capabilities for plugins

### 2.3. **PreBus Validation Plugin** - Business Rules

**File**: `ValidateShipping.cs`

```csharp
public partial class ValidateShipping : FlexiBusinessRuleBase, IFlexiBusinessRule<AddToShippingDataPacket>
{
    public override string Id { get; set; } = "3a1cd0401f931dd4a01587e229b720dc";
    public override string FriendlyName { get; set; } = "ValidateShipping";

    protected readonly ILogger<ValidateShipping> _logger;
    protected readonly RepoFactory _repoFactory;

    public ValidateShipping(ILogger<ValidateShipping> logger, RepoFactory repoFactory)
    {
        _logger = logger;
        _repoFactory = repoFactory;
    }

    public virtual async Task Validate(AddToShippingDataPacket packet)
    {
        //Uncomment the below line if validating against a db data using your repo
        //_repoFactory.Init(packet.Dto);

        //If any validation fails, uncomment and use the below line of code to add error to the packet
        //packet.AddError("key", "ErrorMessage");

        await Task.CompletedTask; //If you have any await in the validation, remove this line
    }
}
```

**What Happens:**

* **Business Rule Validation**: Implements specific validation logic
* **Database Access**: Can access repository for data validation
* **Error Reporting**: Adds errors to the data packet if validation fails
* **Async Support**: Supports asynchronous validation operations
* **Dependency Injection**: Receives logger and repository factory

### 2.4. **PreBus Plugin Benefits**

* **Modular Validation**: Each plugin handles one validation concern
* **Reusable Rules**: Plugins can be reused across different features
* **Testable**: Each plugin can be unit tested independently
* **Configurable**: Plugins can be enabled/disabled per feature
* **Extensible**: Easy to add new validation rules
* **Ordered Execution**: Plugins execute in defined sequence

### 3. **Command Handler** - RESTClient Integration

**File**: `AddToShippingHandler.cs`

```csharp
public partial class AddToShippingHandler : IAddToShippingHandler
{
    protected string EventCondition = "";
    protected readonly ILogger<AddToShippingHandler> _logger;
    protected readonly IFlexHost _flexHost;
    protected ShippingRESTClient _restClient;
    protected FlexAppContextBridge? _flexAppContext;

    public AddToShippingHandler(ILogger<AddToShippingHandler> logger, IFlexHost flexHost, ShippingRESTClient restClient)
    {
        _logger = logger;
        _flexHost = flexHost;
        _restClient = restClient;
    }

    public virtual async Task Execute(AddToShippingCommand cmd, IFlexServiceBusContext serviceBusContext)
    {
        // Convert internal DTO to Request DTO
        AddToShippingRequestDto requestParams = new AddToShippingRequestDto
        {
            OrderId = cmd.Dto.OrderId,
            ShippingAddress = cmd.Dto.ShippingAddress,
            TrackingNumber = cmd.Dto.TrackingNumber,
            TotalWeight = cmd.Dto.ShippingItems?.Sum(x => x.Weight) ?? 0,
            ShippingItems = cmd.Dto.ShippingItems?.Select(x => new ShippingItemRequestDto
            {
                ProductId = x.ProductId,
                Quantity = x.Qty,
                Weight = x.Weight,
                Volume = x.Volume
            }).ToList()
        };

        // Call external REST service
        var response = await _restClient.AddToShipping(requestParams);

        // Process response
        if (response.IsSuccessStatusCode)
        {
            var responseContent = await response.Content.ReadAsStringAsync();
            var responseDto = JsonConvert.DeserializeObject<AddToShippingResponseDto>(responseContent);
            
            _logger.LogDebug("Shipping created successfully with external ID: {ExternalId}", responseDto?.Id);
            
            // Set success condition for event firing
            EventCondition = "CONDITION_ONSUCCESS";
        }
        else
        {
            _logger.LogError("Failed to create shipping. Status: {StatusCode}", response.StatusCode);
            EventCondition = "CONDITION_ONFAILED";
        }

        await this.Fire(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **DTO Mapping**: Converts internal DTO to Request DTO for external system
* **RESTClient Call**: Calls external shipping service via RESTClient
* **Response Processing**: Handles success/failure responses from external system
* **Logging**: Logs success/failure of external service call
* **Event Publishing**: Fires events based on external service result

### 4. **NServiceBus Handler** - Message Processing

**File**: `AddToShippingNsbHandler.cs`

```csharp
public class AddToShippingNsbHandler : NsbCommandHandler<AddToShippingCommand>
{
    readonly ILogger<AddToShippingNsbHandler> _logger;
    readonly IFlexHost _flexHost;
    readonly IAddToShippingHandler _handler;

    public AddToShippingNsbHandler(ILogger<AddToShippingNsbHandler> logger, IFlexHost flexHost, IAddToShippingHandler handler)
    {
        _logger = logger;
        _flexHost = flexHost;
        _handler = handler;
    }

    public override async Task Handle(AddToShippingCommand message, IMessageHandlerContext context)
    {
        _logger.LogTrace($"Executing {nameof(AddToShippingNsbHandler)}");

        await _handler.Execute(message, new NsbHandlerContextBridge(context));
    }
}
```

**What Happens:**

* **Message Reception**: Receives `AddToShippingCommand` from message bus
* **Logging**: Logs handler execution
* **Delegation**: Calls the actual command handler
* **Context Bridge**: Converts NServiceBus context to FlexBase context

### 6. **Event Publishing** - Asynchronous Processing

**Event**: `ShippingAddedEvent`

```csharp
public class ShippingAddedEvent : FlexEventBridge<FlexAppContextBridge>
{
    // Event data is automatically populated by FlexBase
}
```

**What Happens:**

* **Event Creation**: FlexBase creates event with shipping data
* **Message Bus**: Event is published to message bus
* **Subscriber Notification**: All subscribers are notified

### 7. **RESTClient Integration** - External Communication

**File**: `ShippingRESTClient_AddToShipping.cs`

```csharp
public async Task<HttpResponseMessage> AddToShipping(AddToShippingRequestDto model)
{
    var httpClient = _httpClientFactory.CreateClient(ShippingServicesRESTClientMaster.Name);

    var serializedModel = JsonConvert.SerializeObject(model);

    var request = new HttpRequestMessage(
           HttpMethod.Post,
           $"yourUri");
    request.Content = new StringContent(serializedModel, Encoding.UTF8, "application/json");
    request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

    return await response.HandleHttpResponse();
}
```

**What Happens:**

* **HTTP Client**: Creates HTTP client for external communication
* **Serialization**: Converts Request DTO to JSON
* **HTTP Request**: Sends POST to external shipping system
* **Response Handling**: Processes HTTP response from external system

### 7.1. **Request DTO** - External Contract

**File**: `AddToShippingRequestDto.cs`

```csharp
public partial class AddToShippingRequestDto
{
    public string OrderId { get; set; }
    public string ShippingAddress { get; set; }
    public string TrackingNumber { get; set; }
    public decimal TotalWeight { get; set; }
    public ICollection<ShippingItemRequestDto> ShippingItems { get; set; }
}
```

**What Happens:**

* **External Contract**: Designed for external system consumption
* **Serialization**: Optimized for JSON serialization
* **Validation**: May include external system specific validation

### 7.2. **Response DTO** - External Contract

**File**: `AddToShippingResponseDto.cs`

```csharp
public partial class AddToShippingResponseDto
{
    public string Id { get; set; }
    public string Status { get; set; }
    public string Message { get; set; }
    public DateTime ProcessedDate { get; set; }
    public string ExternalReferenceId { get; set; }
}
```

**What Happens:**

* **External Contract**: Designed for external system responses
* **Deserialization**: Optimized for JSON deserialization
* **External Fields**: May include external system specific fields

### 7.3. **Mapping Configuration** - DTO Transformation

**File**: `ShippingRESTClientMapperProfile.cs`

```csharp
public class ShippingRESTClientMapperProfile : Profile
{
    public ShippingRESTClientMapperProfile()
    {
        // Internal DTO → Request DTO Mapping
        CreateMap<AddToShippingDto, AddToShippingRequestDto>()
            .ForMember(d => d.TotalWeight, opt => opt.MapFrom(s => s.ShippingItems.Sum(x => x.Weight)))
            .ForMember(d => d.ShippingItems, opt => opt.MapFrom(s => s.ShippingItems));
            
        // Response DTO → Internal DTO Mapping
        CreateMap<AddToShippingResponseDto, AddToShippingDto>()
            .ForMember(d => d.Status, opt => opt.MapFrom(s => ParseStatus(s.Status)))
            .ForMember(d => d.ExternalReferenceId, opt => opt.MapFrom(s => s.ExternalReferenceId));
    }
    
    private ShippingStatus ParseStatus(string status)
    {
        return status?.ToLower() switch
        {
            "created" => ShippingStatus.Created,
            "in_transit" => ShippingStatus.InTransit,
            "delivered" => ShippingStatus.Delivered,
            "cancelled" => ShippingStatus.Cancelled,
            _ => ShippingStatus.Unknown
        };
    }
}
```

**What Happens:**

* **Request Mapping**: Converts internal DTO to external request format
* **Response Mapping**: Converts external response to internal DTO format
* **Field Transformation**: Handles different field names and types
* **Business Logic**: Applies business rules during mapping

### 8. **Event Subscribers** - Side Effects

**File**: `NotifyLogisticsOnShippingAdded.cs`

```csharp
public partial class NotifyLogisticsOnShippingAdded : INotifyLogisticsOnShippingAdded
{
    protected readonly ILogger<NotifyLogisticsOnShippingAdded> _logger;
    protected string EventCondition = "";

    public NotifyLogisticsOnShippingAdded(ILogger<NotifyLogisticsOnShippingAdded> logger)
    {
        _logger = logger;
    }

    public virtual async Task Execute(ShippingAddedEvent @event, IFlexServiceBusContext serviceBusContext)
    {
        _flexAppContext = @event.AppContext;

        //TODO: Write your business logic here:
        // - Send shipping confirmation email
        // - Update inventory levels
        // - Notify logistics system
        // - Update tracking information

        await this.Fire<NotifyLogisticsOnShippingAdded>(EventCondition, serviceBusContext);
    }
}
```

**What Happens:**

* **Event Reception**: Receives `ShippingAddedEvent` from message bus
* **Side Effects**: Executes business logic (emails, notifications, etc.)
* **Additional Events**: Can fire more events if needed

## Data Transfer Objects (DTOs)

### **Internal DTOs** - Application Contracts

#### **Input DTO**: `AddToShippingDto`

```csharp
public partial class AddToShippingDto : DtoBridge 
{
    [StringLength(100)]
    public string OrderId { get; set; }

    [StringLength(200)]
    public string ShippingAddress { get; set; }

    public ICollection<AddToShippingDto_ShippingItem> ShippingItems { get; set; }
}
```

#### **Command**: `AddToShippingCommand`

```csharp
public class AddToShippingCommand : FlexCommandBridge<AddToShippingDto, FlexAppContextBridge>
{
    // Command data is automatically populated by FlexBase
}
```

### **External DTOs** - External System Contracts

#### **Request DTO**: `AddToShippingRequestDto`

```csharp
public partial class AddToShippingRequestDto
{
    public string OrderId { get; set; }
    public string ShippingAddress { get; set; }
    public string TrackingNumber { get; set; }
    public decimal TotalWeight { get; set; }
    public ICollection<ShippingItemRequestDto> ShippingItems { get; set; }
}
```

#### **Response DTO**: `AddToShippingResponseDto`

```csharp
public partial class AddToShippingResponseDto
{
    public string Id { get; set; }
    public string Status { get; set; }
    public string Message { get; set; }
    public DateTime ProcessedDate { get; set; }
    public string ExternalReferenceId { get; set; }
}
```

### **DTO Mapping Relationships**

```
Internal DTO (AddToShippingDto) ←→ Request DTO (AddToShippingRequestDto)
     ↑                                    ↓
     │                              External System
     │                                    ↓
     └── Response DTO (AddToShippingResponseDto) ←┘
```

## Flow Summary

### **Synchronous Flow (Immediate Response)**

1. **POST Request** → Controller receives request
2. **Service Processing** → Business orchestration and PreBus validation
3. **PreBus Plugins** → Sequential validation of business rules
4. **Command Handler** → RESTClient integration
   * Internal DTO → Request DTO mapping
   * External system API call
   * Response DTO processing
5. **Response** → HTTP 201 with shipping ID

### **Asynchronous Flow (Event Processing)**

1. **Event Publishing** → ShippingAddedEvent published to message bus
2. **Subscriber Processing** → NotifyLogisticsOnShippingAdded executes
3. **Side Effects** → Emails, notifications, inventory updates
4. **Additional Events** → Can trigger more business processes

### **External Communication Flow**

1. **Internal DTO** → Request DTO mapping
2. **RESTClient Call** → HTTP request to external system
3. **External Response** → Response DTO from external system
4. **Response Mapping** → Response DTO to Internal DTO
5. **Data Integration** → External data integrated with internal data

## Key Benefits

* **Separation of Concerns**: Each layer has a single responsibility
* **Testability**: Each component can be tested independently
* **Scalability**: Asynchronous processing handles high loads
* **Maintainability**: Clear, readable code structure
* **Event-Driven**: Loose coupling between components

***

**This AddToShipping example demonstrates how FlexBase enables clean, maintainable, and scalable insert operations with proper separation of concerns and event-driven architecture!** 🚀


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.flexbase.in/solution-structure/getting-started/features/rest-services/insert-example.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
