Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions .changeset/sales-pipeline-kanban-section-and-account-workbench.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
'hotcrm': patch
---

Write the pipeline board's kanban section to the board the app really ships, and
put the Sales group's ninth sidebar entry back on the page whose job is to list
them.

**The board cannot show seven stages' worth of deals.** The kanban section of
`content/docs/sales/pipeline-management.mdx` (and both zh pages) opened with "7
columns — one per stage". `crm_opportunity.stage` does carry seven options, but
this board declares its own filter — `stage not_in [closed_won, closed_lost]` in
`src/views/opportunity.view.ts`, whose source comment says the exclusion is what
"keeps all five active stages visible" — so *Closed Won* and *Closed Lost* can
never hold a card here. A reader counting seven and finding two of them
permanently empty had no way to tell a filter from a bug. The page now says what
the metadata proves: one column per stage, **open deals only**, five active
stages, with closed business named where it does live (**All Opportunities** and
the **Sales Performance** dashboard). Whether the console draws the two closed
stages as empty columns or leaves them off is the renderer's choice, not this
app's declaration, and the page now says that rather than guessing a number —
the conservative shape `content/docs/sales/opportunities.mdx` already uses.

**There is no owner avatar on a kanban card.** The card list ran to five items,
ending in *Owner avatar*. Cards are bound by `kanban.columns`, which names four
fields — name, account, amount, close date. `owner_id` is in the view's
top-level `columns`, which is what the grid renderings read, and it is nowhere
on the card. The list is now four, and the owner is re-pointed to the two
surfaces that genuinely carry it: the *Owner* column on **All Opportunities**,
and the **Deal Cards** gallery, whose `visibleFields` include it.

**The stage rules are advice, not a gate.** The page told a rep "the system
enforces the stage rules, so you can't drag from *Prospecting* directly to
*Closed Won*". `opportunity_stage_progression`
(`src/objects/opportunity.object.ts`) does declare that transition illegal, but
at **warning** severity: the move writes one line to the server log and **the
save still goes through**. `content/docs/administration/state-machines` has said
exactly that — naming this very transition — since the state-machine sweep; the
two pages contradicted each other and this was the one that was wrong. Its
wording now matches, and it links there.

**The cadence table's *Open Pipeline Kanban*** named nothing in the product.
`Pipeline Kanban` is a camel-case reading of the identifier `pipeline_kanban`;
the view's label is **Sales Pipeline** and the sidebar entry that opens it reads
**Pipeline**. The daily row now sends a reader to **Pipeline**, matching the
correction the same section's opening paragraph already carries.

**Account Workbench was missing from the sales index.** The *Where to find
things* section of `content/docs/sales/index.mdx` listed eight of the Sales
group's nine entries. The missing one is **Account Workbench**
(`src/pages/account_workbench.page.ts`) — an interface page sitting third in the
group, with a real label in every locale bundle — so the page told a new reader
it does not exist, or that the sidebar they were looking at was broken. The same
question was already answered correctly one page over, in
`content/docs/getting-started/quick-tour.mdx`, which lists all nine. The section
now names it, says what it is (a curated way into the same account records,
reusing the **All Accounts** view with three quick filters and no view
management), and states the group size.

Two guards now hold both pages to their source, because nothing else can — `os
validate` and `pnpm lint` never open `content/docs`:
`test/docs-sales-index-navigation.test.ts` compares the section against the
Sales group in all three locales, and `test/docs-pipeline-kanban-section.test.ts`
pins the kanban section's card fields, filter, active-stage count and advisory
wording, plus the source facts each rests on. Bind an owner onto the cards, drop
the board's filter, raise the rule to `error`, or add a Sales nav entry, and the
docs go red with the metadata.

Docs and tests only — no `src/` change.
3 changes: 2 additions & 1 deletion content/docs/sales/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ Just type into the chat: *"qualify this lead"*, *"draft a follow-up email"*, *"w

## Where to find things

The **Enterprise CRM app** sidebar groups everything under **Sales**:
The **Enterprise CRM app** sidebar groups everything under **Sales**, and that group carries nine entries — six object entries plus three that open something other than an object list:

- Leads · Accounts · Contacts · Opportunities · Quotes · Contracts
- **Account Workbench** — a second, curated way into accounts, sitting right under **Accounts** in the group. It reuses the **All Accounts** view's columns, filter and sort, and adds three quick filters (industry, type, owner); view management and advanced filtering are deliberately not offered. Same records as **Accounts**, a narrower screen.
- **Pipeline** — the kanban board view of opportunities. That is the sidebar label; the view it opens carries its own label, **Sales Pipeline** (`pipeline_kanban`).
- **Sales Performance** — your daily KPIs, from the `sales_dashboard` dashboard. No sidebar item is called *Sales Dashboard*.

Expand Down
3 changes: 2 additions & 1 deletion content/docs/sales/index.zh-Hans.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ Lead ──► Account + Contact ──► Opportunity ──► Quote

## 在哪里找到这些功能

**Enterprise CRM 应用**的侧边栏将所有内容归到**销售**之下:
**Enterprise CRM 应用**的侧边栏将所有内容归到**销售**之下,这个分组一共九个条目——六个对象入口,外加三个打开的不是对象列表的条目

- 线索 · 客户 · 联系人 · 商机 · 报价 · 合同
- **客户工作台**(Account Workbench)——进入客户数据的第二条、经过策展的通道,在分组里就排在**客户**下面。它复用**全部客户**视图的列、过滤与排序,再加三个快捷筛选(行业、类型、负责人);视图管理与高级过滤是刻意不提供的。记录与**客户**完全相同,只是屏幕更窄。
- **销售管道**(Pipeline)——商机的看板视图。侧边栏上的 label 就是这个;它打开的那个视图自身的 label 是**销售流水线**(Sales Pipeline,`pipeline_kanban`)。
- **销售业绩**(Sales Performance)——你的每日 KPI,来自 `sales_dashboard` 仪表盘。没有任何侧边栏条目叫 *销售仪表盘* / *Sales Dashboard*。

Expand Down
3 changes: 2 additions & 1 deletion content/docs/sales/index.zh-Hant.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ Lead ──► Account + Contact ──► Opportunity ──► Quote

## 在哪裡找到這些功能

**Enterprise CRM 應用**的側邊欄將所有內容歸到**銷售**之下:
**Enterprise CRM 應用**的側邊欄將所有內容歸到**銷售**之下,這個分組一共九個條目——六個物件入口,外加三個打開的不是物件清單的條目

- 潛在客戶 · 客戶 · 聯絡人 · 商機 · 報價 · 合約
- **客戶工作台**(Account Workbench)——進入客戶資料的第二條、經過策展的通道,在分組裡就排在**客戶**下面。它複用**全部客戶**檢視的欄、過濾與排序,再加三個快捷篩選(行業、類型、負責人);檢視管理與進階過濾是刻意不提供的。記錄與**客戶**完全相同,只是螢幕更窄。
- **銷售管道**(Pipeline)——商機的看板視圖。側邊欄上的 label 就是這個;它打開的那個視圖自身的 label 是**銷售流水線**(Sales Pipeline,`pipeline_kanban`)。
- **銷售業績**(Sales Performance)——你的每日 KPI,來自 `sales_dashboard` 儀表板。沒有任何側邊欄條目叫 *銷售儀表板* / *Sales Dashboard*。

Expand Down
11 changes: 7 additions & 4 deletions content/docs/sales/pipeline-management.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,18 @@ No dashboard can give you the same figure. The **Sales Performance** dashboard (

## The pipeline kanban view

The kanban board is the **Sales Pipeline** view on Opportunities (`pipeline_kanban`), and the sidebar entry that opens it reads **Pipeline**. It shows the pipeline as 7 columns — one per stage. Each card shows:
The kanban board is the **Sales Pipeline** view on Opportunities (`pipeline_kanban`), and the sidebar entry that opens it reads **Pipeline**. It shows the pipeline **one column per stage, open deals only**: the board carries its own filter — `stage not_in [closed_won, closed_lost]` in `src/views/opportunity.view.ts` — so only the five active stages, *Prospecting*, *Qualification*, *Needs Analysis*, *Proposal* and *Negotiation*, can ever hold a card. Closed business is not hidden, it is elsewhere: **All Opportunities** and the **Sales Performance** dashboard both include it. Whether the two closed stages are drawn as permanently empty columns or left off the board altogether is the console's rendering choice and not something this app declares — either way there is no closed deal on this board to find.

Each card carries the four fields the board binds (`kanban.columns`):

- Opportunity name
- Account
- Amount
- Close date
- Owner avatar

To advance a deal, just **drag the card** to the next column. The system enforces the stage rules, so you can't drag from *Prospecting* directly to *Closed Won*.
**Owner is not on the card.** `owner_id` sits in the view's top-level `columns` list, which is what the grid renderings read, but the card binding names those four fields and stops there. To see the owner next to a deal, use **All Opportunities**, which carries an *Owner* column, or the **Deal Cards** gallery, whose cards do show it.

To advance a deal, just **drag the card** to the next column. The stage rules are **advice, not a gate**. `opportunity_stage_progression` (`src/objects/opportunity.object.ts`) declares which moves are legal — *Prospecting* straight to *Closed Won* is not one of them — but the rule carries **warning** severity, so a move outside the table writes one line to the server log, *"Invalid opportunity stage transition"*, and **the save still goes through**. Nothing in the board stops you. What the log buys you is that a bad import or a misbehaving integration can be found afterwards; see [Administration › State Machines](/docs/administration/state-machines) for what the table is and is not good for.

At the top of each column you'll see **one** number: the sum of *Amount* across that column's deals — the unweighted total for that stage. One is all a kanban column can carry, by design: a board declares a single `summarizeField` (`src/views/opportunity.view.ts`), and this board binds it to `amount`.

Expand Down Expand Up @@ -82,7 +85,7 @@ See [Analytics › Reports](/docs/analytics/reports) for details.

| Cadence | What to do |
| --- | --- |
| **Daily** | Open Pipeline Kanban. Find stalled cards (in-stage > 14 days). Push or close. |
| **Daily** | Open the **Pipeline** board. Find stalled cards (in-stage > 14 days). Push or close. |
| **Weekly** | Run *Pipeline Coverage*. Ask the Sales Copilot: *"what's at risk?"* |
| **Monthly** | Run *Opportunity Funnel by Owner → Stage*. Coach reps with leaky stages 1:1. |
| **Quarter-end** | Run *Won Opportunities by Owner* for commissions. Archive lost deals with a *loss reason*. |
Expand Down
11 changes: 7 additions & 4 deletions content/docs/sales/pipeline-management.zh-Hans.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,18 @@ description: 销售管道的日常运作方式——推进交易、自动概率

## 销售管道看板视图

这块看板是商机上的**销售流水线**视图(`pipeline_kanban`),侧边栏上打开它的那个条目写作**销售管道**。它将销售管道显示为 7 列——每个阶段一列。每张卡片显示:
这块看板是商机上的**销售流水线**视图(`pipeline_kanban`),侧边栏上打开它的那个条目写作**销售管道**。它把销售管道按**每个阶段一列**铺开,且**只放在飞交易**:这块板自带过滤器——`src/views/opportunity.view.ts` 里的 `stage not_in [closed_won, closed_lost]`——所以只有五个活跃阶段(*寻找客户*、*资格审查*、*需求分析*、*提案*、*谈判*)里才可能有卡片。已结束的生意不是被藏了,而是在别处:**全部商机**视图与 **Sales Performance** 仪表盘都算上它们。至于那两个已结束阶段是被画成永远空着的列、还是干脆不出现在板上,那是 console 的算绘选择,本应用的元数据并没有声明——无论哪种,这块板上都没有已结束的交易可找。

每张卡片带的是这块板绑定的四个字段(`kanban.columns`):

- 商机名称
- 客户
- 金额
- 成交日期
- 负责人头像

要推进一笔交易,只需**拖动卡片**到下一列。系统会强制执行阶段规则,因此你无法从*寻找客户*直接拖到*成交*。
**卡片上没有负责人。** `owner_id` 在这个视图顶层的 `columns` 清单里,那是给网格类算绘读的;卡面绑定只点了上面四个字段,到此为止。要在交易旁边看到负责人,请用带 *Owner* 列的**全部商机**视图,或者卡面确实带负责人的 **Deal Cards** 图库视图。

要推进一笔交易,只需**拖动卡片**到下一列。阶段规则是**建议,不是闸门**。`opportunity_stage_progression`(`src/objects/opportunity.object.ts`)声明了哪些跃迁合法——*寻找客户*直接到*成交*并不在其中——但这条规则是**警告**级,所以走出转换表的移动只会往服务端日志写一行 *"Invalid opportunity stage transition"*,而**保存照样通过**。看板上没有任何东西会拦住你。日志给你的价值是:一次糟糕的导入、一个行为异常的集成,事后还能被找出来。这张表能做什么、不能做什么,详见 [Administration › State Machines](/zh-Hans/docs/administration/state-machines)。

在每列顶部你会看到**一个**数字:该列所有交易的*金额*之和,也就是这个阶段的未加权合计。看板每列只能有这一个数,这是设计使然:一块看板只声明一个 `summarizeField`(`src/views/opportunity.view.ts`),而这块板把它绑到了 `amount`。

Expand Down Expand Up @@ -82,7 +85,7 @@ description: 销售管道的日常运作方式——推进交易、自动概率

| 节奏 | 该做什么 |
| --- | --- |
| **每日** | 打开销售管道看板。找出停滞的卡片(阶段内 > 14 天)。推进或关闭。 |
| **每日** | 打开**销售管道**这块板。找出停滞的卡片(阶段内 > 14 天)。推进或关闭。 |
| **每周** | 运行 *Pipeline Coverage*。向 Sales Copilot 提问:*"what's at risk?"* |
| **每月** | 运行 *Opportunity Funnel by Owner → Stage*。对漏斗漏水的销售代表进行一对一辅导。 |
| **季末** | 运行 *Won Opportunities by Owner* 以计算提成。归档*失败*的交易并附上*丢单原因*。 |
Expand Down
11 changes: 7 additions & 4 deletions content/docs/sales/pipeline-management.zh-Hant.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,18 @@ description: 銷售管道的日常運作方式——推進交易、自動機率

## 銷售管道看板視圖

這塊看板是商機上的**銷售流水線**視圖(`pipeline_kanban`),側邊欄上打開它的那個條目寫作**銷售管道**。它將銷售管道顯示為 7 列——每個階段一列。每張卡片顯示:
這塊看板是商機上的**銷售流水線**視圖(`pipeline_kanban`),側邊欄上打開它的那個條目寫作**銷售管道**。它把銷售管道按**每個階段一列**鋪開,且**只放在飛交易**:這塊板自帶過濾器——`src/views/opportunity.view.ts` 裡的 `stage not_in [closed_won, closed_lost]`——所以只有五個活躍階段(*尋找客戶*、*資格審查*、*需求分析*、*提案*、*談判*)裡才可能有卡片。已結束的生意不是被藏了,而是在別處:**全部商機**檢視與 **Sales Performance** 儀表板都算上它們。至於那兩個已結束階段是被畫成永遠空著的欄、還是乾脆不出現在板上,那是 console 的算繪選擇,本應用的元資料並沒有宣告——無論哪種,這塊板上都沒有已結束的交易可找。

每張卡片帶的是這塊板綁定的四個欄位(`kanban.columns`):

- 商機名稱
- 客戶
- 金額
- 成交日期
- 負責人頭像

要推進一筆交易,只需**拖動卡片**到下一列。系統會強制執行階段規則,因此你無法從*尋找客戶*直接拖到*成交*。
**卡片上沒有負責人。** `owner_id` 在這個檢視頂層的 `columns` 清單裡,那是給網格類算繪讀的;卡面綁定只點了上面四個欄位,到此為止。要在交易旁邊看到負責人,請用帶 *Owner* 欄的**全部商機**檢視,或者卡面確實帶負責人的 **Deal Cards** 圖庫檢視。

要推進一筆交易,只需**拖動卡片**到下一列。階段規則是**建議,不是閘門**。`opportunity_stage_progression`(`src/objects/opportunity.object.ts`)宣告了哪些躍遷合法——*尋找客戶*直接到*成交*並不在其中——但這條規則是**警告**級,所以走出轉換表的移動只會往伺服器日誌寫一行 *「Invalid opportunity stage transition」*,而**儲存照樣通過**。看板上沒有任何東西會攔住你。日誌給你的價值是:一次糟糕的匯入、一個行為異常的整合,事後還能被找出來。這張表能做什麼、不能做什麼,詳見 [Administration › State Machines](/zh-Hant/docs/administration/state-machines)。

在每列頂部你會看到**一個**數字:該列所有交易的*金額*之和,也就是這個階段的未加權合計。看板每列只能有這一個數,這是設計使然:一塊看板只宣告一個 `summarizeField`(`src/views/opportunity.view.ts`),而這塊板把它綁到了 `amount`。

Expand Down Expand Up @@ -82,7 +85,7 @@ description: 銷售管道的日常運作方式——推進交易、自動機率

| 節奏 | 該做什麼 |
| --- | --- |
| **每日** | 打開銷售管道看板。找出停滯的卡片(階段內 > 14 天)。推進或關閉。 |
| **每日** | 打開**銷售管道**這塊板。找出停滯的卡片(階段內 > 14 天)。推進或關閉。 |
| **每週** | 執行 *Pipeline Coverage*。向 Sales Copilot 提問:*"what's at risk?"* |
| **每月** | 執行 *Opportunity Funnel by Owner → Stage*。對漏斗漏水的銷售代表進行一對一輔導。 |
| **季末** | 執行 *Won Opportunities by Owner* 以計算提成。歸檔*失敗*的交易並附上*丟單原因*。 |
Expand Down
Loading
Loading