feat(backend): F1-6 sprint2 #2 累计消费总额加入 sandbox_replay
新增指标(无 fdw_queries 原查询 + 0 现有调用方 + 无 thin wrapper),沿用 sprint 1/sprint2 #1 模式 @trace_service + @runtime_aware decorator + 显式 stat_date <= ctx.business_date 上界 + dws_member_consumption_summary .total_consume_amount 字段 items_sum 口径。 双口径数值验证 PASS(member=2799207087163141 黄先生,直接 Python 调用): - 4a live(today=2026-05-05): get_total_consume_amount=1252.65 - 4b sandbox=2026-04-20: get_total_consume_amount=999.99(walkthrough 测试快照) unit test sprint1+sprint2 累计 19/19 PASS,无回归。 记录 thin wrapper 决策原则到 spec §5.5(迁移辅助层,非常态架构; fdw_queries 长远退化纯 ETL 物理访问层,清理放收尾 sprint)。 注:#3 累计交易笔数因 spec §4 字段未明确(dws_order_summary vs total_visit_count)暂停,等 Neo 决断后继续。 详见 docs/audit/changes/2026-05-06__f1_6_sprint2_total_consume_amount.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
# 审计一览表
|
||||
|
||||
> 自动生成于 2026-05-06 00:23:40,请勿手动编辑。
|
||||
> 自动生成于 2026-05-06 00:51:54,请勿手动编辑。
|
||||
|
||||
## 时间线视图
|
||||
|
||||
| 日期 | 项目 | 需求摘要 | 变更类型 | 影响模块 | 风险 | 详情 |
|
||||
|------|------|----------|----------|----------|------|------|
|
||||
| 2026-05-06 | 项目级 | 2026-05-06 · F1-6 Sprint 2 #1 — 60 天消费迁移到 sandbox_replay | 清理 | 其他 | 未知 | [链接](changes/2026-05-06__f1_6_sprint2_consumption_60d.md) |
|
||||
| 2026-05-06 | 项目级 | 2026-05-06 · F1-6 Sprint 2 #2 — 累计消费总额加入 sandbox_replay | 清理 | 其他 | 未知 | [链接](changes/2026-05-06__f1_6_sprint2_total_consume_amount.md) |
|
||||
| 2026-05-05 | 项目级 | 2026-05-05 · F1-6 Sprint 1 沙箱时光机引擎启动 + get_last_visit_days 试点迁移 | bugfix | 其他 | 未知 | [链接](changes/2026-05-05__f1_6_sprint1_sandbox_replay_kickoff.md) |
|
||||
| 2026-05-05 | 项目级 | 2026-05-05 — Wave 1 F1-5a 完整走查(应查尽查版) | bugfix | 其他 | 未知 | [链接](changes/2026-05-05__wave1_f1_5a_backend_walkthrough.md) |
|
||||
| 2026-05-05 | 项目级 | Wave 1 F1-5a — 沙箱 batch-run 接入 runtime_context(MVP + 漂移防御核心) | bugfix | 其他 | 未知 | [链接](changes/2026-05-05__wave1_f1_5a_sandbox_batch_run.md) |
|
||||
@@ -290,6 +291,7 @@
|
||||
| 日期 | 需求摘要 | 变更类型 | 影响模块 | 风险 | 详情 |
|
||||
|------|----------|----------|----------|------|------|
|
||||
| 2026-05-06 | 2026-05-06 · F1-6 Sprint 2 #1 — 60 天消费迁移到 sandbox_replay | 清理 | 其他 | 未知 | [链接](changes/2026-05-06__f1_6_sprint2_consumption_60d.md) |
|
||||
| 2026-05-06 | 2026-05-06 · F1-6 Sprint 2 #2 — 累计消费总额加入 sandbox_replay | 清理 | 其他 | 未知 | [链接](changes/2026-05-06__f1_6_sprint2_total_consume_amount.md) |
|
||||
| 2026-05-05 | 2026-05-05 · F1-6 Sprint 1 沙箱时光机引擎启动 + get_last_visit_days 试点迁移 | bugfix | 其他 | 未知 | [链接](changes/2026-05-05__f1_6_sprint1_sandbox_replay_kickoff.md) |
|
||||
| 2026-05-05 | 2026-05-05 — Wave 1 F1-5a 完整走查(应查尽查版) | bugfix | 其他 | 未知 | [链接](changes/2026-05-05__wave1_f1_5a_backend_walkthrough.md) |
|
||||
| 2026-05-05 | Wave 1 F1-5a — 沙箱 batch-run 接入 runtime_context(MVP + 漂移防御核心) | bugfix | 其他 | 未知 | [链接](changes/2026-05-05__wave1_f1_5a_sandbox_batch_run.md) |
|
||||
@@ -462,6 +464,7 @@
|
||||
| 日期 | 需求摘要 | 变更类型 | 风险 | 详情 |
|
||||
|------|----------|----------|------|------|
|
||||
| 2026-05-06 | 2026-05-06 · F1-6 Sprint 2 #1 — 60 天消费迁移到 sandbox_replay | 清理 | 未知 | [链接](changes/2026-05-06__f1_6_sprint2_consumption_60d.md) |
|
||||
| 2026-05-06 | 2026-05-06 · F1-6 Sprint 2 #2 — 累计消费总额加入 sandbox_replay | 清理 | 未知 | [链接](changes/2026-05-06__f1_6_sprint2_total_consume_amount.md) |
|
||||
| 2026-05-05 | 2026-05-05 · F1-6 Sprint 1 沙箱时光机引擎启动 + get_last_visit_days 试点迁移 | bugfix | 未知 | [链接](changes/2026-05-05__f1_6_sprint1_sandbox_replay_kickoff.md) |
|
||||
| 2026-05-05 | 2026-05-05 — Wave 1 F1-5a 完整走查(应查尽查版) | bugfix | 未知 | [链接](changes/2026-05-05__wave1_f1_5a_backend_walkthrough.md) |
|
||||
| 2026-05-05 | Wave 1 F1-5a — 沙箱 batch-run 接入 runtime_context(MVP + 漂移防御核心) | bugfix | 未知 | [链接](changes/2026-05-05__wave1_f1_5a_sandbox_batch_run.md) |
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
# 2026-05-06 · F1-6 Sprint 2 #2 — 累计消费总额加入 sandbox_replay
|
||||
|
||||
> F1-6 沙箱时光机阶段 B Sprint 2 #2(详见 `docs/_overview/wave1-findings/F1-6-tasks.md` §3)
|
||||
>
|
||||
> 工作量评估 S / 30-50min(实际 ~ 30min,无 UI 走查节省时间)
|
||||
>
|
||||
> Sprint 2 进度:#1 60d 消费 ✅ → **#2 累计消费总额 ☚** → #3 累计交易笔数(字段未定,需 Neo 决断)→ #4 储值卡余额 → #5 累计 GMV
|
||||
>
|
||||
> 完整模块 spec:`docs/_overview/sandbox-replay-engine-spec.md`(§5.5 thin wrapper 决策原则已记录)
|
||||
|
||||
## 背景
|
||||
|
||||
#1 60d 消费完成后,按方案 A 顺序推进 #2 累计消费总额。本指标在后端 / 4 个前端**全无现有调用方**,Neo 同意接受"无 UI 走查,仅 unit test + 直接 Python 双口径数值验证",理由:
|
||||
1. AI app7 客户分析 prompt 拼接 可能传入此值
|
||||
2. 即将迭代的新版本会使用这些数据
|
||||
|
||||
## 改动清单
|
||||
|
||||
### Step 3 实施
|
||||
|
||||
**修改文件**(2 个,本指标**无 thin wrapper**):
|
||||
- [apps/backend/app/services/sandbox_replay/consumption_replay.py](apps/backend/app/services/sandbox_replay/consumption_replay.py) — 追加 `get_total_consume_amount` 函数(`@trace_service + @runtime_aware`)
|
||||
- [apps/backend/app/services/sandbox_replay/__init__.py](apps/backend/app/services/sandbox_replay/__init__.py) — re-export `get_total_consume_amount_replay`
|
||||
|
||||
**未改文件**:
|
||||
- `apps/backend/app/services/fdw_queries.py` — **不加 thin wrapper**(原无同名查询 + 0 调用方,加空 wrapper 违反改动最小化原则,详见 spec §5.5 决策原则)
|
||||
|
||||
**测试文件**(本地不入仓 `.gitignore:71`):
|
||||
- [apps/backend/tests/test_sandbox_replay_sprint2.py](apps/backend/tests/test_sandbox_replay_sprint2.py) — 累计 9 case(本指标 4 case)
|
||||
|
||||
测试覆盖:
|
||||
- 正常返回 Decimal
|
||||
- 无快照行返回 None
|
||||
- `total_consume_amount` 字段为 NULL 返回 None
|
||||
- sandbox 模式 SQL 显式带 `stat_date <= ctx.business_date` 上界
|
||||
|
||||
合并 sprint 1 + sprint 2 #1 测试套件:**19/19 PASS,无回归**。
|
||||
|
||||
### Step 4 双口径数值验证(无 UI,直接 Python 调用)
|
||||
|
||||
**目标 member**: 2799207087163141(黄先生)
|
||||
|
||||
**口径**(`BD_manual_dws_member_consumption_summary.md` §金额口径):
|
||||
```
|
||||
total_consume_amount 基于 items_sum 口径:
|
||||
items_sum = table_charge_money + goods_money + assistant_pd_money
|
||||
+ assistant_cx_money + electricity_money
|
||||
```
|
||||
|
||||
**双口径结果**:
|
||||
|
||||
| 维度 | 4a live (today=2026-05-05) | 4b sandbox=2026-04-20 |
|
||||
|------|---------------------------|----------------------|
|
||||
| stat_date 数据 | 2026-05-01(真实) | 2026-04-15(walkthrough 测试快照) |
|
||||
| `total_consume_amount` 字段值 | 1252.65 | 999.99(测试值) |
|
||||
| `get_total_consume_amount` 返回 | **1252.65** ✓ | **999.99** ✓ |
|
||||
|
||||
走查脚本(归档):
|
||||
- `_DEL/walkthrough_f1_6/step_sprint2_total_consume_4a_4b.py` — 一键完成 4a 验证 + sandbox 切换 + 4b 验证 + 清理
|
||||
|
||||
**关键证据**:sandbox 切换时,`get_total_consume_amount` 函数读 `ctx.business_date=2026-04-20` 作为 SQL 上界,视图层同时按 `stat_date <= app.business_date_now()=2026-04-20` 过滤,双重保障下取 stat_date=2026-04-15 行的 `total_consume_amount=999.99`,完全符合"沙箱时光机"语义。
|
||||
|
||||
测试快照已自动清理(脚本末尾 DELETE),sandbox 已切回 live。
|
||||
|
||||
### Step 5 审计
|
||||
|
||||
本文件 + F1-6-tasks.md Sprint 2 进度推进 + spec §5.5 thin wrapper 原则记录。
|
||||
|
||||
## 影响范围
|
||||
|
||||
| 端 | 影响 | 验证 |
|
||||
|----|------|------|
|
||||
| 后端 sandbox_replay.consumption_replay | 新增 `get_total_consume_amount` 函数 | unit test 4/4 + 累计 19/19 PASS |
|
||||
| 后端 fdw_queries | **无影响**(不加 thin wrapper) | — |
|
||||
| 后端 customer_service / board / 其他 | 无影响(0 现有调用方) | — |
|
||||
| 小程序 / admin-web / 租户后台 / ETL | 无影响(0 现有调用方) | — |
|
||||
|
||||
## 测试
|
||||
|
||||
- 后端 unit test 19/19 PASS(本地 `apps/backend/tests/test_sandbox_replay_sprint{1,2}.py`,因 `.gitignore:71` 不入仓)
|
||||
- 直接 Python 调用 4a/4b 双口径 PASS(1252.65 vs 999.99)
|
||||
- **无 UI 走查**(本指标 0 调用方,Neo 已确认接受)
|
||||
|
||||
## 风险与未覆盖
|
||||
|
||||
- **无 UI 走查**:Neo 已认可,理由是 AI app7 + 新版本迭代场景。该指标接入到真实业务调用方时(未来),应补做 UI 走查。
|
||||
- **不加 thin wrapper 与 #1 模式不一致**:已在 spec §5.5 记录决策原则(不一致是正确的,改动最小化原则)。
|
||||
- **未来调用方接入路径**:`from app.services.sandbox_replay.consumption_replay import get_total_consume_amount`,直接 import 不绕 fdw_queries。
|
||||
|
||||
## 回滚策略
|
||||
|
||||
```bash
|
||||
git revert <commit_hash>
|
||||
```
|
||||
|
||||
回滚后:
|
||||
- `sandbox_replay/consumption_replay.py` 删除 `get_total_consume_amount` 函数
|
||||
- `sandbox_replay/__init__.py` 移除 `get_total_consume_amount_replay` re-export
|
||||
- 0 调用点无影响(本指标无现有调用方)
|
||||
- 测试文件本地保留(`.gitignore` 范围内)
|
||||
|
||||
## Co-Authored-By
|
||||
|
||||
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||||
Reference in New Issue
Block a user