All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 4m39s
5.8 KiB
5.8 KiB
MODIFIED Requirements
Requirement: 支持未实名状态购买套餐
系统 SHALL 允许后台管理端为未实名的载体(设备/卡)购买套餐,套餐状态为"待生效"(status=0)。对于 expiry_base=from_activation 的套餐,系统 SHALL 在创建 PackageUsage 时检查载体当前实名状态:若已实名则直接激活;若未实名则标记 pending_realname_activation=true 等待实名触发。
实名状态判定规则:
iot_card载体:查询该卡的real_name_status字段device载体:通过tb_device_sim_binding(bind_status=1)查询是否存在任意已实名(real_name_status=1)的绑定卡;存在任意一张即视为设备已实名
Scenario: 后台为未实名设备购买 from_activation 套餐——待生效
- GIVEN 设备 ID=2,绑定的所有卡
real_name_status=0(均未实名) - AND 套餐
expiry_base=from_activation,购买者为代理商(非 C 端) - WHEN 管理员通过后台为该设备购买套餐
- THEN 系统创建 PackageUsage:
status=0,pending_realname_activation=true,activated_at=NULL,expires_at=NULL
Scenario: 后台为已有实名卡的设备购买 from_activation 套餐——直接激活并触发复机
- GIVEN 设备 ID=2,至少一张绑定卡
real_name_status=1(已实名),且设备下有卡因无套餐停机(stop_reason=no_package) - AND 套餐
expiry_base=from_activation,购买者为代理商(非 C 端) - WHEN 管理员通过后台为该设备购买套餐
- THEN 系统创建 PackageUsage:
status=1,pending_realname_activation=false,activated_at=购买时间,expires_at按套餐配置计算 - AND
tryResumeAfterPayment检测到activatedCount=1,异步调用ResumeCardIfStopped("device", 2) - AND 设备下已实名且因
no_package停机的卡自动开机
Scenario: 后台为已实名单卡购买 from_activation 套餐——直接激活
- GIVEN IoT 卡 ID=10,
real_name_status=1(已实名) - AND 套餐
expiry_base=from_activation,购买者为代理商(非 C 端) - WHEN 管理员通过后台为该卡购买套餐
- THEN 系统创建 PackageUsage:
status=1,pending_realname_activation=false,activated_at=购买时间,expires_at按套餐配置计算
Scenario: 后台为未实名单卡购买 from_activation 套餐——待生效
- GIVEN IoT 卡 ID=10,
real_name_status=0(未实名) - AND 套餐
expiry_base=from_activation,购买者为代理商(非 C 端) - WHEN 管理员通过后台为该卡购买套餐
- THEN 系统创建 PackageUsage:
status=0,pending_realname_activation=true,activated_at=NULL,expires_at=NULL
Scenario: from_purchase 套餐不检查实名状态——始终直接激活
- GIVEN 设备 ID=2,所有绑定卡均未实名(
real_name_status=0) - AND 套餐
expiry_base=from_purchase - WHEN 管理员通过后台为该设备购买套餐
- THEN 系统创建 PackageUsage:
status=1,pending_realname_activation=false,立即生效
Scenario: 客户端购买套餐——必须先实名(不受本次变更影响)
- GIVEN 设备 ID=2,购买者为个人客户(C 端)
- WHEN 客户通过 H5/小程序购买套餐
- THEN 系统前置检查已实名,行为不变
ADDED Requirements
Requirement: 卡首次实名时同时触发所属设备的设备级套餐激活
当轮询系统检测到某张 IoT 卡的实名状态从 0 变为 1(首次实名),系统 SHALL 除提交该卡的 TaskTypePackageFirstActivation 任务外,额外查询该卡是否属于某个设备(通过 tb_device_sim_binding),若存在有效绑定则同时提交以该设备为载体(carrier_type=device)的 TaskTypePackageFirstActivation 任务。
设计约束:
- 若卡未绑定任何设备(
GetActiveBindingByCardID返回ErrRecordNotFound)则静默跳过,不报错 - 提交任务失败记录 Warn 日志,不阻塞卡级激活流程
- 任务幂等:
ActivateByRealname(ctx, "device", deviceID)若查不到pending_realname_activation=true的套餐则直接返回 nil
Scenario: 设备下某张卡首次实名——同时触发设备级套餐激活与复机
- GIVEN IoT 卡 ID=4,绑定于设备 ID=2(
tb_device_sim_binding中存在有效绑定) - AND 设备 ID=2 存在
status=0, pending_realname_activation=true的设备级 PackageUsage - AND 设备下有卡因
not_realname停机(stop_reason=not_realname) - WHEN 轮询系统检测到卡 ID=4 实名状态 0→1
- THEN 系统提交两个 Asynq 任务:
carrier_type=iot_card, carrier_id=4(卡级激活)carrier_type=device, carrier_id=2(设备级激活)
- AND 设备级 PackageUsage 最终
status=1, pending_realname_activation=false, activated_at已设置 - AND
ActivateByRealname激活成功后异步调用ResumeCardIfStopped("device", 2),设备下已实名的停机卡自动开机
Scenario: 独立卡(未绑定设备)首次实名——仅触发卡级激活
- GIVEN IoT 卡 ID=10,未绑定任何设备(
tb_device_sim_binding中无有效记录) - WHEN 轮询系统检测到卡 ID=10 实名状态 0→1
- THEN 系统仅提交卡级 Asynq 任务(
carrier_type=iot_card, carrier_id=10) - AND 不报错,不记录 Error 日志
Scenario: 设备下某张卡实名但设备无待激活套餐——任务执行幂等返回
- GIVEN IoT 卡 ID=4,绑定于设备 ID=2
- AND 设备 ID=2 无
pending_realname_activation=true的套餐 - WHEN 轮询系统检测到卡 ID=4 实名状态 0→1,并提交设备级激活任务
- THEN 任务 Worker 执行
ActivateByRealname(ctx, "device", 2),查询结果为空,直接返回 nil(无错误)