## 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`)