# API Documentation - Truck Management

## Mục lục
1. [Quản lý Xe Tải](#1-quản-lý-xe-tải)
2. [Models & Enums](#2-models--enums)

---

## 1. Quản lý Xe Tải

### 1.1. Tạo hoặc cập nhật thông tin xe tải

**Endpoint:** `POST /api/Truck/CreateOrUpdate`

**Authorization:** `Truck.CreateOrUpdate`

**Mô tả:** Tạo mới hoặc cập nhật thông tin xe tải, bao gồm cả ảnh giấy tờ xe (đăng ký, đăng kiểm).

**Request (Form-Data):**
- `Id` (int, required): ID xe tải (0 = tạo mới, >0 = cập nhật)
- `LicensePlate` (string, required, max 20): Biển số xe
- `Brand` (string, optional): Thương hiệu xe tải (ví dụ: "Kia", "Hyundai", "Isuzu")
- `Model` (string, optional): Model xe tải (ví dụ: "K200", "Porter", "D-Max")
- `AgencyId` (int, required): ID chi nhánh mà xe tải thuộc về
- `MaxPayload` (decimal, optional): Tải trọng tối đa cho phép (tấn)
- `CargoLength` (int, optional): Chiều dài khu vực chứa hàng (cm)
- `CargoWidth` (int, optional): Chiều rộng khu vực chứa hàng (cm)
- `CargoHeight` (int, optional): Chiều cao khu vực chứa hàng (cm)
- `OperatingStatus` (int, required): Trạng thái vận hành (1=Stop, 2=Running, 3=Repair)
- `Status` (int, required): Trạng thái xe tải (1=Normal, 2=MaintenanceRequired, 3=UnderMaintenance)
- `CurrentDriverId` (int, required): ID tài xế hiện đang phụ trách xe
- `ManufacturingYear` (int, optional): Năm sản xuất của xe tải
- `RegistrationInfo` (string, optional, max 200): Thông tin đăng kiểm
- `FuelQuotaPer100Km` (decimal, optional): Định mức khoán xăng dầu (lít/100km)
- `Files` (IFormFile[], optional): Danh sách file ảnh upload mới (ảnh đăng ký, đăng kiểm)
- `MediaTypes` (int[], optional): Loại media tương ứng với từng file (20=RegistrationPhoto, 21=InspectionPhoto)
- `ExistingMediaIds` (int[], optional): Danh sách ID TruckMedia hiện có cần giữ lại (khi cập nhật). ID = 0 nghĩa là vị trí đó cần upload file mới.

**Example Request 1 - Tạo mới xe tải:**
```
POST /api/Truck/CreateOrUpdate
Content-Type: multipart/form-data

Id: 0
LicensePlate: 29C-12345
Brand: Hyundai
Model: Porter H150
AgencyId: 1
MaxPayload: 1.5
CargoLength: 310
CargoWidth: 160
CargoHeight: 160
OperatingStatus: 1
Status: 1
CurrentDriverId: 50
ManufacturingYear: 2023
RegistrationInfo: Đăng kiểm đến 30/12/2026
FuelQuotaPer100Km: 11.5
Files: [registration.jpg, inspection.jpg]
MediaTypes: [20, 21]
```

**Example Request 2 - Cập nhật thông tin (không đổi ảnh):**
```
POST /api/Truck/CreateOrUpdate
Content-Type: multipart/form-data

Id: 10
LicensePlate: 29C-12345
Brand: Hyundai
Model: Porter H150
AgencyId: 1
MaxPayload: 1.5
CargoLength: 310
CargoWidth: 160
CargoHeight: 160
OperatingStatus: 2
Status: 1
CurrentDriverId: 51
ManufacturingYear: 2023
RegistrationInfo: Đăng kiểm đến 30/12/2026
FuelQuotaPer100Km: 11.5
```

**Example Request 3 - Cập nhật có thay đổi ảnh (tối ưu):**
```
POST /api/Truck/CreateOrUpdate
Content-Type: multipart/form-data

Id: 10
LicensePlate: 29C-12345
Brand: Hyundai
Model: Porter H150
AgencyId: 1
MaxPayload: 1.5
CargoLength: 310
CargoWidth: 160
CargoHeight: 160
OperatingStatus: 2
Status: 1
CurrentDriverId: 51
ManufacturingYear: 2023
RegistrationInfo: Đăng kiểm đến 30/12/2026
FuelQuotaPer100Km: 11.5
ExistingMediaIds: [1, 0]  // Giữ media ID 1 và upload ảnh mới cho vị trí 2
Files: [new_inspection.jpg]  // Chỉ upload 1 ảnh mới
MediaTypes: [21]  // Loại ảnh tương ứng
```

**Response (Tạo mới):**
```json
{
  "Result": 1,
  "Message": "Tạo xe tải thành công"
}
```

**Response (Cập nhật):**
```json
{
  "Result": 1,
  "Message": "Cập nhật thông tin xe tải thành công"
}
```

> [!IMPORTANT]
> **Tính năng Tạo hoặc Cập nhật**
> - Sử dụng `Id = 0` để tạo mới, `Id > 0` để cập nhật
> - Khi cập nhật, tất cả các trường đều phải được gửi lại (không hỗ trợ partial update)

> [!NOTE]
> **OperatingStatus - Trạng thái vận hành**
> - `1` = Stop (Đang Dừng / Đỗ)
> - `2` = Running (Đang Hoạt Động)
> - `3` = Repair (Bảo Trì / Sửa Chữa)

> [!NOTE]
> **Status - Trạng thái xe tải**
> - `1` = Normal (Tốt)
> - `2` = MaintenanceRequired (Cần được bảo dưỡng)
> - `3` = UnderMaintenance (Đang được bảo dưỡng)

> [!NOTE]
> **MediaTypes - Loại ảnh giấy tờ xe**
> - `20` = RegistrationPhoto (Ảnh đăng ký)
> - `21` = InspectionPhoto (Ảnh đăng kiểm)

> [!TIP]
> **ExistingMediaIds - Tối ưu cập nhật hình ảnh**
> - Khi **tạo mới** (`Id = 0`): Không cần truyền `ExistingMediaIds`
> - Khi **cập nhật** (`Id > 0`):
>   - **Không đổi ảnh**: Không cần truyền `Files`, `MediaTypes`, `ExistingMediaIds`
>   - **Đổi một số ảnh**: Truyền `ExistingMediaIds` với ID của ảnh giữ lại và `0` cho vị trí cần upload mới
>   - **Ví dụ**: `[1, 0]` = Giữ media ID 1 và upload ảnh mới cho vị trí thứ 2
>   - Chỉ cần upload file cho các vị trí có ID = 0 trong `Files` array
> - **Lợi ích**: Tiết kiệm băng thông, không cần upload lại toàn bộ ảnh khi chỉ thay đổi 1 ảnh

---

### 1.2. Xóa xe tải

**Endpoint:** `POST /api/Truck/TruckDelete`

**Authorization:** `Truck.TruckDelete`

**Mô tả:** Xóa thông tin xe tải khỏi hệ thống.

**Request Parameters:**
- `id` (int, required, query string): ID của xe tải cần xóa

**Example Request:**
```
POST /api/Truck/TruckDelete?id=10
```

**Response (Thành công):**
```json
{
  "Result": 1,
  "Message": "Xóa xe tải thành công"
}
```

**Response (Thất bại):**
```json
{
  "Result": 0,
  "Message": "Không tìm thấy xe tải hoặc xe tải đã bị xóa"
}
```

> [!IMPORTANT]
> **Quy tắc xóa xe tải**
> - Chỉ có thể xóa xe tải khi không còn phát sinh dữ liệu liên quan (chuyến hàng, bảo trì, v.v.)
> - Sau khi xóa, dữ liệu sẽ được đánh dấu xóa mềm (soft delete) và có thể khôi phục nếu cần

> [!NOTE]
> **Lưu ý khi xóa**
> - Hệ thống sẽ kiểm tra các ràng buộc dữ liệu trước khi cho phép xóa
> - Nếu xe tải đang được gán cho tài xế hoặc có chuyến hàng đang hoạt động, việc xóa sẽ bị từ chối

---

## 2. Models & Enums

### TruckModel

```csharp
public class TruckModel
{
    public int Id { get; set; }
    public string LicensePlate { get; set; }  // Biển số xe (bắt buộc, max 20 ký tự)
    public string? Brand { get; set; }  // Thương hiệu
    public string? Model { get; set; }  // Model xe
    public int AgencyId { get; set; }  // ID chi nhánh
    public decimal? MaxPayload { get; set; }  // Tải trọng tối đa (tấn)
    public int? CargoLength { get; set; }  // Chiều dài khu vực chứa hàng (cm)
    public int? CargoWidth { get; set; }  // Chiều rộng khu vực chứa hàng (cm)
    public int? CargoHeight { get; set; }  // Chiều cao khu vực chứa hàng (cm)
    public OperatingStatus OperatingStatus { get; set; }  // Trạng thái vận hành
    public TruckStatus Status { get; set; }  // Trạng thái xe tải
    public int CurrentDriverId { get; set; }  // ID tài xế hiện tại
    public int? ManufacturingYear { get; set; }  // Năm sản xuất
    public string? RegistrationInfo { get; set; }  // Thông tin đăng kiểm (max 200 ký tự)
    public decimal? FuelQuotaPer100Km { get; set; }  // Định mức khoán xăng dầu (lít/100km)
    
    // Media
    public List<IFormFile>? Files { get; set; }  // Danh sách file ảnh upload mới
    public List<TruckMediaType>? MediaTypes { get; set; }  // Loại media tương ứng
    public List<int>? ExistingMediaIds { get; set; }  // Danh sách ID media giữ lại
}
```

### OperatingStatus Enum

| Value | Name | Description |
|-------|------|-------------|
| 1 | Stop | Đang Dừng / Đỗ |
| 2 | Running | Đang Hoạt Động |
| 3 | Repair | Bảo Trì / Sửa Chữa |

### TruckStatus Enum

| Value | Name | Description |
|-------|------|-------------|
| 1 | Normal | Tốt |
| 2 | MaintenanceRequired | Cần được bảo dưỡng |
| 3 | UnderMaintenance | Đang được bảo dưỡng |

### TruckMediaType Enum

| Value | Name | Description |
|-------|------|-------------|
| 20 | RegistrationPhoto | Ảnh đăng ký |
| 21 | InspectionPhoto | Ảnh đăng kiểm |

---

## Lưu ý chung

> [!IMPORTANT]
> **PascalCase cho JSON Property**
> Trong .NET Backend của dự án này, mặc định JSON Serializer sử dụng **PascalCase**.
> - **ĐÚNG**: `LicensePlate`, `AgencyId`, `CurrentDriverId`
> - **SAI**: `licensePlate`, `agencyId`, `currentDriverId`
>
> Khi gọi API, **BẮT BUỘC** phải sử dụng PascalCase cho các key để khớp với DTO C#.
