Files
LabelChange-server/.trae/documents/arrival-scan-record-table-plan.md
2026-06-01 16:30:29 +08:00

6.3 KiB
Raw Blame History

收货扫描记录表arrival_scan_records设计与实现计划

一、背景分析

当前 ArrivalHandoverFormController/api/arrival-handover/receipt-query 接口(ArrivalHandoverFormController.cs:L447-L495)用于 PDA 收货扫描查询。

ArrivalHandoverFormService.GetReceiptInfoAsync 方法(ArrivalHandoverFormService.cs:L181-L281)的核心逻辑:

  • 接收 arrivalNumber(大箱号或提单号)
  • label_replace_requests 表中按 BillOfLadingNumberMasterPackageNumber 匹配
  • 返回 (packageCount, labelRate, arrivalTime, billOfLadingNumber, masterPackageNumber)
  • 同时自动创建/更新 arrival_handover_forms 记录

需要新增PDA 每次扫描收货时,将扫描记录持久化到一张独立的记录表中,便于后续追溯和统计。


二、表结构设计

表名:arrival_scan_records

字段 类型 约束 说明
Id INT UNSIGNED PK, AUTO_INCREMENT 主键
ArrivalNumber VARCHAR(100) NOT NULL PDA扫描的大箱号即 request.ArrivalNumber
CustomerId INT NULL 客户ID冗余字段关联 customers 表)
BillOfLadingNumber VARCHAR(100) NULL 提单号
MasterPackageNumber VARCHAR(100) NULL 大箱号
CreatedAt DATETIME NOT NULL PDA收货扫描时间创建时间
UpdatedAt DATETIME NOT NULL 更新时间

索引设计

索引名 字段 用途
idx_arrival_number ArrivalNumber 按扫描号查询历史记录
idx_created_at CreatedAt 按时间范围统计查询
idx_customer_id CustomerId 按客户维度查询

设计说明

  1. ArrivalNumber 对应 PDA 扫描时传入的 request.ArrivalNumber,是本次扫描的核心标识
  2. CustomerId 为冗余字段,从 label_replace_requests 表中获取,便于按客户维度查询,避免每次查询都要 JOIN
  3. BillOfLadingNumber / MasterPackageNumberGetReceiptInfoAsync 返回值中获取
  4. CreatedAt 即为 PDA 收货扫描时间
  5. 遵循项目现有的命名规范和注解风格PascalCase 属性名 + [SugarColumn] 注解)

三、实现步骤

步骤 1创建 SQL 建表脚本

文件src/DB/Scripts/CreateArrivalScanRecordTable.sql

参考 CreateLabelReplaceTable.sql 的格式:

  • InnoDB 引擎
  • utf8mb4 字符集
  • 包含中文注释
  • 创建必要索引

步骤 2创建 Entity 实体类

文件src/MDL/Models/ArrivalScanRecordEntity.cs

参考 LabelScanEntity.csLabelReplaceEntity.cs 的写法:

  • [SugarTable("arrival_scan_records")]
  • [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] 主键
  • 时间字段默认值 DateTime.UtcNow
  • 完整的中文 XML 注释

步骤 3创建 Repository 仓库层

文件

  • src/DAL/Interfaces/IArrivalScanRecordRepository.cs — 接口定义
  • src/DAL/Repositories/ArrivalScanRecordRepository.cs — 实现

参考 CustomerRepository.cs 的模式:

  • 通过 ISqlSugarProvider 操作数据库
  • 至少需要 InsertAsync 方法

步骤 4修改 ArrivalHandoverFormService

文件src/BLL/Services/ArrivalHandoverFormService.cs

GetReceiptInfoAsync 方法中,查询完成后插入一条扫描记录到 arrival_scan_records 表:

// 在 return 之前插入扫描记录
var scanRecord = new ArrivalScanRecordEntity
{
    ArrivalNumber = arrivalNumber,
    CustomerId = labelReplaceEntities.FirstOrDefault()?.CustomerId,
    BillOfLadingNumber = billOfLadingNumber,
    MasterPackageNumber = masterPackageNumber,
    CreatedAt = DateTime.UtcNow,
    UpdatedAt = DateTime.UtcNow
};
await db.Insertable(scanRecord).ExecuteCommandAsync();

关键点

  • CustomerIdlabel_replace_entities 的第一个匹配记录中获取(冗余存储)
  • 插入操作应在 try-catch 内部,且不应影响主流程(即使插入失败也不应阻止接口正常返回)
  • 建议用独立的 try-catch 包裹插入逻辑,避免扫描记录入库失败导致接口报错

步骤 5注册依赖注入

文件src/CONTROLLER/Program.cs(或对应的 DI 注册文件)

  • 注册 IArrivalScanRecordRepositoryArrivalScanRecordRepository
  • ArrivalHandoverFormService 构造函数中注入(如需要)

可选简化方案:由于 ArrivalHandoverFormService 已经持有 ISqlSugarProvider,可以直接通过 _provider.GetClient() 操作数据库,无需单独创建 Repository。是否需要独立 Repository 取决于项目的分层规范。


四、文件清单

文件 操作 说明
src/DB/Scripts/CreateArrivalScanRecordTable.sql 新增 建表 SQL 脚本
src/MDL/Models/ArrivalScanRecordEntity.cs 新增 实体类
src/DAL/Interfaces/IArrivalScanRecordRepository.cs 新增 仓库接口
src/DAL/Repositories/ArrivalScanRecordRepository.cs 新增 仓库实现
src/BLL/Services/ArrivalHandoverFormService.cs 修改 在 GetReceiptInfoAsync 中插入扫描记录
src/CONTROLLER/Program.cs 修改 注册 DI如需独立 Repository

五、待确认事项

  1. Repository 分层:是否需要创建独立的 Repository还是直接在 Service 中通过 ISqlSugarProvider 操作?(推荐后者,与现有模式一致,因为 ArrivalHandoverFormService 已经直接使用 _provider.GetClient() 操作数据库)
  2. 插入时机:是否仅在 Mock 数据分支TEST 开头的 arrivalNumber不插入建议仅在实际数据库查询成功后插入。
  3. 错误处理策略:扫描记录插入失败时,是静默忽略(不影响接口返回)还是抛出异常?建议静默忽略,确保核心业务不受影响。