---
name: BackendCRUD
description: Hướng dẫn tạo tính năng CRUD (Create, Read, Update, Delete) chuẩn cho Backend.
---

# Backend CRUD Development Skill

Tài liệu này hướng dẫn các bước tiêu chuẩn để phát triển một tính năng CRUD backend trong dự án LADA.

## 1. Tạo Entity

- **Vị trí**: `Lada.Framework/Data/Domains/[Module]/[EntityName].cs`
- **Quy tắc**:
  - Class phải kế thừa từ `BaseEntity` (có Id, CreatedTime, etc.) hoặc `BaseEntity<T>` nếu key không phải int.
  - Sử dụng Data Annotations (`[Table]`, `[Key]`, ...) nếu cần thiết.

```csharp
using System.ComponentModel.DataAnnotations.Schema;
using Lada.Framework.Data.Domains;

namespace Lada.Framework.Data.Domains.MyModule
{
    [Table("MyEntities")]
    public class MyEntity : BaseEntity
    {
        public string Name { get; set; }
        public string Description { get; set; }
        // Các properties khác
    }
}
```

## 2. Tạo DTO (Data Transfer Objects)

- **Vị trí**: `Ladaer.BackEnd/Ladaer.BackEnd/Infrastructures/DTO` (theo cấu trúc thư mục tương ứng)
  - `Models/[Module]/[EntityName]Model.cs`: Dùng cho Create/Update.
  - `Items/[Module]/[EntityName]Item.cs`: Dùng cho List/View.
  - `Results/[Module]/[EntityName]Result.cs`: Dùng cho kết quả trả về (thường kế thừa `BaseResult`).

```csharp
// Model
public class CreateMyEntityModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    // ...
    public int UpdatedBy { get; set; }
    public string UpdatedByUserName { get; set; }
}

// Item
public class MyEntityItem
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTimeOffset CreatedTime { get; set; }
}
```

## 3. Cấu hình AutoMapper

- **Vị trí**: `Ladaer.BackEnd/Infrastructures/DTO/MappingExtensions.cs` (hoặc Profile riêng trong thư mục `Profiles`).
- **Nội dung**: Thêm các phương thức extension method để map giữa Entity và DTO.

```csharp
public static MyEntityItem ToItem(this MyEntity entity)
{
    return entity.MapTo<MyEntity, MyEntityItem>();
}

public static MyEntity ToEntity(this CreateMyEntityModel model)
{
    return model.MapTo<CreateMyEntityModel, MyEntity>();
}
```

*Lưu ý: Đảm bảo đã config trong `AutoMapperConfig` hoặc Profile tương ứng.*

## 4. Tạo Service

### 4.1 Interface
- **Vị trí**: `Ladaer.BackEnd/Infrastructures/Services/[Module]/I[EntityName]Service.cs` hoặc `Services/I[EntityName]ManagementService.cs`.

```csharp
public interface IMyEntityService
{
    Task<SmartTableResult<MyEntityItem>> Search(SmartTableParam param);
    Task<BaseResult> CreateOrUpdate(CreateMyEntityModel model);
    Task<CreateMyEntityModel> GetById(int id);
    Task<BaseResult> Delete(int id);
}
```

### 4.2 Implementation
- **Vị trí**: `Ladaer.BackEnd/Infrastructures/Services/[Module]/[EntityName]Service.cs`.
- **Dependency**: Inject `IRepository<MyEntity>`.

```csharp
public class MyEntityService : IMyEntityService
{
    private readonly IRepository<MyEntity> _repository;

    public MyEntityService(IRepository<MyEntity> repository)
    {
        _repository = repository;
    }

    public async Task<SmartTableResult<MyEntityItem>> Search(SmartTableParam param)
    {
        var query = _repository.Query();
        // Filter logic...
        return await query.ToSmartTableResultAsync(param, x => x.ToItem());
    }

    // Implement CreateOrUpdate, GetById, Delete...
}
```

## 5. Đăng ký Dependency Injection

- **Vị trí**: `Ladaer.BackEnd/Infrastructures/Startup/DependencyRegister.cs`.
- **Hành động**: Thêm dòng đăng ký service.

```csharp
services.AddScoped<IMyEntityService, MyEntityService>();
```

## 6. Tạo Controller

- **Vị trí**: `Ladaer.BackEnd/Controllers/[Module]/[EntityName]Controller.cs`.
- **Base Class**: `ControllerBase`.
- **Attributes**: `[Route("api/[controller]")]`, `[ApiController]`, `[Authorize]`.

```csharp
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class MyEntityController : ControllerBase
{
    private readonly IMyEntityService _service;

    public MyEntityController(IMyEntityService service)
    {
        _service = service;
    }

    [HttpPost("Search")]
    [Authorize(Roles = "MyEntity.Search")]
    public async Task<IActionResult> Search([FromBody] SmartTableParam param)
    {
        var result = await _service.Search(param);
        return Ok(result);
    }

    // Các action CreateOrUpdate, GetById, Delete...
}
```
