# Cập nhật chức năng Bỏ duyệt - API v3.1

## Tổng quan
Đã kích hoạt chức năng "Bỏ duyệt" (Unapprove) cho chi phí theo API v3.1.

## Thay đổi chính

### 1. Kích hoạt API call thực sự

#### **detail.vue**
- ✅ Xóa code tạm thời (toast warning)
- ✅ Kích hoạt API call: `expenseService.unapprove(id, reason)`
- ✅ Xử lý response thành công/thất bại
- ✅ Reload dữ liệu sau khi bỏ duyệt thành công

#### **index.vue**
- ✅ Xóa code tạm thời (toast warning)
- ✅ Kích hoạt API call: `expenseService.unapprove(id, reason)`
- ✅ Xử lý response thành công/thất bại
- ✅ Reload danh sách sau khi bỏ duyệt thành công

### 2. Điều kiện hiển thị

**Nút/Menu "Bỏ duyệt" chỉ xuất hiện khi:**
- ✅ `expense.Status === 1` (Đã duyệt)
- ✅ Có quyền (được kiểm tra bởi backend qua API)

**Files:**
- `detail.vue` dòng 25: `v-if="expense && expense.Status === 1 && expense.CanReject"`
- `index.vue` dòng 176: `v-if="expense.Status === 1"`

### 3. API Integration

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

**Request Body**:
```json
{
  "Reason": "Lý do bỏ duyệt"
}
```

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

**Authorization**:
- Role: `Expense.Approve` (giống quyền duyệt)
- Chỉ người duyệt (ApprovedBy) hoặc Founder có thể bỏ duyệt

**Lịch sử tự động**: 
- Ghi lịch sử `Approved → Pending` 
- Note: "Bỏ duyệt chi phí"
- Reason: Lý do do người dùng nhập

## Workflow hoàn chỉnh

```
Tạo chi phí → Chờ duyệt (0)
                 ↓
           ┌─ Từ chối (2) ✅
           │
           └→ Phê duyệt (1)
                 ↓
        ┌─ Bỏ duyệt 🆕 → quay về Chờ duyệt (0)
        │
        └→ Đánh dấu thanh toán → Đã thanh toán (3)
```

## UI/UX

### Nút "Bỏ duyệt"
- **Màu**: Warning (vàng)
- **Icon**: `fe-x-circle`
- **Text**: "Bỏ duyệt"
- **Vị trí**: Header actions (detail.vue) và dropdown menu (index.vue)

### Modal xác nhận
- **Tiêu đề**: "Bỏ duyệt chi phí"
- **Cảnh báo**: Alert warning - "Chi phí sẽ quay về trạng thái 'Chờ duyệt' sau khi bỏ duyệt"
- **Input**: Textarea để nhập lý do bỏ duyệt
- **Nút**: Warning button "Xác nhận bỏ duyệt"

### Toast notifications
- **Thành công**: "Bỏ duyệt chi phí thành công"
- **Thất bại**: Hiển thị message từ API hoặc "Có lỗi xảy ra khi bỏ duyệt"

## Error Handling

```javascript
try {
  const result = await expenseService.unapprove(id, reason)
  
  if (result.Result === 1) {
    // Success
    toast.success(result.Message)
    loadData() // Reload
  } else {
    // Business logic error
    toast.error(result.Message)
  }
} catch (error) {
  // Network or system error
  console.error('Error:', error)
  toast.error('Có lỗi xảy ra khi bỏ duyệt chi phí')
}
```

## Permission Logic

### Frontend
- Điều kiện hiển thị dựa vào `expense.Status === 1`
- Có thể sử dụng `expense.CanReject` hoặc tương lai có thể thêm `expense.CanUnapprove`

### Backend
Backend phải kiểm tra:
1. Chi phí có trạng thái `Approved` (Status = 1)
2. User có quyền `Expense.Approve`
3. User là người duyệt (`ApprovedBy`) hoặc có role `Founder`

Nếu không đủ điều kiện, trả về:
```json
{
  "Result": 0,
  "Message": "Bạn không có quyền bỏ duyệt chi phí này"
}
```

## Testing Checklist

- [ ] Nút "Bỏ duyệt" chỉ hiện khi Status = Approved
- [ ] Modal hiển thị đúng thông báo cảnh báo
- [ ] Có thể nhập lý do bỏ duyệt
- [ ] API call thành công với response Result = 1
- [ ] Toast success hiển thị đúng message
- [ ] Dữ liệu được reload sau khi bỏ duyệt
- [ ] Chi phí quay về trạng thái "Chờ duyệt"
- [ ] Lịch sử ghi nhận đúng: Approved → Pending
- [ ] Error handling khi API trả về lỗi
- [ ] Error handling khi network error

## Files Changed

1. ✅ `src/views/finances/expenses/detail.vue` - Kích hoạt API call
2. ✅ `src/views/finances/expenses/index.vue` - Kích hoạt API call
3. ✅ `src/services/expenseService.js` - Đã có method `unapprove()` (không thay đổi)
4. ✅ `src/infrastructure/apiPaths/expensePath.js` - Đã có endpoint (không thay đổi)

## Breaking Changes

Không có breaking changes. Code tương thích ngược.

## Notes

- Method `unapprove()` trong expenseService đã sẵn sàng từ trước
- Endpoint `/api/Expense/Unapprove` đã được định nghĩa
- Chỉ cần uncomment code gọi API để kích hoạt
- Backend cần implement endpoint theo đúng spec trong `API_Expense.md`

## Next Steps

1. **Test với backend API**:
   - Verify endpoint `/api/Expense/Unapprove/{id}` hoạt động
   - Test response format đúng spec
   - Test error cases (không có quyền, status không hợp lệ, etc.)

2. **Có thể cải tiến**:
   - Thêm trường `CanUnapprove` vào API response để kiểm tra quyền chính xác hơn
   - Update `index.vue` line 176 để thêm check permission: `v-if="expense.Status === 1 && expense.CanUnapprove"`

## Version

- **API Version**: 3.1
- **Updated**: 2025-12-20
- **Status**: ✅ Ready for Testing
