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

135 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 收货扫描记录表arrival_scan_records设计与实现计划
## 一、背景分析
当前 `ArrivalHandoverFormController``/api/arrival-handover/receipt-query` 接口([ArrivalHandoverFormController.cs:L447-L495](file:///d:/EPproject/LabelReplaceServer/src/CONTROLLER/Controllers/ArrivalHandoverFormController.cs#L447-L495))用于 PDA 收货扫描查询。
`ArrivalHandoverFormService.GetReceiptInfoAsync` 方法([ArrivalHandoverFormService.cs:L181-L281](file:///d:/EPproject/LabelReplaceServer/src/BLL/Services/ArrivalHandoverFormService.cs#L181-L281))的核心逻辑:
- 接收 `arrivalNumber`(大箱号或提单号)
-`label_replace_requests` 表中按 `BillOfLadingNumber``MasterPackageNumber` 匹配
- 返回 `(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 / MasterPackageNumber**`GetReceiptInfoAsync` 返回值中获取
4. **CreatedAt** 即为 PDA 收货扫描时间
5. 遵循项目现有的命名规范和注解风格PascalCase 属性名 + `[SugarColumn]` 注解)
---
## 三、实现步骤
### 步骤 1创建 SQL 建表脚本
**文件**`src/DB/Scripts/CreateArrivalScanRecordTable.sql`
参考 [CreateLabelReplaceTable.sql](file:///d:/EPproject/LabelReplaceServer/src/DB/Scripts/CreateLabelReplaceTable.sql) 的格式:
- InnoDB 引擎
- utf8mb4 字符集
- 包含中文注释
- 创建必要索引
### 步骤 2创建 Entity 实体类
**文件**`src/MDL/Models/ArrivalScanRecordEntity.cs`
参考 [LabelScanEntity.cs](file:///d:/EPproject/LabelReplaceServer/src/MDL/Models/LabelScanEntity.cs) 和 [LabelReplaceEntity.cs](file:///d:/EPproject/LabelReplaceServer/src/MDL/Models/LabelReplaceEntity.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](file:///d:/EPproject/LabelReplaceServer/src/DAL/repositories/CustomerRepository.cs) 的模式:
- 通过 `ISqlSugarProvider` 操作数据库
- 至少需要 `InsertAsync` 方法
### 步骤 4修改 ArrivalHandoverFormService
**文件**`src/BLL/Services/ArrivalHandoverFormService.cs`
`GetReceiptInfoAsync` 方法中,查询完成后插入一条扫描记录到 `arrival_scan_records` 表:
```csharp
// 在 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();
```
**关键点**
- `CustomerId``label_replace_entities` 的第一个匹配记录中获取(冗余存储)
- 插入操作应在 try-catch 内部,且不应影响主流程(即使插入失败也不应阻止接口正常返回)
- 建议用独立的 try-catch 包裹插入逻辑,避免扫描记录入库失败导致接口报错
### 步骤 5注册依赖注入
**文件**`src/CONTROLLER/Program.cs`(或对应的 DI 注册文件)
- 注册 `IArrivalScanRecordRepository``ArrivalScanRecordRepository`
-`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. **错误处理策略**:扫描记录插入失败时,是静默忽略(不影响接口返回)还是抛出异常?建议静默忽略,确保核心业务不受影响。