# Change: 添加钱包、换卡、标签系统模型和表结构

## Why

在审查现有的 IoT 卡管理和订单系统后，发现以下关键功能缺失，需要补充模型和表结构设计：

1. **钱包系统缺失**：当前订单表支持 `payment_method=wallet`，但没有钱包表和钱包明细表，无法支持用户/代理充值和余额管理
2. **换卡记录缺失**：IoT 卡有 `owner_type`/`owner_id` 可变更，但没有换卡记录表追踪换卡历史（老卡→新卡的套餐、代理、权益转移）
3. **标签系统完全缺失**：企业用户无法为设备/卡片打标签进行分类管理
4. **运营商渠道管理不足**：现有 `tb_carrier` 表只有运营商名称，无法区分运营商类型（四大运营商固定）和渠道（可自定义）

## What Changes

本提案**仅涉及模型和表结构设计**，不包含 API、Service、Store 层实现。

### 1. 钱包系统（新增）

- **新增表**：`tb_wallet`、`tb_wallet_transaction`、`tb_recharge_record`
- **新增模型**：`Wallet`、`WalletTransaction`、`RechargeRecord`
- **功能支持**：
  - 用户钱包和代理钱包统一管理
  - 用户可充值到钱包，购买套餐时选择钱包支付或直接支付
  - 代理可预充值到钱包，用成本价购买套餐
  - 完整的钱包明细记录（充值、扣款、退款、分佣、提现）
  - 使用乐观锁（version 字段）防止并发扣款

### 2. 换卡系统（新增）

- **新增表**：`tb_card_replacement_record`
- **新增模型**：`CardReplacementRecord`
- **功能支持**：
  - 记录老卡和新卡的关联关系
  - 套餐权益转移快照（剩余流量、过期时间等，使用 JSONB 存储）
  - 代理关系转移记录
  - 所有者信息转移记录
  - 换卡原因和审批状态

### 3. 标签系统（新增）

- **新增表**：`tb_tag`、`tb_resource_tag`
- **新增模型**：`Tag`、`ResourceTag`
- **功能支持**：
  - 标签定义（名称、颜色、使用次数）
  - 统一的资源-标签关联表（支持设备、IoT卡、号卡）
  - 企业用户可为设备/卡片打标签
  - 支持按标签查询和筛选

### 4. 运营商渠道管理改进（修改）

- **修改表**：`tb_carrier`
- **修改模型**：`Carrier`
- **新增字段**：
  - `carrier_type`：运营商类型（枚举：CMCC/CUCC/CTCC/CBN）
  - `channel_name`：渠道名称（可自定义）
  - `channel_code`：渠道编码（可自定义）
- **唯一约束**：`(carrier_type, channel_code)` 在 `deleted_at IS NULL` 条件下唯一

### 5. 订单系统改进（修改）

- **修改表**：`tb_order`
- **修改模型**：`Order`
- **新增字段**：
  - `wallet_payment_amount`：钱包支付金额（分）
  - `online_payment_amount`：在线支付金额（分）
- **说明**：支持混合支付（钱包 + 在线支付）

## Impact

### 受影响的 specs
- **新增**：wallet、card-replacement、tag
- **修改**：carrier（运营商管理）、iot-order（订单支付方式）

### 受影响的代码
- **新增文件**：
  - `internal/model/wallet.go`
  - `internal/model/card_replacement.go`
  - `internal/model/tag.go`
  - `migrations/000XXX_add_wallet_transfer_tag_tables.up.sql`
  - `migrations/000XXX_add_wallet_transfer_tag_tables.down.sql`
  - `pkg/constants/wallet.go`
  - `pkg/constants/tag.go`
- **修改文件**：
  - `internal/model/carrier.go`
  - `internal/model/order.go`

### 破坏性变更
- **无破坏性变更**：所有修改都是新增字段，有默认值，向后兼容

### 数据迁移
- 需要为现有 `tb_carrier` 记录填充默认的 `carrier_type` 值
- 建议在迁移文件中添加数据初始化脚本

## 设计原则遵循

- ✅ 表名使用 `tb_` 前缀，模型名使用单数形式
- ✅ 所有表包含软删除（`deleted_at`）和审计字段（`creator`、`updater`）
- ✅ 所有金额字段使用 `BIGINT` 类型，单位为分
- ✅ 唯一索引包含 `WHERE deleted_at IS NULL` 条件
- ✅ 禁止使用数据库外键约束
- ✅ 所有常量定义在 `pkg/constants/` 目录
- ✅ 使用 GORM 标准字段标签
- ✅ 钱包使用乐观锁（version 字段）防止并发问题
