docs: 归档 asset-wallet-interface OpenSpec 提案,更新卡钱包 spec

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-03-16 23:30:48 +08:00
parent 63ca12393b
commit f3297f0529
8 changed files with 927 additions and 148 deletions

View File

@@ -0,0 +1,103 @@
## MODIFIED Requirements
### Requirement: 卡钱包实体定义
系统 SHALL 定义资产钱包AssetWallet实体管理物联网卡和设备级别的钱包支持资源转手场景。原 `CardWallet` / `tb_card_wallet` 全量改名为 `AssetWallet` / `tb_asset_wallet`
**核心概念**
- **物联网卡钱包**:归属单张物联网卡,卡转手时钱包跟着卡走
- **设备钱包**归属设备含1-4张卡设备的多张卡共享钱包设备转手时钱包跟着设备走
**实体字段(与原 CardWallet 完全一致,仅表名改变)**
- `id`:钱包 ID主键BIGINT自增
- `resource_type`资源类型VARCHAR(20),枚举值:"iot_card" | "device"
- `resource_id`:资源 IDBIGINT
- `balance`余额BIGINT单位默认 0
- `frozen_balance`冻结余额BIGINT单位默认 0
- `currency`币种VARCHAR(10),默认 "CNY"
- `status`钱包状态INT1-正常 2-冻结 3-关闭,默认 1
- `version`版本号INT乐观锁
- `shop_id_tag`:店铺 ID 标签(多租户过滤)
- `enterprise_id_tag`:企业 ID 标签(可空)
- `created_at` / `updated_at` / `deleted_at`
**表名变更**`tb_card_wallet``tb_asset_wallet`
#### Scenario: 创建物联网卡钱包
- **WHEN** 个人客户通过 ICCID "8986001234567890" 登录,为该卡充值
- **THEN** 系统创建钱包记录写入 `tb_asset_wallet``resource_type` 为 "iot_card"`resource_id` 为卡 ID
#### Scenario: 创建设备钱包
- **WHEN** 个人客户通过设备号登录,为设备充值
- **THEN** 系统创建钱包记录写入 `tb_asset_wallet``resource_type` 为 "device",设备的所有卡共享该钱包
#### Scenario: 计算可用余额
- **WHEN** 钱包余额 10000 分,冻结余额 3000 分
- **THEN** 可用余额 = 7000 分
#### Scenario: 防止同一资源重复创建钱包
- **WHEN** 物联网卡ID=100已有钱包尝试再次创建
- **THEN** 系统拒绝,返回错误"该资源已存在钱包"
---
### Requirement: 资产钱包交易记录
系统 SHALL 记录所有资产钱包余额变动,包括充值、套餐扣费、退款,确保完整收支审计追踪。原 `CardWalletTransaction` / `tb_card_wallet_transaction` 全量改名为 `AssetWalletTransaction` / `tb_asset_wallet_transaction`,同时 `reference_id (bigint)` 字段改为 `reference_no (varchar 50)`
**实体字段**
- `id`:交易记录 ID主键
- `asset_wallet_id`:资产钱包 ID关联 `tb_asset_wallet.id`,原 `card_wallet_id`
- `resource_type`:资源类型(冗余字段)
- `resource_id`:资源 ID冗余字段
- `user_id`:操作人用户 ID
- `transaction_type`:交易类型(`recharge` / `deduct` / `refund`
- `amount`:变动金额(分,充值为正,扣款/退款为负)
- `balance_before`:变动前余额(分)
- `balance_after`:变动后余额(分)
- `status`交易状态1-成功 2-失败 3-处理中)
- `reference_type`:关联业务类型(`recharge``order`,可空)
- `reference_no`:关联业务编号,存储充值单号(`CRCH…`)或订单号(`ORD…`VARCHAR(50),可空)— **原字段 `reference_id (bigint)` 改名并变更类型**
- `remark`备注TEXT可空
- `metadata`扩展信息JSONB可空
- `creator`:创建人 ID
- `shop_id_tag` / `enterprise_id_tag`:多租户标签
**表名变更**`tb_card_wallet_transaction``tb_asset_wallet_transaction`
**字段变更**`reference_id bigint``reference_no varchar(50)`
#### Scenario: 充值写入流水记录
- **WHEN** 个人客户完成充值(充值单号 CRCH20260309001金额 100 元),充值回调成功
- **THEN** 系统在 `tb_asset_wallet_transaction` 写入一条记录:`transaction_type="recharge"``amount=10000``reference_type="recharge"``reference_no="CRCH20260309001"`
#### Scenario: 钱包支付套餐写入扣款流水
- **WHEN** 个人客户使用钱包支付套餐订单(订单号 ORD20260310001金额 30 元),`WalletPay` 执行成功
- **THEN** 系统在同一事务内向 `tb_asset_wallet_transaction` 写入一条记录:`transaction_type="deduct"``amount=-3000``reference_type="order"``reference_no="ORD20260310001"``balance_before` 为扣款前余额,`balance_after` = `balance_before - 3000`
#### Scenario: 充值流水 reference_no 格式
- **WHEN** 系统写入充值流水
- **THEN** `reference_no` 存储充值单号(格式:`CRCH` + 时间戳 + 随机数),而非数据库主键 ID
#### Scenario: 扣款流水 reference_no 格式
- **WHEN** 系统写入扣款流水
- **THEN** `reference_no` 存储订单号(格式:`ORD` + 时间戳 + 6位随机数而非数据库主键 ID
---
### Requirement: 充值记录表改名
系统 SHALL 将原 `tb_card_recharge_record` 表重命名为 `tb_asset_recharge_record`,对应 Go 类型由 `CardRechargeRecord` 改名为 `AssetRechargeRecord`。H5 充值接口 JSON 响应字段 `wallet_id` 不变(保持向后兼容)。
#### Scenario: H5 充值接口字段不变
- **WHEN** 前端调用 `GET /api/h5/wallets/recharges/:id`,充值记录关联的钱包 ID 为 123
- **THEN** 响应 JSON 中 `wallet_id` 仍为 `123`JSON 字段名不变(仅 Go 内部字段名从 `CardWalletID` 改为 `AssetWalletID`