344 lines
10 KiB
Markdown
344 lines
10 KiB
Markdown
# USPS 自动集包开发检查清单
|
||
|
||
## 开发前准备
|
||
|
||
- [ ] 已阅读 USPS自动集包需求文档.md
|
||
- [ ] 已阅读 spec.md 接口规范
|
||
- [ ] 已阅读 tasks.md 任务分解
|
||
- [ ] 已确认数据库表结构(label_replace_requests, bag_tag_waybills)
|
||
- [ ] 已确认 USPS 运单号识别规则
|
||
|
||
---
|
||
|
||
## 阶段一:模型定义
|
||
|
||
### 任务 1.1:创建任务状态模型
|
||
**文件**:`src/MDL/Models/AutoPackTaskStatus.cs`
|
||
|
||
- [ ] 创建 `AutoPackTaskStatus` 类
|
||
- [ ] TaskId (string)
|
||
- [ ] TagNumber (string)
|
||
- [ ] Status (string)
|
||
- [ ] TotalCount (int)
|
||
- [ ] ProcessedCount (int)
|
||
- [ ] SuccessCount (int)
|
||
- [ ] FailedCount (int)
|
||
- [ ] CurrentWaybill (string)
|
||
- [ ] StartTime (DateTime)
|
||
- [ ] EndTime (DateTime?)
|
||
- [ ] FailedItems (List<AutoPackFailedItem>)
|
||
- [ ] CancellationTokenSource (CancellationTokenSource)
|
||
- [ ] 创建 `AutoPackFailedItem` 类
|
||
- [ ] WaybillNumber (string)
|
||
- [ ] ErrorCode (int)
|
||
- [ ] ErrorMessage (string)
|
||
- [ ] 添加必要的 using 语句
|
||
- [ ] 编译通过
|
||
|
||
### 任务 1.2:创建请求/响应 DTO
|
||
**文件**:`src/MDL/Models/AutoPackRequest.cs`
|
||
|
||
- [ ] 创建 `StartAutoPackRequest` 类
|
||
- [ ] TagNumber (string)
|
||
- [ ] Creator (string, 默认 "system")
|
||
- [ ] 创建 `StartAutoPackResponse` 类
|
||
- [ ] TaskId (string)
|
||
- [ ] TagNumber (string)
|
||
- [ ] Status (string)
|
||
- [ ] TotalCount (int)
|
||
- [ ] Message (string)
|
||
- [ ] 创建 `AutoPackProgressResponse` 类
|
||
- [ ] TaskId (string)
|
||
- [ ] TagNumber (string)
|
||
- [ ] Status (string)
|
||
- [ ] TotalCount (int)
|
||
- [ ] ProcessedCount (int)
|
||
- [ ] SuccessCount (int)
|
||
- [ ] FailedCount (int)
|
||
- [ ] CurrentWaybill (string)
|
||
- [ ] Progress (int)
|
||
- [ ] Message (string)
|
||
- [ ] StartTime (DateTime)
|
||
- [ ] EstimatedEndTime (DateTime?)
|
||
- [ ] FailedItems (List<AutoPackFailedItem>)
|
||
- [ ] 创建 `AutoPackResultResponse` 类
|
||
- [ ] TaskId (string)
|
||
- [ ] TagNumber (string)
|
||
- [ ] Status (string)
|
||
- [ ] TotalCount (int)
|
||
- [ ] SuccessCount (int)
|
||
- [ ] FailedCount (int)
|
||
- [ ] StartTime (DateTime)
|
||
- [ ] EndTime (DateTime?)
|
||
- [ ] Duration (int)
|
||
- [ ] FailedItems (List<AutoPackFailedItem>)
|
||
- [ ] 编译通过
|
||
|
||
---
|
||
|
||
## 阶段二:数据访问层
|
||
|
||
### 任务 2.1:扩展 Repository 接口
|
||
**文件**:`src/DAL/Interfaces/IBagTagRepository.cs`
|
||
|
||
- [ ] 添加 `GetEligibleUspsWaybillsAsync(DateTime cutoffTime)` 方法声明
|
||
- [ ] 添加 `GetEligibleUspsWaybillCountAsync(DateTime cutoffTime)` 方法声明
|
||
- [ ] 添加 XML 注释
|
||
- [ ] 编译通过
|
||
|
||
### 任务 2.2:实现 Repository 方法
|
||
**文件**:`src/DAL/Repositories/BagTagRepository.cs`
|
||
|
||
- [ ] 实现 `GetEligibleUspsWaybillsAsync` 方法
|
||
- [ ] 使用 SqlSugar 执行 SQL 查询
|
||
- [ ] 查询条件:ReplaceStatus = 'Y'
|
||
- [ ] 查询条件:CreatedAt >= cutoffTime
|
||
- [ ] 查询条件:FinalMileTrackingNumber IS NOT NULL AND != ''
|
||
- [ ] 查询条件:未关联到 bag_tag_waybills(LEFT JOIN + IS NULL)
|
||
- [ ] 查询条件:USPS 格式(REGEXP '^(92|93|94|95)')
|
||
- [ ] 查询条件:USPS 格式(REGEXP '^420[0-9]{5}(92|93|94|95)')
|
||
- [ ] 查询条件:USPS 格式(REGEXP '^420[0-9]{9}(92|93|94|95)')
|
||
- [ ] ORDER BY CreatedAt ASC
|
||
- [ ] 返回 List<string>
|
||
- [ ] 实现 `GetEligibleUspsWaybillCountAsync` 方法
|
||
- [ ] 使用 COUNT(*) 查询
|
||
- [ ] 相同的 WHERE 条件
|
||
- [ ] 返回 int
|
||
- [ ] 添加异常处理
|
||
- [ ] 编译通过
|
||
|
||
---
|
||
|
||
## 阶段三:业务逻辑层
|
||
|
||
### 任务 3.1:扩展 Service 接口
|
||
**文件**:`src/BLL/Interfaces/IBagTagService.cs`
|
||
|
||
- [ ] 添加 `StartAutoPackAsync(string tagNumber, string creator)` 方法声明
|
||
- [ ] 添加 `GetAutoPackProgressAsync(string taskId)` 方法声明
|
||
- [ ] 添加 `CancelAutoPackAsync(string taskId)` 方法声明
|
||
- [ ] 添加 `GetAutoPackResultAsync(string taskId)` 方法声明
|
||
- [ ] 添加 XML 注释
|
||
- [ ] 编译通过
|
||
|
||
### 任务 3.2:实现任务启动逻辑
|
||
**文件**:`src/BLL/Services/BagTagService.cs`
|
||
|
||
- [ ] 注入 ICacheService(如未注入)
|
||
- [ ] 实现 `StartAutoPackAsync` 方法
|
||
- [ ] 验证袋牌存在(GetByTagNumberAsync)
|
||
- [ ] 验证袋牌状态为 "Opened"
|
||
- [ ] 计算 cutoffTime(DateTime.UtcNow.AddHours(-84))
|
||
- [ ] 调用 GetEligibleUspsWaybillsAsync 获取包裹列表
|
||
- [ ] 检查包裹数量 > 0
|
||
- [ ] 生成唯一 TaskId(格式:task_{timestamp}_{guid})
|
||
- [ ] 创建 AutoPackTaskStatus 对象
|
||
- [ ] 存入缓存(key: "autopack:{taskId}", 过期时间 60 分钟)
|
||
- [ ] 启动后台任务(Task.Run)
|
||
- [ ] 返回 StartAutoPackResponse
|
||
- [ ] 添加异常处理
|
||
- [ ] 编译通过
|
||
|
||
### 任务 3.3:实现自动集包执行逻辑
|
||
**文件**:`src/BLL/Services/BagTagService.cs`
|
||
|
||
- [ ] 创建 `ExecuteAutoPackAsync` 私有方法
|
||
- [ ] 参数:taskId, tagNumber, waybills, creator
|
||
- [ ] 创建 Random 对象
|
||
- [ ] 遍历 waybills
|
||
- [ ] 从缓存获取任务状态
|
||
- [ ] 检查 CancellationTokenSource.IsCancellationRequested
|
||
- [ ] 更新 CurrentWaybill
|
||
- [ ] 调用 AssociateWaybillAsync 进行关联
|
||
- [ ] 更新 SuccessCount 或 FailedCount
|
||
- [ ] 记录失败信息到 FailedItems
|
||
- [ ] 更新 ProcessedCount
|
||
- [ ] 保存任务状态到缓存
|
||
- [ ] 随机延迟 2-4 秒(最后一个不延迟)
|
||
- [ ] 任务完成处理
|
||
- [ ] 设置 Status(completed/cancelled)
|
||
- [ ] 设置 EndTime
|
||
- [ ] 清空 CurrentWaybill
|
||
- [ ] 保存最终状态到缓存
|
||
- [ ] 实现 `GetAutoPackProgressAsync` 方法
|
||
- [ ] 从缓存获取任务状态
|
||
- [ ] 计算 Progress 百分比
|
||
- [ ] 计算 EstimatedEndTime
|
||
- [ ] 映射到 AutoPackProgressResponse
|
||
- [ ] 返回响应
|
||
- [ ] 实现 `CancelAutoPackAsync` 方法
|
||
- [ ] 从缓存获取任务状态
|
||
- [ ] 检查任务是否存在且状态为 processing
|
||
- [ ] 调用 CancellationTokenSource.Cancel()
|
||
- [ ] 更新状态为 cancelled
|
||
- [ ] 保存到缓存
|
||
- [ ] 返回 bool
|
||
- [ ] 实现 `GetAutoPackResultAsync` 方法
|
||
- [ ] 从缓存获取任务状态
|
||
- [ ] 映射到 AutoPackResultResponse
|
||
- [ ] 计算 Duration
|
||
- [ ] 返回响应
|
||
- [ ] 添加异常处理
|
||
- [ ] 编译通过
|
||
|
||
---
|
||
|
||
## 阶段四:接口层
|
||
|
||
### 任务 4.1:实现控制器方法
|
||
**文件**:`src/CONTROLLER/Controllers/BagTagController.cs`
|
||
|
||
- [ ] 添加 `StartAutoPack` 方法
|
||
- [ ] HTTP POST 路由:"auto-pack/start"
|
||
- [ ] 参数:[FromBody] StartAutoPackRequest
|
||
- [ ] 调用 _bagTagService.StartAutoPackAsync
|
||
- [ ] 返回统一响应格式 { code, message, data }
|
||
- [ ] 异常处理
|
||
- [ ] 添加 `GetAutoPackProgress` 方法
|
||
- [ ] HTTP GET 路由:"auto-pack/progress/{taskId}"
|
||
- [ ] 参数:string taskId
|
||
- [ ] 调用 _bagTagService.GetAutoPackProgressAsync
|
||
- [ ] 处理任务不存在的情况
|
||
- [ ] 返回统一响应格式
|
||
- [ ] 异常处理
|
||
- [ ] 添加 `CancelAutoPack` 方法
|
||
- [ ] HTTP POST 路由:"auto-pack/cancel/{taskId}"
|
||
- [ ] 参数:string taskId
|
||
- [ ] 调用 _bagTagService.CancelAutoPackAsync
|
||
- [ ] 处理取消失败的情况
|
||
- [ ] 返回统一响应格式
|
||
- [ ] 异常处理
|
||
- [ ] 添加 `GetAutoPackResult` 方法
|
||
- [ ] HTTP GET 路由:"auto-pack/result/{taskId}"
|
||
- [ ] 参数:string taskId
|
||
- [ ] 调用 _bagTagService.GetAutoPackResultAsync
|
||
- [ ] 处理任务不存在的情况
|
||
- [ ] 返回统一响应格式
|
||
- [ ] 异常处理
|
||
- [ ] 编译通过
|
||
|
||
### 任务 4.2:注册依赖注入
|
||
**文件**:`src/CONTROLLER/Program.cs`
|
||
|
||
- [ ] 检查 ICacheService 是否已注册
|
||
- [ ] 检查 IBagTagService 是否已注册
|
||
- [ ] 确认无需额外注册
|
||
|
||
---
|
||
|
||
## 阶段五:测试与优化
|
||
|
||
### 任务 5.1:编写单元测试
|
||
|
||
- [ ] 测试启动任务 - 袋牌不存在
|
||
- [ ] 测试启动任务 - 袋牌未打开
|
||
- [ ] 测试启动任务 - 无符合条件的包裹
|
||
- [ ] 测试启动任务 - 成功启动
|
||
- [ ] 测试查询进度 - 任务不存在
|
||
- [ ] 测试查询进度 - 正常查询
|
||
- [ ] 测试取消任务 - 任务不存在
|
||
- [ ] 测试取消任务 - 任务已完成
|
||
- [ ] 测试取消任务 - 正常取消
|
||
- [ ] 测试自动集包执行 - 全部成功
|
||
- [ ] 测试自动集包执行 - 部分失败
|
||
- [ ] 测试自动集包执行 - 取消操作
|
||
- [ ] 所有测试通过
|
||
|
||
### 任务 5.2:性能优化与联调
|
||
|
||
- [ ] SQL 查询性能优化
|
||
- [ ] 检查 label_replace_requests 表索引(CreatedAt, ReplaceStatus, FinalMileTrackingNumber)
|
||
- [ ] 检查 bag_tag_waybills 表索引(FinalMileTrackingNumber)
|
||
- [ ] 缓存配置优化
|
||
- [ ] 确认缓存过期时间合理(60分钟)
|
||
- [ ] 并发控制
|
||
- [ ] 确认同时只能有一个自动集包任务在运行(可选)
|
||
- [ ] 异常处理完善
|
||
- [ ] 数据库连接异常
|
||
- [ ] 缓存访问异常
|
||
- [ ] 关联操作异常
|
||
- [ ] WinForm 联调
|
||
- [ ] 前端能正常调用启动接口
|
||
- [ ] 前端能正常轮询进度
|
||
- [ ] 进度条实时更新
|
||
- [ ] 取消功能正常
|
||
- [ ] 大数据量测试(100+ 包裹)
|
||
|
||
---
|
||
|
||
## 代码审查清单
|
||
|
||
### 代码规范
|
||
|
||
- [ ] 命名规范符合项目标准
|
||
- [ ] 方法添加 XML 注释
|
||
- [ ] 复杂逻辑添加行内注释
|
||
- [ ] 无死代码
|
||
- [ ] 无 Console.WriteLine(使用 ILogger)
|
||
|
||
### 异常处理
|
||
|
||
- [ ] 所有异步方法有 try-catch
|
||
- [ ] 异常信息不暴露敏感信息
|
||
- [ ] 异常正确记录日志
|
||
|
||
### 性能
|
||
|
||
- [ ] 数据库查询使用参数化 SQL
|
||
- [ ] 避免 N+1 查询问题
|
||
- [ ] 缓存使用合理
|
||
|
||
### 安全
|
||
|
||
- [ ] 输入参数验证
|
||
- [ ] 防止 SQL 注入
|
||
- [ ] 权限检查(如需要)
|
||
|
||
---
|
||
|
||
## 部署检查清单
|
||
|
||
- [ ] 代码编译通过
|
||
- [ ] 单元测试全部通过
|
||
- [ ] 数据库迁移脚本(如需要)
|
||
- [ ] 配置文件更新(如需要)
|
||
- [ ] API 文档更新
|
||
- [ ] 部署到测试环境
|
||
- [ ] 测试环境验证通过
|
||
- [ ] 部署到生产环境
|
||
- [ ] 生产环境验证通过
|
||
|
||
---
|
||
|
||
## 文档检查清单
|
||
|
||
- [ ] spec.md 已更新(如有变更)
|
||
- [ ] tasks.md 已更新(如有变更)
|
||
- [ ] 接口文档已更新
|
||
- [ ] 前端联调文档已提供
|
||
|
||
---
|
||
|
||
## 验收标准
|
||
|
||
### 功能验收
|
||
|
||
- [ ] 创建 USPS 袋牌后能自动触发集包(或手动触发接口)
|
||
- [ ] 正确筛选符合条件的 USPS 包裹(84小时内、未集包、已换单)
|
||
- [ ] 逐个关联包裹,间隔 2-4 秒
|
||
- [ ] 实时反馈进度(总数、已处理数、成功数、失败数)
|
||
- [ ] 支持取消操作
|
||
- [ ] 记录操作日志
|
||
|
||
### 性能验收
|
||
|
||
- [ ] 100 个包裹处理时间 < 10 分钟
|
||
- [ ] 前端轮询响应时间 < 100ms
|
||
- [ ] 内存占用稳定,无内存泄漏
|
||
|
||
### 兼容性验收
|
||
|
||
- [ ] WinForm 前端正常调用
|
||
- [ ] 接口响应格式符合规范
|
||
- [ ] 错误码定义清晰
|