All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m33s
主要改动: - 新增交互式环境配置脚本 (scripts/setup-env.sh) - 新增本地启动快捷脚本 (scripts/run-local.sh) - 新增环境变量模板文件 (.env.example) - 部署模式改版:使用嵌入式配置 + 环境变量覆盖 - 添加对象存储功能支持 - 改进 IoT 卡片导入任务 - 优化 OpenAPI 文档生成 - 删除旧的配置文件,改用嵌入式默认配置
8.1 KiB
8.1 KiB
iot-card-import-task Specification
Purpose
TBD - created by archiving change iot-card-standalone-management. Update Purpose after archive.
Requirements
Requirement: 导入任务实体定义
系统 SHALL 定义 IoT 卡导入任务(IotCardImportTask)实体,用于跟踪 IoT 卡批量导入的进度和结果。
实体字段:
任务信息:
id: 任务 ID(主键,BIGINT)task_no: 任务编号(VARCHAR(50),唯一,格式: IMP-YYYYMMDD-XXXXXX)status: 任务状态(INT,1-待处理 2-处理中 3-已完成 4-失败)
导入参数:
carrier_id: 运营商 ID(BIGINT,必填)carrier_type: 运营商类型(VARCHAR(10),CMCC/CUCC/CTCC/CBN)batch_no: 批次号(VARCHAR(100),可选)file_name: 原始文件名(VARCHAR(255),可选)
待导入数据:
card_list: 待导入卡列表(JSONB,结构: [{iccid, msisdn}],替代原 iccid_list)
进度统计:
total_count: 总数(INT,CSV 文件总行数)success_count: 成功数(INT,成功导入的卡数量)skip_count: 跳过数(INT,因重复等原因跳过的数量)fail_count: 失败数(INT,因格式错误等原因失败的数量)
结果详情:
skipped_items: 跳过记录详情(JSONB,结构: [{line, iccid, msisdn, reason}])failed_items: 失败记录详情(JSONB,结构: [{line, iccid, msisdn, reason}])
时间和错误:
started_at: 开始处理时间(TIMESTAMP,可空)completed_at: 完成时间(TIMESTAMP,可空)error_message: 任务级错误信息(TEXT,可空,如文件解析失败等)
系统字段:
shop_id: 店铺 ID(BIGINT,可空,记录发起导入的店铺)created_at: 创建时间(TIMESTAMP,自动填充)updated_at: 更新时间(TIMESTAMP,自动填充)creator: 创建人 ID(BIGINT)updater: 更新人 ID(BIGINT)
Scenario: 创建导入任务
- GIVEN 管理员上传包含 ICCID 和 MSISDN 两列的 CSV 文件
- WHEN 系统解析 CSV 并创建导入任务
- THEN 系统创建导入任务记录,
card_list包含 [{iccid, msisdn}] 结构,status为 1(待处理)
Requirement: 导入任务状态流转
系统 SHALL 管理导入任务的状态流转,确保状态变更符合业务规则。
状态定义:
- 1-待处理: 任务已创建,等待 Worker 处理
- 2-处理中: Worker 正在处理导入
- 3-已完成: 导入处理完成(可能有部分失败)
- 4-失败: 任务级别错误,导入中断
状态流转规则:
- 待处理(1) → 处理中(2): Worker 开始处理
- 处理中(2) → 已完成(3): 处理完成
- 处理中(2) → 失败(4): 发生严重错误
- 待处理(1) → 失败(4): 文件验证失败等
Scenario: 正常状态流转
- WHEN 导入任务经历完整生命周期
- THEN 状态依次变更: 待处理(1) → 处理中(2) → 已完成(3)
Scenario: 异常状态流转
- WHEN 导入任务处理过程中发生严重错误
- THEN 状态变更: 待处理(1) → 处理中(2) → 失败(4)
Requirement: 导入任务列表查询
系统 SHALL 支持查询导入任务列表,用于管理和监控导入任务。
查询条件:
- 任务状态(status): 可选,1-待处理 2-处理中 3-已完成 4-失败
- 运营商 ID(carrier_id): 可选
- 批次号(batch_no): 可选,模糊匹配
- 创建时间范围: 可选
分页:
- 默认每页 20 条,最大每页 100 条
- 默认按创建时间倒序排列
数据权限:
- 基于 shop_id 自动应用数据权限过滤
- 代理只能看到自己店铺及下级店铺发起的导入任务
Scenario: 查询所有导入任务
- WHEN 管理员查询导入任务列表
- THEN 系统返回导入任务列表,包含任务编号、状态、运营商、总数、成功数、跳过数、失败数、创建时间
Scenario: 按状态筛选导入任务
- WHEN 管理员查询状态为 2(处理中) 的导入任务
- THEN 系统返回所有正在处理的导入任务列表
Requirement: 导入任务详情查询
系统 SHALL 支持查询单个导入任务的详细信息,包括跳过/失败记录详情。
详情信息:
- 任务基本信息: 任务编号、状态、运营商、批次号、文件名
- 进度统计: 总数、成功数、跳过数、失败数
- 时间信息: 创建时间、开始时间、完成时间
- 跳过记录详情: 行号、ICCID、原因
- 失败记录详情: 行号、ICCID、原因
- 错误信息: 任务级错误(如有)
Scenario: 查询导入任务详情
- WHEN 管理员查询导入任务(ID 为 1)的详情
- THEN 系统返回任务完整信息,包括跳过和失败记录的详细列表
Scenario: 查询导入任务的跳过记录
- WHEN 管理员查询导入任务(ID 为 1)的跳过记录
- THEN 系统返回跳过记录列表,每条包含: 行号(line)、ICCID、原因(如"ICCID 已存在")
Scenario: 查询导入任务的失败记录
- WHEN 管理员查询导入任务(ID 为 1)的失败记录
- THEN 系统返回失败记录列表,每条包含: 行号(line)、ICCID、原因(如"电信 ICCID 必须为 19 位")
Requirement: 导入任务数据校验
系统 SHALL 对导入任务数据进行校验,确保数据完整性和一致性。
校验规则:
- 任务编号(task_no): 必填,系统自动生成,格式 IMP-YYYYMMDD-XXXXXX,唯一
- 任务状态(status): 必填,枚举值 1(待处理) | 2(处理中) | 3(已完成) | 4(失败)
- 运营商 ID(carrier_id): 必填,必须是有效的运营商 ID
- 总数(total_count): 必填,≥ 0
- 成功数(success_count): 必填,≥ 0,≤ total_count
- 跳过数(skip_count): 必填,≥ 0,≤ total_count
- 失败数(fail_count): 必填,≥ 0,≤ total_count
- 数量一致性: success_count + skip_count + fail_count ≤ total_count
Scenario: 创建任务时运营商 ID 无效
- WHEN 创建导入任务时 carrier_id 不存在
- THEN 系统拒绝创建,返回错误信息"运营商 ID 无效"
Scenario: 更新任务时数量不一致
- WHEN 更新导入任务时 success_count + skip_count + fail_count > total_count
- THEN 系统拒绝更新,返回错误信息"统计数量不一致"
Requirement: CSV 文件格式规范
系统 SHALL 要求 CSV 文件必须包含 ICCID 和 MSISDN 两列。
文件格式要求:
- 第一列: ICCID(必填,不能为空)
- 第二列: MSISDN/接入号(必填,不能为空)
- 支持表头行(自动识别并跳过)
- 表头识别关键字: iccid/卡号 + msisdn/接入号/手机号
解析规则:
- 自动去除首尾空格
- 跳过空行
- 第一行为表头时自动跳过
- 列数不足 2 列的文件拒绝导入
- ICCID 为空的行记录为失败
- MSISDN 为空的行记录为失败
Scenario: 解析标准双列 CSV 文件
- GIVEN CSV 文件内容为:
iccid,msisdn 89860012345678901234,13800000001 89860012345678901235,13800000002 - WHEN 系统解析该 CSV 文件
- THEN 解析结果包含 2 条有效记录,每条包含 ICCID 和 MSISDN
Scenario: 拒绝单列 CSV 文件
- GIVEN CSV 文件内容仅包含 ICCID 单列
- WHEN 系统尝试解析该 CSV 文件
- THEN 系统返回错误 "CSV 文件格式错误:缺少 MSISDN 列"
Scenario: MSISDN 为空的行记录失败
- GIVEN CSV 文件内容为:
iccid,msisdn 89860012345678901234,13800000001 89860012345678901235, - WHEN 系统解析该 CSV 文件
- THEN 第一条记录解析成功,第二条记录标记为失败,原因为 "MSISDN 不能为空"
Scenario: ICCID 为空的行记录失败
- GIVEN CSV 文件内容为:
iccid,msisdn 89860012345678901234,13800000001 ,13800000002 - WHEN 系统解析该 CSV 文件
- THEN 第一条记录解析成功,第二条记录标记为失败,原因为 "ICCID 不能为空"
Requirement: 导入时填充 MSISDN 字段
系统 SHALL 在创建 IoT 卡记录时填充 MSISDN 字段。
处理规则:
- 从
card_list中获取 ICCID 和 MSISDN - 创建
IotCard记录时同时设置iccid和msisdn字段
Scenario: 创建卡记录时填充 MSISDN
- GIVEN 导入任务包含卡数据 [{iccid: "898600...", msisdn: "13800000001"}]
- WHEN Worker 处理导入任务创建卡记录
- THEN 创建的
IotCard记录iccid为 "898600...",msisdn为 "13800000001"