# 批量推送扫描记录接口开发计划

## 需求分析

用户需要开发一个接口，支持：
1. 按批量订单号查询扫描记录
2. 按时间范围查询扫描记录
3. 对每个客户推送其订单最新的扫描记录
4. 有最新记录则推送，没有则不推送

## 现有代码结构

### 核心组件
- **LabelController** (`src/CONTROLLER/Controllers/LabelController.cs`): 控制器，包含webhook推送方法
- **ILabelScanService** (`src/BLL/Interfaces/ILabelScanService.cs`): 扫描服务接口
- **LabelScanService** (`src/BLL/Services/LabelScanService.cs`): 扫描服务实现
- **LabelScanEntity** (`src/MDL/Models/LabelScanEntity.cs`): 扫描记录实体
- **CustomerEntity** (`src/MDL/Models/CustomerEntity.cs`): 客户实体

### 现有Webhook方法
| 客户代码 | 推送方法 | 参数 |
|---------|---------|------|
| PT_GZ | `SendWebhookToPatuen` | waybillNumber, scanTime, printTime |
| XT_JX | `SendWebhookToXunTong` | waybillNumber, scanTime, printTime, scanResult, scanDescription |
| ZY_SH | `SendWebhookToZunYou` | waybillNumber, scanTime, printTime, scanResult, finalMileTrackingNumber |
| IDI_ZJ | `SendWebhookToIDI` | waybillNumber, scanTime, printTime, scanResult, scanDescription |
| WEM_ZJ | `SendWebhookToWEM` | waybillNumber, scanTime, printTime, scanResult, scanDescription |

## 实现方案

### 1. 新增DTO定义

创建批量推送请求和响应DTO：

```csharp
// 请求DTO
public class BatchPushRequestDto
{
    public List<string> WaybillNumbers { get; set; }  // 批量订单号（可选）
    public string StartTime { get; set; }              // 开始时间（可选，格式：yyyy-MM-dd HH:mm:ss）
    public string EndTime { get; set; }                // 结束时间（可选，格式：yyyy-MM-dd HH:mm:ss）
    public string CustomerCode { get; set; }           // 客户代码（可选，指定推送特定客户）
}

// 响应DTO
public class BatchPushResponseDto
{
    public string Status { get; set; }
    public string Message { get; set; }
    public int TotalOrders { get; set; }
    public int PushedCount { get; set; }
    public int SkippedCount { get; set; }
    public List<PushResultDetail> Details { get; set; }
}

public class PushResultDetail
{
    public string WaybillNumber { get; set; }
    public string CustomerCode { get; set; }
    public bool Success { get; set; }
    public string Message { get; set; }
    public DateTime? ScanTime { get; set; }
}
```

### 2. 新增服务方法

在 `ILabelScanService` 接口中添加：

```csharp
/// <summary>
/// 获取指定条件的最新扫描记录（按订单号分组，取最新的一条）
/// </summary>
Task<List<LabelScanEntity>> GetLatestScanRecordsAsync(
    List<string> waybillNumbers = null, 
    DateTime? startTime = null, 
    DateTime? endTime = null,
    int? customerId = null);
```

### 3. 新增Controller接口

在 `LabelController` 中添加：

```csharp
/// <summary>
/// 批量推送扫描记录到客户系统
/// </summary>
[HttpPost("webhook/batch-push")]
public async Task<IActionResult> BatchPushWebhook([FromBody] BatchPushRequestDto request)
```

### 4. 核心业务逻辑

1. **参数校验**：验证请求参数，至少提供订单号列表或时间范围
2. **数据查询**：根据条件查询扫描记录，按订单号分组取最新记录
3. **客户匹配**：根据订单关联的客户ID获取客户信息
4. **条件过滤**：如果指定了客户代码，只处理该客户的订单
5. **推送执行**：根据客户代码调用对应的webhook方法
6. **结果汇总**：返回推送结果统计

## 文件修改清单

| 文件 | 修改类型 | 说明 |
|-----|---------|------|
| `src/MDL/DTOs/BatchPushDto.cs` | 新建 | 批量推送请求/响应DTO |
| `src/BLL/Interfaces/ILabelScanService.cs` | 修改 | 添加获取最新扫描记录方法 |
| `src/BLL/Services/LabelScanService.cs` | 修改 | 实现获取最新扫描记录方法 |
| `src/DAL/Interfaces/ILabelScanRepository.cs` | 修改 | 添加仓储方法 |
| `src/DAL/Repositories/LabelScanRepository.cs` | 修改 | 实现仓储方法 |
| `src/CONTROLLER/Controllers/LabelController.cs` | 修改 | 添加批量推送接口 |

## 数据库查询逻辑

获取每个订单的最新扫描记录：

```sql
SELECT * FROM label_scan_history 
WHERE (NeutralWaybillNumber IN (@waybillNumbers) OR @waybillNumbers IS NULL)
  AND (CreatedAt >= @startTime OR @startTime IS NULL)
  AND (CreatedAt <= @endTime OR @endTime IS NULL)
  AND (CustomerId = @customerId OR @customerId IS NULL)
ORDER BY NeutralWaybillNumber, CreatedAt DESC
```

然后按订单号分组，取每组第一条（最新的）记录。

## 注意事项

1. **性能考虑**：批量查询时限制单次最大订单数量（建议2000条以内）
2. **异步处理**：推送操作应异步执行，不阻塞接口响应
3. **日志记录**：记录每条推送的详细结果，便于问题排查
4. **异常处理**：单个订单推送失败不应影响其他订单
5. **幂等性**：相同订单重复推送时应考虑是否需要重复发送

## 接口调用示例

### 请求

```json
POST /api/label/webhook/batch-push
{
    "waybillNumbers": ["WB001", "WB002", "WB003"],
    "customerCode": "XT_JX"
}
```

### 响应

```json
{
    "status": "ok",
    "message": "批量推送完成",
    "totalOrders": 3,
    "pushedCount": 2,
    "skippedCount": 1,
    "details": [
        {
            "waybillNumber": "WB001",
            "customerCode": "XT_JX",
            "success": true,
            "message": "推送成功",
            "scanTime": "2024-01-15 10:30:00"
        },
        {
            "waybillNumber": "WB002",
            "customerCode": "XT_JX",
            "success": true,
            "message": "推送成功",
            "scanTime": "2024-01-15 10:35:00"
        },
        {
            "waybillNumber": "WB003",
            "customerCode": "XT_JX",
            "success": false,
            "message": "无扫描记录",
            "scanTime": null
        }
    ]
}
```
