---
name: Fuel Card Management
overview: Phát triển chức năng quản lý thẻ xăng dầu, giao dịch thẻ (import Excel), đổ dầu với hình ảnh ODO, tính toán định mức khoán và thanh toán tiền dầu cho lái xe.
todos:
  - id: phase1-entities
    content: Tạo các Entity mới (FuelCard, FuelCardTransaction, FuelRefill, DriverFuelQuotaBalance, DriverFuelQuotaHistory, FuelQuotaPayment) và Enums
    status: pending
  - id: phase1-truck-modify
    content: Thêm field FuelQuotaPer100Km vào Entity Truck
    status: pending
  - id: phase1-mappings
    content: Tạo Entity Mappings và cập nhật DbContext
    status: pending
  - id: phase1-migration
    content: Tạo Migration script cho database
    status: pending
  - id: phase2-dtos
    content: Tạo DTOs (Items, Models, Results) cho FuelCards, DriverFuelQuota và Payment
    status: pending
  - id: phase2-automapper
    content: Cấu hình AutoMapper profiles cho mapping Entity <-> DTO
    status: pending
  - id: phase3-services
    content: Tạo FuelCardService, FuelCardTransactionService, FuelRefillService, DriverFuelQuotaService
    status: pending
  - id: phase3-quota-logic
    content: Implement logic tính toán định mức khoán, chênh lệch dầu và thanh toán
    status: pending
  - id: phase4-controller
    content: Tạo FuelCardController với các API endpoints
    status: pending
  - id: phase4-di
    content: Đăng ký services vào DependencyRegister
    status: pending
  - id: phase5-docs
    content: Viết API documentation và tests
    status: pending
---

# Kế hoạch phát triển chức năng Quản lý Thẻ Xăng Dầu

## Phân tích hiện trạng

### Đã có sẵn:

- **TruckActivity**: Entity ghi hoạt động xe với `ActionType.FuelRefill` và `CurrentOdo`
- **TruckActivityMedia**: Lưu ảnh với `TruckActivityMediaType.FuelRefillPhoto`
- **TruckActivityService.FuelRefillTruck()**: Method đổ dầu cơ bản
- **BankStatementImport/BankTransaction**: Pattern import sao kê ngân hàng

### Cần phát triển mới:

- Entity quản lý thẻ xăng dầu
- Entity giao dịch thẻ xăng dầu (import từ Excel)
- Mở rộng TruckActivity để lưu chi tiết đổ dầu
- Các loại ảnh ODO trước/sau, cây dầu, hóa đơn
- **Định mức khoán xăng dầu** cho mỗi xe (lít/100km)
- **Tính toán chênh lệch dầu** cho lái xe sau mỗi lần đổ
- **Thanh toán tiền dầu khoán** cho lái xe

---

## Thiết kế Database

### 0. Mở rộng Entity Truck (Thêm định mức khoán)

```
[Lada.Framework/Data/Domains/Trucks/Truck.cs] - MODIFY
+ FuelQuotaPer100Km (decimal) - Định mức khoán xăng dầu (lít/100km)
  Ví dụ: 11 lít => xe chạy 100km được công ty trả 11 lít dầu
```

### 1. Entity FuelCard (Thẻ xăng dầu)

```
[Lada.Framework/Data/Domains/Finance/FuelCard.cs]
- Id (int)
- CardNumber (string) - Số thẻ (52347217____5261)
- CardholderName (string) - Tên chủ thẻ
- BankName (string) - Ngân hàng phát hành
- TruckId (int?) - Xe được gán thẻ
- CurrentDriverId (int?) - Lái xe hiện tại sử dụng thẻ
- Status (enum: Active, Inactive, Lost, Expired)
- ExpiryDate (DateTimeOffset?)
- CreditLimit (decimal?) - Hạn mức
- Notes (string)
```

### 2. Entity FuelCardTransaction (Giao dịch thẻ)

```
[Lada.Framework/Data/Domains/Finance/FuelCardTransaction.cs]
- Id (Guid)
- FuelCardId (int) - FK to FuelCard
- TransactionDate (DateTimeOffset) - Thời gian GD
- Amount (decimal) - Số tiền
- Currency (string) - Loại tiền (VND)
- TransactionType (string) - Loại GD (Retail)
- Location (string) - Địa điểm (PLX_HAI PHONG_CH 30)
- Status (enum: Success, Failed, Pending)
- RawData (string) - Dữ liệu thô từ Excel
- ImportId (Guid?) - FK to FuelCardStatementImport
- FuelRefillId (int?) - Liên kết đến lần đổ dầu (để đối soát)
- IsReconciled (bool) - Đã đối soát chưa
```

### 3. Entity FuelCardStatementImport (Import sao kê)

```
[Lada.Framework/Data/Domains/Finance/FuelCardStatementImport.cs]
- Id (Guid)
- OriginalFileName (string)
- FilePath (string)
- TotalRows, ProcessedRows, ErrorRows, DuplicateRows
- ImportStatus (enum)
- ImportedByUserId
- Tương tự BankStatementImport
```

### 4. Entity FuelRefill (Chi tiết đổ dầu)

```
[Lada.Framework/Data/Domains/Trucks/FuelRefill.cs]
- Id (int)
- TruckActivityId (int) - FK to TruckActivity
- TruckId (int)
- DriverId (int)
- FuelCardId (int?) - Thẻ sử dụng (nếu có)

# Thông tin ODO
- PreviousOdo (int) - ODO lần đổ dầu trước (hoặc ODO nhận xe nếu lần đầu)
- CurrentOdo (int) - ODO hiện tại khi đổ dầu
- DistanceKm (int) - Số km đã chạy = CurrentOdo - PreviousOdo

# Thông tin đổ dầu thực tế
- Amount (decimal) - Số tiền đổ dầu (VD: 500,000)
- UnitPrice (decimal) - Đơn giá dầu (VD: 20,000/lít)
- ActualLiters (decimal) - Số lít thực tế = Amount / UnitPrice (VD: 25 lít)

# Thông tin định mức khoán
- FuelQuotaPer100Km (decimal) - Định mức của xe tại thời điểm đổ (copy từ Truck)
- QuotaLiters (decimal) - Số lít được hưởng = (DistanceKm * FuelQuotaPer100Km) / 100
- DifferenceLiters (decimal) - Chênh lệch = QuotaLiters - ActualLiters (+ là lái xe được, - là lái xe bù)

# Thông tin khác
- PaymentMethod (enum: Card, Cash)
- StationName (string) - Tên cây xăng
- StationAddress (string)
- RefillTime (DateTimeOffset)
- FuelCardTransactionId (Guid?) - Liên kết giao dịch thẻ
- Notes (string)
```

### 5. Entity DriverFuelQuotaBalance (Số dư dầu khoán của lái xe)

```
[Lada.Framework/Data/Domains/Trucks/DriverFuelQuotaBalance.cs]
- Id (int)
- DriverId (int) - FK to User (lái xe)
- TotalQuotaLiters (decimal) - Tổng số lít được hưởng
- TotalActualLiters (decimal) - Tổng số lít đã đổ thực tế
- TotalPaidLiters (decimal) - Tổng số lít đã thanh toán
- BalanceLiters (decimal) - Số dư = TotalQuota - TotalActual - TotalPaid
- LastUpdated (DateTimeOffset)
```

### 6. Entity DriverFuelQuotaHistory (Lịch sử biến động số dư)

```
[Lada.Framework/Data/Domains/Trucks/DriverFuelQuotaHistory.cs]
- Id (int)
- DriverId (int) - FK to User (lái xe)
- FuelRefillId (int?) - FK to FuelRefill (null nếu là thanh toán/điều chỉnh)
- FuelQuotaPaymentId (int?) - FK to FuelQuotaPayment (nếu là thanh toán)
- TruckId (int?) - FK to Truck
- TransactionType (enum: Refill, Payment, Adjustment, Reset)
- DistanceKm (int?) - Số km chạy được (chỉ có khi Refill)
- QuotaLiters (decimal?) - Số lít được hưởng (chỉ có khi Refill)
- ActualLiters (decimal?) - Số lít thực tế đổ (chỉ có khi Refill)
- DifferenceLiters (decimal) - Chênh lệch/Số lít thanh toán
- BalanceBeforeLiters (decimal) - Số dư trước giao dịch
- BalanceAfterLiters (decimal) - Số dư sau giao dịch
- Notes (string)
- CreatedDate (DateTimeOffset)
```

### 7. Entity FuelQuotaPayment (Thanh toán tiền dầu khoán)

```
[Lada.Framework/Data/Domains/Trucks/FuelQuotaPayment.cs]
- Id (int)
- DriverId (int) - FK to User (lái xe)
- PaymentDate (DateTimeOffset) - Ngày thanh toán
- PaidLiters (decimal) - Số lít được thanh toán
- FuelUnitPrice (decimal) - Đơn giá dầu tại thời điểm thanh toán
- PaidAmount (decimal) - Số tiền thanh toán = PaidLiters x FuelUnitPrice
- BalanceBeforeLiters (decimal) - Số dư trước thanh toán
- BalanceAfterLiters (decimal) - Số dư sau thanh toán
- PaymentMethod (string) - Phương thức (Tiền mặt, Chuyển khoản)
- PaymentReference (string) - Mã tham chiếu
- Notes (string)
- ApprovedByUserId (int)
- ApprovedByUserName (string)
- Status (enum: Pending, Approved, Paid, Cancelled)
```

### 8. Enum mở rộng

```
[Lada.Framework/Data/Enums/TruckEnum.cs] - Mở rộng TruckActivityMediaType
- OdoBeforePhoto = 10  // Ảnh đồng hồ ODO trước khi đổ
- OdoAfterPhoto = 11   // Ảnh đồng hồ ODO sau khi đổ
- FuelPumpPhoto = 12   // Ảnh cây dầu (số tiền, số lít, đơn giá)
- FuelReceiptPhoto = 13 // Ảnh hóa đơn

[Lada.Framework/Data/Enums/FinanceEnum.cs] - NEW
- FuelCardStatus: Active, Inactive, Lost, Expired
- FuelCardTransactionStatus: Success, Failed, Pending
- FuelQuotaTransactionType: Refill, Payment, Adjustment, Reset
- FuelQuotaPaymentStatus: Pending, Approved, Paid, Cancelled
- FuelRefillPaymentMethod: Card, Cash
```

---

## Cấu trúc Files cần tạo/sửa

### Entities (Lada.Framework)

- `Lada.Framework/Data/Domains/Trucks/Truck.cs` (MODIFY - thêm FuelQuotaPer100Km)
- `Lada.Framework/Data/Domains/Finance/FuelCard.cs` (NEW)
- `Lada.Framework/Data/Domains/Finance/FuelCardTransaction.cs` (NEW)
- `Lada.Framework/Data/Domains/Finance/FuelCardStatementImport.cs` (NEW)
- `Lada.Framework/Data/Domains/Trucks/FuelRefill.cs` (NEW)
- `Lada.Framework/Data/Domains/Trucks/DriverFuelQuotaBalance.cs` (NEW)
- `Lada.Framework/Data/Domains/Trucks/DriverFuelQuotaHistory.cs` (NEW)
- `Lada.Framework/Data/Domains/Trucks/FuelQuotaPayment.cs` (NEW)
- `Lada.Framework/Data/Enums/TruckEnum.cs` (MODIFY)
- `Lada.Framework/Data/Enums/FinanceEnum.cs` (MODIFY)

### Entity Mappings

- `Lada.Framework/Data/Mappings/EntityMappings/Finance/FuelCardMap.cs` (NEW)
- `Lada.Framework/Data/Mappings/EntityMappings/Finance/FuelCardTransactionMap.cs` (NEW)
- `Lada.Framework/Data/Mappings/EntityMappings/Finance/FuelCardStatementImportMap.cs` (NEW)
- `Lada.Framework/Data/Mappings/EntityMappings/Trucks/FuelRefillMap.cs` (NEW)
- `Lada.Framework/Data/Mappings/EntityMappings/Trucks/DriverFuelQuotaBalanceMap.cs` (NEW)
- `Lada.Framework/Data/Mappings/EntityMappings/Trucks/DriverFuelQuotaHistoryMap.cs` (NEW)
- `Lada.Framework/Data/Mappings/EntityMappings/Trucks/FuelQuotaPaymentMap.cs` (NEW)
- `Lada.Framework/Data/Mappings/DbContexts/LadaDbContext.FuelCard.cs` (NEW)

### DTOs (Ladaer.BackEnd)

- `Ladaer.BackEnd/Infrastructures/DTO/Items/FuelCards/FuelCardItem.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/DTO/Items/FuelCards/FuelCardTransactionItem.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/DTO/Items/FuelCards/FuelRefillItem.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/DTO/Items/FuelCards/DriverFuelQuotaBalanceItem.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/DTO/Items/FuelCards/DriverFuelQuotaHistoryItem.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/DTO/Items/FuelCards/FuelQuotaPaymentItem.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/DTO/Models/FuelCards/FuelCardModel.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/DTO/Models/FuelCards/FuelCardTransactionImportModel.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/DTO/Models/FuelCards/FuelRefillModel.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/DTO/Models/FuelCards/FuelQuotaPaymentModel.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/DTO/Results/FuelCards/FuelCardResult.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/DTO/Results/FuelCards/DriverFuelQuotaResult.cs` (NEW)

### Services

- `Ladaer.BackEnd/Infrastructures/Services/FuelCards/FuelCardService.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/Services/FuelCards/FuelCardTransactionService.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/Services/FuelCards/FuelRefillService.cs` (NEW)
- `Ladaer.BackEnd/Infrastructures/Services/FuelCards/DriverFuelQuotaService.cs` (NEW)

### Controllers

- `Ladaer.BackEnd/Controllers/Finance/FuelCardController.cs` (NEW)

---

## API Endpoints

### FuelCard (Quản lý thẻ)

- `POST /api/FuelCard/Search` - Tìm kiếm thẻ
- `POST /api/FuelCard/CreateOrUpdate` - Tạo/cập nhật thẻ
- `POST /api/FuelCard/Delete` - Xóa thẻ
- `GET /api/FuelCard/GetById` - Lấy thông tin thẻ
- `POST /api/FuelCard/AssignToTruck` - Gán thẻ cho xe

### FuelCardTransaction (Giao dịch thẻ)

- `POST /api/FuelCard/ImportStatement` - Import sao kê Excel
- `POST /api/FuelCard/SearchTransactions` - Tìm kiếm giao dịch
- `GET /api/FuelCard/GetTransactionById` - Chi tiết giao dịch
- `POST /api/FuelCard/ReconcileTransaction` - Đối soát với lần đổ dầu

### FuelRefill (Đổ dầu)

- `POST /api/FuelCard/RefillFuel` - Lái xe đổ dầu (upload ảnh + tự động tính chênh lệch)
- `POST /api/FuelCard/SearchRefills` - Tìm kiếm lịch sử đổ dầu
- `GET /api/FuelCard/GetRefillById` - Chi tiết lần đổ dầu
- `GET /api/FuelCard/GetRefillsByTruck` - Lịch sử đổ dầu theo xe
- `GET /api/FuelCard/GetRefillsByDriver` - Lịch sử đổ dầu theo lái xe

### DriverFuelQuota (Định mức khoán)

- `GET /api/FuelCard/GetDriverQuotaBalance` - Lấy số dư dầu khoán của lái xe
- `POST /api/FuelCard/SearchDriverQuotaHistory` - Lịch sử chênh lệch dầu
- `POST /api/FuelCard/AdjustDriverQuota` - Điều chỉnh số dư (Admin)

### FuelQuotaPayment (Thanh toán)

- `POST /api/FuelCard/CreatePayment` - Tạo phiếu thanh toán tiền dầu
- `POST /api/FuelCard/ApprovePayment` - Duyệt thanh toán
- `POST /api/FuelCard/SearchPayments` - Tìm kiếm lịch sử thanh toán
- `GET /api/FuelCard/GetPaymentById` - Chi tiết thanh toán

---

## Luồng nghiệp vụ

```mermaid
flowchart TD
    subgraph Admin[Admin/Kế toán]
        A1[Tạo thẻ xăng dầu]
        A2[Gán thẻ cho xe/lái xe]
        A3[Cấu hình định mức khoán cho xe]
        A4[Import sao kê Excel]
        A5[Đối soát giao dịch]
        A6[Tạo phiếu thanh toán tiền dầu]
        A7[Duyệt và thanh toán]
    end
    
    subgraph Driver[Lái xe]
        D1[Chụp ảnh ODO trước đổ]
        D2[Đổ dầu]
        D3[Chụp ảnh cây dầu]
        D4[Chụp ảnh ODO sau đổ]
        D5[Chụp ảnh hóa đơn]
        D6[Nhập số tiền + đơn giá]
        D7[Chọn thanh toán: Thẻ/Tiền mặt]
        D8[Gửi báo cáo đổ dầu]
        D9[Xem số dư dầu khoán]
    end
    
    subgraph SystemRefill[Hệ thống - Khi đổ dầu]
        S1[Lưu FuelRefill + Media]
        S2[Tính số km = ODO hiện tại - ODO trước]
        S3[Tính số lít thực tế = Số tiền / Đơn giá]
        S4[Tính số lít khoán = km x định mức / 100]
        S5[Tính chênh lệch = Khoán - Thực tế]
        S6[Cập nhật DriverFuelQuotaBalance]
        S7[Lưu DriverFuelQuotaHistory type=Refill]
    end
    
    subgraph SystemPayment[Hệ thống - Khi thanh toán]
        P1[Tạo FuelQuotaPayment]
        P2[Tính tiền = Số lít x Đơn giá dầu]
        P3[Cập nhật DriverFuelQuotaBalance]
        P4[Lưu DriverFuelQuotaHistory type=Payment]
    end
    
    A1 --> A2 --> A3
    A4 --> A5
    A6 --> A7 --> P1
    D1 --> D2 --> D3 --> D4 --> D5 --> D6 --> D7 --> D8
    D8 --> S1 --> S2 --> S3 --> S4 --> S5 --> S6 --> S7
    P1 --> P2 --> P3 --> P4
```

---

## Logic tính toán

### Khi đổ dầu:

```
Xe A có định mức: 11 lít/100km
Lái xe đổ dầu:
 - ODO lần trước: 10,000 km
 - ODO hiện tại: 10,300 km
 - Số km đã chạy: 300 km
  
 - Số tiền đổ: 500,000 VND
 - Đơn giá: 20,000 VND/lít
 - Số lít thực tế: 25 lít

 - Số lít khoán: (300 x 11) / 100 = 33 lít
 - Chênh lệch: 33 - 25 = +8 lít (lái xe được hưởng)
  
=> Cập nhật Balance: +8 lít
=> Lưu History: TransactionType=Refill, DifferenceLiters=+8
```

### Khi thanh toán:

```
Lái xe có số dư: +50 lít
Công ty thanh toán:
 - Số lít thanh toán: 50 lít
 - Đơn giá dầu hiện tại: 21,000 VND/lít
 - Số tiền thanh toán: 50 x 21,000 = 1,050,000 VND

=> Cập nhật Balance: -50 lít (về 0)
=> Lưu History: TransactionType=Payment, DifferenceLiters=-50
=> Lưu FuelQuotaPayment: PaidLiters=50, PaidAmount=1,050,000
```

### Quy tắc xác định ODO trước đó:

1. **Nếu có lịch sử đổ dầu**: Lấy CurrentOdo của lần đổ dầu gần nhất
2. **Nếu chưa có lịch sử đổ dầu**: Lấy CurrentOdo từ TruckActivity CheckIn (nhận xe) gần nhất
3. **Nếu không có cả hai**: Yêu cầu lái xe nhập ODO trước đó thủ công

---

## Thứ tự thực hiện

1. **Phase 1 - Database & Entities**

      - Tạo các Entity mới
      - Tạo Entity Mappings
      - Tạo Migration

2. **Phase 2 - DTOs & Models**

      - Tạo các Item, Model, Result classes
      - Cấu hình AutoMapper profiles

3. **Phase 3 - Services**

      - FuelCardService (CRUD thẻ)
      - FuelCardTransactionService (Import Excel, đối soát)
      - FuelRefillService (Quản lý việc đổ dầu + tính chênh lệch)
      - DriverFuelQuotaService (Quản lý số dư + thanh toán)

4. **Phase 4 - Controllers & APIs**

      - FuelCardController với các endpoints
      - Authorization setup

5. **Phase 5 - Testing & Documentation**

      - Unit tests
      - API documentation