# Tóm tắt triển khai API Báo cáo Thu Chi

## ✅ Đã hoàn thành

### 1. Sửa bug ExpenseService ⚠️ **QUAN TRỌNG**

**File**: `Ladaer.BackEnd/Infrastructures/Services/Finances/ExpenseService.cs`

**Vấn đề**: Khi đánh dấu Expense là Paid và tạo Transaction, không có `CostCategoryId` được set.

**Giải pháp**: Đã thêm dòng:

```csharp
CostCategoryId = expense.ExpenseCategoryId, // Link to ExpenseCategory for reporting
```

**Tại sao quan trọng**:

- CostCategoryId trong Transaction được dùng để phân loại chi phí trong báo cáo
- Không có CostCategoryId thì chi phí vận hành sẽ hiển thị là "Chi phí khác" thay vì theo đúng danh mục

### 2. Tạo DTOs

**Files tạo mới**:

- `Ladaer.BackEnd/Infrastructures/DTO/Models/Finance/IncomeExpenseReportModel.cs`
  - `IncomeExpenseReportRequest`: Request với FromDate, ToDate
- `Ladaer.BackEnd/Infrastructures/DTO/Results/Finance/IncomeExpenseReportResult.cs`
  - `IncomeExpenseReportResult`: Response chính
  - `IncomeExpenseReportRowItem`: Từng dòng trong báo cáo (danh mục + số tiền theo ngày)
  - `TransactionReportRow`: Model nhận từ stored procedure

### 3. Tạo Stored Procedure

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

**Tính năng**:

- Sử dụng CTE để xây dựng hierarchy của ExpenseCategory
- Query Transaction với filter theo khoảng thời gian
- Map TransactionType thành CategoryName dễ hiểu
- Group by Date + Category
- Sắp xếp: Income trước, Expense sau, theo Level và DisplayOrder

**Cần làm**: Chạy script này trong SQL Server để tạo stored procedure.

### 4. Implement Service

**File**: `Ladaer.BackEnd/Infrastructures/Services/Report/Finance/IncomeExpenseReportService.cs`

**Tính năng**:

- `GetIncomeExpenseReportAsync()`: API chính
- `GenerateDateColumns()`: Tạo danh sách các cột ngày
- `BuildReportMatrix()`: Chuyển dữ liệu từ SP sang ma trận
- `BuildIncomeRows()`: Xây dựng phần THU
- `BuildExpenseRows()`: Xây dựng phần CHI (bao gồm cây ExpenseCategory)
- `CalculateTotals()`: Tính tổng thu, tổng chi, chênh lệch

**Validations**:

- FromDate <= ToDate
- Khoảng thời gian <= 1 năm

### 5. Tạo Controller

**File**: `Ladaer.BackEnd/Controllers/Finance/IncomeExpenseReportController.cs`

**Endpoint**: `POST /api/IncomeExpenseReport/GetReport`

**Authorization**: Cần role `IncomeExpenseReport.View`

### 6. Đăng ký Service

**File**: `Ladaer.BackEnd/Infrastructures/Startup/DependencyRegister.cs`

Đã thêm:

- Using statement: `using Ladaer.BackEnd.Infrastructures.Services.Report.Finance;`
- Service registration: `services.AddTransient<IIncomeExpenseReportService, IncomeExpenseReportService>();`

### 7. Documentation

**File**: `Ladaer.BackEnd/Docs/IncomeExpenseReport.md`

Tài liệu đầy đủ về:

- Cách triển khai
- Cách sử dụng API
- Cấu trúc dữ liệu
- Phân loại thu/chi
- Lưu ý quan trọng
- Cách test

## 📊 Cấu trúc Báo cáo

### Cột

- Cột đầu tiên: Tên danh mục
- Các cột tiếp theo: Mỗi ngày một cột (yyyy-MM-dd)
- Cột cuối: Tổng cộng

### Hàng (Rows)

**Phần THU**:

1. Thu cước phí (TransactionType=OrderFee)
2. Thu tiền từ lái xe (TransactionType=CollectFromDriver)
3. Thu tiền từ khách hàng (TransactionType=CollectFromCustomer)
4. Nạp tiền (TransactionType=Recharge)
5. **Tổng thu** (sum của các dòng trên)

**Phần CHI**:

1. Chi phí đối soát (TransactionType=Reconciliation)
2. Chi phí vận hành (TransactionType=Withdraw):
   - Hiển thị theo cây ExpenseCategory
   - Level 0: Danh mục gốc
   - Level 1, 2, 3...: Danh mục con
3. **Tổng chi** (sum của các dòng trên)

**Chênh lệch**: Thu - Chi

## 🚀 Các bước tiếp theo

### 1. Chạy Stored Procedure (BẮT BUỘC)

```sql
-- Mở SQL Server Management Studio hoặc Azure Data Studio
-- Kết nối đến database
-- Chạy file: Ladaer.BackEnd/Scripts/sp_GetIncomeExpenseReport.sql
```

### 2. Thêm Permission

Cần thêm permission mới vào hệ thống:

- Permission Name: `IncomeExpenseReport.View`
- Description: "Xem báo cáo thu chi"
- Assign cho roles cần thiết (Founder, Accountant, Manager, ...)

### 3. Test API

```bash
# Build project
cd Ladaer.BackEnd
dotnet build

# Run project
dotnet watch run

# Test API (sử dụng Swagger hoặc Postman)
# URL: https://localhost:7284/swagger
# Endpoint: POST /api/IncomeExpenseReport/GetReport
```

### 4. Kiểm tra dữ liệu

Đảm bảo:

- Có Transaction trong khoảng thời gian test
- Expense đã được MarkAsPaid sẽ có CostCategoryId trong Transaction
- ExpenseCategory đã được tạo và có cấu trúc cây hợp lý

## 🔍 Debugging

### Nếu không có dữ liệu trong báo cáo

1. **Kiểm tra Transaction**:

```sql
SELECT * FROM Transactions
WHERE TransactionDate >= '2025-10-01'
  AND TransactionDate <= '2025-10-31'
ORDER BY TransactionDate
```

2. **Kiểm tra CostCategoryId**:

```sql
SELECT
    t.TransactionType,
    t.TransactionDirection,
    t.CostCategoryId,
    ec.Name as CategoryName,
    COUNT(*) as Count,
    SUM(t.Amount) as TotalAmount
FROM Transactions t
LEFT JOIN ExpenseCategories ec ON t.CostCategoryId = ec.Id
WHERE t.TransactionDate >= '2025-10-01'
  AND t.TransactionDate <= '2025-10-31'
GROUP BY t.TransactionType, t.TransactionDirection, t.CostCategoryId, ec.Name
```

3. **Kiểm tra ExpenseCategory hierarchy**:

```sql
WITH CategoryHierarchy AS (
    SELECT Id, Name, ParentId, DisplayOrder, 0 AS Level
    FROM ExpenseCategories
    WHERE ParentId IS NULL AND IsDeleted = 0

    UNION ALL

    SELECT ec.Id, ec.Name, ec.ParentId, ec.DisplayOrder, ch.Level + 1
    FROM ExpenseCategories ec
    INNER JOIN CategoryHierarchy ch ON ec.ParentId = ch.Id
    WHERE ec.IsDeleted = 0
)
SELECT * FROM CategoryHierarchy
ORDER BY Level, DisplayOrder
```

## 📝 Notes

### Lợi ích của approach Transaction-based

1. **Single Source of Truth**: Transaction là nguồn dữ liệu tập trung cho tất cả giao dịch thu chi
2. **Dễ mở rộng**: Thêm TransactionType mới chỉ cần update SP
3. **Performance**: Stored procedure tối ưu với CTE
4. **Audit Trail**: Transaction lưu đầy đủ lịch sử
5. **Nhất quán**: CostCategory được sync từ ExpenseCategory

### So với approach cũ (OrderFin + Reconciliation + Expense)

**Cũ** (không dùng):

- Query nhiều bảng: OrderFin, OrderTimeTrack, Reconciliation, Expense
- Logic phức tạp ở C# code
- Khó maintain khi có thay đổi

**Mới** (đang dùng):

- Query 1 bảng chính: Transaction
- Logic đơn giản, tập trung ở SQL
- Dễ maintain và mở rộng

## ✅ Checklist triển khai

- [x] Sửa bug ExpenseService
- [x] Tạo DTO models
- [x] Tạo stored procedure
- [x] Implement service
- [x] Tạo controller
- [x] Đăng ký service
- [x] Build thành công
- [x] Tạo documentation
- [ ] Chạy stored procedure trong database ⚠️ **QUAN TRỌNG**
- [ ] Thêm permission `IncomeExpenseReport.View`
- [ ] Test với dữ liệu thực
- [ ] Demo cho user

## 📞 Support

Nếu có vấn đề, kiểm tra:

1. Stored procedure đã được tạo chưa?
2. Permission đã được thêm chưa?
3. Có dữ liệu Transaction trong khoảng thời gian test không?
4. CostCategoryId có được set trong Transaction không? (sau khi apply fix ExpenseService)
