Skip to content

fix(opportunity): 补齐 needs_analysis 的阶段路径与 Open Deals 行着色,并加派生式完整性守卫 - #761

Merged
yinlianghui merged 2 commits into
mainfrom
claude/issue-759-needs-analysis-stage-coverage
Aug 5, 2026
Merged

yinlianghui merged 2 commits into
mainfrom
claude/issue-759-needs-analysis-stage-coverage

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Fixes #759

前提复核(对 origin/main = c55aaf5)

issue 的两处指认都成立,唯一的更正是路径那处的键名是 stages 而不是 steps,以及 picklist 的实际路径是 src/objects/_picklists.ts(issue 正文写对了,派单摘要写成了 src/data/):

  • src/objects/_picklists.ts:111-119 OPPORTUNITY_STAGE_OPTIONS 有 7 个规范取值。
  • src/pages/opportunity_detail.page.ts 的 record:path 只列了 6 个,缺 needs_analysis。
  • src/views/opportunity.view.ts open_opportunities 的 rowColor.colors 只列了 6 个,同样缺 needs_analysis。

并且按要求排查了"是否还有别的逐项枚举 stage 的地方也漏了" —— 结论是没有,这两处就是全部:

站点 是否逐项枚举 7 个是否齐全
opportunity.object.ts:110 stage 字段 options 是([...OPPORTUNITY_STAGE_OPTIONS],派生) 齐
opportunity.object.ts:421-428 状态机 transitions 是(手写) 齐(含两个终态空数组)
opportunity.hook.ts STAGE_PROBABILITY / STAGE_FORECAST 是(手写) 齐
4 份 locale pack 的 stage.options 是(手写) 齐(en / zh-CN / es-ES / ja-JP)
mass_update_stage 的 stage 参数 是(plainOptions(...),派生) 齐
pipeline_kanban 否(groupByField: 'stage',列由 picklist 生成) 不适用
dashboards / reports / datasets 否(只有 closed_won / $nin: [closed_won, closed_lost] 这类过滤,不逐项列举) 不适用
quote-generation.flow.ts 否(三值条件表达式,已含 needs_analysis) 不适用

所以无需另开 issue,越界文件面为空。

修法

阶段路径 —— 在 Qualification 与 Proposal 之间插一步。终态的处理沿用现有约定:closed_won / closed_lost 仍排在最后(先赢后输),与 lead_detail 的 converted/unqualified 收尾一致,不做 variant 之类的特殊标注。

行着色 —— 取 teal #14b8a6。这里没有照搬 issue 建议的、_picklists.ts 里该项自带的 #FFD700:rowColor 用的是另一套 Tailwind 调色板(slate-400 / blue-400 / amber-500 / purple-500 / green-600 / red-600),而金色与相邻的 proposal #f59e0b 只差一个色相档,两个相邻阶段的行会染成看不出差别的同一种颜色 —— 那等于用一种更难发现的形式把 bug 重新做一遍。teal 落在 qualification 冷蓝与 proposal 暖琥珀之间,正好接上这条冷→暖的漏斗渐变。

守卫

test/metadata-references.test.ts 原本已经检查这两处,但只查一个方向:写下来的每个值必须是真实 option(子集)。一张只列了 7 个里的 6 个的表,在子集检查下完全合法 —— 这就是它没被发现的原因。新增 4 条断言补上反方向,且期望值派生自 OPPORTUNITY_STAGE_OPTIONS 而非手抄:手抄的清单需要和它守卫的元数据在同一个 commit 里一起改,也就会在同一个 commit 里一起被忘掉。

  • 每个规范阶段都必须在每个绑定 crm_opportunity.stage 的 record:path 上有一步;
  • 每个规范阶段都必须在每个以 stage 为键的 rowColor 里有一项;
  • 任意两个阶段不得共用同一个色值;
  • crm_opportunity.stage 字段本身必须仍然由该常量构建(否则前两条就是在对着一份运行时已经不认的清单较劲)。

两条完整性断言各自先 expect(sites.length).toBeGreaterThan(0) —— 组件类型或 statusField 一旦改名,站点集合会静默变空、断言退化成空转,这个文件的注释里记着导航守卫就是这么"一直通过"了很久的。

反向验证(方向是先预测再跑的)

预测:红,并且报出被删阶段的名字。断言遍历的是 canonical(删 UI 条目不会让它变短),而 sites.length 守卫挡住了"集合变空所以通过"那条退路 —— 所以这里不存在 #5046 那种"删掉一条反而少一个 finding"的计数反转,也不存在 #5009 那种前后都红的倒挂。四项实测与预测一致:

删掉路径那一步:

FAIL … > every stage has a step on the opportunity stage path
AssertionError: incomplete stage paths:
  opportunity_detail_page / opp_stage_path: no path step for stage "needs_analysis"

删掉 rowColor 那一项:

FAIL … > every stage has a row colour in the opportunity list views that tint by stage
AssertionError: incomplete stage row colours:
  view "open_opportunities": no rowColor entry for stage "needs_analysis"

把 needs_analysis 的颜色改成 proposal 的 #f59e0b(即"照搬 #FFD700 会走到的那一步"的放大版):

FAIL … > stage colours stay distinguishable from one another
AssertionError: stages sharing a row colour:
  view "open_opportunities": "proposal" and "needs_analysis" are both #f59e0b

把 statusField 改名(验证守卫本身不空转):

AssertionError: no record:path bound to crm_opportunity.stage was found: expected 0 to be greater than 0

验证

pnpm typecheck                     → 通过(tsc --noEmit 无输出)
pnpm vitest run --maxWorkers=2      → Test Files 62 passed (62) / Tests 1479 passed | 1 skipped (1480)
pnpm validate                       → exit 0(余下 warning 均为既有项:审批流 approver 组、campaign_member 字段组)
pnpm build                          → exit 0,dist/objectstack.json 1913.4 KB
pnpm hygiene                        → ✓ no raw control bytes in source files

平台依旧钉在 17.0.0-rc.2,无版本变动、无平台绕行。文件面严格限于 issue 授权范围:stale_opportunities 的注释块(#744)与 closing_this_quarter 的过滤(#746)均未触碰,content/docs/** 未触碰(#758/#756 在飞)。用户可见,已附 changeset。


Generated by Claude Code

…ls row colours

`crm_opportunity.stage` has seven canonical values in
OPPORTUNITY_STAGE_OPTIONS, but the detail page's `record:path` and the Open
Deals `rowColor` map each enumerated six, both omitting `needs_analysis`. A deal
in Needs Analysis lit up no step on the path and got no row tint, which reads as
corrupted data rather than as missing metadata.

The path gains a step between Qualification and Proposal (funnel order; the two
terminal stages stay last), and `rowColor` gains teal #14b8a6 — between the cool
qualification blue and the warm proposal amber. Deliberately not the #FFD700 the
option carries in _picklists.ts: that map is a separate Tailwind palette and gold
is one hue step from proposal's #f59e0b, so reusing it would leave two adjacent
stages tinting rows indistinguishably.

The existing guards checked these surfaces only in the subset direction — every
value written must be a real option — which passes on a map listing six of
seven. Four assertions add the converse, derived from OPPORTUNITY_STAGE_OPTIONS
rather than hand-copied, so an eighth stage cannot ship half-covered.

Fixes #759

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

vercel Bot commented Aug 5, 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 5, 2026 6:07pm

Request Review

@github-actions github-actions Bot added ci/cd CI plumbing and the verification pipeline metadata Declarative metadata — schema, security posture, UI surfaces labels Aug 5, 2026
…st name

The assertion is derived from OPPORTUNITY_STAGE_OPTIONS; spelling "seven" in
the title reintroduces, in the test name, the hand-copied count the guard exists
to prevent — an eighth stage would leave the name lying while the test passed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa
@yinlianghui
yinlianghui marked this pull request as ready for review August 5, 2026 18:09
@yinlianghui
yinlianghui added this pull request to the merge queue Aug 5, 2026
Merged via the queue into main with commit 484425f Aug 5, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd CI plumbing and the verification pipeline metadata Declarative metadata — schema, security posture, UI surfaces

Projects

None yet

Development

Successfully merging this pull request may close these issues.

商机的 7 个阶段里 needs_analysis 在详情页阶段路径和 Open Deals 行着色里都被漏掉(两处都只列 6 个)

2 participants