---
name: AutoMapperPattern
description: Quy tắc chuẩn cho DTO mapping sử dụng AutoMapper Profile trong dự án Ladaer.BackEnd.
---

# AutoMapper Mapping Pattern

## Tổng quan
Dự án sử dụng **AutoMapper** để mapping giữa Entity ↔ Item/Model DTO. Mọi mapping phải được khai báo qua **Profile** class, **KHÔNG** được viết manual mapping (hand-coded `new XxxItem { ... }`) trong extension methods.

## Cấu trúc chuẩn

### 1. File Profile
- **Vị trí**: `Infrastructures/DTO/Profiles/{Module}MappingProfile.cs`
- **Naming**: `{Module}MappingProfile` (VD: `CrmMappingProfile`, `RewardPenaltyMappingProfile`)
- **Cấu trúc**: Profile class + Extension methods class **trong cùng 1 file**

### 2. Profile class

```csharp
using AutoMapper;
using Lada.Framework.Data.Domains.{Module};
using Lada.Framework.Infrastructures.Helpers; // nếu dùng .GetDescription()
using Ladaer.BackEnd.Infrastructures.DTO.Items.{Module};
using Ladaer.BackEnd.Infrastructures.DTO.Models.{Module};

namespace Ladaer.BackEnd.Infrastructures.DTO.Profiles
{
    public class {Module}MappingProfile : Profile
    {
        public {Module}MappingProfile()
        {
            #region {EntityName}
            // Mapping đơn giản (properties trùng tên)
            CreateMap<Entity, EntityItem>();
            CreateMap<Entity, EntityModel>();
            CreateMap<EntityModel, Entity>();

            // Mapping có custom logic
            CreateMap<Entity, EntityItem>()
                .ForMember(dest => dest.CustomProp, opt => opt.MapFrom(src => src.Navigation?.PropertyName ?? ""));
            #endregion
        }
    }
}
```

### 3. Extension methods class

```csharp
public static class {Module}MappingExtensions
{
    // Entity → Item
    public static EntityItem ToItem(this Entity entity)
        => entity.MapTo<Entity, EntityItem>();

    // Entity → Model
    public static EntityModel ToModel(this Entity entity)
        => entity.MapTo<Entity, EntityModel>();

    // Model → Entity
    public static Entity ToEntity(this EntityModel model)
        => model.MapTo<EntityModel, Entity>();
}
```

### 4. Sử dụng trong Service

```csharp
using Ladaer.BackEnd.Infrastructures.DTO.Profiles; // KHÔNG dùng DTO.Extensions

// Trong method:
var item = entity.ToItem();
var model = entity.ToModel();
var entity = model.ToEntity();

// Trong SmartTable:
return await query.ToSmartTableResultAsync(param, x => x.ToItem());
```

## Các mẫu ForMember thường gặp

### Navigation property (nullable)
```csharp
.ForMember(dest => dest.CustomerName, 
    opt => opt.MapFrom(src => src.Customer != null ? src.Customer.FullName : ""))
```

### Nullable DateTimeOffset → non-nullable
```csharp
.ForMember(dest => dest.CreatedTime, 
    opt => opt.MapFrom(src => src.CreatedTime ?? DateTimeOffset.MinValue))
```

### Collection count
```csharp
.ForMember(dest => dest.LevelCount, 
    opt => opt.MapFrom(src => src.Levels != null ? src.Levels.Count : 0))
```

### Enum → Description string
```csharp
.ForMember(dest => dest.StatusStr, 
    opt => opt.MapFrom(src => src.Status.GetDescription()))
```

### Format DateTime
```csharp
.ForMember(dest => dest.CreatedTime, 
    opt => opt.MapFrom(src => src.CreatedTime.HasValue 
        ? src.CreatedTime.Value.ToString("dd/MM/yyyy HH:mm") : ""))
```

## ❌ Anti-patterns (KHÔNG làm)

1. **KHÔNG** tạo file Extension riêng trong `DTO/Extensions/` với manual mapping
2. **KHÔNG** viết `return new XxxItem { Prop1 = entity.Prop1, ... }` trong extension methods
3. **KHÔNG** dùng `using Ladaer.BackEnd.Infrastructures.DTO.Extensions;` trong Services — dùng `DTO.Profiles` thay thế

## Danh sách Profiles hiện tại

| Profile | Module | File |
|---|---|---|
| `CmsMappingProfile` | CMS | `Profiles/CmsMappingProfile.cs` |
| `CrmMappingProfile` | CRM | `Profiles/CrmMappingProfile.cs` |
| `RewardPenaltyMappingProfile` | Rewards | `Profiles/RewardPenaltyMappingProfile.cs` |
| `FinanceMappingProfile` | Finance | `Profiles/FinanceMappingProfile.cs` |
| `FuelCardMappingProfile` | FuelCards | `Profiles/FuelCardMappingProfile.cs` |
| `HrMappingProfile` | HR | `Profiles/HrMappingProfile.cs` |
| `IdentityMappingProfile` | Identity | `Profiles/IdentityMappingProfile.cs` |
| `OrdersMappingProfile` | Orders | `Profiles/OrdersMappingProfile.cs` |
| `TruckMappingProfile` | Trucks | `Profiles/TruckMappingProfile.cs` |
| `PremiseMappingProfile` | Premises | `Profiles/PremiseMappingProfile.cs` |
