From 55a7de0048ec1e7c3a9b373a00dfec9aa68191da Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 5 Aug 2026 22:43:14 +0000 Subject: [PATCH] docs(contracts): rewrite the three residual fabrications against the flows and the object (#826) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The expiration sweep's second notification, the renewal reminder's one-click action, and four ghost fields on the record table — all three languages. - contract-expiration.flow.ts notifies only `{currentContract.owner_id}`; the page's third step promised the account owner a message nobody sends. - contract-renewal.flow.ts's notify carries actionUrl to the contract detail page. There is no "Create Renewal Opportunity" button; the renewal deal is created by the flow when auto_renewal is on, and the renewal task the flow files first was never documented at all. - activation_date / renewal_terms / account_exec / order_form are zero hits under src/. The table is rebuilt from contract.object.ts's six fieldGroups (#792's shape), and Renewal Terms' second recommendation further down the page goes with it. Docs only. No src/ change — whether Contract should carry any of those four fields is a product decision and stays open. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa --- .changeset/contracts-docs-residual-drift.md | 51 ++++++++++++++++ content/docs/revenue/contracts.mdx | 60 +++++++++++++------ content/docs/revenue/contracts.zh-Hans.mdx | 64 ++++++++++++++------- content/docs/revenue/contracts.zh-Hant.mdx | 64 ++++++++++++++------- 4 files changed, 181 insertions(+), 58 deletions(-) create mode 100644 .changeset/contracts-docs-residual-drift.md diff --git a/.changeset/contracts-docs-residual-drift.md b/.changeset/contracts-docs-residual-drift.md new file mode 100644 index 000000000..d284ce700 --- /dev/null +++ b/.changeset/contracts-docs-residual-drift.md @@ -0,0 +1,51 @@ +--- +'hotcrm': patch +--- + +Rewrite the three remaining fabricated passages on the Contracts page against the +flows and the object that actually run, in all three languages. #805 fixed only +the activation section; these three were on the same page, and none of them was +caused by that change. + +**The expiration sweep sends one notification, not two.** The loop body of +`src/flows/contract-expiration.flow.ts` holds exactly two nodes — `mark_expired` +and `notify_owner`, whose recipient list is `{currentContract.owner_id}` alone. +Nothing in the flow reads the account's owner, so the page's third step +("Notification to the account owner") described a message nobody ever receives — +the failure mode where an account owner believes they will be told a contract has +lapsed. The page now says the contract owner is the only recipient and that +anyone else has to be arranged by an admin, and adds the two facts that decide +whether a given contract is touched at all: the sweep reads *Activated* contracts +only, and takes at most 500 per run. + +**The renewal reminder has no one-click action, and it does more than remind.** +`notify_owner` in `src/flows/contract-renewal.flow.ts` carries +`actionUrl: '/crm_contract/{currentContract.id}'` — the contract detail page. +There is no "Create Renewal Opportunity" button on it, and opening it creates +nothing; the renewal opportunity is created *by the flow itself*, unprompted, when +`auto_renewal` is on and the account has no open renewal deal. The section now +lists what the sweep does in the order it does it — the renewal task it files +first (which the page never mentioned), the notification, and the conditional +renewal opportunity with the values it copies — plus the idempotency the task +provides: an open *Renewal due* task means the day is already handled, and +completing it lets the next morning file a fresh one. The 120-day look-ahead is +written down too, because it caps notice windows set longer than that. + +**Four field names on the record table do not exist.** `activation_date`, +`renewal_terms`, `account_exec` and `order_form` are each zero hits under `src/`. +Following #792, the table is rebuilt from the six `fieldGroups` declared in +`src/objects/contract.object.ts`, so it is now the full inventory rather than an +invented one, with the required fields called out. The four absent names are +addressed head-on rather than quietly dropped, since a reader who went looking for +them deserves to know where the capability really lives: activation stamps +**Signed Date**, renewal instructions belong in **Special Terms**, ownership is the +single **Contract Owner** lookup, and **Contract Document** is a URL — the executed +PDF is an attachment on the record, and there is no *Order Form* field. +*Renewal Terms* was recommended a second time further down the same page, in the +Renewals section and in the tips for contract owners; both now point at Special +Terms. The zh pages take **计费周期 / 計費週期** for billing frequency from the +locale pack, matching the field-group headings the table now uses. + +Documentation only — no metadata, behaviour or field changes. Whether Contract +*should* carry an activation date, a renewal-terms field, an account exec or a +file-typed contract document is a product decision and stays open. Fixes #826. diff --git a/content/docs/revenue/contracts.mdx b/content/docs/revenue/contracts.mdx index dae94da51..e623c999a 100644 --- a/content/docs/revenue/contracts.mdx +++ b/content/docs/revenue/contracts.mdx @@ -32,14 +32,26 @@ Activation is the key transition — it triggers the account to be promoted to * ## What a contract record stores -| Section | Fields | +A contract record declares its fields in **six groups**. The contract form shows a curated subset of them across its tabs, so read this as the full inventory of what a contract carries rather than a screen-by-screen map: + +| Group | What's in it | | --- | --- | -| **Parties & Type** | Contract number *(auto)*, account, type, opportunity *(if originated from a deal)* | -| **Status & Dates** | Status, start date, end date, signed date, activation date | -| **Financials** | Contract value, billing frequency, payment terms | -| **Renewal** | Auto-renewal flag, renewal notice (days), renewal terms | -| **Ownership** | Contract owner, account exec | -| **Documents** | Signed contract (file), order form (file) | +| **Contract Information** | Contract Number *(auto-numbered `CTR-0001`)*, Contract Type, Contract Document, Description | +| **Parties** | Contract Owner, Account, Primary Contact, Related Opportunity — the contact and opportunity pickers are scoped to the account you pick first | +| **Terms & Dates** | Contract Term (Months), Start Date, End Date, Special Terms | +| **Contract Value** | Contract Value, Billing Frequency, Payment Terms, Billing Address | +| **Status & Approval** | Status, Signed Date, Signed By | +| **Renewal** | Auto Renewal, Renewal Notice (Days) | + +Account, Primary Contact, Contract Term, Start Date, End Date, Contract Value and Status are all **required** — a contract cannot be saved without them. + +Three field names people go looking for and do not find: + +- **Activation Date.** There is none, and no other field records the moment of activation. Activation stamps **Signed Date** instead (see *On contract activation* below), so that is the date any "when did this go live" report has to read. +- **Renewal Terms.** Renewal is exactly the two fields above. Free-text renewal instructions belong in **Special Terms**, which travels with the contract. +- **Account Exec.** Ownership is the single **Contract Owner** lookup; a contract carries no second ownership field. + +**Contract Document** is a **link**, not an upload — it holds a URL pointing at wherever the document lives. The executed PDF itself goes on the record as an **attachment**; files are enabled on Contract, which is what makes that possible. There is no separate *Order Form* field. ## Billing frequency @@ -63,13 +75,14 @@ When the customer pays: ## Renewals -Three fields drive renewals: +Two fields drive renewals: + +- **Auto Renewal** — off unless you turn it on. With it on, the daily renewal sweep opens the renewal deal for you; with it off, the sweep still reminds you but creates no deal. +- **Renewal Notice (Days)** — how many days before the end date the reminder fires. Defaults to 30, and each contract carries its own. -- **Auto-Renew** — does the contract roll over automatically? -- **Renewal Notice Days** — how many days before end-date to alert the team (e.g., 60 days) -- **Renewal Terms** — free-text instructions ("renew at 5% uplift unless customer opts out") +There is no *Renewal Terms* field. Instructions like "renew at 5% uplift unless the customer opts out" go in **Special Terms**, the free-text field on the contract itself. -When the contract enters its renewal window, the system creates a follow-up task and emails the contract owner. +When a contract enters its renewal window, the system files a follow-up task and emails the contract owner — see *Daily — renewal reminder* below for everything it creates. ## What the system does automatically @@ -84,14 +97,25 @@ Nothing is sent and nobody is told. Activation raises no notification for the co Both writes run *after* the save, with failures logged rather than raised, so the contract stays activated even if promoting the account fails. They also hang off an **update** — a contract that arrives already *Activated* (a data import, seed data, an integration that writes the record in one shot) triggers neither, and its account stays a *Prospect*. ### Daily — expiration sweep -Each night at midnight the system finds *Activated* contracts whose end date has passed: +Each night at midnight the system finds *Activated* contracts whose end date has passed, and does two things to each — only these two: 1. **Status → Expired**. -2. **Notification** to the contract owner. -3. **Notification** to the account owner. +2. **Notification to the contract owner** — inbox and email, linking to the contract. + +Nobody else is told. There is no second notification: the account owner, the primary contact and the rest of the account team hear nothing when a contract lapses, so if anyone beyond the contract owner needs to know, an admin has to add that. The sweep also reads *Activated* contracts only — one still sitting in *Draft* or *In Approval* past its end date is left alone — and it takes at most 500 contracts per run. ### Daily — renewal reminder -At 8 AM the system finds contracts entering their renewal window (within `renewal_notice_days` of end date) and sends a reminder to the contract owner with a one-click action to "Create Renewal Opportunity". +At 8 AM the system finds *Activated* contracts whose end date falls inside that contract's own *Renewal Notice (Days)* window, and for each one, in this order: + +1. **Files a renewal task** for the contract owner — *"Renewal due: contract CTR-0042"*, a high-priority follow-up due on the contract's end date, filed against the account. +2. **Notifies the contract owner** — inbox and email. The notification links to the contract record, and that is all it does: there is no one-click action on it, and opening it creates nothing. +3. **Opens a renewal opportunity** — but only when *Auto Renewal* is on. An *Existing Customer - Renewal* deal on the same account, at *Proposal* stage, amount copied from the contract value, close date set to the contract's end date, owner copied from the contract, next step *"Confirm renewal terms with customer"*. It is skipped when that account already has an open renewal deal. + +So the renewal deal is never something you click for. With *Auto Renewal* on it is already in the pipeline by the time you read the reminder; with it off, nobody opens one for you and the task is the whole of it. + +The task is also what keeps the sweep from repeating itself: the same contract matches every morning of its notice window, and an open *Renewal due* task for it means the day is already handled — no second task, no second notification, no second deal. Complete that task and the next morning's sweep files a fresh one, for as long as the contract is still inside its window. + +Two bounds worth knowing: the sweep looks 120 days ahead at most, so a notice window set longer than that only starts firing at 120 days out; and it takes at most 500 contracts per run. ### Manual termination The owner can change status to *Terminated*. This is a one-way action — terminated contracts can't be reactivated. Audit log records who and when. @@ -123,8 +147,8 @@ If your org wants contracts to follow the account, an admin has to author that, ## Tips for contract owners - ✅ **Attach the signed PDF** when activating — auditors will thank you. -- ✅ **Set Renewal Notice Days = 90** for enterprise deals — gives you a full quarter to negotiate. -- ✅ **Use Renewal Terms field** to capture the deal — "price-locked for 3 years; 5% uplift on renewal". +- ✅ **Set Renewal Notice (Days) = 90** for enterprise deals — gives you a full quarter to negotiate, and the sweep looks far enough ahead to honour it. +- ✅ **Record what you agreed in Special Terms** — "price-locked for 3 years; 5% uplift on renewal". There is no *Renewal Terms* field, and Special Terms is the note that will still be on the contract when the reminder lands. ## Tips for sales reps diff --git a/content/docs/revenue/contracts.zh-Hans.mdx b/content/docs/revenue/contracts.zh-Hans.mdx index 95d4e454f..d61746683 100644 --- a/content/docs/revenue/contracts.zh-Hans.mdx +++ b/content/docs/revenue/contracts.zh-Hans.mdx @@ -32,16 +32,28 @@ description: 与客户签署的协议——条款、价值、续约,以及自 ## 合同记录存储的内容 -| 区块 | 字段 | +合同记录把自己的字段声明为 **6 个区块**。合同表单只把其中一部分挑进各个标签页,所以下表是一份合同携带的字段全集,而不是逐屏对照表: + +| 区块 | 其中内容 | | --- | --- | -| **Parties & Type** | 合同编号 *(自动)*、账户、类型、商机 *(如果源自某笔交易)* | -| **Status & Dates** | 状态、开始日期、结束日期、签署日期、激活日期 | -| **Financials** | 合同价值、计费频率、付款条款 | -| **Renewal** | 自动续约标记、续约通知(天数)、续约条款 | -| **Ownership** | 合同所有者、客户经理 | -| **Documents** | 已签署合同(文件)、订单表(文件) | +| **合同信息** | 合同编号 *(自动编号 `CTR-0001`)*、合同类型、合同文档、描述 | +| **签约方** | 合同负责人、所属客户、主要联系人、关联商机——联系人和商机的选择器都按你先选定的客户过滤 | +| **条款与日期** | 合同期限(月)、开始日期、结束日期、特殊条款 | +| **合同金额** | 合同金额、计费周期、付款条款、账单地址 | +| **状态与审批** | 状态、签署日期、签署人 | +| **续约** | 自动续约、续约通知(天) | + +所属客户、主要联系人、合同期限、开始日期、结束日期、合同金额和状态都是**必填**的——缺一项合同就存不下来。 + +有三个字段名读者会去找,但它们并不存在: -## 计费频率 +- **激活日期**。没有这个字段,也没有别的字段记录激活的那一刻。激活时系统盖的是**签署日期**(见下文*合同激活时*),所以"什么时候生效的"这类报表只能读它。 +- **续约条款**。续约就是上面那两个字段。自由文本的续约说明写进**特殊条款**——它跟着合同一起走。 +- **客户经理**。所有权只有**合同负责人**这一个查找字段,合同上没有第二个负责人字段。 + +**合同文档**是一个**链接**,不是上传——它存的是指向文档实际所在位置的 URL。已签署的 PDF 本身是作为**附件**挂在记录上的;Contract 对象启用了文件,这才使它成为可能。也没有单独的*订单表*字段。 + +## 计费周期 客户被开票的频率: @@ -63,13 +75,14 @@ description: 与客户签署的协议——条款、价值、续约,以及自 ## 续约 -三个字段驱动续约: +两个字段驱动续约: + +- **自动续约**——默认关闭,要你自己打开。打开后,每日续约扫描会替你开出续约商机;关着的时候,扫描照样提醒你,但不会建任何商机。 +- **续约通知(天)**——在结束日期前多少天触发提醒。默认 30 天,而且每份合同各带各的。 -- **Auto-Renew**——合同是否自动滚动续约? -- **Renewal Notice Days**——在结束日期前多少天提醒团队(例如 60 天) -- **Renewal Terms**——自由文本说明("续约时上调 5%,除非客户选择退出") +没有*续约条款*字段。"续约时上调 5%,除非客户选择退出"这类说明写进**特殊条款**——合同自己身上的那个自由文本字段。 -当合同进入其续约窗口时,系统会创建一个跟进任务并向合同所有者发送邮件。 +当合同进入其续约窗口时,系统会建一条跟进任务并向合同负责人发邮件——它到底建了些什么,见下文*每日——续约提醒*。 ## 系统自动做的事 @@ -84,14 +97,25 @@ description: 与客户签署的协议——条款、价值、续约,以及自 这两次写入都在保存**之后**执行,失败只记日志、不向上抛,所以即使账户提升失败,合同也已经是激活状态。它们还只挂在**更新**上——创建时就已经是 *Activated* 的合同(数据导入、种子数据、一次性写入整条记录的集成)两次都不会触发,其账户仍然停留在潜在客户。 ### 每日——到期扫描 -每晚午夜,系统会查找结束日期已过的 *Activated* 合同: +每晚午夜,系统会查找结束日期已过的 *Activated* 合同,并对每一份做两件事,也只有这两件: 1. **状态 → Expired**。 -2. 向合同所有者发送**通知**。 -3. 向账户所有者发送**通知**。 +2. 向**合同负责人**发送**通知**——站内消息加邮件,链接指向这份合同。 + +别的人一概不会被告知。这里没有第二条通知:合同到期时,客户负责人、主要联系人以及客户团队的其他人什么都收不到,所以如果合同负责人之外还有人需要知道,得由管理员另行配置。这次扫描也只看 *Activated* 的合同——过了结束日期却还停在 *Draft* 或 *In Approval* 的合同不会被动——而且每次运行最多处理 500 份合同。 ### 每日——续约提醒 -每天上午 8 点,系统会查找进入其续约窗口的合同(在结束日期的 `renewal_notice_days` 范围内),并向合同所有者发送一条提醒,带一个一键操作"创建续约商机"。 +每天上午 8 点,系统会查找结束日期落在这份合同自己的*续约通知(天)*窗口内的 *Activated* 合同,并按以下顺序对每一份: + +1. **给合同负责人建一条续约任务**——*"Renewal due: contract CTR-0042"*,一条高优先级的跟进任务,到期日就是合同的结束日期,归属在该客户名下。 +2. **通知合同负责人**——站内消息加邮件。通知里的链接指向合同记录,也仅此而已:上面没有任何一键操作,点开它不会创建任何东西。 +3. **开一笔续约商机**——但仅当*自动续约*打开时。在同一个客户下开一笔 *Existing Customer - Renewal* 商机,阶段为 *Proposal*,金额从合同金额复制,关闭日期取合同的结束日期,负责人从合同复制,下一步写 *"Confirm renewal terms with customer"*。如果该客户下已经有一笔在途的续约商机,这一步会被跳过。 + +所以续约商机从来不是你点出来的。*自动续约*开着时,你读到提醒的时候它已经在管道里了;关着时,没有人替你开,提醒和那条任务就是全部。 + +那条任务同时也是扫描不重复自己的原因:续约窗口内的每天早上,同一份合同都会被匹配上,而只要它还挂着一条未完成的 *Renewal due* 任务,这一天就算已经处理过了——不会有第二条任务、第二条通知、第二笔商机。把这条任务标记完成,只要合同仍在窗口内,第二天早上的扫描就会再建一条新的。 + +两个值得知道的边界:扫描最多往前看 120 天,所以续约通知天数设得比 120 更长时,它也要等到 120 天这个点上才开始触发;每次运行最多处理 500 份合同。 ### 手动终止 所有者可以将状态更改为 *Terminated*。这是一个单向操作——已终止的合同无法重新激活。审计日志记录谁在何时操作。 @@ -123,8 +147,8 @@ description: 与客户签署的协议——条款、价值、续约,以及自 ## 给合同所有者的提示 - ✅ **激活时附上已签署的 PDF**——审计人员会感谢你。 -- ✅ **为企业级交易设置 Renewal Notice Days = 90**——给你整整一个季度去谈判。 -- ✅ **使用 Renewal Terms 字段**来记录交易——"价格锁定 3 年;续约时上调 5%"。 +- ✅ **为企业级交易把「续约通知(天)」设为 90**——给你整整一个季度去谈判,而且扫描往前看得足够远,撑得住这个设置。 +- ✅ **把谈定的续约约定写进特殊条款**——"价格锁定 3 年;续约时上调 5%"。没有*续约条款*字段,而提醒到达时,特殊条款仍然写在这份合同上。 ## 给销售代表的提示 @@ -134,4 +158,4 @@ description: 与客户签署的协议——条款、价值、续约,以及自 ## 给管理员的提示 - 合同激活是一个**对象 hook**(`src/objects/contract.hook.ts`),不是 flow——盖签署日期和提升账户都写在那里,流程列表里找不到它。到期扫描和续约提醒**才是**定时 flow。参见 [管理 › 自动化](/zh-Hans/docs/administration/automation)。 -- 合同类型和计费频率选项列表是可扩展的。 +- 合同类型和计费周期选项列表是可扩展的。 diff --git a/content/docs/revenue/contracts.zh-Hant.mdx b/content/docs/revenue/contracts.zh-Hant.mdx index 7fc6cee96..a3a4dc172 100644 --- a/content/docs/revenue/contracts.zh-Hant.mdx +++ b/content/docs/revenue/contracts.zh-Hant.mdx @@ -32,16 +32,28 @@ description: 與客戶簽署的協議——條款、價值、續約,以及自 ## 合約記錄儲存的內容 -| 區塊 | 欄位 | +合約記錄把自己的欄位宣告為 **6 個區塊**。合約表單只把其中一部分挑進各個標籤頁,所以下表是一份合約攜帶的欄位全集,而不是逐屏對照表: + +| 區塊 | 其中內容 | | --- | --- | -| **Parties & Type** | 合約編號 *(自動)*、帳戶、類型、商機 *(如果源自某筆交易)* | -| **Status & Dates** | 狀態、開始日期、結束日期、簽署日期、啟用日期 | -| **Financials** | 合約價值、計費頻率、付款條款 | -| **Renewal** | 自動續約標記、續約通知(天數)、續約條款 | -| **Ownership** | 合約所有者、客戶經理 | -| **Documents** | 已簽署合約(檔案)、訂單表(檔案) | +| **合約資訊** | 合約編號 *(自動編號 `CTR-0001`)*、合約類型、合約文件、描述 | +| **簽約方** | 合約負責人、所屬客戶、主要聯絡人、關聯商機——聯絡人和商機的選擇器都按你先選定的客戶過濾 | +| **條款與日期** | 合約期限(月)、開始日期、結束日期、特殊條款 | +| **合約金額** | 合約金額、計費週期、付款條款、帳單地址 | +| **狀態與審批** | 狀態、簽署日期、簽署人 | +| **續約** | 自動續約、續約通知(天) | + +所屬客戶、主要聯絡人、合約期限、開始日期、結束日期、合約金額和狀態都是**必填**的——缺一項合約就存不下來。 + +有三個欄位名讀者會去找,但它們並不存在: -## 計費頻率 +- **啟用日期**。沒有這個欄位,也沒有別的欄位記錄啟用的那一刻。啟用時系統蓋的是**簽署日期**(見下文*合約啟用時*),所以"什麼時候生效的"這類報表只能讀它。 +- **續約條款**。續約就是上面那兩個欄位。自由文字的續約說明寫進**特殊條款**——它跟著合約一起走。 +- **客戶經理**。所有權只有**合約負責人**這一個查找欄位,合約上沒有第二個負責人欄位。 + +**合約文件**是一個**連結**,不是上傳——它存的是指向文件實際所在位置的 URL。已簽署的 PDF 本身是作為**附件**掛在記錄上的;Contract 物件啟用了檔案,這才使它成為可能。也沒有單獨的*訂單表*欄位。 + +## 計費週期 客戶被開票的頻率: @@ -63,13 +75,14 @@ description: 與客戶簽署的協議——條款、價值、續約,以及自 ## 續約 -三個欄位驅動續約: +兩個欄位驅動續約: + +- **自動續約**——預設關閉,要你自己打開。打開後,每日續約掃描會替你開出續約商機;關著的時候,掃描照樣提醒你,但不會建任何商機。 +- **續約通知(天)**——在結束日期前多少天觸發提醒。預設 30 天,而且每份合約各帶各的。 -- **Auto-Renew**——合約是否自動滾動續約? -- **Renewal Notice Days**——在結束日期前多少天提醒團隊(例如 60 天) -- **Renewal Terms**——自由文字說明("續約時上調 5%,除非客戶選擇退出") +沒有*續約條款*欄位。"續約時上調 5%,除非客戶選擇退出"這類說明寫進**特殊條款**——合約自己身上的那個自由文字欄位。 -當合約進入其續約視窗時,系統會建立一個跟進任務並向合約所有者發送郵件。 +當合約進入其續約視窗時,系統會建一條跟進任務並向合約負責人發郵件——它到底建了些什麼,見下文*每日——續約提醒*。 ## 系統自動做的事 @@ -84,14 +97,25 @@ description: 與客戶簽署的協議——條款、價值、續約,以及自 這兩次寫入都在儲存**之後**執行,失敗只記日誌、不向上拋,所以即使帳戶提升失敗,合約也已經是啟用狀態。它們還只掛在**更新**上——建立時就已經是 *Activated* 的合約(資料匯入、種子資料、一次性寫入整條記錄的整合)兩次都不會觸發,其帳戶仍然停留在潛在客戶。 ### 每日——到期掃描 -每晚午夜,系統會查找結束日期已過的 *Activated* 合約: +每晚午夜,系統會查找結束日期已過的 *Activated* 合約,並對每一份做兩件事,也只有這兩件: 1. **狀態 → Expired**。 -2. 向合約所有者發送**通知**。 -3. 向帳戶所有者發送**通知**。 +2. 向**合約負責人**發送**通知**——站內訊息加郵件,連結指向這份合約。 + +別的人一概不會被告知。這裡沒有第二條通知:合約到期時,客戶負責人、主要聯絡人以及客戶團隊的其他人什麼都收不到,所以如果合約負責人之外還有人需要知道,得由管理員另行設定。這次掃描也只看 *Activated* 的合約——過了結束日期卻還停在 *Draft* 或 *In Approval* 的合約不會被動——而且每次執行最多處理 500 份合約。 ### 每日——續約提醒 -每天上午 8 點,系統會查找進入其續約視窗的合約(在結束日期的 `renewal_notice_days` 範圍內),並向合約所有者發送一條提醒,帶一個一鍵操作"建立續約商機"。 +每天上午 8 點,系統會查找結束日期落在這份合約自己的*續約通知(天)*視窗內的 *Activated* 合約,並按以下順序對每一份: + +1. **給合約負責人建一條續約任務**——*"Renewal due: contract CTR-0042"*,一條高優先級的跟進任務,到期日就是合約的結束日期,歸屬在該客戶名下。 +2. **通知合約負責人**——站內訊息加郵件。通知裡的連結指向合約記錄,也僅此而已:上面沒有任何一鍵操作,點開它不會建立任何東西。 +3. **開一筆續約商機**——但僅當*自動續約*打開時。在同一個客戶下開一筆 *Existing Customer - Renewal* 商機,階段為 *Proposal*,金額從合約金額複製,關閉日期取合約的結束日期,負責人從合約複製,下一步寫 *"Confirm renewal terms with customer"*。如果該客戶下已經有一筆在途的續約商機,這一步會被跳過。 + +所以續約商機從來不是你點出來的。*自動續約*開著時,你讀到提醒的時候它已經在管道裡了;關著時,沒有人替你開,提醒和那條任務就是全部。 + +那條任務同時也是掃描不重複自己的原因:續約視窗內的每天早上,同一份合約都會被匹配上,而只要它還掛著一條未完成的 *Renewal due* 任務,這一天就算已經處理過了——不會有第二條任務、第二條通知、第二筆商機。把這條任務標記完成,只要合約仍在視窗內,第二天早上的掃描就會再建一條新的。 + +兩個值得知道的邊界:掃描最多往前看 120 天,所以續約通知天數設得比 120 更長時,它也要等到 120 天這個點上才開始觸發;每次執行最多處理 500 份合約。 ### 手動終止 所有者可以將狀態更改為 *Terminated*。這是一個單向操作——已終止的合約無法重新啟用。審計日誌記錄誰在何時操作。 @@ -123,8 +147,8 @@ description: 與客戶簽署的協議——條款、價值、續約,以及自 ## 給合約所有者的提示 - ✅ **啟用時附上已簽署的 PDF**——審計人員會感謝你。 -- ✅ **為企業級交易設定 Renewal Notice Days = 90**——給你整整一個季度去談判。 -- ✅ **使用 Renewal Terms 欄位**來記錄交易——"價格鎖定 3 年;續約時上調 5%"。 +- ✅ **為企業級交易把「續約通知(天)」設為 90**——給你整整一個季度去談判,而且掃描往前看得夠遠,撐得住這個設定。 +- ✅ **把談定的續約約定寫進特殊條款**——"價格鎖定 3 年;續約時上調 5%"。沒有*續約條款*欄位,而提醒到達時,特殊條款仍然寫在這份合約上。 ## 給銷售代表的提示 @@ -134,4 +158,4 @@ description: 與客戶簽署的協議——條款、價值、續約,以及自 ## 給管理員的提示 - 合約啟用是一個**物件 hook**(`src/objects/contract.hook.ts`),不是 flow——蓋簽署日期和提升帳戶都寫在那裡,流程列表裡找不到它。到期掃描和續約提醒**才是**排程 flow。參見 [管理 › 自動化](/zh-Hant/docs/administration/automation)。 -- 合約類型和計費頻率選項列表是可擴展的。 +- 合約類型和計費週期選項列表是可擴展的。