bindbox-game/.claude/plan/gmv-payment-breakdown.md
2026-03-17 16:00:23 +08:00

136 lines
4.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 实施计划GMV 支付方式拆分展示
### 需求分析
当前渠道统计只展示一个"累计实付金额"(GMV 总数),用户无法看到这笔钱的构成。需要拆分为:
- **现金支付** (`actual_amount`) — 用户通过微信支付的真金白银
- **优惠券抵扣** (`discount_amount`) — 优惠券抵扣部分
- **积分抵扣** (`points_amount`) — 积分抵扣部分当前数据为0但字段已预留
验证:`total_amount = actual_amount + discount_amount + points_amount` 在所有订单上完全成立0条不等式
### 数据现状dev 环境)
| 支付方式 | 订单数 | 金额(元) | 占比 |
|---------|--------|---------|------|
| GMV 总额 | 3,595 | 124,526.80 | 100% |
| 现金 | 3,595 | 90,067.85 | 72.3% |
| 优惠券 | 1,896 | 34,458.95 | 27.7% |
| 积分 | 0 | 0.00 | 0% |
### 技术方案
orders 表已有完整的拆分字段,**无需新建表或字段**,只需在查询和展示层增加维度。
### 实施步骤
#### Step 1: 后端 — 扩展数据结构
文件:`internal/service/channel/channel.go`
1.1 `StatsOverview` 结构体新增字段:
```go
CashCents int64 `json:"cash_cents"` // 现金支付(分)
CouponCents int64 `json:"coupon_cents"` // 优惠券抵扣(分)
PointsCents int64 `json:"points_cents"` // 积分抵扣(分)
```
1.2 `StatsDailyItem` 结构体新增字段:
```go
CashCents int64 `json:"cash_cents"`
CouponCents int64 `json:"coupon_cents"`
PointsCents int64 `json:"points_cents"`
```
#### Step 2: 后端 — 修改 GMV 查询方法
文件:`internal/service/channel/channel.go`
2.1 `calcGMVByTotalAmount` 改为同时返回 actual_amount / discount_amount / points_amount 的分组统计:
```go
type GMVBreakdown struct {
Total int64
Cash int64
Coupon int64
Points int64
}
func calcGMVByTotalAmount(...) (GMVBreakdown, map[string]GMVBreakdown)
```
查询 SELECT 增加:`orders.actual_amount, orders.discount_amount, orders.points_amount`
2.2 `GetStats` 方法中将拆分数据写入 Overview 和 Daily
```go
out.Overview.CashCents = breakdown.Cash
out.Overview.CouponCents = breakdown.Coupon
out.Overview.PointsCents = breakdown.Points
```
#### Step 3: 后端 — List 接口也返回拆分数据(可选)
文件:`internal/service/channel/channel.go`
`ChannelWithStat` 结构体和 `List` 方法中的 GMV 查询也增加拆分统计,用于渠道列表页 tooltip 展示。
#### Step 4: 前端 — API 类型更新
文件:`web/admin/src/api/channels.ts`
```ts
interface StatsOverview {
// ... existing fields
cash_cents?: number
coupon_cents?: number
points_cents?: number
}
interface StatsDailyItem {
// ... existing fields
cash_cents?: number
coupon_cents?: number
points_cents?: number
}
```
#### Step 5: 前端 — Stats 概览卡片展示
文件:`web/admin/src/views/operations/channels/index.vue`
在"累计实付金额"卡片下方或旁边展示支付构成:
- 显示 3 个子指标:现金 / 优惠券 / 积分
- 各自显示金额和占比百分比
- 积分为 0 时可隐藏或灰显
#### Step 6: 前端 — 每日趋势图支持
文件:`web/admin/src/views/operations/channels/index.vue`
在 revenue tab 的折线图中,可以选择查看:
- GMV 总额(默认)
- 现金 / 优惠券 / 积分 分层堆叠
#### Step 7: 测试
文件:`internal/service/channel/channel_stats_test.go`
更新测试用例,验证 GMV 拆分字段的正确性。
### 关键文件
| 文件 | 操作 | 说明 |
|------|------|------|
| `internal/service/channel/channel.go` | 修改 | 数据结构 + 查询逻辑 |
| `internal/service/channel/channel_stats_test.go` | 修改 | 测试覆盖拆分字段 |
| `web/admin/src/api/channels.ts` | 修改 | API 类型定义 |
| `web/admin/src/views/operations/channels/index.vue` | 修改 | 概览卡片 + 图表展示 |
### 风险与缓解
| 风险 | 缓解措施 |
|------|----------|
| 旧版前端未适配新字段 | 新字段均为可选,不影响旧版展示 |
| 积分字段当前全为0 | 字段预留,后续开启积分抵扣时自动生效 |
| 查询性能 | 无额外 JOIN只增加 3 个 SUM 列,影响可忽略 |