All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m21s
主要变更: - 新增 AssetIdentifier 模型及 Store,统一管理资产标识符(ICCID/IMEI/SN 等) - 新增迁移:asset_identifier 表、order 表新增 asset_identifier 字段、iot_card.virtual_no NOT NULL 约束 - 资产 Handler/Service/Route 全面重构,支持标识符路由查询与解析 - 新增资产历史订单查询接口,支持跨设备/卡/钱包维度的订单聚合 - 设备与物联卡导入任务强制校验虚拟号,缺失时直接拒绝 - Excel 工具函数优化,前端导入指引文档同步更新 - 归档三个 OpenSpec 提案:asset-identifier-standardization、asset-historical-orders、import-mandatory-virtual-no - 更新 OpenAPI 文档及相关 DTO Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
3.3 KiB
3.3 KiB
MODIFIED Requirements
Requirement: 统一资产解析入口
系统 SHALL 提供统一的资产查找接口,通过任意标识符定位卡或设备,并返回该资产的中等聚合信息。
API 端点: GET /api/admin/assets/resolve/:identifier
查找顺序(更新后):
- 主路径:查
tb_asset_identifierWHERE identifier = ? → 命中则得到 asset_type + asset_id,直接查对应表取完整记录 - Fallback 路径(注册表未命中时):
- 先查
tb_device(匹配virtual_no = ? OR imei = ? OR sn = ?) - 未命中则查
tb_iot_card(匹配virtual_no = ? OR iccid = ? OR msisdn = ?)
- 先查
- 两条路径均未命中 → 返回 HTTP 404
数据权限规则:
- 代理用户:只能查看
shop_id在自己及下级店铺范围内的资产 - 平台用户(SuperAdmin/Platform):可查看所有资产
- 企业账号:暂不支持此接口,调用时返回 HTTP 403
响应结构(AssetResolveResponse):
通用字段(device 和 card 均有):
asset_type: 资产类型("device"或"card")asset_id: 资产主键 IDidentifier: 本次查询所用的标识符(原样回传)virtual_no: 虚拟号(设备/卡均使用此字段)status: 资产状态(整型)asset_status: 业务状态(1-在库 2-已销售 3-已换货 4-已停用)generation: 资产世代编号batch_no: 批次号shop_id: 所属店铺 ID(平台库存时为空)shop_name: 所属店铺名称series_id: 套餐系列 ID(未绑定时为空)series_name: 套餐系列名称first_commission_paid: 一次性佣金是否已发放accumulated_recharge: 累计充值金额(分)activated_at: 激活时间(未激活时为空)created_at: 创建时间updated_at: 更新时间
状态与套餐字段(device 和 card 均有):
real_name_status: 实名状态(整型)current_package: 当前套餐名称(无套餐时返回空字符串)package_total_mb、package_used_mb、package_remain_mb: 套餐流量信息device_protect_status: 保护期状态
绑定关系字段:
iccid: 仅 card 类型时有值bound_device_id、bound_device_no、bound_device_name: 仅 card 类型且绑定设备时有值bound_card_count、cards: 仅 device 类型时有值
Scenario: 通过注册表主路径精确解析
- WHEN 管理员输入 identifier 为已存在于
tb_asset_identifier的 VirtualNo 或 ICCID - THEN 系统单次查询注册表命中,直接查对应表返回完整资产信息,响应时间 < 50ms
Scenario: Fallback 路径解析 IMEI
- WHEN 管理员输入 identifier 为设备 IMEI(不在注册表中)
- THEN 注册表未命中,系统 fallback 查 tb_device 的 imei 字段,找到后返回资产信息
- THEN 响应中
identifier字段原样回传该 IMEI 值
Scenario: Fallback 路径解析 MSISDN
- WHEN 管理员输入 identifier 为 IoT 卡的手机号(MSISDN)
- THEN 注册表未命中,fallback 查 tb_iot_card 的 msisdn 字段
- THEN 若存在多张卡的 MSISDN 相同,返回第一条匹配记录(MSISDN 非唯一,存在歧义,记录 warn 日志)
Scenario: 标识符完全不存在
- WHEN 管理员输入的 identifier 在注册表和 fallback 均未找到
- THEN 返回 HTTP 404,错误消息"资产不存在"