--- phase: 02-perm-fin-realname-poll plan: "01" subsystem: perm-fin-poll tags: - permissions - finance - polling - enterprise - concurrency dependency_graph: requires: [] provides: - PERM-01 - PERM-02 - FIN-01 - FIN-02 - FIN-03 - POLL-01 - POLL-02 - POLL-03 - POLL-04 affects: - internal/handler/admin/asset.go - internal/service/commission_withdrawal/service.go - internal/handler/admin/commission_withdrawal.go - internal/service/commission_withdrawal_setting/service.go - internal/store/postgres/wechat_config_store.go - internal/polling/scheduler.go - internal/service/iot_card/stop_resume_service.go - internal/service/asset/service.go - internal/store/postgres/package_store.go - internal/service/package_series/service.go tech_stack: added: [] patterns: - gorm.io/gorm/clause FOR UPDATE 行锁防并发 - go-playground/validator 参数校验 - 函数签名扩展(分页参数) key_files: created: [] modified: - internal/handler/admin/asset.go - internal/service/commission_withdrawal/service.go - internal/handler/admin/commission_withdrawal.go - internal/service/commission_withdrawal_setting/service.go - internal/store/postgres/wechat_config_store.go - internal/polling/scheduler.go - internal/service/iot_card/stop_resume_service.go - internal/service/asset/service.go - internal/model/dto/asset_dto.go - internal/store/postgres/package_store.go - internal/service/package_series/service.go - internal/bootstrap/handlers.go - internal/bootstrap/services.go - pkg/openapi/handlers.go decisions: - 企业账号权限边界:Resolve 可查(删除拦截),Refresh 不可主动刷新(新增拦截) - GetPackages 分页在内存中排序后切片,避免改动 Store 层查询逻辑 - Series 删除检查在 Service 层实现(非 DB 约束),符合项目禁止外键规范 - CommissionWithdrawalHandler 新增 validator 字段注入,与其他 Handler 保持一致 metrics: duration: "约 10 分钟" completed_date: "2026-03-28" tasks: 2 files: 14 --- # Phase 02 Plan 01: PERM + FIN + POLL 9项独立修复 Summary 企业账号权限边界(Resolve 可查/Refresh 只读)、提现流程数据完整性(审批人字段/remark 必填/激活并发锁)、轮询调度和停复机安全修复,全部为独立小修,共 9 个需求 8 个 commit。 ## 执行结果 所有 9 个需求(PERM-01/02, FIN-01/02/03, POLL-01/02/03/04)均已修复,`go build ./...` 零新增错误(已有两个预存在的 `service/package` 字段缺失错误不在本 plan 范围内)。 ## Task 1: PERM + FIN 修复 ### PERM-01 (commit: 2a92ab6) - **文件**: `internal/handler/admin/asset.go` - **变更**: 删除 `Resolve` 方法中对企业账号的错误拦截(企业账号应可查询资产) ### PERM-02 (commit: 2a92ab6) - **文件**: `internal/handler/admin/asset.go` - **变更**: `Refresh` 方法开头新增企业账号拦截(企业账号只读,不允许主动触发运营商刷新) ### FIN-01 (commit: 8f62496) - **文件**: `internal/service/commission_withdrawal/service.go` - **变更**: `Approve` 的 `updates` map 补充 `approved_by` 和 `approved_at` 字段 ### FIN-02 (commit: 9ee2f0b) - **文件**: `internal/handler/admin/commission_withdrawal.go`, `internal/bootstrap/handlers.go`, `pkg/openapi/handlers.go` - **变更**: `CommissionWithdrawalHandler` 新增 `validator` 字段;`RejectWithdrawal` 补充 `validator.Struct` 参数验证,确保 `remark` 必填 ### FIN-03 (commit: bdac4ab) - **文件**: `internal/service/commission_withdrawal_setting/service.go`, `internal/store/postgres/wechat_config_store.go` - **变更**: 激活配置事务内首步加 `clause.Locking{Strength: "UPDATE"}` 行锁,防止并发时两个事务同时置 `is_active=true` ## Task 2: POLL 修复 ### POLL-01 (commit: 922a3d0) - **文件**: `internal/polling/scheduler.go` - **变更**: `processSchedule` 新增 `TaskTypePollingProtect` 的 `processManualQueue` 和 `processTimedQueue` 调用 ### POLL-02 (commit: 8a53123) - **文件**: `internal/service/iot_card/stop_resume_service.go` - **变更**: `stopCardWithRetry` 和 `resumeCardWithRetry` 中 `gatewayClient==nil` 时返回 `errors.New(CodeInternalError, ...)` 而非 `nil`(原来假装成功会误更新卡状态) ### POLL-03 (commit: 8553a46) - **文件**: `internal/model/dto/asset_dto.go`, `internal/service/asset/service.go`, `internal/handler/admin/asset.go`, `internal/handler/app/client_asset.go` - **变更**: 新增 `AssetPackagesResult` DTO;`GetPackages` 签名新增 `page/pageSize` 参数(默认 page=1, pageSize=50, max=100);admin handler 从 Query 参数读取;client_asset.go 调用处同步更新 ### POLL-04 (commit: 47aa5f8) - **文件**: `internal/store/postgres/package_store.go`, `internal/service/package_series/service.go`, `internal/bootstrap/services.go` - **变更**: `PackageStore` 新增 `CountBySeriesID` 方法;`PackageSeries.Service` 注入 `packageStore` 字段;`Delete` 前检查关联套餐数量,有则拒绝删除 ## Deviations from Plan ### Auto-fixed Issues **1. [Rule 3 - Blocking] pkg/openapi/handlers.go 需同步更新签名** - **Found during**: Task 1 FIN-02 完成后最终编译验证 - **Issue**: `CommissionWithdrawalHandler` 构造函数新增了 `validator` 参数,`pkg/openapi/handlers.go` 中文档生成器调用处仍使用旧签名导致编译失败 - **Fix**: `admin.NewCommissionWithdrawalHandler(nil)` 改为 `admin.NewCommissionWithdrawalHandler(nil, nil)` - **Files modified**: `pkg/openapi/handlers.go` - **Commit**: 754bbcd ## Known Stubs 无 — 所有修复均为实际业务逻辑,无留桩或占位符。 ## Commits | Commit | Message | |--------|---------| | 2a92ab6 | fix(perm): 修复企业账号资产权限边界 PERM-01/02 | | 8f62496 | fix(fin): 补全提现审批人字段 FIN-01 | | 9ee2f0b | fix(fin): 提现拒绝补 remark 必填校验 FIN-02 | | bdac4ab | fix(fin): 激活配置并发行锁保护 FIN-03 | | 922a3d0 | fix(poll): polling:protect 接入调度器 POLL-01 | | 8a53123 | fix(poll): gatewayClient=nil 时停复机返回错误而非成功 POLL-02 | | 8553a46 | fix(poll): GetPackages 接口新增分页 POLL-03 | | 47aa5f8 | fix(poll): Series 删除前检查关联套餐 POLL-04 | | 754bbcd | fix(fin): 同步更新 openapi handlers 中 CommissionWithdrawalHandler 签名 | ## Self-Check: PASSED 所有关键文件存在,所有 commits 均可在 git log 中查到。