109 lines
4.5 KiB
Markdown
109 lines
4.5 KiB
Markdown
# Requirements: Bindbox Game 盈亏统计函数
|
||
|
||
**Defined:** 2026-03-21
|
||
**Core Value:** 提供可复用的盈亏统计方法,使平台运营能从用户和活动两个维度快速了解各类资产的收支状况
|
||
|
||
## v1 Requirements
|
||
|
||
Requirements for initial release. Each maps to roadmap phases.
|
||
|
||
### Core P&L Functions
|
||
|
||
- [ ] **PNL-01**: 函数接收 ProfitLossParams 参数结构体,所有字段可选(资产类型、维度ID、时间范围)
|
||
- [ ] **PNL-02**: Revenue 计算口径为 actual_amount + discount_amount,排除已退款/取消订单(status=3,4)
|
||
- [ ] **PNL-03**: Game-pass 订单通过 finance.IsGamePassOrder 三条件检测(source_type=4、order_no LIKE 'GP%'、remark含use_game_pass),与现金收入严格互斥
|
||
- [ ] **PNL-04**: Game-pass 订单收入通过 finance.ComputeGamePassValue 计算(draw_count × activity_price)
|
||
- [ ] **PNL-05**: Prize cost 通过 finance.ComputePrizeCostWithMultiplier 计算,包含道具卡倍率
|
||
- [ ] **PNL-06**: Profit 通过 finance.ComputeProfit 计算,返回 int64 分 + float64 利润率
|
||
- [ ] **PNL-07**: 排除已作废库存(remark LIKE '%void%' 或 status=2)不计入成本
|
||
- [ ] **PNL-08**: 兼容 order_id=0 或 NULL 的历史数据(不受订单状态过滤影响)
|
||
|
||
### Query Dimensions
|
||
|
||
- [ ] **DIM-01**: QueryUserProfitLoss 接收 []int64 用户ID,空切片=统计全部用户
|
||
- [ ] **DIM-02**: QueryActivityProfitLoss 接收 []int64 活动ID,空切片=统计全部活动
|
||
- [ ] **DIM-03**: 时间范围过滤使用 *time.Time(nil=不限),不使用零值作哨兵
|
||
- [ ] **DIM-04**: AssetType 可选过滤,nil/All(0)=统计全部资产类型
|
||
|
||
### Return Structure
|
||
|
||
- [ ] **RET-01**: ProfitLossResult 包含汇总数据:总收入、总成本、净盈亏、利润率
|
||
- [ ] **RET-02**: ProfitLossResult 包含 []ProfitLossBreakdown 按资产类型拆分明细
|
||
- [ ] **RET-03**: 所有金额以 int64 分为单位,不使用 float64 存储金额
|
||
|
||
### Asset Types
|
||
|
||
- [ ] **AST-01**: 定义 AssetType 枚举:Points(1)、Coupon(2)、ItemCard(3)、Product(4)、Fragment(5)、All(0)
|
||
- [ ] **AST-02**: 每种资产类型对应不同的数据源表和 JOIN 路径
|
||
- [ ] **AST-03**: Fragment 成本从 fragment_synthesis_logs 表获取
|
||
|
||
### Code Quality
|
||
|
||
- [ ] **QUA-01**: 新函数放在 internal/service/finance/ 包下
|
||
- [ ] **QUA-02**: Service 构造器仅注入 DbR(读库),包内不出现 GetDbW() 调用
|
||
- [ ] **QUA-03**: 每个 Scan() 调用必须检查 .Error 并返回错误,不静默吞掉
|
||
- [ ] **QUA-04**: 复用现有 finance.* 工具函数(ClassifyOrderSpending、IsGamePassOrder 等),不重复实现
|
||
- [ ] **QUA-05**: 使用 fan-out + in-memory merge 查询模式(多次独立 Scan,Go 层合并)
|
||
|
||
## v2 Requirements
|
||
|
||
Deferred to future release.
|
||
|
||
### Performance & Caching
|
||
|
||
- **PERF-01**: Redis TTL 缓存包装(查询延迟超过 2s 时启用)
|
||
- **PERF-02**: 增量/时间桶聚合 + 物化统计表
|
||
|
||
### Integration
|
||
|
||
- **INT-01**: 抖音/直播间订单纳入用户维度盈亏统计
|
||
- **INT-02**: 新增对应 Admin API endpoint 供前端调用
|
||
|
||
## Out of Scope
|
||
|
||
| Feature | Reason |
|
||
|---------|--------|
|
||
| 复用现有 Dashboard 盈亏逻辑 | 现有逻辑耦合 HTTP 上下文,计算口径不一致 |
|
||
| Service 层内置缓存 | 缓存属于调用层责任,不应在 Service 函数内实现 |
|
||
| 分页 | 聚合函数返回完整结果集,分页由 API 层处理 |
|
||
| 返回格式化金额字符串 | 格式化属于展示层,Service 返回 int64 分 |
|
||
| 物化表预计算 | 需要 schema 变更和写权限,v1 直接查询 |
|
||
| 实时推送盈亏变化 | 需要事件基础设施,超出 v1 范围 |
|
||
|
||
## Traceability
|
||
|
||
| Requirement | Phase | Status |
|
||
|-------------|-------|--------|
|
||
| PNL-01 | Phase 1 | Pending |
|
||
| PNL-02 | Phase 1 | Pending |
|
||
| PNL-03 | Phase 1 | Pending |
|
||
| PNL-04 | Phase 1 | Pending |
|
||
| PNL-05 | Phase 1 | Pending |
|
||
| PNL-06 | Phase 1 | Pending |
|
||
| PNL-07 | Phase 1 | Pending |
|
||
| PNL-08 | Phase 1 | Pending |
|
||
| DIM-01 | Phase 1 | Pending |
|
||
| DIM-02 | Phase 1 | Pending |
|
||
| DIM-03 | Phase 1 | Pending |
|
||
| DIM-04 | Phase 1 | Pending |
|
||
| RET-01 | Phase 1 | Pending |
|
||
| RET-02 | Phase 2 | Pending |
|
||
| RET-03 | Phase 1 | Pending |
|
||
| AST-01 | Phase 1 | Pending |
|
||
| AST-02 | Phase 2 | Pending |
|
||
| AST-03 | Phase 2 | Pending |
|
||
| QUA-01 | Phase 1 | Pending |
|
||
| QUA-02 | Phase 1 | Pending |
|
||
| QUA-03 | Phase 1 | Pending |
|
||
| QUA-04 | Phase 1 | Pending |
|
||
| QUA-05 | Phase 1 | Pending |
|
||
|
||
**Coverage:**
|
||
- v1 requirements: 23 total
|
||
- Mapped to phases: 23
|
||
- Unmapped: 0 ✓
|
||
|
||
---
|
||
*Requirements defined: 2026-03-21*
|
||
*Last updated: 2026-03-21 after roadmap creation*
|