Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
12 KiB
1. 数据库迁移(先行)
- 1.1 创建迁移文件:
tb_card_wallet→tb_asset_wallet,tb_card_wallet_transaction→tb_asset_wallet_transaction,tb_card_recharge_record→tb_asset_recharge_record(三张表在同一个迁移文件中完成) - 1.2 创建迁移文件:
tb_asset_wallet_transaction.reference_id (bigint, nullable)→reference_no (varchar 50, nullable)(ALTER TABLE RENAME COLUMN + ALTER COLUMN TYPE) - 1.3 执行全部迁移,使用 PostgreSQL MCP 确认三张表改名成功,
reference_no字段类型为 varchar(50)
2. Model 层全量重命名
- 2.1 重命名
internal/model/card_wallet.go→internal/model/asset_wallet.go,文件内所有类型改名:CardWallet→AssetWallet,TableName()返回"tb_asset_wallet"CardWalletTransaction→AssetWalletTransaction,TableName()返回"tb_asset_wallet_transaction"CardRechargeRecord→AssetRechargeRecord,TableName()返回"tb_asset_recharge_record"
- 2.2 更新
AssetWalletTransaction结构体字段:CardWalletID uint json:"card_wallet_id"→AssetWalletID uint json:"asset_wallet_id"(GORM column tag 同步更新为column:asset_wallet_id);ReferenceID *uint json:"reference_id,omitempty"→ReferenceNo *string json:"reference_no,omitempty"(GORM column tag 改为column:reference_no;type:varchar(50)) - 2.3 更新
AssetRechargeRecord结构体字段:CardWalletID uint json:"card_wallet_id"→AssetWalletID uint json:"asset_wallet_id"(GORM column tag 同步更新) - 2.4 运行
go build ./...确认 Model 层无编译错误
3. Store 层全量重命名
- 3.1 重命名
internal/store/postgres/card_wallet_store.go→asset_wallet_store.go,类型CardWalletStore→AssetWalletStore,构造函数NewCardWalletStore→NewAssetWalletStore,方法内model.CardWallet→model.AssetWallet - 3.2 重命名
internal/store/postgres/card_wallet_transaction_store.go→asset_wallet_transaction_store.go,类型CardWalletTransactionStore→AssetWalletTransactionStore,构造函数及方法内 Model 引用同步更新 - 3.3 重命名
internal/store/postgres/card_recharge_store.go→asset_recharge_store.go,类型CardRechargeStore→AssetRechargeStore,构造函数及方法内 Model 引用同步更新 - 3.4 运行
go build ./...确认 Store 层无编译错误
4. Bootstrap 层更新
- 4.1 更新
internal/bootstrap/stores.go:字段名CardWallet→AssetWallet,CardWalletTransaction→AssetWalletTransaction,CardRecharge→AssetRecharge;构造函数调用同步更新为NewAssetWalletStore、NewAssetWalletTransactionStore、NewAssetRechargeStore - 4.2 更新
internal/bootstrap/services.go:依赖注入中所有s.CardWallet*引用改为s.AssetWallet*、s.CardRecharge改为s.AssetRecharge - 4.3 运行
go build ./...确认 bootstrap 层无编译错误
5. 常量层更新
- 5.1 更新
pkg/constants/redis.go:RedisCardWalletBalanceKey→RedisAssetWalletBalanceKey,函数体不变,仅函数名改变 - 5.2 全局搜索
RedisCardWalletBalanceKey调用处(card_wallet_store.go),替换为RedisAssetWalletBalanceKey
6. Service 层适配:order service
- 6.1 更新
internal/service/order/service.go:结构体字段cardWalletStore *postgres.CardWalletStore→assetWalletStore *postgres.AssetWalletStore,构造函数参数及所有调用点同步更新 - 6.2 在
WalletPay卡钱包支付路径(resourceType != "shop"分支)中,扣款成功后在同一事务内补写AssetWalletTransaction扣款流水:- 在事务内扣款前记录
balanceBefore = wallet.Balance - 扣款成功(
RowsAffected == 1)后,INSERT一条AssetWalletTransaction:AssetWalletID=wallet.ID、ResourceType=resourceType、ResourceID=resourceID、UserID=buyerID、TransactionType="deduct"、Amount=-order.TotalAmount、BalanceBefore=balanceBefore、BalanceAfter=balanceBefore-order.TotalAmount、Status=1、ReferenceType=strPtr("order")、ReferenceNo=&order.OrderNo、Remark=strPtr("钱包支付套餐")、ShopIDTag=wallet.ShopIDTag、EnterpriseIDTag=wallet.EnterpriseIDTag
- 在事务内扣款前记录
- 6.3 运行
go build ./...确认 order service 无编译错误
7. Service 层适配:recharge service
- 7.1 更新
internal/service/recharge/service.go:结构体字段及构造函数cardWalletStore→assetWalletStore,cardWalletTransactionStore→assetWalletTransactionStore;所有 Model 引用model.CardWallet*→model.AssetWallet* - 7.2 更新充值回调写入流水记录处(约第 320 行):
ReferenceID: &recharge.ID→ReferenceNo: &recharge.RechargeNo(同时删除原ReferenceID字段赋值) - 7.3 运行
go build ./...确认 recharge service 无编译错误
8. DTO 新增
-
8.1 新建
internal/model/dto/asset_wallet_dto.go,定义以下 DTO(含所有字段及descriptiontag):AssetWalletResponse(钱包概况响应):
wallet_id uint、resource_type string、resource_id uintbalance int64、frozen_balance int64、available_balance int64currency string、status int、status_text stringcreated_at time.Time、updated_at time.Time
AssetWalletTransactionListRequest(流水列表请求,查询参数):
page int(默认 1)、page_size int(默认 20,最大 100)transaction_type *string(可选,oneof=recharge deduct refund)start_time *time.Time(可选)、end_time *time.Time(可选)
AssetWalletTransactionItem(单条流水):
id uinttransaction_type string、transaction_type_text stringamount int64、balance_before int64、balance_after int64reference_type *string、reference_no *stringremark *stringcreated_at time.Time
AssetWalletTransactionListResponse(流水列表响应):
list []*AssetWalletTransactionItemtotal int64、page int、page_size int、total_pages int
-
8.2 运行
lsp_diagnostics确认 DTO 无错误
9. AssetWalletService 新增
- 9.1 新建
internal/service/asset_wallet/service.go,定义Service结构体,依赖注入:AssetWalletStore、AssetWalletTransactionStore - 9.2 实现
GetWallet(ctx, assetType string, assetID uint) (*dto.AssetWalletResponse, error):- 将
assetType(card/device)映射到resourceType(iot_card/device) - 调用
AssetWalletStore.GetByResourceTypeAndID(ctx, resourceType, assetID) - 组装
AssetWalletResponse(计算available_balance = balance - frozen_balance,翻译status_text) - 钱包不存在时返回
errors.New(errors.CodeNotFound, "该资产暂无钱包记录")
- 将
- 9.3 实现
ListTransactions(ctx, assetType string, assetID uint, req *dto.AssetWalletTransactionListRequest) (*dto.AssetWalletTransactionListResponse, error):- 将
assetType映射为resourceType - 调用
AssetWalletTransactionStore.ListByResourceID(ctx, resourceType, assetID, offset, limit)和CountByResourceID获取分页数据 - 组装响应:翻译
transaction_type_text(recharge→充值 / deduct→扣款 / refund→退款),计算total_pages - 如有
transaction_type过滤参数,在 Store 层新增对应过滤方法(或在 Service 层 in-memory 过滤——推荐 Store 层)
- 将
- 9.4 运行
lsp_diagnostics确认 Service 无错误
10. Store 层新增查询方法
- 10.1 在
AssetWalletTransactionStore中新增ListByResourceIDWithFilter(ctx, resourceType string, resourceID uint, transactionType *string, startTime, endTime *time.Time, offset, limit int) ([]*model.AssetWalletTransaction, error)方法,支持transaction_type、时间范围过滤,应用ApplyShopTagFilter数据权限 - 10.2 在
AssetWalletTransactionStore中新增CountByResourceIDWithFilter(ctx, resourceType string, resourceID uint, transactionType *string, startTime, endTime *time.Time) (int64, error)方法 - 10.3 运行
lsp_diagnostics确认 Store 无错误
11. AssetWalletHandler 新增
-
11.1 新建
internal/handler/admin/asset_wallet.go,定义AssetWalletHandler结构体(依赖*assetWalletSvc.Service),实现两个 Handler 方法:GetWallet(
GET /api/admin/assets/:asset_type/:id/wallet):- 检查企业账号:
user_type == UserTypeEnterprise→ 返回 403 - 解析路径参数
asset_type(校验为card或device)和id(校验为正整数) - 调用
assetWalletSvc.GetWallet(ctx, assetType, id)→ 返回response.Success
ListTransactions(
GET /api/admin/assets/:asset_type/:id/wallet/transactions):- 检查企业账号:同上
- 解析路径参数和查询参数(
QueryParser绑定AssetWalletTransactionListRequest) - 参数验证:
page_size最大 100,transaction_type需为合法枚举值 - 调用
assetWalletSvc.ListTransactions(ctx, assetType, id, &req)→ 返回response.Success
- 检查企业账号:
-
11.2 运行
lsp_diagnostics确认 Handler 无编译错误
12. 路由注册
-
12.1 在
internal/routes/asset.go的registerAssetRoutes函数末尾追加两条路由(需传入*admin.AssetWalletHandler参数):Register(assets, doc, groupPath, "GET", "/:asset_type/:id/wallet", walletHandler.GetWallet, RouteSpec{ Summary: "资产钱包概况", Description: "查询指定卡或设备的钱包余额概况。企业账号禁止调用。", Tags: []string{"资产管理"}, Input: new(dto.AssetTypeIDRequest), Output: new(dto.AssetWalletResponse), Auth: true, }) Register(assets, doc, groupPath, "GET", "/:asset_type/:id/wallet/transactions", walletHandler.ListTransactions, RouteSpec{ Summary: "资产钱包流水列表", Description: "分页查询指定资产的钱包收支流水,含充值/扣款来源编号。企业账号禁止调用。", Tags: []string{"资产管理"}, Input: new(dto.AssetWalletTransactionListRequest), Output: new(dto.AssetWalletTransactionListResponse), Auth: true, }) -
12.2 更新
registerAssetRoutes函数签名,增加walletHandler *admin.AssetWalletHandler参数 -
12.3 更新
internal/routes/routes.go中registerAssetRoutes的调用处,传入AssetWalletHandler
13. Bootstrap 层注册新 Handler/Service
- 13.1 更新
internal/bootstrap/types.go:Handlers结构体新增AssetWallet *admin.AssetWalletHandler;Services结构体新增AssetWallet *assetWalletSvc.Service(如需独立 service 包则导入) - 13.2 更新
internal/bootstrap/services.go:实例化assetWalletSvc.New(s.AssetWallet, s.AssetWalletTransaction) - 13.3 更新
internal/bootstrap/handlers.go:实例化admin.NewAssetWalletHandler(svcs.AssetWallet) - 13.4 更新
cmd/api/docs.go和cmd/gendocs/main.go:handlers.AssetWallet = admin.NewAssetWalletHandler(nil)(文档生成器注册) - 13.5 运行
go build ./...全量确认无编译错误
14. 文档和最终验收
- 14.1 运行
go run cmd/gendocs/main.go确认两个新接口(资产钱包概况、资产钱包流水列表)出现在 OpenAPI 文档中 - 14.2 使用 PostgreSQL MCP 验证三张表改名成功:
tb_asset_wallet、tb_asset_wallet_transaction(含reference_no varchar(50)字段)、tb_asset_recharge_record - 14.3 使用 PostgreSQL MCP 或 curl 验证:H5 充值接口
GET /api/h5/wallets/recharges/:id响应中wallet_id字段仍正常返回 - 14.4 运行
go build ./...全量确认无编译错误 - 14.5 tasks.md 全部任务标记完成