docs: 归档 excel-import-refactor,同步更新主 specs
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 50s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 50s
- 将变更目录移至 archive/2026-04-09-excel-import-refactor - device-import spec:更新为固定列位置读取(IMEI 调整至第5列),新增 MaxSimSlots 范围校验说明 - iot-card-import-task spec:更新为固定列位置读取,新增"导入批次支持卡业务类型"需求 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -192,73 +192,56 @@ TBD - created by archiving change iot-card-standalone-management. Update Purpose
|
||||
|
||||
### Requirement: Excel 文件格式规范
|
||||
|
||||
系统 SHALL 要求 Excel 文件必须包含 ICCID 和 MSISDN 两列,并支持可选的 `virtual_no` 列。
|
||||
系统 SHALL 要求 Excel 文件必须包含 ICCID、MSISDN、虚拟号三列,按固定列位置读取,表头行内容不影响解析结果。
|
||||
|
||||
**文件格式要求**:
|
||||
- **文件格式**: 仅支持 `.xlsx` (Excel 2007+)
|
||||
- **Sheet**: 读取第一个sheet,或优先读取名为"导入数据"的sheet
|
||||
- **表头行**: 第1行(可选,但建议包含)
|
||||
- **表头识别关键字**:
|
||||
- ICCID 列: iccid/ICCID/卡号/号码
|
||||
- MSISDN 列: msisdn/MSISDN/接入号/手机号/电话/号码
|
||||
- virtual_no 列(**必填**): virtual_no/VirtualNo/虚拟号/设备号
|
||||
- **列数要求**: 至少 3 列(ICCID、MSISDN、virtual_no),virtual_no 为必填列
|
||||
- **表头行**: 第1行固定为表头,永远跳过,内容不限(中文、英文均可)
|
||||
- **列位置(固定,不可变)**:
|
||||
- 第1列(索引0): ICCID
|
||||
- 第2列(索引1): MSISDN
|
||||
- 第3列(索引2): 虚拟号(必填)
|
||||
- **列格式**: 应设置为文本格式(避免长数字被转为科学记数法)
|
||||
|
||||
**解析规则**:
|
||||
- 自动检测表头(第1行包含识别关键字则跳过)
|
||||
- 按列索引取值,不识别列名,第一行永远跳过
|
||||
- 自动去除单元格首尾空格
|
||||
- 跳过空行
|
||||
- ICCID 为空的行记录为失败
|
||||
- MSISDN 为空的行记录为失败
|
||||
- virtual_no 为空的行:**[BREAKING]** 记录为失败行,失败原因为"虚拟号(virtual_no)不能为空"(原行为为跳过该列)
|
||||
- Excel 中不包含 virtual_no 列时:所有数据行均因 VirtualNo 为空而失败,返回错误提示"Excel 文件缺少 virtual_no 列,请使用最新模板"
|
||||
- 若 ICCID、MSISDN、virtual_no 三列皆为空,视为空行跳过,不计入 total,不计入失败
|
||||
- ICCID 为空(但其他列非空)的行记录为失败,失败原因为"ICCID 不能为空"
|
||||
- MSISDN 为空(但其他列非空)的行记录为失败,失败原因为"MSISDN 不能为空"
|
||||
- virtual_no(第3列)为空的行记录为失败,失败原因为"虚拟号(virtual_no)不能为空"
|
||||
|
||||
**virtual_no 导入规则**:
|
||||
- virtual_no 为必填列,为空则该行记录为失败
|
||||
- virtual_no 为必填,为空则该行记录为失败
|
||||
- virtual_no 全局唯一(跨卡和设备),重复则失败,原因为"虚拟号已被占用: <值>"
|
||||
- **批次级唯一性检查**:在执行导入前,先检查整批中所有 virtual_no 是否与数据库现存值重复;有任意冲突则**整批失败**,响应中返回冲突的 virtual_no 及行号列表
|
||||
|
||||
**示例 Excel 内容**:
|
||||
```
|
||||
| ICCID | MSISDN | 虚拟号 |
|
||||
|----------------------|-------------|-----------|
|
||||
| 89860012345678901234 | 13800000001 | CARD-001 |
|
||||
| 89860012345678901235 | 13800000002 | |
|
||||
```
|
||||
|
||||
#### Scenario: 正常导入(ICCID 和 VirtualNo 均有值)
|
||||
|
||||
- **WHEN** Excel 中某行 ICCID="898600XXXXX",virtual_no="CARD-001",msisdn="13800000001"
|
||||
- **WHEN** Excel 中某行第1列 ICCID="898600XXXXX",第3列 virtual_no="CARD-001",第2列 msisdn="13800000001"
|
||||
- **THEN** 导入成功,卡记录写入数据库,VirtualNo 和 ICCID 同步注册到 `tb_asset_identifier`
|
||||
|
||||
#### Scenario: 中文表头正常导入
|
||||
|
||||
- **GIVEN** Excel 文件第1行表头为 `ICCID | 接入号 | 虚拟号`(任意中文或英文内容)
|
||||
- **WHEN** 系统解析该 Excel 文件
|
||||
- **THEN** 系统跳过第1行,从第2行开始按列位置解析数据
|
||||
|
||||
#### Scenario: VirtualNo 为空的行被拒绝
|
||||
|
||||
- **WHEN** Excel 中某行 ICCID="898600YYYYY",virtual_no 列为空或未填写
|
||||
- **WHEN** Excel 中某行第3列为空
|
||||
- **THEN** 该行计入失败,失败原因为"虚拟号(virtual_no)不能为空"
|
||||
- **THEN** 其他合法行继续导入,不因此行中断
|
||||
|
||||
#### Scenario: VirtualNo 重复被拒绝
|
||||
|
||||
- **WHEN** Excel 中某行的 virtual_no 与已有卡/设备的 VirtualNo 重复(跨表)
|
||||
- **WHEN** Excel 中某行第3列的值与已有卡/设备的 VirtualNo 重复(跨表)
|
||||
- **THEN** 该行计入失败,原因为"虚拟号已被占用: <值>"
|
||||
|
||||
#### Scenario: Excel 文件中无 VirtualNo 列
|
||||
#### Scenario: 三列皆空时跳过不计入 total
|
||||
|
||||
- **WHEN** Excel 表头中不包含 `virtual_no`/`虚拟号`/`设备号` 等可识别列名
|
||||
- **THEN** 所有数据行均因 VirtualNo 为空而失败,导入结果中 `fail_count = 总行数`,`success_count = 0`
|
||||
- **THEN** 返回错误提示:"Excel 文件缺少 virtual_no 列,请使用最新模板"
|
||||
|
||||
#### Scenario: 批次中有 virtual_no 与现存数据重复
|
||||
|
||||
- **WHEN** Excel 中某行 virtual_no = "CARD-001",但数据库中另一张卡已有 virtual_no = "CARD-001"
|
||||
- **THEN** 系统拒绝整批导入,响应返回冲突的 virtual_no 值和行号,提示"虚拟号重复,整批导入已终止"
|
||||
|
||||
#### Scenario: 支持中文表头
|
||||
|
||||
- **GIVEN** Excel 文件表头为 `卡号 | 接入号 | 虚拟号`
|
||||
- **WHEN** 系统解析该 Excel 文件
|
||||
- **THEN** 系统正确识别三列,按规则处理 virtual_no
|
||||
- **WHEN** Excel 中某行 ICCID、MSISDN、virtual_no 三列均为空
|
||||
- **THEN** 该行视为空行跳过,不计入 total,不计入失败
|
||||
|
||||
#### Scenario: 导入任务完成后的结果报告
|
||||
|
||||
@@ -274,13 +257,12 @@ TBD - created by archiving change iot-card-standalone-management. Update Purpose
|
||||
|
||||
#### Scenario: MSISDN 为空的行记录失败
|
||||
|
||||
- **GIVEN** Excel 文件第二行 MSISDN 为空
|
||||
- **WHEN** 系统解析该 Excel 文件
|
||||
- **THEN** 第一条记录解析成功,第二条记录标记为失败,原因为"MSISDN 不能为空"
|
||||
- **WHEN** Excel 中某行第2列为空
|
||||
- **THEN** 该行标记为失败,原因为"MSISDN 不能为空"
|
||||
|
||||
#### Scenario: 长数字无损解析
|
||||
|
||||
- **GIVEN** Excel 文件中 ICCID 列设置为文本格式,包含 20 位数字 "89860012345678901234"
|
||||
- **GIVEN** Excel 文件中第1列设置为文本格式,包含 20 位数字 "89860012345678901234"
|
||||
- **WHEN** 系统解析该 Excel 文件
|
||||
- **THEN** ICCID 完整保留为 "89860012345678901234",无精度损失,无科学记数法
|
||||
|
||||
@@ -324,3 +306,33 @@ TBD - created by archiving change iot-card-standalone-management. Update Purpose
|
||||
- **WHEN** 管理员创建物联网卡导入任务
|
||||
- **THEN** 系统根据 carrier_id 查询 Carrier 表,将 carrier_name 写入导入任务记录
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 导入批次支持卡业务类型
|
||||
|
||||
系统 SHALL 在 IoT 卡导入请求中支持 `card_category` 参数,以批次为单位指定导入卡的业务类型,默认为普通卡。
|
||||
|
||||
**请求字段**:
|
||||
- `card_category`: 卡业务类型(枚举:`normal` / `industry`,可选,默认 `normal`)
|
||||
|
||||
**任务字段**:
|
||||
- `IotCardImportTask` 新增 `card_category` 字段(VARCHAR(20),默认 `normal`)
|
||||
|
||||
**导入行为**:
|
||||
- 导入任务中所有卡统一使用 `card_category` 的值,不支持同一批次混用
|
||||
|
||||
#### Scenario: 不传 card_category 时默认为普通卡
|
||||
|
||||
- **WHEN** 导入请求未包含 `card_category` 字段
|
||||
- **THEN** 导入的所有卡 `card_category` 为 `normal`
|
||||
|
||||
#### Scenario: 指定行业卡导入
|
||||
|
||||
- **WHEN** 导入请求中 `card_category` = `industry`
|
||||
- **THEN** 该批次导入的所有卡 `card_category` 均为 `industry`
|
||||
|
||||
#### Scenario: 传入无效 card_category
|
||||
|
||||
- **WHEN** 导入请求中 `card_category` = `unknown`(非枚举值)
|
||||
- **THEN** 系统返回参数校验错误,提示卡业务类型无效
|
||||
|
||||
|
||||
Reference in New Issue
Block a user