# API Documentation - Expense Management

## Overview

API quản lý chi phí với tính năng ghi lịch sử tự động cho mọi thay đổi trạng thái.

**Base URL**: `/api/Expense`

**Version**: 3.1 (Updated: 2025-12-20)

---

## Endpoints

### 1. Tìm kiếm chi phí

**Endpoint**: `POST /api/Expense/Search`

**Authorization**: Required - Role: `Expense.Search`

**Request Body**:
```json
{
  "Search": {
    "PredicateObject": {
      "Keyword": "string",
      "ExpenseCategoryId": 0,
      "Status": 0,
      "CreatedStart": "2025-12-20T00:00:00Z",
      "CreatedEnd": "2025-12-20T23:59:59Z"
    }
  },
  "Sort": {
    "Predicate": "CreatedTime",
    "Reverse": true
  },
  "Pagination": {
    "PageIndex": 1,
    "PageSize": 20
  }
}
```

**Response**: Danh sách chi phí với phân trang

---

### 2. Lấy chi tiết chi phí

**Endpoint**: `GET /api/Expense/{id}`

**Authorization**: Required - Role: `Expense.GetById`

**Response**:
```json
{
  "Id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "Description": "Chi phí văn phòng phẩm",
  "Note": "Mua bút, giấy A4",
  "Amount": 500000,
  "ExpenseCategoryId": 1,
  "ExpenseCategoryName": "Văn phòng",
  "Status": 1,
  "ApprovedBy": 10,
  "ApprovedByUserName": "admin",
  "RejectReason": null,
  "UserBankAccountId": 5,
  "UserBankAccountInfo": "Nguyen Van A - 1234567890 (VCB)",
  "BankAccountNumber": "1234567890",
  "BankAccountHolderName": "Nguyen Van A",
  "BankCode": "VCB",
  "BankName": "Vietcombank",
  "BankBranchName": "Chi nhánh TP.HCM",
  "CanApprove": true,
  "CanReject": true,
  "CanMarkAsPaid": false,
  "CreatedTime": "2025-12-20T10:00:00Z",
  "CreatedBy": 5,
  "CreatedByUserName": "user01",
  "Histories": [
    {
      "Id": 3,
      "ExpenseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "OldStatus": 0,
      "OldStatusDisplay": "Chờ duyệt",
      "NewStatus": 1,
      "NewStatusDisplay": "Đã duyệt",
      "Reason": null,
      "Note": "Duyệt chi phí",
      "ActionByUserName": "admin",
      "CreatedTime": "2025-12-20T11:00:00Z",
      "CreatedBy": 10,
      "CreatedByUserName": "admin"
    },
    {
      "Id": 2,
      "ExpenseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "OldStatus": 0,
      "OldStatusDisplay": "Chờ duyệt",
      "NewStatus": 0,
      "NewStatusDisplay": "Chờ duyệt",
      "Reason": null,
      "Note": "Cập nhật thông tin chi phí",
      "ActionByUserName": "user01",
      "CreatedTime": "2025-12-20T10:30:00Z",
      "CreatedBy": 5,
      "CreatedByUserName": "user01"
    },
    {
      "Id": 1,
      "ExpenseId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "OldStatus": null,
      "OldStatusDisplay": "Tạo mới",
      "NewStatus": 0,
      "NewStatusDisplay": "Chờ duyệt",
      "Reason": null,
      "Note": "Tạo mới chi phí",
      "ActionByUserName": "user01",
      "CreatedTime": "2025-12-20T10:00:00Z",
      "CreatedBy": 5,
      "CreatedByUserName": "user01"
    }
  ]
}
```

**Lưu ý**:
- Trường `Histories` là **mảng lịch sử thay đổi trạng thái**, sắp xếp theo thứ tự mới nhất trước
- `OldStatus = null` nghĩa là đây là lần tạo mới
- `OldStatusDisplay` và `NewStatusDisplay` hiển thị tên trạng thái bằng tiếng Việt

---

### 3. Tạo hoặc cập nhật chi phí

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

**Authorization**: Required - Role: `Expense.CreateOrUpdate`

**Request Body**:
```json
{
  "Id": "00000000-0000-0000-0000-000000000000",
  "Description": "Chi phí văn phòng phẩm",
  "Note": "Mua bút, giấy A4",
  "Amount": 500000,
  "ExpenseCategoryId": 1,
  "UserBankAccountId": 5
}
```

**Response**:
```json
{
  "Result": 1,
  "Message": "Tạo chi phí thành công"
}
```

**Lịch sử tự động**:
- **Tạo mới** (Id = Guid.Empty): Tự động ghi lịch sử `null → Pending` với note "Tạo mới chi phí"
- **Cập nhật** (Id có giá trị): Tự động ghi lịch sử `Status → Status` với note "Cập nhật thông tin chi phí"

---

### 4. Duyệt chi phí

**Endpoint**: `POST /api/Expense/Approve/{id}`

**Authorization**: Required - Role: `Expense.Approve`

**Response**:
```json
{
  "Result": 1,
  "Message": "Duyệt chi phí thành công"
}
```

**Lịch sử tự động**: Ghi lịch sử `Pending/Rejected → Approved` với note "Duyệt chi phí"

---

### 5. Bỏ duyệt chi phí

**Endpoint**: `POST /api/Expense/Unapprove/{id}`

**Authorization**: Required - Role: `Expense.Approve`

**Response**:
```json
{
  "Result": 1,
  "Message": "Bỏ duyệt chi phí thành công"
}
```

**Lịch sử tự động**: Ghi lịch sử `Approved → Pending` với note "Bỏ duyệt chi phí"

**Lưu ý**:
- Chỉ có thể bỏ duyệt chi phí có trạng thái `Approved`
- Yêu cầu quyền `Expense.Approve` (giống như duyệt)
- Chỉ người được chỉ định duyệt (ApprovedBy) hoặc Founder mới có thể bỏ duyệt

---

### 6. Từ chối chi phí

**Endpoint**: `POST /api/Expense/Reject/{id}`

**Authorization**: Required - Role: `Expense.Reject`

**Request Body**:
```json
{
  "RejectReason": "Không đủ hồ sơ chứng minh"
}
```

**Response**:
```json
{
  "Result": 1,
  "Message": "Từ chối chi phí thành công"
}
```

**Lịch sử tự động**: Ghi lịch sử `Pending/Approved → Rejected` với:
- Note: "Từ chối chi phí"
- Reason: Lý do từ chối được cung cấp

---

### 7. Đánh dấu đã chuyển tiền

**Endpoint**: `POST /api/Expense/MarkAsPaid/{id}`

**Authorization**: Required - Role: `Expense.MarkAsPaid`

**Request Body**:
```json
{
  "Note": "Đã chuyển qua VCB vào 20/12/2025"
}
```

**Response**:
```json
{
  "Result": 1,
  "Message": "Đã chuyển tiền thành công. Số tiền: 500,000 VND"
}
```

**Lịch sử tự động**: Ghi lịch sử `Approved → Paid` với note từ request

---

### 8. Xóa chi phí

**Endpoint**: `DELETE /api/Expense/{id}`

**Authorization**: Required - Role: `Expense.Delete`

**Response**:
```json
{
  "Result": 1,
  "Message": "Xóa chi phí thành công"
}
```

**Lưu ý**: Soft delete - chi phí không bị xóa vật lý mà chỉ đánh dấu `IsDeleted = true`

---

## Data Models

### ExpenseStatus Enum

| Value | Name | Display Name |
|-------|------|--------------|
| 0 | Pending | Chờ duyệt |
| 1 | Approved | Đã duyệt |
| 2 | Rejected | Đã từ chối |
| 3 | Paid | Đã thanh toán |

### ExpenseHistoryItem

```typescript
{
  Id: number;
  ExpenseId: string; // GUID
  OldStatus: number | null; // null = tạo mới
  OldStatusDisplay: string; // Tên tiếng Việt
  NewStatus: number;
  NewStatusDisplay: string; // Tên tiếng Việt
  Reason: string | null; // Lý do từ chối
  Note: string | null; // Ghi chú
  ActionByUserName: string; // Người thực hiện
  CreatedTime: string; // ISO 8601
  CreatedBy: number;
  CreatedByUserName: string;
}
```

---

## Breaking Changes

### Version 3.0 (2025-12-20)

**Thay đổi trong ExpenseHistoryItem**:
- ❌ **Removed**: `Status` (single status field)
- ✅ **Added**: `OldStatus`, `OldStatusDisplay`, `NewStatus`, `NewStatusDisplay`

**Migration Guide**:
```javascript
// Before (v2.0)
const statusName = history.Status; // Chỉ có 1 trạng thái

// After (v3.0)
const transition = `${history.OldStatusDisplay} → ${history.NewStatusDisplay}`;
// Example: "Chờ duyệt → Đã duyệt"
```

**Thay đổi trong ExpenseItem**:
- ✅ **Added**: `Histories` - Mảng lịch sử thay đổi trạng thái

---

## Error Codes

| Code | Message | Meaning |
|------|---------|---------|
| 0 | Success | Thành công |
| 1 | Failed | Thất bại (lỗi logic) |
| 2 | SystemError | Lỗi hệ thống |

---

## Notes

1. **Automatic History Tracking**: Mọi thay đổi trạng thái đều được ghi lại tự động
2. **Cascade Delete**: Khi xóa Expense, tất cả ExpenseHistory liên quan cũng bị xóa
3. **AutoMapper**: Response mapping sử dụng AutoMapper để đảm bảo consistency
4. **Permissions**: Mỗi endpoint yêu cầu role cụ thể, kiểm tra qua JWT token

---

## Examples

### Flow hoàn chỉnh

1. **Tạo chi phí**:
```bash
POST /api/Expense/CreateOrUpdate
→ Tự động ghi: null → Pending
```

2. **Cập nhật thông tin**:
```bash
POST /api/Expense/CreateOrUpdate (với Id)
→ Tự động ghi: Pending → Pending
```

3. **Duyệt chi phí**:
```bash
POST /api/Expense/Approve/{id}
→ Tự động ghi: Pending → Approved
```

4. **Bỏ duyệt chi phí** (nếu cần):
```bash
POST /api/Expense/Unapprove/{id}
→ Tự động ghi: Approved → Pending
```

5. **Duyệt lại**:
```bash
POST /api/Expense/Approve/{id}
→ Tự động ghi: Pending → Approved
```

6. **Đánh dấu đã chuyển tiền**:
```bash
POST /api/Expense/MarkAsPaid/{id}
→ Tự động ghi: Approved → Paid
```

7. **Xem lịch sử**:
```bash
GET /api/Expense/{id}
→ Response chứa mảng Histories với đầy đủ records
```
