1、调整凭证
2、调整运单
This commit is contained in:
+305
@@ -0,0 +1,305 @@
|
||||
# 运输计划导入增强校验说明
|
||||
|
||||
## 修改日期
|
||||
2026-09-08
|
||||
|
||||
## 一、导入逻辑变更
|
||||
|
||||
### 原有逻辑
|
||||
- 逐条导入,遇错即停
|
||||
- 部分数据可能已入库
|
||||
- 错误信息简单
|
||||
|
||||
### 新逻辑(参考 /base/port-terminal)
|
||||
1. **第一阶段:全部校验**
|
||||
- 先校验所有数据
|
||||
- 收集所有错误信息
|
||||
- 不进行任何数据库操作
|
||||
|
||||
2. **第二阶段:批量导入**
|
||||
- 仅当所有数据校验通过后才导入
|
||||
- 任何一条数据有错误,全部回滚
|
||||
- 保证数据一致性
|
||||
|
||||
3. **错误处理**
|
||||
- 导出包含错误信息的Excel
|
||||
- 每条错误数据标注具体错误原因
|
||||
- 支持多个错误信息(编号列表)
|
||||
|
||||
## 二、详细校验规则
|
||||
|
||||
### 1. 必填字段校验
|
||||
|
||||
| 字段 | 校验规则 | 错误提示 |
|
||||
|------|---------|---------|
|
||||
| *计划名称 | 不能为空 | 计划名称不能为空 |
|
||||
| *运输类型 | 不能为空 | 运输类型不能为空 |
|
||||
| *发货地址 | 不能为空 | 发货地址不能为空 |
|
||||
| *到货地址 | 不能为空 | 到货地址不能为空 |
|
||||
| *货物类型 | 不能为空 | 货物类型不能为空 |
|
||||
|
||||
### 2. 枚举值校验
|
||||
|
||||
#### 运输类型
|
||||
**允许值:**
|
||||
- 公路整车
|
||||
- 公路配载/零担
|
||||
- 铁路运输
|
||||
- 水路运输
|
||||
- 跨境海运
|
||||
- 航空运输
|
||||
|
||||
**错误提示:** 运输类型需系统枚举值(公路整车、公路配载/零担、铁路运输、水路运输、跨境海运、航空运输)
|
||||
|
||||
#### 计量单位
|
||||
**常用值:**
|
||||
- 吨、千克、立方米、件、车、箱、托盘、个、套、台
|
||||
|
||||
**错误提示:** 计量单位不存在
|
||||
|
||||
### 3. 唯一性校验
|
||||
|
||||
#### 计划名称(当前组织下不重复)
|
||||
- 检查本次导入数据中的重复
|
||||
- 检查数据库中当前组织的重复
|
||||
- **错误提示:**
|
||||
- 计划名称在导入数据中重复
|
||||
- 计划名称在当前组织下已存在
|
||||
|
||||
### 4. 格式校验
|
||||
|
||||
#### 联系电话
|
||||
**规则:** 11位数字
|
||||
- 发货联系人电话
|
||||
- 收货联系人电话
|
||||
|
||||
**错误提示:**
|
||||
- 发货联系人电话格式不正确(需11位数字)
|
||||
- 收货联系人电话格式不正确(需11位数字)
|
||||
|
||||
#### 日期时间
|
||||
**格式:** YYYY-MM-DD
|
||||
- 计划开始时间(非必填)
|
||||
- 计划结束时间(非必填)
|
||||
|
||||
**逻辑校验:** 计划结束时间不得早于计划开始时间
|
||||
|
||||
**错误提示:**
|
||||
- 计划开始时间格式必须为 YYYY-MM-DD
|
||||
- 计划结束时间格式必须为 YYYY-MM-DD
|
||||
- 计划结束时间不得早于计划开始时间
|
||||
|
||||
### 5. 数值校验
|
||||
|
||||
#### 数量
|
||||
**规则:** 必须为正数或零
|
||||
**错误提示:** 数量必须为正数
|
||||
|
||||
#### 里程(km)
|
||||
**规则:** 必须为正数或零
|
||||
**错误提示:** 里程必须为正数
|
||||
|
||||
### 6. 长度校验
|
||||
|
||||
| 字段 | 最大长度 | 错误提示 |
|
||||
|------|---------|---------|
|
||||
| 计划名称 | 255字符 | 计划名称不能超过255个字符 |
|
||||
| 发货地址 | 255字符 | 发货地址不能超过255个字符 |
|
||||
| 到货地址 | 255字符 | 到货地址不能超过255个字符 |
|
||||
| 发货联系人 | 255字符 | 发货联系人不能超过255个字符 |
|
||||
| 收货联系人 | 255字符 | 收货联系人不能超过255个字符 |
|
||||
| 同一计划标识号 | 255字符 | 同一计划标识号不能超过255个字符 |
|
||||
| 备注 | 500字符 | 备注不能超过500个字符 |
|
||||
|
||||
### 7. 同一计划标识号校验
|
||||
|
||||
**用途:** 当需要导入的计划的货物包含多个时,需拆分多行,并填写该标识,来标记多行为同一计划
|
||||
|
||||
**校验规则:**
|
||||
- 同一标识号下的所有记录应保持以下字段一致:
|
||||
- 计划名称
|
||||
- 运输类型
|
||||
- 发货地址
|
||||
- 到货地址
|
||||
|
||||
**警告提示:** 注意:同一计划标识号应保持计划名称、运输类型、发货地址、到货地址一致
|
||||
|
||||
### 8. 地址匹配校验(警告级别)
|
||||
|
||||
**规则:** 地址应能匹配到系统地址库
|
||||
|
||||
**警告提示:**
|
||||
- 警告:发货地址未匹配到地址库,轨迹回放将受影响
|
||||
- 警告:到货地址未匹配到地址库,轨迹回放将受影响
|
||||
|
||||
**说明:** 此为警告级别,不阻止导入,但会影响后续功能
|
||||
|
||||
## 三、错误信息格式
|
||||
|
||||
### 单条错误
|
||||
```
|
||||
1. 计划名称不能为空
|
||||
```
|
||||
|
||||
### 多条错误
|
||||
```
|
||||
1. 计划名称不能为空
|
||||
2. 运输类型需系统枚举值(公路整车、公路配载/零担、铁路运输、水路运输、跨境海运、航空运输)
|
||||
3. 发货联系人电话格式不正确(需11位数字)
|
||||
```
|
||||
|
||||
## 四、导入流程
|
||||
|
||||
### 用户操作流程
|
||||
1. 下载导入模板
|
||||
2. 填写计划数据
|
||||
3. 上传Excel文件
|
||||
4. 等待校验结果
|
||||
|
||||
### 系统处理流程
|
||||
|
||||
#### 情况1:所有数据校验通过
|
||||
```
|
||||
解析Excel → 全部校验(通过) → 批量导入 → 提示成功
|
||||
```
|
||||
|
||||
#### 情况2:存在校验错误
|
||||
```
|
||||
解析Excel → 全部校验(失败) → 生成错误Excel → 下载错误明细
|
||||
```
|
||||
- 不会导入任何数据
|
||||
- 用户下载包含错误信息的Excel
|
||||
- 修正后重新导入
|
||||
|
||||
## 五、后端实现要点
|
||||
|
||||
### 1. 两阶段提交
|
||||
```java
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public List<TransportPlanImportExcel> importTransportPlan(...) {
|
||||
// 第一阶段:全部校验
|
||||
Map<Integer, TransportPlanImportExcel> errorMap = new TreeMap<>();
|
||||
for (int index = 0; index < data.size(); index++) {
|
||||
List<String> errors = validateImportExcel(excel, ...);
|
||||
if (Func.isNotEmpty(errors)) {
|
||||
excel.setErrorMessage(formatErrorMessage(errors));
|
||||
errorMap.put(index, excel);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果有错误,回滚事务
|
||||
if (Func.isNotEmpty(errorMap)) {
|
||||
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
||||
return new ArrayList<>(errorMap.values());
|
||||
}
|
||||
|
||||
// 第二阶段:批量导入
|
||||
for (TransportPlan plan : importPlans) {
|
||||
save(plan);
|
||||
}
|
||||
|
||||
return new ArrayList<>();
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 错误收集器
|
||||
- 使用 `TreeMap` 保持顺序
|
||||
- 索引作为key,保持与Excel行号对应
|
||||
- 错误信息格式化为编号列表
|
||||
|
||||
### 3. 校验方法
|
||||
```java
|
||||
private List<String> validateImportExcel(...) {
|
||||
List<String> errors = new ArrayList<>();
|
||||
// 收集所有错误,不立即抛出异常
|
||||
if (condition) {
|
||||
errors.add("错误信息");
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
```
|
||||
|
||||
## 六、前端修改(transport-plan-import.vue)
|
||||
|
||||
### 无需修改
|
||||
前端保持原有逻辑,后端返回的错误Excel会自动触发下载
|
||||
|
||||
## 七、测试用例
|
||||
|
||||
### 测试用例1:必填字段缺失
|
||||
**输入:** 计划名称为空
|
||||
**预期:**
|
||||
- 不导入任何数据
|
||||
- 错误信息:计划名称不能为空
|
||||
|
||||
### 测试用例2:运输类型枚举值错误
|
||||
**输入:** 运输类型 = "陆运"
|
||||
**预期:**
|
||||
- 不导入任何数据
|
||||
- 错误信息:运输类型需系统枚举值
|
||||
|
||||
### 测试用例3:电话格式错误
|
||||
**输入:** 发货联系人电话 = "12345"
|
||||
**预期:**
|
||||
- 不导入任何数据
|
||||
- 错误信息:发货联系人电话格式不正确(需11位数字)
|
||||
|
||||
### 测试用例4:计划名称重复
|
||||
**输入:** 两条数据的计划名称相同
|
||||
**预期:**
|
||||
- 不导入任何数据
|
||||
- 错误信息:计划名称在导入数据中重复
|
||||
|
||||
### 测试用例5:部分数据错误
|
||||
**输入:** 10条数据,第5条有错误
|
||||
**预期:**
|
||||
- 不导入任何数据(包括前4条正确的)
|
||||
- 仅第5条有错误信息
|
||||
|
||||
### 测试用例6:多个错误
|
||||
**输入:** 一条数据同时缺少计划名称和运输类型
|
||||
**预期:**
|
||||
```
|
||||
1. 计划名称不能为空
|
||||
2. 运输类型不能为空
|
||||
```
|
||||
|
||||
### 测试用例7:同一计划标识号
|
||||
**输入:** 3条数据,同一标识号,货物信息不同
|
||||
**预期:**
|
||||
- 可以导入
|
||||
- 3条记录关联到同一计划标识号
|
||||
|
||||
## 八、与 port-terminal 导入的对比
|
||||
|
||||
| 特性 | port-terminal | transport-plan |
|
||||
|------|---------------|----------------|
|
||||
| 两阶段校验 | ✓ | ✓ |
|
||||
| 错误即回滚 | ✓ | ✓ |
|
||||
| 错误信息编号 | ✓ | ✓ |
|
||||
| 唯一性校验 | ✓ | ✓ |
|
||||
| 枚举值校验 | ✓ | ✓ |
|
||||
| 格式校验 | ✓ | ✓ |
|
||||
| 批量导入 | ✓ | ✓ |
|
||||
|
||||
## 九、后续优化建议
|
||||
|
||||
1. **地址匹配校验**
|
||||
- 实现发货地址和到货地址的地址库匹配
|
||||
- 返回警告信息(不阻止导入)
|
||||
|
||||
2. **货物类型智能匹配**
|
||||
- 根据货物名称自动匹配货物类型
|
||||
- 未匹配到时归为"其他"类
|
||||
|
||||
3. **同一计划标识号一致性校验**
|
||||
- 完整实现同一标识号的字段一致性检查
|
||||
- 在第一阶段校验中完成
|
||||
|
||||
4. **计量单位字典化**
|
||||
- 从数据字典读取有效的计量单位列表
|
||||
- 支持自定义扩展
|
||||
|
||||
5. **导入预览**
|
||||
- 前端增加导入预览功能
|
||||
- 用户可在导入前查看解析结果
|
||||
Reference in New Issue
Block a user