# Delete Example

## Overview

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

## Complete Flow Architecture

```
DELETE Request → Controller → Service → PreBus Plugins → Command Handler → Domain Model → Database → Event Publishing → Subscribers
```

### **Detailed Flow Breakdown**

```
1. DELETE Request
   ↓
2. Controller (API Entry Point)
   ↓
3. Service Layer (Business Orchestration)
   ↓
4. PreBus Processing (Validation Pipeline)
   ├── DeleteProductSequence (Plugin Registration)
   ├── DeleteProductDataPacket (Validation Context)
   └── IsValidProduct Plugin (Business Rules)
   ↓
5. Command Handler (Data Processing)
   ↓
6. Domain Model (Business Logic)
   ↓
7. Database (Data Persistence)
   ↓
8. Event Publishing (Asynchronous Processing)
   ↓
9. Subscribers (Side Effects)
```

## Step-by-Step Implementation

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

**File**: `ProductsController_DeleteProduct.cs`

```csharp
[HttpDelete()]
[Route("DeleteProduct/{id}")]
public async Task<IActionResult> DeleteProduct(string id)
{
    DeleteProductDto dto = new DeleteProductDto();
    dto.Id = id;
    return await RunService(200, dto, _processProductsService.DeleteProduct);
}
```

**What Happens:**

* **HTTP Method**: `DELETE /api/Products/DeleteProduct/{id}`
* **Input**: Product ID from URL parameter
* **DTO Creation**: Creates `DeleteProductDto` with the ID
* **Action**: Calls the service layer to process the product deletion
* **Response**: HTTP 200 OK with success status

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

**File**: `ProcessProductsService_DeleteProduct.cs`

```csharp
public async Task<CommandResult> DeleteProduct(DeleteProductDto dto)
{
    var packet = await ProcessBusinessRuleSequence<DeleteProductDataPacket, DeleteProductSequence, DeleteProductDto, FlexAppContextBridge>(dto);

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

        await ProcessCommand(cmd);

        CommandResult cmdResult = new CommandResult(Status.Success);

        YourOutputResultModel outputResult = new YourOutputResultModel();
        cmdResult.result = outputResult;
        return cmdResult;
    }
}
```

**What Happens:**

* **PreBus Processing**: Executes business rule sequences (plugins)
* **Validation**: Processes business rule sequences
* **ID Generation**: Generates unique key for tracking
* **Command Creation**: Creates `DeleteProductCommand` with DTO
* **Command Processing**: Calls the command handler
* **Result**: Returns success status

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

**File**: `DeleteProductSequence.cs`

```csharp
public class DeleteProductSequence : FlexiBusinessRuleSequenceBase<DeleteProductDataPacket>
{
    public DeleteProductSequence()
    {
        this.Add<IsValidProduct>(); 
    }
}
```

**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**: `DeleteProductDataPacket.cs`

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

    public DeleteProductDataPacket(ILogger<DeleteProductDataPacket> 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**: `IsValidProduct.cs`

```csharp
public partial class IsValidProduct : FlexiBusinessRuleBase, IFlexiBusinessRule<DeleteProductDataPacket>
{
    public override string Id { get; set; } = "3a1cd5b1fa98b4c63378de9607706082";
    public override string FriendlyName { get; set; } = "IsValidProduct";

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

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

    public virtual async Task Validate(DeleteProductDataPacket 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

### 3. **Command Handler** - Data Processing

**File**: `DeleteProductHandler.cs`

```csharp
public virtual async Task Execute(DeleteProductCommand cmd, IFlexServiceBusContext serviceBusContext)
{
    _flexAppContext = cmd.Dto.GetAppContext();
    _repoFactory.Init(cmd.Dto);

    _model = _flexHost.GetDomainModel<Product>().DeleteProduct(cmd);

    if (_model != null)
    {
        _repoFactory.GetRepo().InsertOrUpdate(_model);

        int records = await _repoFactory.GetRepo().SaveAsync();
        if (records > 0)
        {
            _logger.LogDebug("{} with {} deleted from Database: ", typeof(Product).Name, _model.Id);
        }
        else
        {
            _logger.LogWarning("No records deleted for {} with {}", typeof(Product).Name, _model.Id);
        }

        //EventCondition = CONDITION_ONSUCCESS;
    }
    else
    {
        //you may raise an event here to notify about the error
        //EventCondition = CONDITION_ONFAILED;
    }
    await this.Fire(EventCondition, serviceBusContext);
}
```

**What Happens:**

* **Context Setup**: Initializes application context and repository
* **Domain Logic**: Calls domain model to process business rules
* **Null Check**: Handles case where product doesn't exist
* **Database Save**: Updates the product in database (soft delete)
* **Logging**: Logs success/failure of database operation
* **Event Publishing**: Fires events for subscribers

### 4. **Domain Model** - Business Logic

**File**: `Product/DeleteProduct.cs`

```csharp
public virtual Product DeleteProduct(DeleteProductCommand cmd)
{
    Guard.AgainstNull("Product model cannot be empty", cmd);

    this.Id = cmd.Dto.Id;
    this.SetDeleted();

    //Set your appropriate SetDeleted for the inner object here

    return this;
}
```

**What Happens:**

* **Validation**: Guards against null commands
* **ID Assignment**: Sets the product ID from DTO
* **State Management**: Marks entity as deleted (soft delete)
* **Child Objects**: Processes child object deletions

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

**File**: `DeleteProductNsbHandler.cs`

```csharp
public class DeleteProductNsbHandler : NsbCommandHandler<DeleteProductCommand>
{
    readonly ILogger<DeleteProductNsbHandler> _logger;
    readonly IFlexHost _flexHost;
    readonly IDeleteProductHandler _handler;

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

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

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

**What Happens:**

* **Message Reception**: Receives `DeleteProductCommand` 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**: `ProductDeletedEvent` (if implemented)

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

**What Happens:**

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

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

**File**: `NotifyInventoryOnProductDeleted.cs` (if implemented)

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

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

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

        //TODO: Write your business logic here:
        // - Update inventory levels
        // - Notify suppliers
        // - Update analytics
        // - Archive related data

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

**What Happens:**

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

## Data Transfer Objects (DTOs)

### **Input DTO**: `DeleteProductDto`

```csharp
public partial class DeleteProductDto : DtoBridge 
{
    public string Id { get; set; }
}
```

### **Command**: `DeleteProductCommand`

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

## Key Differences from Insert/Update Flow

### **Delete-Specific Characteristics**

1. **URL Parameter**: ID comes from URL path instead of request body
2. **DTO Creation**: Controller creates DTO with ID from URL
3. **Soft Delete**: Uses `SetDeleted()` instead of `SetAdded()` or `SetModified()`
4. **State Management**: Marks entity as deleted (soft delete pattern)
5. **HTTP Method**: Uses `DELETE` instead of `POST` or `PUT`
6. **Minimal Data**: Only requires ID for deletion

### **PreBus Validation Focus**

* **IsValidProduct**: Validates product exists and can be deleted
* **Business Rules**: Ensures product can be removed (not in use, not referenced)
* **Data Integrity**: Validates deletion doesn't violate business constraints

### **Soft Delete Pattern**

* **Database**: Entity is marked as deleted, not physically removed
* **Queries**: Soft-deleted entities are filtered out of normal queries
* **Recovery**: Deleted entities can be restored if needed
* **Audit Trail**: Maintains complete history of deletions

## Flow Summary

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

1. **DELETE Request** → Controller receives request with ID
2. **Service Processing** → Business orchestration and PreBus validation
3. **PreBus Plugins** → Sequential validation of business rules
4. **Command Handler** → Data processing and soft delete
5. **Domain Logic** → Business rules and state management
6. **Response** → HTTP 200 OK with success status

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

1. **Event Publishing** → ProductDeletedEvent published to message bus
2. **Subscriber Processing** → NotifyInventoryOnProductDeleted executes
3. **Side Effects** → Inventory updates, supplier notifications, analytics

## Key Benefits

* **Data Safety**: Soft delete preserves data for recovery
* **Business Rules**: Validates deletion is allowed
* **Audit Trail**: Tracks who deleted what and when
* **Event-Driven**: Notifies other systems of deletions
* **Testable**: Each component can be tested independently
* **Maintainable**: Clear separation of concerns

***

**This DeleteProduct example demonstrates how FlexBase enables clean, maintainable, and scalable delete operations with proper validation, soft delete patterns, 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/crud/delete-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.
