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
23 changes: 23 additions & 0 deletions .changeset/service-behavior-residue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
'hotcrm': patch
---

按 flow / hook / skill 源码写实 service 三页族剩下的两组行为性失实,三语同步(#886、#890)。

**#886 — `content/docs/service/sla-and-escalation.mdx` 及其 `zh-Hans` / `zh-Hant` 双生页**

- **升级触发条件里那个 `High + Customer` 分支根本不存在。** 页面「何时触发升级」一节写着「Critical,**或者** High 优先级且关联账户为 Customer」,管理员提示里又复述了一遍。`src/flows/case-escalation.flow.ts` 的 start 条件全文只有一个优先级项 —— `record.priority == "critical"` —— 外加防止二次升级的 `escalated_date` / `status` 守卫;它的 insert 版孪生 `case_escalation_on_create` 复用同一条件,只把 `triggerType` 换成 `record-after-create`。全仓 24 个 flow 里没有任何一处读取账户类型或账户分层。现在写实为:只有 Critical 会自动升级;**High 工单永远不会**,无论其账户是 Customer 还是潜在客户,升级它是手动步骤(工单记录上的 Escalate Case 按钮)。管理员提示同步改为点名两个流程,并提醒改条件要两个一起改,否则新建路径仍会漏掉。
- **兜底路径对 High 同样不生效。** `case_sla_monitor` 按 `sla_due_date` 过期扫单,但 `src/objects/case.hook.ts` 只为 `critical` 打 4 小时 SLA,其余优先级一律留空(该字段非 readonly,可以手工填)。所以一个没人过问的 High 工单两条路径都进不去 —— 页面现在明说这批工单需要人工巡检。此处只陈述当前行为,不预判 High 是否*应该*自动升级或*应该*有 SLA(#595 的产品问题)。
- **Critical 违约行承诺的两样东西都不存在。** SLA 目标表 Critical 行写的是「工单详情上的红色横幅、向支持经理发出警报」。`grep -rn banner src/` 在整个 app 里只有 `src/objects/opportunity.object.ts` 的一句无关注释 —— 没有任何横幅机制;违约通知来自 `src/flows/case-sla-monitor.flow.ts` 的 `notify` 节点,`recipients` 只有 `{currentCase.owner_id}` 一项,节点标签就叫 `Alert Owner`。现在写实为:SLA 监控标记违约、升级工单、通过站内消息 + 邮件提醒**工单负责人**,并点名说清没有红色横幅、也不通知支持经理。

**#890 — `content/docs/service/cases.mdx`、`content/docs/service/index.mdx`、`content/docs/service/sla-and-escalation.mdx` 及各自的 `zh-Hans` / `zh-Hant`**

三页把「检索知识库并起草回复」「用知识库对相似历史工单做模式匹配」记在做不到这件事的技能名下:

- `src/skills/case-triage.skill.ts` 的 `tools` 只有 `['describe_object', 'get_record']` —— 没有任何检索类工具,既检索不了文章,也拉不出相似的历史工单;
- `src/skills/email-drafting.skill.ts` 的五步 instructions 从头到尾没有一步去取知识来源,因此草稿不会引用文章;
- 真正读文章的是 `src/skills/customer-360.skill.ts`,它用 `query_records` 查 `status` 已发布、按工单的 category / tags 匹配的 `crm_knowledge_article`。

三处整句按 #861 / #865 的既有口径重写:检索归 Customer 360°,起草回复归邮件撰写,并说明工单分流两件都不做。句中「Support Knowledge Base」是 #808 / #892 已清掉的虚构知识库名,链接保持指向 `/docs/service/knowledge-base`,标签改为该页的真实称谓(知识文章 / knowledge articles)。

纯文档改动,9 个文件。未触碰 `src/**`,没有任何 flow、hook、skill、条件、收件人或字段发生变化 —— 是页面向已经在跑的行为对齐。
2 changes: 1 addition & 1 deletion content/docs/service/cases.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ You don't have to configure any of this — every CRM object ships with `trackHi
The [service skills](/docs/ai-copilot/service-copilot) auto-activate on any case. Ask:

- *"Triage this case"* — Case Triage skill recommends a priority based on subject and description.
- *"Suggest a resolution"* — searches the [Support Knowledge Base](/docs/service/knowledge-base) and drafts a customer reply.
- *"Suggest a resolution"* — no one skill does this end to end. **Case Triage** declares two tools, `describe_object` and `get_record`, and no query tool at all, so it searches nothing. Ask **Customer 360°** for the published [knowledge articles](/docs/service/knowledge-base) matched on the case's category or tags, then **Email Drafting** for the customer reply — the draft is grounded in the contact and account records, not in those articles, so paste in whatever it should quote.
- *"Customer 360"* — pulls the full account context (open opportunities, past cases, contract tier).

If the Copilot decides the priority is *Critical*, it will also recommend immediate escalation and draft an internal notification message.
Expand Down
2 changes: 1 addition & 1 deletion content/docs/service/cases.zh-Hans.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ Activity 标签页是工单上发生过什么的唯一可信来源。它将四
[服务技能](/zh-Hans/docs/ai-copilot/service-copilot) 会在任何工单上自动激活。你可以问:

- *"分流这个工单"*——工单分流技能根据主题和描述推荐优先级。
- *"建议一个解决方案"*——搜索[支持知识库](/zh-Hans/docs/service/knowledge-base)并起草客户回复。
- *"建议一个解决方案"*——没有哪个技能能端到端做完这件事。**工单分流**只声明了 `describe_object` 与 `get_record` 两个工具,完全没有检索类工具,因此它什么都不检索。请向 **Customer 360°** 要按工单分类或标签匹配出来的已发布[知识文章](/zh-Hans/docs/service/knowledge-base),再向**邮件撰写**要客户回复——草稿的依据是联系人与账户记录,而不是那些文章,需要援引哪一篇请自己贴进去。
- *"Customer 360"*——拉取完整的账户上下文(未结商机、过往工单、合同等级)。

如果 Copilot 判断优先级为 *Critical*,它还会建议立即升级并起草内部通知消息。
Expand Down
2 changes: 1 addition & 1 deletion content/docs/service/cases.zh-Hant.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ Activity 標籤頁是工單上發生過什麼的唯一可信來源。它將四
[服務技能](/zh-Hant/docs/ai-copilot/service-copilot) 會在任何工單上自動啟動。你可以問:

- *"分流這個工單"*——工單分流技能根據主題和描述推薦優先順序。
- *"建議一個解決方案"*——搜尋[支援知識庫](/zh-Hant/docs/service/knowledge-base)並起草客戶回覆。
- *"建議一個解決方案"*——沒有哪個技能能端到端做完這件事。**工單分流**只宣告了 `describe_object` 與 `get_record` 兩個工具,完全沒有檢索類工具,因此它什麼都不檢索。請向 **Customer 360°** 要按工單分類或標籤匹配出來的已發布[知識文章](/zh-Hant/docs/service/knowledge-base),再向**郵件撰寫**要客戶回覆——草稿的依據是聯絡人與帳戶記錄,而不是那些文章,需要援引哪一篇請自己貼進去。
- *"Customer 360"*——拉取完整的帳戶上下文(未結商機、過往工單、合約等級)。

如果 Copilot 判斷優先順序為 *Critical*,它還會建議立即升級並起草內部通知訊息。
Expand Down
2 changes: 1 addition & 1 deletion content/docs/service/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ New ──► In Progress ──► Waiting on Customer ──► Resolved ─
The [service skills](/docs/ai-copilot/service-copilot) are built into every case. Ask the assistant:

- *"Triage this case"* — assigns a priority based on subject, description and customer tier.
- *"Suggest a resolution"* — searches the support knowledge base and drafts a customer reply.
- *"Suggest a resolution"* — two skills, not one. **Customer 360°** reads the published knowledge articles (`crm_knowledge_article` is an ordinary object it queries), and **Email Drafting** writes the customer reply. Case Triage does neither: it has no query tool, and no drafting step.
- *"Summarise this customer"* — Customer 360 view including past cases and open opportunities.

## Standard dashboards & reports
Expand Down
2 changes: 1 addition & 1 deletion content/docs/service/index.zh-Hans.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ New ──► In Progress ──► Waiting on Customer ──► Resolved ─
[服务技能](/zh-Hans/docs/ai-copilot/service-copilot) 内置于每个工单中。你可以问助手:

- *"分流这个工单"*——根据主题、描述和客户等级分配优先级。
- *"建议一个解决方案"*——搜索支持知识库并起草客户回复。
- *"建议一个解决方案"*——这是两个技能的事,不是一个。**Customer 360°** 读取已发布的知识文章(`crm_knowledge_article` 就是它查询的一个普通对象),**邮件撰写**写客户回复。工单分流两件都不做:它没有检索类工具,也没有起草这一步。
- *"总结这个客户"*——包括过往工单和未结商机的 Customer 360 视图。

## 标准仪表盘与报表
Expand Down
2 changes: 1 addition & 1 deletion content/docs/service/index.zh-Hant.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ New ──► In Progress ──► Waiting on Customer ──► Resolved ─
[服務技能](/zh-Hant/docs/ai-copilot/service-copilot) 內建於每個工單中。你可以問助手:

- *"分流這個工單"*——根據主題、描述和客戶等級分配優先順序。
- *"建議一個解決方案"*——搜尋支援知識庫並起草客戶回覆。
- *"建議一個解決方案"*——這是兩個技能的事,不是一個。**Customer 360°** 讀取已發布的知識文章(`crm_knowledge_article` 就是它查詢的一個普通物件),**郵件撰寫**寫客戶回覆。工單分流兩件都不做:它沒有檢索類工具,也沒有起草這一步。
- *"總結這個客戶"*——包括過往工單和未結商機的 Customer 360 檢視。

## 標準儀表板與報表
Expand Down
16 changes: 10 additions & 6 deletions content/docs/service/sla-and-escalation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Every case gets an **SLA due date** the moment it's created. The target is based

| Priority | Default SLA target | What "breach" looks like |
| --- | --- | --- |
| **Critical** | 4 hours | Red banner on case detail, alert to support manager |
| **Critical** | 4 hours | The SLA monitor flags **SLA Violated**, escalates the case, and alerts the **case owner** by inbox + email. No red banner on the case detail page — this app has no banner mechanism — and no alert to a support manager: the notify node's recipient list is `{currentCase.owner_id}` alone |
| **High** | 8 hours | Red badge in list views |
| **Medium** | 2 business days | Amber badge |
| **Low** | 7 business days | Grey badge |
Expand Down Expand Up @@ -54,10 +54,14 @@ The Case Escalation process automatically flags stuck or critical cases as escal

### When escalation triggers

The escalation flow runs the moment a case meets either of these conditions:
The escalation flow runs on exactly one condition: **the case is at Critical priority**. Two flows carry that condition — `case_escalation` fires when a case is *edited* to Critical, `case_escalation_on_create` when a case is *created* Critical — and both read `record.priority == "critical"`, alongside the guards that keep an already-escalated, resolved or closed case from being escalated a second time.

- The case is set to **Critical** priority, OR
- The case is **High** priority **AND** the related account is a **Customer** (not a prospect)
Two conditions this page used to list do not exist:

- **There is no High-priority branch.** A High case is never escalated automatically. Raising one is a manual step — the **Escalate Case** button on the case record.
- **No escalation condition reads the account.** Neither *Customer* nor *prospect*, nor any account tier, appears in any of them — no flow in this app reads an account's type at all. A Customer's High case and a prospect's High case are treated identically: neither escalates on its own.

The time-based path does not catch them either. `case_sla_monitor` escalates any open case whose **SLA Due Date** has passed, but nothing stamps that date on a High case: the SLA hook fills `sla_due_date` for `critical` only and leaves it empty at every other priority, unless a person sets it by hand. So a High case nobody touches enters neither path — plan a human review pass for those rather than waiting on an automation.

### What the escalation does

Expand Down Expand Up @@ -102,7 +106,7 @@ The [Service Copilot's Case Triage skill](/docs/ai-copilot/skills#case-triage) c

- A customer-tier account with a vague subject still gets **High** because of the customer relationship.
- A prospect with *"production is down"* in the description gets **Critical** despite not being a paying customer.
- The Copilot uses the [Support Knowledge Base](/docs/service/knowledge-base) to pattern-match against similar past cases.
- **Case Triage does not** pattern-match against similar past cases. It declares `describe_object` and `get_record` only, so it reads the one case in front of it and can neither search [knowledge articles](/docs/service/knowledge-base) nor pull up the account's other cases. Matching published articles on a case's category or tags is **Customer 360°**'s job, and a separate ask.

If priority resolves to **Critical**, the Copilot immediately recommends escalation and drafts an internal notification message.

Expand Down Expand Up @@ -131,5 +135,5 @@ If priority resolves to **Critical**, the Copilot immediately recommends escalat

- The SLA target per priority is set via the case object's automation (a SLA-calculation hook). To adjust, edit `src/objects/case.hook.ts` (binds to `crm_case`) or change the underlying configuration — see [Administration › Automation](/docs/administration/automation).
- Business-hours vs. calendar-hours behaviour is controlled by your tenant's business-hours setup. See [Administration › Setup](/docs/administration/setup).
- Escalation triggers (Critical, or High+Customer) live in the [Case Escalation flow definition](/docs/administration/automation#flows-multi-step). Adjust the condition there to change when escalation fires.
- The escalation trigger — Critical priority, and nothing else; there is no High+Customer condition — lives in the [Case Escalation flow definition](/docs/administration/automation#flows-multi-step), i.e. `src/flows/case-escalation.flow.ts`. Two flows carry it: `case_escalation` (on update) and `case_escalation_on_create` (on insert). Change the condition in **both**, or a case created at the new priority still slips through.
- Neither recipient list is configurable on a Setup screen. *Notify on Critical* is the Case Escalation flow's `notify` node, and its list is the single entry `{caseRecord.owner_id}` — edit it in `src/flows/case-escalation.flow.ts`. *Notify on Escalation* has no recipient list at all, because it sends no message: what the escalated status fires is the `case_status_side_effects` hook in `src/objects/case.hook.ts`, and the person it reaches is the account owner, through the follow-up task.
16 changes: 10 additions & 6 deletions content/docs/service/sla-and-escalation.zh-Hans.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ SLA(服务级别协议)系统根据每个工单的优先级为其赋予一

| 优先级 | 默认 SLA 目标 | "违约"是什么样子 |
| --- | --- | --- |
| **Critical** | 4 小时 | 工单详情上的红色横幅、向支持经理发出警报 |
| **Critical** | 4 小时 | SLA 监控流程把它标记为 **SLA 已违约**并升级,然后通过站内消息 + 邮件提醒**工单负责人**。工单详情页上没有红色横幅——本应用没有任何横幅机制——也不会向支持经理发出警报:该 notify 节点的收件人列表只有 `{currentCase.owner_id}` 一项 |
| **High** | 8 小时 | 列表视图中的红色徽章 |
| **Medium** | 2 个工作日 | 琥珀色徽章 |
| **Low** | 7 个工作日 | 灰色徽章 |
Expand Down Expand Up @@ -54,10 +54,14 @@ SLA 目标可按优先级配置——参见下方的*给管理员的提示*部

### 何时触发升级

升级流程在工单满足以下任一条件的那一刻运行:
升级流程只在一个条件下运行:**工单处于 Critical 优先级**。承载这个条件的是两个流程——`case_escalation` 在工单被*编辑*为 Critical 时触发,`case_escalation_on_create` 在工单被*创建*为 Critical 时触发——两者读的都是 `record.priority == "critical"`,外加那些防止已升级、已解决或已关闭的工单被二次升级的守卫项。

- 工单被设为 **Critical** 优先级,或
- 工单为 **High** 优先级**且**关联账户为 **Customer**(非潜在客户)
本页过去列出的另外两个条件并不存在:

- **不存在 High 优先级这一分支。** High 工单永远不会被自动升级。要升级它,是一个手动步骤——工单记录上的 **Escalate Case** 按钮。
- **没有任何升级条件会读取账户。** *Customer*、潜在客户、以及任何账户等级,都不出现在这些条件里——本应用中没有任何流程读取账户类型。Customer 的 High 工单与潜在客户的 High 工单待遇完全相同:两者都不会自行升级。

基于时间的那条路径同样兜不住它们。`case_sla_monitor` 会升级任何 **SLA 截止日期**已过的未结工单,但没有任何东西会给 High 工单打上这个日期:SLA 钩子只为 `critical` 填 `sla_due_date`,其余优先级一律留空,除非有人手工填写。所以一个没人过问的 High 工单,两条路径都进不去——请为这批工单安排人工巡检,而不是等待自动化去捞。

### 升级会做什么

Expand Down Expand Up @@ -102,7 +106,7 @@ SLA 目标可按优先级配置——参见下方的*给管理员的提示*部

- 一个客户等级的账户即使主题含糊,仍会因客户关系而获得 **High**。
- 一个描述中含 *"production is down"* 的潜在客户会获得 **Critical**,尽管它不是付费客户。
- Copilot 使用[支持知识库](/zh-Hans/docs/service/knowledge-base)与过往的相似工单进行模式匹配。
- **工单分流不会**与过往的相似工单做模式匹配。它只声明了 `describe_object` 与 `get_record`,因此只能读眼前这一个工单,既检索不了[知识文章](/zh-Hans/docs/service/knowledge-base),也拉不出该账户的其它工单。按工单的分类或标签匹配已发布文章,是 **Customer 360°** 的活,需要单独去问它。

如果优先级解析为 **Critical**,Copilot 会立即推荐升级并起草内部通知消息。

Expand Down Expand Up @@ -131,5 +135,5 @@ SLA 目标可按优先级配置——参见下方的*给管理员的提示*部

- 每个优先级的 SLA 目标通过工单对象的自动化(一个 SLA 计算钩子)设置。要调整,请编辑 `src/objects/case.hook.ts`(绑定到 `crm_case`)或更改底层配置——参见 [管理 › 自动化](/zh-Hans/docs/administration/automation)。
- 营业时间与日历时间的行为由你租户的营业时间设置控制。参见 [管理 › 设置](/zh-Hans/docs/administration/setup)。
- 升级触发条件(Critical,或 High+Customer)存在于 [工单升级流程定义](/zh-Hans/docs/administration/automation)中。在那里调整条件即可更改升级何时触发。
- 升级触发条件——只有 Critical 优先级这一项,不存在 High+Customer 这个条件——写在 [工单升级流程定义](/zh-Hans/docs/administration/automation)里,即 `src/flows/case-escalation.flow.ts`。承载它的是两个流程:`case_escalation`(更新时)与 `case_escalation_on_create`(新建时)。要改就**两个一起改**,否则以新条件新建的工单仍会漏掉。
- 这两处的收件人列表都不是 Setup 界面上的配置项。*紧急时通知* 就是工单升级流程的 `notify` 节点,其列表只有 `{caseRecord.owner_id}` 一项——要改就改 `src/flows/case-escalation.flow.ts`。*升级时通知* 根本没有收件人列表,因为它不发出任何消息:状态转为已升级触发的是 `src/objects/case.hook.ts` 里的 `case_status_side_effects` 钩子,它触达的是账户负责人,靠的是那条跟进任务。
Loading
Loading