Skip to content

docs(sales): 按真名写「预测汇总」的仪表盘与报表两条 (#985) - #990

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-985-pipeline-forecast-lines
Aug 6, 2026
Merged

docs(sales): 按真名写「预测汇总」的仪表盘与报表两条 (#985)#990
yinlianghui merged 1 commit into
mainfrom
claude/issue-985-pipeline-forecast-lines

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes #985

事实复核(两个源码锚点,逐一重验,均未漂移)

立单正文给出的两条断言在 origin/maine4d7c43f,即 PR #987 刚落地之后)上完全成立,premise 有效。

锚点一 —— 仪表盘真名

  • src/dashboards/sales.dashboard.ts:22 —— label: 'Sales Performance'
  • src/apps/crm.app.ts:61 —— { id: 'nav_sales_dashboard', type: 'dashboard', dashboardName: 'sales_dashboard', label: 'Sales Performance', icon: 'chart-line' }

Sales Dashboard 两者皆非:sales_dashboard 是标识符,不是展示名。与 #947 的服务侧不同,这里导航 label 与仪表盘自身 label 是同一个字符串,所以无需 #947 那种「主要指称 + 附注另一个名」的双名处理,一个名写到底即可。

锚点二 —— 报表维度实名

src/reports/opportunity.report.ts:35-:42 逐字:

export const PipelineCoverageByQuarterReport: ReportInput = {
  name: 'pipeline_coverage_by_quarter',
  label: 'Pipeline Coverage by Forecast × Quarter',
  dataset: 'opportunity_metrics', rows: ['forecast_category'], columns: ['close_quarter'], values: ['total_amount', 'opp_count'],
  type: 'matrix',
  runtimeFilter: { stage: { $nin: ['closed_won', 'closed_lost'] } },
};

预测类别(行)× 结束季度(列)。立单说的「轴写反且写错」两点都对:stage 只出现在 runtimeFilter 里用于排除已结单,根本不是一个轴;而季度是 close_quartersrc/datasets/opportunity.dataset.ts:39,同一 close_date 字段上 dateGranularity: 'quarter' 的专用维度)。

名字一侧同样复核过:侧边栏 Insights 组的条目 label 是 Pipeline Coveragesrc/apps/crm.app.ts:153),报表自身 label 是 Pipeline Coverage by Forecast × Quarter —— 两者都真,只是长短不同,所以本 PR 把短名作主要指称、把长名作括注(读者顺 :78 的链接到 Analytics › Reports,看到的正是长名)。

抄平口径

第二条与 PR #975 已写实的 analytics/reports 那一行原本直接矛盾。本 PR 的措辞逐字沿用该行,让两页说同一句话:

措辞
analytics/reports.mdx:22#975 已落地) a matrix of open pipeline: forecast category down the rows, close quarter across the columns
本 PR pipeline-management.mdx:95 a matrix of open pipeline: forecast category down the rows, close quarter across the columns

中文两页同样抄平各自的对应行 —— zh-Hans 用「行 / 列」(reports.zh-Hans.mdx:22),zh-Hant 用「列 / 欄」(reports.zh-Hant.mdx:22),这是两地对 row/column 的正常译法差异,不是漂移。

三语译法(沿既有落地惯例,非自创)

两个展示名在中文两页保留拉丁原文,与紧邻的 :93(PR #987 刚落地的 **Opportunity Metrics** dataset)同形,也与读者点过去会看到的那几页一致:analytics/dashboards.zh-Hans.mdx:48 的章节标题就是 ## 📈 Sales Performanceanalytics/index.zh-Hans.mdx:18quick-tour.zh-Hans.mdx:55 亦然。此处若译成中文,读者顺链接过去反而对不上标题 —— 与 #947 保留 Customer Service 原文是同一条理由。

未附中文译名括注:语言包只有 zh-CNsrc/translations/zh-CN.ts:1193 nav_sales_dashboard: { label: '销售业绩' }),没有 zh-TW/zh-Hant 包,在 zh-Hant 页上写一个繁体译名等于凭空造名。三语一律拉丁原文,同步且零杜撰。

逐处处理

content/docs/sales/pipeline-management{,.zh-Hans,.zh-Hant}.mdx:94 / :95 两行,三语共 6 行。列表形状对齐 :93真名 + 反引号标识符 + 破折号描述

- The **Sales Dashboard** widgets (pipeline by stage, win rate, top deals)
- The **Pipeline Coverage** report (quarter × stage matrix)
+ The **Sales Performance** dashboard (`sales_dashboard`) — widgets for pipeline by stage, win rate, top deals
+ The **Pipeline Coverage** report (`pipeline_coverage_by_quarter`, whose own label reads **Pipeline Coverage by Forecast × Quarter**) — a matrix of open pipeline: forecast category down the rows, close quarter across the columns

标识符入正文是有意的:把 sales_dashboard 显式写出来,正好解释了「Sales Dashboard」这个幻名是怎么来的 —— 带着旧名来找的读者一眼看懂那是 id 而非展示名。

括号里那三块磁贴的名字逐字保留未动,按立单「面限两条行族」的边界。实施时逐个核过(见下「越界发现」),结论另立单,不在本 PR 里改。

:93#987 落地行)逐字未动,零回退 —— 见 diff。src/ 零改动,@objectstack/* 版本零改动,content/docs/releases/ 未触碰。

验证

六道门在共享验证锁 /tmp/os-heavy-verify.lock 内串行跑,全绿:

退出码 关键行
pnpm validate 0 ✓ Validation passed (1774ms);5 条 warning 皆为既有的 approval / field-group 提示
pnpm typecheck 0 tsc --noEmit 无输出
pnpm lint 0 13 warning(s), 14 suggestion(s)
pnpm hygiene 0 ✓ no raw control bytes in first-party files(扫描面 255 files under src/test/e2e/scripts + 447 under content/.changeset)
pnpm build 0 Artifact: dist/objectstack.json (1921.3 KB)
pnpm test -- --maxWorkers=2 0 Test Files 75 passed (75) / Tests 1757 passed | 1 skipped (1758)

控制字节另做过一次超出 gate 覆盖面的自扫(grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f]',含 0x01check:nul-bytes 不扫的字节),四个文件全部零命中。

反向验证:预测 GREEN,实测 GREEN(守卫盲区)

方向是先定后跑的,而且这里预测就是「不变红」#987 新增的守卫 test/docs-analytics-vocabulary.test.ts 是本页最近的一道,先查它的覆盖面再定方向:

  • 它的 PAGES 常量(:113-:139)只有 content/docs/analytics/index{,.zh-Hans,.zh-Hant}.mdx 三个文件;
  • 唯一全仓遍历的规则是 :310cubes/ 目录扫描,本 PR 两行不含该路径;
  • 其余按名指定的载体是 reference/faqreference/performance-and-limitsreference/glossary 六到九个文件,均不含本页。

全仓 grep -rln "pipeline-management" test/ scripts/ 零命中 —— 没有任何守卫读这三个文件。

把两行还原成幻名(git stash,重扫确认 6 行幻名全部回来,含 :34 / :72 上那两处本 PR 不动的同名残留),再跑四个读 content/docs 的测试文件 + hygiene:

Test Files  4 passed (4)
     Tests  99 passed (99)
DOCGUARDS_REVERSE_EXIT=0
HYGIENE_REVERSE_EXIT=0

改后同样四个文件:4 passed / 99 passed,逐项一致。也就是说这两行的措辞没有任何守卫在读,本 PR 无法被任何现有测试钉红,也不是「我忘了加测试」。

本 PR 未新增守卫:能覆盖它的那条规则是「文档里出现的展示名必须解析到真实 label」这一能力,已作为观察类 finding 记在 #802 / #809 / #867 名下(docs-analytics-vocabulary 也是按页硬编码载体、而非按名解析),在本单里做属于越界。这一段如实写出,而不是造一个「before red / after green」的假证据。

越界发现(已另立 #989,未在本 PR 修)

按立单「不预判括号里三块磁贴」的边界,实施时把它们逐个核了一遍,同时扫到同页另外两处同族失实。均已按 Prime Directive #10 另立 #989(先搜后立:Pipeline Coverage / Sales Dashboard / top deals / Expected Revenue 四轮开放 issue 检索,除 #985 外无命中):

  1. :34 —— 同一个幻名 Sales Dashboard 的第二处,并且「sums Expected Revenue」是假能力:opportunity_metrics 没有任何 measure 读 expected_revenue,仪表盘求的是 total_amount。这条涉及能力主张,是 sales/pipeline-management 剩余的仪表盘/报表指称漂移::34 的 Sales Dashboard「求和 Expected Revenue」是假能力,:68/:72 的报表表格四行名字对不上,:94 括号里的 top deals 磁贴不存在 #989 里最重的一条。
  2. :68 + :72-:76 —— 侧边栏没有 Reports 分组(是 Insights),且五行里四行的报表名对不上真实 label;:72 还带着与 :95 同一处的「quarter × stage」失实。
  3. :94 括号里的 top deals —— 不存在,且按 ADR-0021 仪表盘 table 只能聚合、结构性地列不出逐笔排行(sales.dashboard.ts Row 5 注释记录了它被删的经过)。pipeline by stagewin rate 两个则逐字为真。

变更集

新增 .changeset/pipeline-management-forecast-rollup-real-names.md(patch)。


Generated by Claude Code

…ll-up (#985)

The "Forecasting roll-up" list on content/docs/sales/pipeline-management.mdx
pointed at a "Sales Dashboard" and a "Pipeline Coverage" report holding a
"quarter x stage" matrix. Neither was findable as written.

sales_dashboard renders under the label "Sales Performance", which is also its
Sales sidebar entry (src/dashboards/sales.dashboard.ts:22,
src/apps/crm.app.ts:61). And pipeline_coverage_by_quarter is a matrix over
forecast_category (rows) by close_quarter (columns) with total_amount and
opp_count in each cell; stage appears only in the runtimeFilter that drops
closed deals, so it is not an axis at all
(src/reports/opportunity.report.ts:35-42).

Both lines now carry the real label plus the metadata identifier, in all three
locales, worded the same way as the entry PR #975 landed on analytics/reports
so the two pages no longer contradict each other.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hotcrm Ignored Ignored Aug 6, 2026 3:01pm

Request Review

@yinlianghui
yinlianghui marked this pull request as ready for review August 6, 2026 15:04
@yinlianghui
yinlianghui added this pull request to the merge queue Aug 6, 2026
Merged via the queue into main with commit 541e134 Aug 6, 2026
9 checks passed
yinlianghui added a commit to yinlianghui/hotcrm that referenced this pull request Aug 10, 2026
…objectstack-ai#994)

同一页上三族指称漂移,读者按现文在产品里都找不到东西。三语同步,
`src/` 零改动。

一、:34 的「Sales Dashboard 求和 Expected Revenue」两半都不成立。幻名是
PR objectstack-ai#990 刚从同页 :94 修掉的那个(真身 sales_dashboard,label 与 Sales 组
导航项都是 Sales Performance)。能力那半更重:opportunity_metrics 没有
任何 measure 读 expected_revenue,它暴露的金额类度量 total_amount /
avg_amount / won_amount / lost_amount 一律 field: 'amount'
(src/datasets/opportunity.dataset.ts:44-91),所以 Total Pipeline 磁贴给的是
未加权的管道总额。真正对 expected_revenue 求和的是两张表格视图 ——
open_opportunities (Open Deals) 与 all_opportunities (All Opportunities) 各
声明 { field: 'expected_revenue', summary: 'sum' }
(src/views/opportunity.view.ts:37, :138),也正是
content/docs/sales/opportunities.mdx:120 已经写对的那件事。现改为指向列表
视图,并写明仪表盘为什么给不出同一个数。

二、:68 的「Reports 分组」侧边栏上没有:分组叫 Insights
(src/apps/crm.app.ts:143-156),只钉了 Pipeline Coverage / Lead Inflow /
SLA Performance 三张报表,外加 CRM Overview 与 Forecasts,所以本表五行里
只有第一行在导航上。四行报表名按 src/reports/opportunity.report.ts 的真实
label 补全(Pipeline Coverage by Forecast x Quarter、Opportunity Funnel by
Owner -> Stage、Won Opportunities by Owner),coverage 行的轴按 PR objectstack-ai#990 刚在
:95 落地的写法抄平(行是预测类别、列是预计成交季度),不再写反的
quarter x stage。:86 / :87 / :107 / :108 的截断名同步补全;:108 原来的
Pipeline Coverage by Quarter 两边都不是,归到导航名 Pipeline Coverage,与
:85 一致。zh 两页里被意译成中文的报表名同样归位 —— 没有任何翻译文件为它们
背书。

三、:94 括号里的 top deals 磁贴不存在,且改名也救不了:仪表盘 table 绑的是
分析 dataset,只能聚合、列不出原始记录 (ADR-0021),原先那块
Top Open Opportunities 正因此被换成按负责人聚合的 Open Pipeline by Owner,
经过记在 src/dashboards/sales.dashboard.ts 第 5 行区的注释里。现点名说清
并把逐笔排行指向商机列表视图。同括号里的 pipeline by stage 与 win rate 逐字
为真(shared-widgets.ts 的 Pipeline by Stage、sales.dashboard.ts:143 的
Win Rate (12M)),未动。

六道门全绿(validate / typecheck / lint / hygiene / build / test 均 exit 0,
75 个测试文件 1757 passed)。守卫盲区如实记录:docs-drift 的磁贴规则只扫
analytics/dashboards*.mdx,docs-analytics-vocabulary 的全树扫描只查 cubes/
字样,两者在带缺陷与已修两种状态下都是 73/73 绿 —— 本页的仪表盘/报表词汇
无门可拦。

复核中另发现两条本单面外的缺陷,已按 Prime Directive objectstack-ai#10 另立:objectstack-ai#992
(:48-:51 看板列顶「两个数字」是假能力,kanban 只有一个 summarizeField 且绑
amount;objectstack-ai#989 正文把 :51 当作已写对的参照系,该判断不成立,故本 PR 未引用
:51)、objectstack-ai#993 (Sales 组两个非对象导航项在 sales/index 与本页 :38 被按侧边栏上
没有的名字指称)。

Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa

Co-authored-by: Claude <noreply@anthropic.com>
yinlianghui added a commit to yinlianghui/hotcrm that referenced this pull request Aug 10, 2026
…-ai#993) (objectstack-ai#999)

两单同族、行集互斥,一次扫平。三语同步,`src/` 零改动。

一、objectstack-ai#992:pipeline-management「看板列顶两个数字(未加权 + 加权)」两点都
不成立。看板列顶只能有一个数:@objectstack/spec 的 KanbanConfigSchema 把
summarizeField 声明为单数可选字符串(src/ui/view.zod.ts:591,describe 写作
"Field to sum at top of column"),不是数组;而 pipeline_kanban 把它绑到
amount(src/views/opportunity.view.ts:155)。所以未加权那条是真的、加权那条
在看板上根本不存在,「两个」也是错的。销售代表按现文去列顶找加权合计,读到
的是未加权的金额之和,两者差着一个概率系数。现改写为「每列一个数 = 该列
金额之和」,并把加权预测指回 PR objectstack-ai#994 刚在 :34 立好的口径 —— open_opportunities
(Open Deals) 与 all_opportunities (All Opportunities) 各声明
{ field: 'expected_revenue', summary: 'sum' }(同文件 :37、:138),与
content/docs/sales/opportunities.mdx:120 一致。

二、objectstack-ai#993:Sales 组两个非对象导航项的幻名第三处。真名在
src/apps/crm.app.ts:nav_pipeline 的 label 是 Pipeline(:55),
nav_sales_dashboard 的是 Sales Performance(:61);zh-CN 语言包对应
销售管道 / 销售业绩(src/translations/zh-CN.ts:1190、:1193)。
sales/index :63/:64 的 Sales Pipeline / Sales Dashboard 两条都不是侧边栏上的
字 —— 前者是那张视图自己的 label(opportunity.view.ts:150),后者两边都不是,
正是 PR objectstack-ai#990(:94)与 PR objectstack-ai#994(:34)已修掉的同一个幻名。pipeline-management
:40 的「sidebar shortcut Sales Pipeline」同理。三处一律按
opportunities.mdx:122 已有的正确口径处理:视图名与导航名分开说。zh 两页用
语言包里的真 label,繁体只作字形转换,不另造名。

六道门全绿(validate / typecheck / lint / hygiene / build / test 均 exit 0,
75 个测试文件 1766 passed | 1 skipped)。守卫盲区如实记录:docs-drift 的
磁贴规则只扫 analytics/dashboards*.mdx,docs-quick-tour-navigation 只钉
quick-tour 一页的侧边栏,两页的导航指称与看板合计口径无门可拦 —— 带缺陷与
已修两种状态下六道门都是绿的,故本 PR 预测且实测为 GREEN,不存在 red→green
的方向可报。

复核中另发现三条本单面外的缺陷,已按 Prime Directive objectstack-ai#10 另立、未在本 PR
中修:objectstack-ai#996(同页看板小节的 7 列 / Owner 头像 / :86 残留的 Pipeline Kanban
名)、objectstack-ai#997(sales/index :62 三语漏 Account Workbench)、objectstack-ai#998(全站 22 页把
应用叫 Enterprise CRM,真 label 是 HotCRM)。

Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants