# 钱包系统分离 - 实施任务清单

## 1. 数据库迁移 - 创建新表结构

- [x] 1.1 创建代理钱包主表迁移文件（`tb_agent_wallet`），包含 shop_id、wallet_type、balance、frozen_balance、version 等字段，添加唯一索引和多租户索引
- [x] 1.2 创建代理钱包交易记录表迁移文件（`tb_agent_wallet_transaction`），包含 agent_wallet_id、shop_id、transaction_type、amount、balance_before、balance_after 等字段，添加 4 个查询索引
- [x] 1.3 创建代理充值记录表迁移文件（`tb_agent_recharge_record`），包含 recharge_no、amount、payment_method、status 等字段，添加状态和店铺索引
- [x] 1.4 创建卡钱包主表迁移文件（`tb_card_wallet`），包含 resource_type、resource_id、balance、frozen_balance、version 等字段，添加唯一索引和多租户索引
- [x] 1.5 创建卡钱包交易记录表迁移文件（`tb_card_wallet_transaction`），包含 card_wallet_id、resource_type、resource_id、transaction_type、amount 等字段，添加 4 个查询索引
- [x] 1.6 创建卡充值记录表迁移文件（`tb_card_recharge_record`），包含 recharge_no、amount、payment_method、status 等字段，添加状态和资源索引
- [x] 1.7 执行数据库迁移，验证 6 张新表创建成功，检查索引和约束

## 2. 代理钱包系统 - Model 层实现

- [x] 2.1 创建 `internal/model/agent_wallet.go`，定义 AgentWallet 结构体，包含 ShopID、WalletType、Balance、FrozenBalance、Version、BaseModel 等字段
- [x] 2.2 在 `agent_wallet.go` 中定义 AgentWalletTransaction 结构体，包含 AgentWalletID、ShopID、TransactionType、Amount、BalanceBefore、BalanceAfter 等字段
- [x] 2.3 在 `agent_wallet.go` 中定义 AgentRechargeRecord 结构体，包含 UserID、AgentWalletID、ShopID、RechargeNo、Amount、PaymentMethod、Status 等字段
- [x] 2.4 为所有 Model 实现 TableName() 方法，返回对应的表名（tb_agent_wallet、tb_agent_wallet_transaction、tb_agent_recharge_record）
- [x] 2.5 添加中文注释说明每个字段的用途和约束
- [x] 2.6 编译验证 Model 定义正确，无语法错误

## 3. 代理钱包系统 - Store 层实现

- [x] 3.1 创建 `internal/store/postgres/agent_wallet_store.go`，定义 AgentWalletStore 结构体，包含 db 和 redis 字段
- [x] 3.2 实现 `NewAgentWalletStore` 构造函数
- [x] 3.3 实现 `GetCommissionWallet(ctx, shopID)` 方法，查询店铺的分佣钱包
- [x] 3.4 实现 `GetMainWallet(ctx, shopID)` 方法，查询店铺的主钱包
- [x] 3.5 实现 `GetByShopIDAndType(ctx, shopID, walletType)` 方法，根据店铺 ID 和钱包类型查询
- [x] 3.6 实现 `GetByID(ctx, id)` 方法，根据钱包 ID 查询
- [x] 3.7 实现 `DeductFrozenBalanceWithTx(ctx, tx, walletID, amount)` 方法，从冻结余额扣款（带事务）
- [x] 3.8 实现 `UnfreezeBalanceWithTx(ctx, tx, walletID, amount)` 方法，解冻余额到可用余额（带事务）
- [x] 3.9 实现 `FreezeBalanceWithTx(ctx, tx, walletID, amount, version)` 方法，冻结余额（带事务，使用乐观锁）
- [x] 3.10 实现 `GetShopCommissionSummaryBatch(ctx, shopIDs)` 方法，批量获取店铺佣金钱包汇总
- [x] 3.11 创建 `internal/store/postgres/agent_wallet_transaction_store.go`，定义 AgentWalletTransactionStore 结构体
- [x] 3.12 实现 `CreateWithTx(ctx, tx, transaction)` 方法，创建代理钱包交易记录（带事务）
- [x] 3.13 实现 `ListByShopID(ctx, shopID, offset, limit)` 方法，按店铺查询交易记录（支持分页）
- [x] 3.14 创建 `internal/store/postgres/agent_recharge_store.go`，定义 AgentRechargeStore 结构体
- [x] 3.15 实现充值记录的 CRUD 方法（Create、GetByRechargeNo、UpdateStatus 等）
- [x] 3.16 编译验证 Store 层代码正确，无语法错误

## 4. 卡钱包系统 - Model 层实现

- [x] 4.1 创建 `internal/model/card_wallet.go`，定义 CardWallet 结构体，包含 ResourceType、ResourceID、Balance、FrozenBalance、Version、BaseModel 等字段
- [x] 4.2 在 `card_wallet.go` 中定义 CardWalletTransaction 结构体，包含 CardWalletID、ResourceType、ResourceID、TransactionType、Amount、BalanceBefore、BalanceAfter 等字段
- [x] 4.3 在 `card_wallet.go` 中定义 CardRechargeRecord 结构体，包含 UserID、CardWalletID、ResourceType、ResourceID、RechargeNo、Amount、PaymentMethod、Status 等字段
- [x] 4.4 为所有 Model 实现 TableName() 方法，返回对应的表名（tb_card_wallet、tb_card_wallet_transaction、tb_card_recharge_record）
- [x] 4.5 添加中文注释说明每个字段的用途和约束
- [x] 4.6 编译验证 Model 定义正确，无语法错误

## 5. 卡钱包系统 - Store 层实现

- [x] 5.1 创建 `internal/store/postgres/card_wallet_store.go`，定义 CardWalletStore 结构体，包含 db 和 redis 字段
- [x] 5.2 实现 `NewCardWalletStore` 构造函数
- [x] 5.3 实现 `GetByResourceTypeAndID(ctx, resourceType, resourceID)` 方法，根据资源类型和 ID 查询钱包
- [x] 5.4 实现 `GetByID(ctx, id)` 方法，根据钱包 ID 查询
- [x] 5.5 实现 `DeductBalanceWithTx(ctx, tx, walletID, amount, version)` 方法，扣款（带事务，使用乐观锁）
- [x] 5.6 实现 `AddBalanceWithTx(ctx, tx, walletID, amount)` 方法，增加余额（带事务）
- [x] 5.7 创建 `internal/store/postgres/card_wallet_transaction_store.go`，定义 CardWalletTransactionStore 结构体
- [x] 5.8 实现 `CreateWithTx(ctx, tx, transaction)` 方法，创建卡钱包交易记录（带事务）
- [x] 5.9 实现 `ListByResourceID(ctx, resourceType, resourceID, offset, limit)` 方法，按资源查询交易记录（支持分页）
- [x] 5.10 创建 `internal/store/postgres/card_recharge_store.go`，定义 CardRechargeStore 结构体
- [x] 5.11 实现充值记录的 CRUD 方法（Create、GetByRechargeNo、UpdateStatus 等）
- [x] 5.12 编译验证 Store 层代码正确，无语法错误

## 6. 常量定义更新

- [x] 6.1 更新 `pkg/constants/wallet.go`，按钱包类型重新组织常量定义
- [x] 6.2 添加代理钱包专用常量（AgentRechargeOrderPrefix、AgentRechargeMinAmount、AgentRechargeMaxAmount）
- [x] 6.3 添加卡钱包专用常量（CardWalletResourceTypeIotCard、CardWalletResourceTypeDevice、CardRechargeOrderPrefix、CardRechargeMinAmount、CardRechargeMaxAmount）
- [x] 6.4 定义 Redis Key 生成函数：`RedisAgentWalletBalanceKey(shopID, walletType)`
- [x] 6.5 定义 Redis Key 生成函数：`RedisAgentWalletLockKey(shopID, walletType)`
- [x] 6.6 定义 Redis Key 生成函数：`RedisCardWalletBalanceKey(resourceType, resourceID)`
- [x] 6.7 定义 Redis Key 生成函数：`RedisCardWalletLockKey(resourceType, resourceID)`
- [x] 6.8 为所有常量和函数添加中文注释
- [x] 6.9 编译验证常量定义正确，无语法错误

## 7. Bootstrap 层 - 注册新 Store

- [x] 7.1 在 `internal/bootstrap/stores.go` 中添加 AgentWalletStore 字段到 Stores 结构体
- [x] 7.2 在 `internal/bootstrap/stores.go` 中添加 AgentWalletTransactionStore 字段到 Stores 结构体
- [x] 7.3 在 `internal/bootstrap/stores.go` 中添加 AgentRechargeStore 字段到 Stores 结构体
- [x] 7.4 在 `internal/bootstrap/stores.go` 中添加 CardWalletStore 字段到 Stores 结构体
- [x] 7.5 在 `internal/bootstrap/stores.go` 中添加 CardWalletTransactionStore 字段到 Stores 结构体
- [x] 7.6 在 `internal/bootstrap/stores.go` 中添加 CardRechargeStore 字段到 Stores 结构体
- [x] 7.7 在 `NewStores()` 函数中初始化所有新 Store 实例（调用 NewXxxStore 构造函数）
- [x] 7.8 编译验证 Bootstrap 层代码正确，无语法错误

## 8. Service 层重构 - 佣金相关服务

- [x] 8.1 更新 `internal/service/commission_calculation/service.go`，将 `WalletStore` 依赖改为 `AgentWalletStore`
- [x] 8.2 更新 `internal/service/commission_calculation/service.go` 中所有调用钱包的方法，使用新的 AgentWalletStore API
- [x] 8.3 更新 `internal/service/commission_withdrawal/service.go`，将 `WalletStore` 依赖改为 `AgentWalletStore`
- [x] 8.4 更新 `internal/service/commission_withdrawal/service.go` 中所有调用钱包的方法，使用新的 AgentWalletStore API
- [x] 8.5 更新 `internal/service/shop_commission/service.go`，将 `WalletStore` 依赖改为 `AgentWalletStore`
- [x] 8.6 更新 `internal/service/shop_commission/service.go` 中所有调用钱包的方法，使用新的 AgentWalletStore API
- [x] 8.7 更新 `internal/service/my_commission/service.go`，将 `WalletStore` 依赖改为 `AgentWalletStore`
- [x] 8.8 更新 `internal/service/my_commission/service.go` 中所有调用钱包的方法，使用新的 AgentWalletStore API
- [x] 8.9 编译验证所有佣金相关服务重构正确，无语法错误

## 9. Service 层重构 - 订单服务

- [x] 9.1 更新 `internal/service/order/service.go`，将 `WalletStore` 依赖改为 `AgentWalletStore` 和 `CardWalletStore`
- [x] 9.2 更新 `internal/service/order/service.go` 中的 `WalletPay()` 方法，使用新的 AgentWalletStore 和 CardWalletStore API（根据买家类型分别处理）
- [x] 9.3 更新 `internal/service/order/service.go` 中的 `HandlePaymentCallback()` 方法，使用新的钱包 API
- [x] 9.4 更新 `internal/service/order/service.go` 中所有其他调用钱包的方法，使用新的钱包 Store API
- [x] 9.5 编译验证订单服务重构正确，无语法错误

## 10. Service 层重构 - 充值服务（注：实际采用原地重构方案，未拆分为两个独立服务）

- [x] 10.1 更新 `internal/service/recharge/service.go`，将依赖从 WalletStore 改为 CardWalletStore、CardWalletTransactionStore、CardRechargeStore
- [x] 10.2 更新 Service 构造函数 New()，注入新的 CardWallet 相关 Store
- [x] 10.3 更新 `Create()` 方法，使用 CardRechargeStore 创建充值订单，使用 CardWalletStore 查询钱包
- [x] 10.4 更新 `HandlePaymentCallback()` 方法，使用 CardRechargeStore 和 CardWalletStore 处理支付回调
- [x] 10.5 更新 `buildRechargeResponse()` 方法，适配 CardRechargeRecord 模型
- [x] 10.6 更新 `List()` 方法，使用 CardRechargeStore.List() 查询充值记录
- [x] 10.7 更新 `GetByID()` 方法，使用 CardRechargeStore.GetByID() 查询充值订单
- [x] 10.8 更新所有佣金触发逻辑，使用 AgentWalletStore 处理佣金入账
- [x] 10.9 在 CardRechargeStore 中添加 List()、UpdatePaymentInfo()、UpdateStatusWithOptimisticLock() 方法
- [x] 10.10 更新 bootstrap/services.go，注入 CardRecharge、CardWallet、CardWalletTransaction Store
- [x] 10.11 编译验证充值服务重构正确，无语法错误

## 11. Bootstrap 层 - 更新 Service 依赖注入

- [x] 11.1 在 `internal/bootstrap/services.go` 中更新 CommissionCalculationService，注入 AgentWalletStore 和 AgentWalletTransactionStore
- [x] 11.2 在 `internal/bootstrap/services.go` 中更新 CommissionWithdrawalService，注入 AgentWalletStore 和 AgentWalletTransactionStore
- [x] 11.3 在 `internal/bootstrap/services.go` 中更新 ShopCommissionService，注入 AgentWalletStore
- [x] 11.4 在 `internal/bootstrap/services.go` 中更新 MyCommissionService，注入 AgentWalletStore 和 AgentWalletTransactionStore
- [x] 11.5 在 `internal/bootstrap/services.go` 中更新 OrderService，注入 AgentWalletStore 和 CardWalletStore
- [x] 11.6 在 `internal/bootstrap/services.go` 中更新 RechargeService，注入 CardRechargeStore、CardWalletStore、CardWalletTransactionStore
- [x] 11.7 在 `internal/bootstrap/worker_services.go` 中更新 CommissionCalculationService，注入 AgentWalletStore 和 AgentWalletTransactionStore
- [x] 11.8 在 `pkg/queue/types.go` 中更新 WorkerStores，添加 AgentWallet 和 AgentWalletTransaction 字段
- [x] 11.9 编译验证 Service 依赖注入更新正确，无语法错误

## 12. 清理旧代码 - 删除旧 Model 和 Store

- [x] 12.1 删除 `internal/model/wallet.go` 文件（包含 Wallet、WalletTransaction、RechargeRecord、WalletMetadata）
- [x] 12.2 删除 `internal/store/postgres/wallet_store.go` 文件
- [x] 12.3 删除 `internal/store/postgres/wallet_transaction_store.go` 文件
- [x] 12.4 从 `internal/bootstrap/stores.go` 中移除 WalletStore 和 WalletTransactionStore 字段
- [x] 12.5 从 `internal/bootstrap/stores.go` 的 `NewStores()` 函数中移除 WalletStore 和 WalletTransactionStore 初始化
- [x] 12.6 编译检查，确保无旧代码引用残留

## 13. 数据库迁移 - 删除旧表

- [x] 13.1 创建删除旧表的迁移文件（DROP TABLE tb_wallet、tb_wallet_transaction、tb_recharge_record）
- [x] 13.2 执行数据库迁移，验证旧表删除成功
- [x] 13.3 检查数据库中只剩下新的 6 张表

## 14. 手动测试 - 代理钱包核心流程

- [ ] 14.1 测试代理钱包创建：为店铺 ID 10 创建主钱包和分佣钱包
- [ ] 14.2 测试代理钱包充值：主钱包充值 100000 分（1000 元），验证余额正确
- [ ] 14.3 测试代理钱包扣款：主钱包扣款 30000 分（300 元），验证余额正确，创建交易记录
- [ ] 14.4 测试余额不足场景：尝试扣款超过可用余额，验证返回"余额不足"错误
- [ ] 14.5 测试冻结余额：分佣钱包冻结 50000 分用于提现，验证 frozen_balance 增加，可用余额减少
- [ ] 14.6 测试解冻余额：取消提现，验证冻结余额减少，可用余额恢复
- [ ] 14.7 测试并发扣款：模拟两个并发请求同时扣款，验证乐观锁生效（一个成功，一个失败重试）
- [ ] 14.8 测试交易记录查询：按店铺 ID 查询交易历史，验证分页和排序正确

## 15. 手动测试 - 卡钱包核心流程

- [ ] 15.1 测试卡钱包创建：为物联网卡（resource_type=iot_card, resource_id=100）创建钱包
- [ ] 15.2 测试卡钱包充值：卡钱包充值 10000 分（100 元），验证余额正确
- [ ] 15.3 测试卡钱包扣款：购买套餐扣款 3000 分（30 元），验证余额正确，创建交易记录
- [ ] 15.4 测试订单退款：退款 3000 分，验证余额恢复，创建退款交易记录
- [ ] 15.5 测试余额不足场景：尝试扣款超过可用余额，验证返回"余额不足"错误
- [ ] 15.6 测试设备钱包：为设备（resource_type=device, resource_id=200）创建钱包，验证设备的多张卡共享钱包
- [ ] 15.7 测试并发扣款：模拟两个并发请求同时扣款，验证乐观锁生效
- [ ] 15.8 测试交易记录查询：按资源 ID 查询交易历史，验证分页和排序正确

## 16. 手动测试 - 充值流程

- [ ] 16.1 测试代理充值最小金额限制：尝试充值 50 元，验证返回"充值金额不能低于 100 元"错误
- [ ] 16.2 测试代理充值订单创建：创建充值订单，验证生成唯一的 recharge_no（ARCH 前缀），状态为"待支付"
- [ ] 16.3 测试代理充值支付完成：模拟支付回调，验证状态从"待支付"变为"已支付"
- [ ] 16.4 测试代理充值到账：处理充值到账，验证钱包余额增加，状态变为"已完成"，创建交易记录
- [ ] 16.5 测试卡充值最小金额限制：尝试充值 0.5 元，验证返回"充值金额不能低于 1 元"错误
- [ ] 16.6 测试卡充值订单创建：创建充值订单，验证生成唯一的 recharge_no（CRCH 前缀），状态为"待支付"
- [ ] 16.7 测试卡充值支付完成：模拟支付回调，验证状态从"待支付"变为"已支付"
- [ ] 16.8 测试卡充值到账：处理充值到账，验证钱包余额增加，状态变为"已完成"，创建交易记录

## 17. 数据一致性验证

- [ ] 17.1 验证代理钱包交易记录的 balance_before 和 balance_after 准确性：查询所有交易记录，计算余额变动，与实际余额对比
- [ ] 17.2 验证卡钱包交易记录的 balance_before 和 balance_after 准确性：查询所有交易记录，计算余额变动，与实际余额对比
- [ ] 17.3 验证乐观锁 version 字段在并发场景下的有效性：模拟高并发扣款，验证 version 正确递增，无丢失更新
- [ ] 17.4 验证 Redis 缓存一致性：余额变动后，检查缓存是否被正确删除，下次查询是否重新加载

## 18. 最终验证和清理

- [x] 18.1 运行 `go build ./...` 编译整个项目，确保无编译错误
- [x] 18.2 运行 `go mod tidy` 清理未使用的依赖
- [x] 18.3 检查所有文件的中文注释是否完整
- [x] 18.4 检查所有常量是否定义在 `pkg/constants/` 中，无硬编码
- [x] 18.5 检查所有错误返回是否使用 `errors.New()` 或 `errors.Wrap()`，无 `fmt.Errorf()`
- [x] 18.6 使用 `gofmt -w .` 格式化所有代码
- [x] 18.7 检查 git status，确认所有变更符合预期
- [x] 18.8 准备提交代码，编写 Git Commit 信息（中文）

---

**注意事项**：

1. **任务顺序不可颠倒**：必须先完成数据库迁移和 Model 层，再实现 Store 层，最后重构 Service 层
2. **逐项标记完成**：每完成一个任务，将 `[ ]` 改为 `[x]`
3. **遇到问题时停止**：如果某个任务无法完成或发现设计问题，立即停止并与团队讨论
4. **编译验证**：每个阶段完成后必须编译验证，确保无语法错误
5. **手动测试不可跳过**：所有核心流程必须手动测试验证，确保功能正确
