## 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`：资源 ID（BIGINT）
- `balance`：余额（BIGINT，单位：分，默认 0）
- `frozen_balance`：冻结余额（BIGINT，单位：分，默认 0）
- `currency`：币种（VARCHAR(10)，默认 "CNY"）
- `status`：钱包状态（INT，1-正常 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`）
