## API: Báo cáo năng suất lái xe theo từng ngày

- Service: IDriverReportService.GetDriverProductivityReportByDateAsync(SmartTableParam param, int userId)
- Controller: DriverReportController
- Route: POST /api/DriverReport/GetDriverProductivityReportByDate
- Authorization: [Authorize(Roles = "DriverReport.GetDriverProductivityReportByDate")]
- Mục đích: Lấy báo cáo năng suất lái xe theo từng ngày, nhóm dữ liệu theo DriverId và tính tổng số lượng đơn hàng lấy hàng, giao hàng.

### Mô tả tổng quan

Endpoint này cung cấp báo cáo năng suất lái xe với các thông tin:

- **Items**: Danh sách lái xe với thống kê tổng hợp theo khoảng thời gian
- **DriverProductivityTotalItem**: Dòng tổng cộng của tất cả lái xe
- **TotalRecord**: Tổng số lượng lái xe có hoạt động

Mỗi item trong danh sách chứa:

- Thông tin lái xe: DriverId, DriverUserName, DriverFullName
- Thống kê hoạt động: PickupCount, DeliveryCount, TotalCount
- Thông tin thời gian: ActivityDate, DayOfWeek, FromDate, ToDate

Dữ liệu được nhóm theo DriverId và tính tổng số lượng đơn hàng trong khoảng thời gian được chỉ định.

### Request

- Method: POST
- URL: /api/DriverReport/GetDriverProductivityReportByDate
- Body (PascalCase):

```
{
  "Pagination": {
    "From": 0,
    "PageIndex": 1,
    "PageSize": 10
  },
  "Search": {
    "PredicateObject": {
      "FromDate": "2024-01-01T00:00:00+07:00",
      "ToDate": "2024-01-31T23:59:59+07:00",
      "DriverIds": [1, 2, 3]
    }
  },
  "Sort": {
    "Predicate": "TotalCount",
    "Reverse": true
  },
  "IsExport": false
}
```

**Tham số:**

- `Pagination.From`: Vị trí bắt đầu phân trang (tự động tính từ PageIndex và PageSize)
- `Pagination.PageIndex`: Số trang (mặc định: 1)
- `Pagination.PageSize`: Số lượng bản ghi mỗi trang (mặc định: 10)
- `Search.PredicateObject.FromDate`: Thời gian bắt đầu (DateTimeOffset, nullable)
- `Search.PredicateObject.ToDate`: Thời gian kết thúc (DateTimeOffset, nullable)
- `Search.PredicateObject.DriverIds`: Danh sách ID lái xe cần lọc (array of int, nullable)
- `Sort.Predicate`: Tên trường sắp xếp (string, nullable)
- `Sort.Reverse`: Sắp xếp ngược (boolean, mặc định: false)
- `IsExport`: Có xuất dữ liệu hay không (boolean, mặc định: false)

**Ghi chú:** Nếu không truyền FromDate/ToDate, hệ thống sẽ lấy dữ liệu tháng hiện tại.

- Header: Authorization: Bearer <jwt-token> (yêu cầu quyền DriverReport.GetDriverProductivityReportByDate)

### Response

- HTTP 200 OK
- Content-Type: application/json

Ví dụ:

```
{
  "Result": 1,
  "Message": "",
  "Items": [
    {
      "DriverId": 1,
      "DriverUserName": "driver1",
      "DriverFullName": "Nguyễn Văn A",
      "PickupCount": 25,
      "DeliveryCount": 18,
      "TotalCount": 43,
      "DailyDetails": [
        {
          "DriverId": 1,
          "DriverUserName": "driver1",
          "DriverFullName": "Nguyễn Văn A",
          "ActivityDate": "2024-01-15T00:00:00",
          "PickupCount": 15,
          "DeliveryCount": 10,
          "TotalCount": 25,
          "DayOfWeek": "Monday",
          "FromDate": "2024-01-01T00:00:00+07:00",
          "ToDate": "2024-01-31T23:59:59+07:00"
        },
        {
          "DriverId": 1,
          "DriverUserName": "driver1",
          "DriverFullName": "Nguyễn Văn A",
          "ActivityDate": "2024-01-14T00:00:00",
          "PickupCount": 10,
          "DeliveryCount": 8,
          "TotalCount": 18,
          "DayOfWeek": "Sunday",
          "FromDate": "2024-01-01T00:00:00+07:00",
          "ToDate": "2024-01-31T23:59:59+07:00"
        }
      ]
    },
    {
      "DriverId": 2,
      "DriverUserName": "driver2",
      "DriverFullName": "Trần Thị B",
      "PickupCount": 20,
      "DeliveryCount": 15,
      "TotalCount": 35,
      "DailyDetails": [
        {
          "DriverId": 2,
          "DriverUserName": "driver2",
          "DriverFullName": "Trần Thị B",
          "ActivityDate": "2024-01-16T00:00:00",
          "PickupCount": 12,
          "DeliveryCount": 9,
          "TotalCount": 21,
          "DayOfWeek": "Tuesday",
          "FromDate": "2024-01-01T00:00:00+07:00",
          "ToDate": "2024-01-31T23:59:59+07:00"
        },
        {
          "DriverId": 2,
          "DriverUserName": "driver2",
          "DriverFullName": "Trần Thị B",
          "ActivityDate": "2024-01-15T00:00:00",
          "PickupCount": 8,
          "DeliveryCount": 6,
          "TotalCount": 14,
          "DayOfWeek": "Monday",
          "FromDate": "2024-01-01T00:00:00+07:00",
          "ToDate": "2024-01-31T23:59:59+07:00"
        }
      ]
    }
  ],
  "DriverProductivityTotalItem": {
    "DriverId": 0,
    "DriverUserName": "",
    "DriverFullName": "TỔNG CỘNG",
    "PickupCount": 45,
    "DeliveryCount": 33,
    "TotalCount": 78,
    "DailyDetails": []
  },
  "TotalRecord": 2
}
```

**Cấu trúc Response:**

- `Result`: Mã kết quả (1 = thành công, 0 = thất bại)
- `Message`: Thông báo lỗi (nếu có)
- `Items`: Danh sách lái xe với thống kê năng suất (mỗi item là một lái xe)
- `DriverProductivityTotalItem`: Dòng tổng cộng
- `TotalRecord`: Tổng số lái xe có hoạt động

**Cấu trúc Group Item (mỗi lái xe):**

- `DriverId`: ID lái xe
- `DriverUserName`: Tên đăng nhập lái xe
- `DriverFullName`: Tên đầy đủ lái xe
- `PickupCount`: Tổng số đơn hàng lấy hàng trong khoảng thời gian
- `DeliveryCount`: Tổng số đơn hàng giao hàng trong khoảng thời gian
- `TotalCount`: Tổng số đơn hàng trong khoảng thời gian (PickupCount + DeliveryCount)
- `DailyDetails`: Danh sách chi tiết theo từng ngày (sắp xếp giảm dần theo ngày)

**Cấu trúc Daily Detail Item (chi tiết từng ngày):**

- `DriverId`: ID lái xe
- `DriverUserName`: Tên đăng nhập lái xe
- `DriverFullName`: Tên đầy đủ lái xe
- `ActivityDate`: Ngày hoạt động
- `PickupCount`: Số đơn hàng lấy hàng trong ngày
- `DeliveryCount`: Số đơn hàng giao hàng trong ngày
- `TotalCount`: Tổng số đơn hàng trong ngày (PickupCount + DeliveryCount)
- `DayOfWeek`: Tên ngày trong tuần (Monday, Tuesday, ...)
- `FromDate`: Thời gian bắt đầu khoảng lọc
- `ToDate`: Thời gian kết thúc khoảng lọc

### Xử lý lỗi

- **HTTP 400 Bad Request**: Khi có lỗi trong quá trình xử lý
- **HTTP 401 Unauthorized**: Khi không có token hoặc token không hợp lệ
- **HTTP 403 Forbidden**: Khi không có quyền truy cập

Ví dụ lỗi:

```
{
  "Message": "Không tìm thấy thông tin người dùng"
}
```

### Phụ thuộc & Liên quan

- **Stored Procedure**: sp_GetDriverProductivityReportByDate
- **DTO**:
  - Ladaer.BackEnd/Infrastructures/DTO/Reports/Results/DriverProductivityReportByDateResult.cs
  - Ladaer.BackEnd/Infrastructures/DTO/Reports/Items/Operations/DriverProductivityGroupItem.cs
  - Ladaer.BackEnd/Infrastructures/DTO/Reports/Items/Operations/DriverProductivityReportByDateItem.cs
- **Service & Controller**:
  - Ladaer.BackEnd/Infrastructures/Services/Report/OperationReports/DriverReportService.cs
  - Ladaer.BackEnd/Controllers/Reports/Operations/DriverReportController.cs
- **Database Tables**:
  - OrderOps (PickedupById, DeliveredById)
  - OrderTimeTrack (PickupTime, DeliveryDate)
  - User (thông tin lái xe)

### Logic nghiệp vụ

1. **Lọc dữ liệu**: Chỉ lấy các đơn hàng có PickupTime hoặc DeliveryDate trong khoảng thời gian chỉ định
2. **Nhóm dữ liệu**: Nhóm theo DriverId và tính tổng số lượng đơn hàng
3. **Sắp xếp**: Theo TotalCount giảm dần, sau đó theo DriverFullName tăng dần
4. **Phân quyền**: Founder có thể xem tất cả lái xe, người khác chỉ xem lái xe được chỉ định

### Thay đổi gần đây

- 2024-12-19: Tạo API báo cáo năng suất lái xe theo ngày với nhóm dữ liệu theo DriverId
