Status: done # 无虚拟号单卡 C 端完整链路 ## Parent `.scratch/customer-binding-architecture/PRD.md` ## What to build 扩展 `CustomerBinding` 模块,使无虚拟号的独立 IoT 卡(单卡)能够完整走通 C 端业务流程:登录绑定、实名认证、购买套餐。 **仅影响 IoT 卡(单卡)。设备资产必然有虚拟号,不在本切片处理范围内。** ### 扩展 Bind() 当资产为 IoT 卡且 `virtual_no` 为空时: - 写 `tb_personal_customer_iccid`(按 ICCID 绑定),而非 `tb_personal_customer_device` - `PersonalCustomerICCIDStore` 已有完整实现,直接注入使用 当资产为 IoT 卡且 `virtual_no` 不为空时:行为与切片 1 一致,不变。 ### 修复 firstEverBind + markAssetAsSold 当前 `firstEverBind` 通过查 `tb_personal_customer_device WHERE virtual_no = ""` 来判断是否首次绑定,对无虚拟号的卡完全失效(所有无虚拟号的卡共用同一个空 key)。 修复方式:在 `Bind()` 内,按路径分别判断首绑: - 有虚拟号路径:查 `tb_personal_customer_device WHERE virtual_no = ?` - 无虚拟号路径:查 `tb_personal_customer_iccid WHERE iccid = ?` 首次绑定后正常触发 `markAssetAsSold()`,将卡的 `asset_status` 从在库(1)更新为已销售(2)。 ### 扩展 OwnsAsset() 当资产为 IoT 卡时: - 若卡有 `virtual_no`:查 `tb_personal_customer_device`(与切片 1 一致) - 若卡无 `virtual_no`:查 `tb_personal_customer_iccid WHERE iccid = ? AND status = 1` 当资产为设备时:行为不变,只查 `tb_personal_customer_device`。 ## Acceptance criteria - [ ] 无虚拟号的单卡 C 端登录后,`tb_personal_customer_iccid` 中出现对应的绑定记录 - [ ] 无虚拟号单卡首次登录后,`tb_iot_card.asset_status` 变为 2(已销售) - [ ] 无虚拟号单卡登录后,实名认证接口返回成功(不报"无权限") - [ ] 无虚拟号单卡登录后,购买套餐接口归属验证通过 - [ ] 有虚拟号卡的全部行为与切片 1 完成后保持一致(无回归) - [ ] 设备资产的全部行为不受影响 ## Blocked by `.scratch/customer-binding-architecture/issues/01-customer-binding-module-refactor.md`