diff --git a/.changeset/2362-docs-site-measured-rules.md b/.changeset/2362-docs-site-measured-rules.md new file mode 100644 index 000000000..d68cd77df --- /dev/null +++ b/.changeset/2362-docs-site-measured-rules.md @@ -0,0 +1,13 @@ +--- +"hotcrm": patch +--- + +Clause-②: no +Metadata-protocol: none + +**The documentation site now states four rules the way the app enforces them.** Nothing in the app changes; the pages were wrong, in English and both Chinese versions. + +- **Setup checklist, lead routing:** only a lead from the public web-to-lead form goes to the sales-rep round-robin. A lead created in the app, sent through the API, or imported from a CSV or JSON file is owned by the person who put it in, and the page links the import guide's section on owners. +- **Products:** a List Price of zero is accepted and only a negative one is refused; a Cost above the List Price is refused rather than warned about. +- **Campaigns:** the End Date must be after the Start Date, so a campaign that ends on the day it starts is refused. +- **Campaigns, attribution:** converting a lead does not set the Campaign on the opportunity it creates, even when the lead is a member of a campaign, so the deal is credited only once someone sets Campaign on it. The field is named by its real label, *Campaign*, instead of *Source Campaign*. diff --git a/content/docs/administration/setup.mdx b/content/docs/administration/setup.mdx index 54e58a873..3aafcc68d 100644 --- a/content/docs/administration/setup.mdx +++ b/content/docs/administration/setup.mdx @@ -65,7 +65,9 @@ What follows from that is on the SLA side: deadlines run on **calendar hours**. ### 8. Lead routing — nothing to configure -**There is no Setup → Lead Settings screen**, and there are no routing rules to write. An ownerless lead — web-to-lead, CSV import, API capture — is assigned on insert by `src/sales/objects/lead.hook.ts`: it goes to whichever holder of the `sales_rep` position has the **fewest open leads**. That is a self-balancing round-robin, not a rule matching region, industry or source; there is no territory routing, no queue, and no auto-response email to the submitter. If nobody holds `sales_rep` the hook does nothing and the lead stays ownerless until someone claims it. +**There is no Setup → Lead Settings screen**, and there are no routing rules to write. Web-to-lead is the one way into the round-robin: a lead submitted through the public web form arrives with nobody behind it, so it is assigned on insert by `src/sales/objects/lead.hook.ts` to whichever holder of the `sales_rep` position has the **fewest open leads**. That is a self-balancing round-robin, not a rule matching region, industry or source; there is no territory routing, no queue, and no auto-response email to the submitter. If nobody holds `sales_rep` the hook does nothing and the lead stays ownerless until someone claims it. + +Every other way a lead comes in has a person behind it, and that person becomes the owner: a lead created in the app, one sent through the API under someone's sign-in or API key, and one imported from a CSV or JSON file. An import never goes to the round-robin — a row with a blank owner is owned by whoever ran the import, so plan to reassign imported leads afterwards. See [Owners](/docs/guides/importing-your-data#owners) in *Import your own data*. - [ ] Assign the `sales_rep` position to every rep who should receive intake — that pool *is* the routing table - [ ] Read what happens next in the `lead_assignment` flow (a rating-based follow-up date, and an alert to the new owner) at **Studio → Automation → Flows** diff --git a/content/docs/administration/setup.zh-Hans.mdx b/content/docs/administration/setup.zh-Hans.mdx index cdfd39958..c63add8b5 100644 --- a/content/docs/administration/setup.zh-Hans.mdx +++ b/content/docs/administration/setup.zh-Hans.mdx @@ -65,7 +65,9 @@ description: 让 HotCRM 为你的团队做好生产准备的第一周任务。 ### 8. 潜在客户路由 —— 没有需要配置的东西 -**不存在“系统设置 → 潜在客户设置”这个屏幕**,也没有任何路由规则可写。一条无所有者的线索 —— 网页表单、CSV 导入、API 采集 —— 会在插入时由 `src/sales/objects/lead.hook.ts` 分配:交给持有 `sales_rep` 岗位的人中**未结线索最少**的那一位。这是一个自平衡的轮询,而不是按区域、行业或来源匹配的规则;没有区域路由,没有队列,也没有发给提交者的自动回复邮件。如果没有人持有 `sales_rep`,这个钩子什么也不做,线索就一直无主,直到有人认领。 +**不存在“系统设置 → 潜在客户设置”这个屏幕**,也没有任何路由规则可写。网页表单(web-to-lead)是进入轮询的唯一入口:通过公开网页表单提交的线索背后没有具体的人,所以会在插入时由 `src/sales/objects/lead.hook.ts` 分配:交给持有 `sales_rep` 岗位的人中**未结线索最少**的那一位。这是一个自平衡的轮询,而不是按区域、行业或来源匹配的规则;没有区域路由,没有队列,也没有发给提交者的自动回复邮件。如果没有人持有 `sales_rep`,这个钩子什么也不做,线索就一直无主,直到有人认领。 + +其他所有来路的线索背后都有一个人,这个人就是所有者:在应用里新建的线索、用某人的登录或 API 密钥通过 API 提交的线索,以及从 CSV 或 JSON 文件导入的线索。导入从不进入轮询 —— 所有者留空的行归执行导入的人所有,所以导入线索之后要安排重新分配。参见[导入你自己的数据](/zh-Hans/docs/guides/importing-your-data)中的“关于负责人”一节。 - [ ] 把 `sales_rep` 岗位分配给每一位应当接收线索的销售代表 —— 这个人员池*就是*路由表 - [ ] 在 **Studio → 自动化 → 流程** 中查看接下来 `lead_assignment` 流程做了什么(按评级设置跟进日期,并提醒新的所有者) diff --git a/content/docs/administration/setup.zh-Hant.mdx b/content/docs/administration/setup.zh-Hant.mdx index 69100a69f..560a747be 100644 --- a/content/docs/administration/setup.zh-Hant.mdx +++ b/content/docs/administration/setup.zh-Hant.mdx @@ -67,7 +67,9 @@ description: 讓 HotCRM 為你的團隊做好生產準備的第一週任務。 ### 8. 潛在客戶路由 —— 沒有需要設定的東西 -**不存在「Setup → Lead Settings」這個畫面**,也沒有任何路由規則可寫。一條無所有者的潛在客戶 —— 網頁表單、CSV 匯入、API 擷取 —— 會在插入時由 `src/sales/objects/lead.hook.ts` 指派:交給持有 `sales_rep` 職位的人當中**未結潛在客戶最少**的那一位。這是一個自平衡的輪詢,而不是按區域、行業或來源比對的規則;沒有區域路由,沒有佇列,也沒有發給提交者的自動回覆郵件。如果沒有人持有 `sales_rep`,這個掛鉤什麼也不做,潛在客戶就一直無主,直到有人認領。 +**不存在「Setup → Lead Settings」這個畫面**,也沒有任何路由規則可寫。網頁表單(web-to-lead)是進入輪詢的唯一入口:透過公開網頁表單提交的潛在客戶背後沒有具體的人,所以會在插入時由 `src/sales/objects/lead.hook.ts` 指派:交給持有 `sales_rep` 職位的人當中**未結潛在客戶最少**的那一位。這是一個自平衡的輪詢,而不是按區域、行業或來源比對的規則;沒有區域路由,沒有佇列,也沒有發給提交者的自動回覆郵件。如果沒有人持有 `sales_rep`,這個掛鉤什麼也不做,潛在客戶就一直無主,直到有人認領。 + +其他所有來路的潛在客戶背後都有一個人,這個人就是所有者:在應用裡新建的潛在客戶、用某人的登入或 API 金鑰透過 API 提交的潛在客戶,以及從 CSV 或 JSON 檔案匯入的潛在客戶。匯入從不進入輪詢 —— 所有者留空的列歸執行匯入的人所有,所以匯入潛在客戶之後要安排重新指派。參見[匯入你自己的資料](/zh-Hant/docs/guides/importing-your-data)中的「關於負責人」一節。 - [ ] 把 `sales_rep` 職位指派給每一位應當接收潛在客戶的業務代表 —— 這個人員池*就是*路由表 - [ ] 在 **Studio → Automation → Flows** 中查看接下來 `lead_assignment` 流程做了什麼(按評級設定跟進日期,並提醒新的所有者) diff --git a/content/docs/marketing/campaigns.mdx b/content/docs/marketing/campaigns.mdx index 55542ebd7..a0d0026c4 100644 --- a/content/docs/marketing/campaigns.mdx +++ b/content/docs/marketing/campaigns.mdx @@ -52,7 +52,7 @@ The **Campaign Code** is auto-generated (e.g., CAMP-000123) so every campaign ha ## Built-in rules -- **End date must be on or after the start date** — basic sanity check. +- **End date must be after the start date** — a campaign that ends on the day it starts is refused, so even a one-day event runs from its start date to the next day. - **Over-budget warning** — if actual cost exceeds budgeted cost, a warning shows on the record. Doesn't block saves, but flags the campaign for finance review. ## What happens automatically @@ -95,7 +95,7 @@ The numbers live on the campaign record itself — the counters and the response ## Attribution: from campaign to revenue -The link is the **Source Campaign** lookup on the opportunity. When a sales rep converts a lead that came from a campaign — or manually sets the source campaign on an opportunity — the system credits the revenue back to the campaign. +The link is the **Campaign** lookup on the opportunity, and it is set by hand. Converting a lead does not fill it in, even when the lead is a member of a campaign: the lead's membership is marked *Converted* and the campaign counts a converted lead, but the opportunity the conversion creates names no campaign, so neither the deal nor its revenue is credited to the campaign. The conversion screen has no Campaign field, so set **Campaign** on the opportunity afterwards; from then on the campaign counts the deal and, once it is won, its revenue. For deals influenced by multiple campaigns (multi-touch), the convention is to record the **last-touch** campaign (the one closest to conversion). For full multi-touch attribution, consider extending the model with a campaign-influence join object — see [Customization](/docs/customization/extending-objects). @@ -126,7 +126,7 @@ Campaigns are **public read-only** for the whole organisation. Anyone in sales c ## Tips for sales reps - ✅ When a lead arrives, check whether they're in a campaign — it tells you which campaigns they were sent, and how they answered. -- ✅ Set **Source Campaign** on opportunities you closed — marketing can't measure ROI without this. +- ✅ Set **Campaign** on the opportunities that came from a campaign, including the ones you converted from a lead — nothing sets it for you, and marketing can't measure ROI without it. ## Tips for admins diff --git a/content/docs/marketing/campaigns.zh-Hans.mdx b/content/docs/marketing/campaigns.zh-Hans.mdx index e1c3fb16f..24f996431 100644 --- a/content/docs/marketing/campaigns.zh-Hans.mdx +++ b/content/docs/marketing/campaigns.zh-Hans.mdx @@ -52,7 +52,7 @@ description: 规划、启动并衡量市场营销举措——电子邮件、网 ## 内置规则 -- **结束日期必须在开始日期当天或之后** — 基本的合理性检查。 +- **结束日期必须晚于开始日期** — 在开始当天就结束的营销活动会被拒绝,所以即使是一天的活动,也要从开始日期排到第二天。 - **超预算警告** — 如果实际成本超过预算成本,记录上会显示警告。它不会阻止保存,但会标记该营销活动以供财务审查。 ## 自动发生的事 @@ -95,7 +95,7 @@ description: 规划、启动并衡量市场营销举措——电子邮件、网 ## 归因:从营销活动到收入 -连接点是商机上的 **Source Campaign** 查找字段。当销售代表转化一个来自营销活动的线索时——或在商机上手动设置来源营销活动时——系统会将收入归功于该营销活动。 +连接点是商机上的 **Campaign** 查找字段,它需要手动设置。转化线索不会填写它,即使这条线索是某个营销活动的成员:线索的成员状态会变为 *Converted*,营销活动也会计入一条已转化线索,但转化创建的商机不指向任何营销活动,所以这笔交易和它的收入都不会归功于该营销活动。转化界面上没有 Campaign 字段,所以要在转化之后到商机上设置 **Campaign**;从那时起营销活动才会计入这笔交易,并在赢单后计入它的收入。 对于受多个营销活动影响的交易(多触点),惯例是记录**末次触点**营销活动(最接近转化的那个)。要实现完整的多触点归因,可考虑使用营销活动影响联接对象扩展模型——请参阅 [自定义](/zh-Hans/docs/customization/extending-objects)。 @@ -126,7 +126,7 @@ description: 规划、启动并衡量市场营销举措——电子邮件、网 ## 给销售代表的提示 - ✅ 当一个线索到来时,检查他们是否在某个营销活动中——它会告诉你他们被发送过哪些营销活动,以及他们是怎么回应的。 -- ✅ 在你成交的商机上设置 **Source Campaign**——没有它市场营销就无法衡量 ROI。 +- ✅ 在来自营销活动的商机上设置 **Campaign**,包括你从线索转化而来的商机——没有任何东西会替你设置它,而没有它市场营销就无法衡量 ROI。 ## 给管理员的提示 diff --git a/content/docs/marketing/campaigns.zh-Hant.mdx b/content/docs/marketing/campaigns.zh-Hant.mdx index 6eb8f1046..1a5c8a8f5 100644 --- a/content/docs/marketing/campaigns.zh-Hant.mdx +++ b/content/docs/marketing/campaigns.zh-Hant.mdx @@ -54,7 +54,7 @@ description: 規劃、啟動並衡量行銷舉措——電子郵件、網路研 ## 內建規則 -- **結束日期必須在開始日期當天或之後** — 基本的合理性檢查。 +- **結束日期必須晚於開始日期** — 在開始當天就結束的行銷活動會被拒絕,所以即使是一天的活動,也要從開始日期排到第二天。 - **超預算警告** — 如果實際成本超過預算成本,記錄上會顯示警告。它不會阻止儲存,但會標記該行銷活動以供財務審查。 ## 自動發生的事 @@ -97,7 +97,7 @@ description: 規劃、啟動並衡量行銷舉措——電子郵件、網路研 ## 歸因:從行銷活動到收入 -連接點是商機上的 **Source Campaign** 查閱欄位。當業務代表轉化一個來自行銷活動的潛在客戶時——或在商機上手動設定來源行銷活動時——系統會將收入歸功於該行銷活動。 +連接點是商機上的 **Campaign** 查閱欄位,它需要手動設定。轉化潛在客戶不會填寫它,即使這條潛在客戶是某個行銷活動的成員:潛在客戶的成員狀態會變為 *Converted*,行銷活動也會計入一條已轉化潛在客戶,但轉化建立的商機不指向任何行銷活動,所以這筆交易和它的收入都不會歸功於該行銷活動。轉化畫面上沒有 Campaign 欄位,所以要在轉化之後到商機上設定 **Campaign**;從那時起行銷活動才會計入這筆交易,並在贏單後計入它的收入。 對於受多個行銷活動影響的交易(多接觸點),慣例是記錄**末次接觸點**行銷活動(最接近轉化的那個)。要實現完整的多接觸點歸因,可考慮使用行銷活動影響聯結物件擴充模型——請參閱 [自訂](/zh-Hant/docs/customization/extending-objects)。 @@ -128,7 +128,7 @@ description: 規劃、啟動並衡量行銷舉措——電子郵件、網路研 ## 給業務代表的提示 - ✅ 當一個潛在客戶到來時,檢查他們是否在某個行銷活動中——它會告訴你他們被寄送過哪些行銷活動,以及他們是怎麼回應的。 -- ✅ 在你成交的商機上設定 **Source Campaign**——沒有它行銷就無法衡量 ROI。 +- ✅ 在來自行銷活動的商機上設定 **Campaign**,包括你從潛在客戶轉化而來的商機——沒有任何東西會替你設定它,而沒有它行銷就無法衡量 ROI。 ## 給管理員的提示 diff --git a/content/docs/revenue/products.mdx b/content/docs/revenue/products.mdx index 05dbd2f97..55ec1cd8f 100644 --- a/content/docs/revenue/products.mdx +++ b/content/docs/revenue/products.mdx @@ -45,7 +45,7 @@ Categories and families let you slice reports by product mix — *"how much SMB- | **List Price** | Standard published price — what shows up on a quote by default | | **Cost** | Your cost — used for margin calculation | -The system warns you if Cost is greater than List Price (which would be a losing sale). +Cost may not be greater than List Price: a save that would make it so is refused, since every sale would lose money. **Tax is a quote-level figure, and the catalog carries no rate.** A quote's total is *subtotal − discount + Tax + Shipping*, where **Tax** is an amount you type on the quote itself; a quote line item carries no tax of its own. A product record stores nothing about tax. @@ -64,8 +64,8 @@ Nothing reads the file's contents. There is no *Product Information* knowledge b ## Built-in rules -- **List price must be greater than zero** — you can't sell a free product (use a $0.01 list price with a 100% discount if you really need to). -- **Cost cannot exceed list price** — warning only, doesn't block save. +- **List price cannot be negative** — a negative List Price is refused. Zero is accepted, so a free product can sit in the catalog at a list price of 0. +- **Cost cannot exceed list price** — a save with Cost above List Price is refused, whether it is a new product or a change to either price. A cost equal to the list price saves. - **Unit price on opportunity / quote line items must be zero or positive** — basic validation. ## Sharing — products are public by default diff --git a/content/docs/revenue/products.zh-Hans.mdx b/content/docs/revenue/products.zh-Hans.mdx index 6283d77ce..b81b5b97b 100644 --- a/content/docs/revenue/products.zh-Hans.mdx +++ b/content/docs/revenue/products.zh-Hans.mdx @@ -45,7 +45,7 @@ description: 你所销售内容的目录——编码、标价和 SKU。 | **List Price** | 标准公布价——默认显示在报价上的价格 | | **Cost** | 你的成本——用于利润计算 | -如果成本大于标价(这会是一笔亏本的销售),系统会警告你。 +成本不能大于标价:会造成这种情况的保存会被拒绝,因为那样每一笔销售都会亏本。 **税是报价单层面的数字,产品目录不保存任何税率。** 报价单的总额是 *小计 − 折扣 + 税额 + 运费*,其中**税额**是你在报价单上自己填的一个金额;报价明细行不单独计税。产品记录不保存任何与税相关的内容。 @@ -64,8 +64,8 @@ description: 你所销售内容的目录——编码、标价和 SKU。 ## 内置规则 -- **标价必须大于零**——你不能销售一个免费产品(如果你确实需要,可使用 $0.01 的标价配合 100% 折扣)。 -- **成本不能超过标价**——仅警告,不阻止保存。 +- **标价不能为负数**——负的标价会被拒绝。零是允许的,所以免费产品可以以 0 的标价放在目录里。 +- **成本不能超过标价**——成本高于标价的保存会被拒绝,无论是新建产品还是修改其中任一价格。成本等于标价时可以保存。 - **商机 / 报价明细行上的单价必须为零或正数**——基本验证。 ## 共享——产品默认公开 diff --git a/content/docs/revenue/products.zh-Hant.mdx b/content/docs/revenue/products.zh-Hant.mdx index 8961f5295..ce3e90834 100644 --- a/content/docs/revenue/products.zh-Hant.mdx +++ b/content/docs/revenue/products.zh-Hant.mdx @@ -47,7 +47,7 @@ description: 你所銷售內容的目錄——編碼、標價和 SKU。 | **List Price** | 標準公佈價——預設顯示在報價上的價格 | | **Cost** | 你的成本——用於利潤計算 | -如果成本大於標價(這會是一筆虧本的銷售),系統會警告你。 +成本不能大於標價:會造成這種情況的儲存會被拒絕,因為那樣每一筆銷售都會虧本。 **稅是報價單層級的數字,產品目錄不保存任何稅率。** 報價單的總額是 *小計 − 折扣 + 稅額 + 運費*,其中**稅額**是你在報價單上自己填的一個金額;報價明細行不單獨計稅。產品記錄不保存任何與稅相關的內容。 @@ -66,8 +66,8 @@ description: 你所銷售內容的目錄——編碼、標價和 SKU。 ## 內建規則 -- **標價必須大於零**——你不能銷售一個免費產品(如果你確實需要,可使用 $0.01 的標價配合 100% 折扣)。 -- **成本不能超過標價**——僅警告,不阻止儲存。 +- **標價不能為負數**——負的標價會被拒絕。零是允許的,所以免費產品可以以 0 的標價放在目錄裡。 +- **成本不能超過標價**——成本高於標價的儲存會被拒絕,無論是新增產品還是修改其中任一價格。成本等於標價時可以儲存。 - **商機 / 報價明細行上的單價必須為零或正數**——基本驗證。 ## 共享——產品預設公開