# Báo cáo Thu Chi Theo Tháng

## Tổng quan

API báo cáo thu chi dựa trên Transaction làm nguồn dữ liệu chính, sử dụng Stored Procedure để tối ưu performance.

## Cách triển khai

### 1. Tạo Stored Procedure trong Database

Chạy script SQL sau để tạo stored procedure:

```sql
-- File: Ladaer.BackEnd/Scripts/sp_GetIncomeExpenseReport.sql
```

Hoặc chạy trực tiếp:

```bash
# Sử dụng SQL Server Management Studio hoặc Azure Data Studio
# Mở file: Ladaer.BackEnd/Scripts/sp_GetIncomeExpenseReport.sql
# Chạy script
```

### 2. Sử dụng API

#### Endpoint

```
POST /api/IncomeExpenseReport/GetReport
Authorization: Bearer {token}
Role Required: IncomeExpenseReport.View
```

#### Request Body

```json
{
  "fromDate": "2025-10-01T00:00:00+07:00",
  "toDate": "2025-10-31T23:59:59+07:00"
}
```

#### Response

```json
{
  "result": 1,
  "message": "Lấy báo cáo thành công",
  "fromDate": "2025-10-01T00:00:00+07:00",
  "toDate": "2025-10-31T23:59:59+07:00",
  "dateColumns": [
    "2025-10-01",
    "2025-10-02",
    ...
    "2025-10-31"
  ],
  "rows": [
    {
      "categoryName": "Thu cước phí",
      "categoryId": null,
      "parentId": null,
      "level": 0,
      "rowType": "Income",
      "dailyAmounts": {
        "2025-10-01": 15000000,
        "2025-10-02": 12000000,
        ...
      },
      "total": 450000000
    },
    {
      "categoryName": "Tổng thu",
      "level": 0,
      "rowType": "Total",
      "dailyAmounts": { ... },
      "total": 450000000
    },
    {
      "categoryName": "Chi phí đối soát",
      "level": 0,
      "rowType": "Expense",
      "dailyAmounts": { ... },
      "total": 200000000
    },
    {
      "categoryName": "Chi phí xăng xe",
      "categoryId": 5,
      "parentId": 1,
      "level": 1,
      "rowType": "Expense",
      "dailyAmounts": { ... },
      "total": 50000000
    },
    {
      "categoryName": "Tổng chi",
      "level": 0,
      "rowType": "Total",
      "dailyAmounts": { ... },
      "total": 250000000
    },
    {
      "categoryName": "Chênh lệch (Thu - Chi)",
      "level": 0,
      "rowType": "Net",
      "dailyAmounts": { ... },
      "total": 200000000
    }
  ],
  "totalIncome": 450000000,
  "totalExpense": 250000000,
  "netAmount": 200000000
}
```

## Cấu trúc dữ liệu

### Nguồn dữ liệu

**Bảng chính**: `Transactions`

- `TransactionDirection`: Thu (Income=1) hoặc Chi (Outcome=2)
- `TransactionType`: Loại giao dịch (OrderFee, Reconciliation, Withdraw, ...)
- `CostCategoryId`: Liên kết với ExpenseCategory (cho chi phí vận hành)
- `TransactionDate`: Ngày giao dịch
- `Amount`: Số tiền

### Phân loại Thu (Income)

| TransactionType         | CategoryName           | Mô tả                               |
| ----------------------- | ---------------------- | ----------------------------------- |
| 3 (OrderFee)            | Thu cước phí           | Cước vận chuyển từ đơn hàng         |
| 4 (CollectFromDriver)   | Thu tiền từ lái xe     | Thu tiền từ lái xe nộp              |
| 6 (CollectFromCustomer) | Thu tiền từ khách hàng | Thu tiền từ khách hàng chuyển khoản |
| 1 (Recharge)            | Nạp tiền               | Nạp tiền vào ví                     |

### Phân loại Chi (Outcome)

| TransactionType    | CategoryName           | Mô tả                                    |
| ------------------ | ---------------------- | ---------------------------------------- |
| 5 (Reconciliation) | Chi phí đối soát       | Chuyển tiền đối soát COD cho khách hàng  |
| 2 (Withdraw)       | {ExpenseCategory.Name} | Chi phí vận hành (theo danh mục chi phí) |

### Cấu trúc cây ExpenseCategory

Chi phí vận hành được tổ chức theo cây phân cấp:

```
- Chi phí vận hành (Level 0)
  ├── Chi phí xe (Level 1)
  │   ├── Xăng xe (Level 2)
  │   └── Sửa chữa (Level 2)
  └── Chi phí nhân sự (Level 1)
      ├── Lương (Level 2)
      └── Thưởng (Level 2)
```

## Lưu ý quan trọng

### 1. Cập nhật CostCategoryId

**Đã sửa bug**: `ExpenseService.MarkAsPaid()` giờ đã tự động set `CostCategoryId` khi tạo Transaction từ Expense.

```csharp
// File: ExpenseService.cs, dòng 681
CostCategoryId = expense.ExpenseCategoryId, // Link to ExpenseCategory for reporting
```

### 2. Quyền truy cập

Cần thêm permission `IncomeExpenseReport.View` vào role của user để có thể truy cập API.

### 3. Giới hạn khoảng thời gian

- Khoảng thời gian tối đa: **1 năm** (365 ngày)
- Từ ngày phải <= Đến ngày

### 4. Performance

- Sử dụng Stored Procedure với CTE để tối ưu query
- Index được tạo sẵn trên `TransactionDate`, `TransactionType`, `TransactionDirection`
- Kết quả được group by ngày để giảm số lượng rows trả về

## Cách test

### Test 1: Kiểm tra dữ liệu cơ bản

```bash
curl -X POST "https://localhost:7284/api/IncomeExpenseReport/GetReport" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "fromDate": "2025-10-01T00:00:00+07:00",
    "toDate": "2025-10-31T23:59:59+07:00"
  }'
```

### Test 2: Kiểm tra khi không có dữ liệu

```bash
curl -X POST "https://localhost:7284/api/IncomeExpenseReport/GetReport" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "fromDate": "2026-01-01T00:00:00+07:00",
    "toDate": "2026-01-31T23:59:59+07:00"
  }'
```

### Test 3: Kiểm tra validation

```bash
# FromDate > ToDate (should fail)
curl -X POST "https://localhost:7284/api/IncomeExpenseReport/GetReport" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "fromDate": "2025-10-31T00:00:00+07:00",
    "toDate": "2025-10-01T23:59:59+07:00"
  }'
```

## Files đã tạo/sửa

1. ✅ `Ladaer.BackEnd/Infrastructures/Services/Finances/ExpenseService.cs` - Sửa bug CostCategoryId
2. ✅ `Ladaer.BackEnd/Scripts/sp_GetIncomeExpenseReport.sql` - Stored procedure
3. ✅ `Ladaer.BackEnd/Infrastructures/DTO/Models/Finance/IncomeExpenseReportModel.cs` - Request model
4. ✅ `Ladaer.BackEnd/Infrastructures/DTO/Results/Finance/IncomeExpenseReportResult.cs` - Response models
5. ✅ `Ladaer.BackEnd/Infrastructures/Services/Report/Finance/IncomeExpenseReportService.cs` - Service implementation
6. ✅ `Ladaer.BackEnd/Controllers/Finance/IncomeExpenseReportController.cs` - Controller
7. ✅ `Ladaer.BackEnd/Infrastructures/Startup/DependencyRegister.cs` - Đăng ký service

## Roadmap

### Phase 1: ✅ Hoàn thành

- [x] Sửa bug CostCategoryId
- [x] Tạo stored procedure
- [x] Tạo DTO models
- [x] Implement service
- [x] Tạo controller
- [x] Đăng ký service

### Phase 2: Tương lai

- [ ] Export Excel báo cáo
- [ ] Cache kết quả báo cáo
- [ ] Chart visualization
- [ ] So sánh theo kỳ (month-over-month, year-over-year)
- [ ] Filter theo agency/branch
- [ ] Drill-down chi tiết giao dịch
