跳转至

Contacts Specification

Contacts 是"一个号码 = 一个客户"的中心化档案表。本文档定义前端 Contacts 页面展示的所有数据及其来源。

完整版字段分析见 Contacts 字段设计


数据来源分类

前端 Contacts 页面的数据来自 4 种来源

来源 说明
① contacts 表 直接存储在 contacts 表中的字段,直读即可
② contact_timeline 表 从 timeline 事件聚合/查询
③ 跨表派生(calls / leads / messages) 从其他表 SQL 查询派生
④ API 层计算 不存 DB,API 运行时计算

一、contacts 表(直读)

字段名和类型以 callytics-common/src/db/schema/contacts.ts 为准。

写入者说明

写入者 含义
代码 数据管道自动写入(通话管道、Lead 管道、SMS 管道)
ai AI 分析写入(Pipeline 1 Per-Call / Pipeline 2 Contact Analysis)
ai+代码 AI 分析 + 规则映射共同决定
ai+员工 AI 可写入,员工可覆盖
员工 仅员工通过 UI 手动操作

字段清单(27 个)

# 前端展示位置 前端展示名 字段 类型 写入者 说明
1 Table + Profile Phone phone text (PK) 代码 E.164 格式,复合 PK 之一
2 不展示 franchiseId text (PK) 代码 所属品牌(franchise 级多租户隔离)
3 不展示 siteId text (PK) 代码 所属门店(RingCentral providerAccountId)
4 Table + Profile Contact firstName text 代码 名(与 lastName 拼接显示)
5 Table + Profile Contact lastName text 代码 姓(与 firstName 拼接显示)
6 Table + Profile + Summary Bar + Filter Stage lifecycleStage text ai+代码 lead / member / churned / unknown
7 不展示 lifecycleState text ai+代码 active / frozen / terminal
8 Table + Profile Notes notes text 员工 备注(Profile 中为可编辑 textarea)
9 Table + Filter DNC doNotContact boolean ai+员工 DNC 标记,全渠道停止触达
10 Table + Profile Card hasCardOnFile boolean 代码 客户是否有信用卡信息存档
11 Table + Profile Last Activity lastActivityAt timestamp 代码 最后活动时间(任何互动都更新)
12 Table + Filter + Profile Follow-up / Action Needed actionNeeded boolean ai 是否需要跟进(Table 列名 Follow-up,Profile 展示名 Action Needed)
13 不展示 actionNeededReason text ai 为什么需要行动(数据存储但前端不展示)
14a Profile Suggested Action suggestedActions[].action jsonb ai AI 建议操作,多条用分号分隔展示
14b Profile Priority suggestedActions[].priority jsonb ai 取所有建议中最高优先级,单个 badge(High / Medium / Low)
14c 不展示 suggestedActions[].reason jsonb ai 为什么建议这个操作(数据存储但前端不展示)
14d 不展示 suggestedActions[].priorityReason jsonb ai 为什么是这个优先级(数据存储但前端不展示)
15 Table + Filter + Profile + Pipeline Bar Lead Status leadStatus text ai 前端展示 9 个:New / Attempted / Connected / Booked / Bad Timing / Not Interested / Unreachable / Lost Contact / Neglected。Showed / Trialed / Converted 后端存储但前端不展示。当 lifecycleStage='lead' 时,Profile 顶部显示 Lead Pipeline 进度条(New → Attempted → Connected → Booked),当前状态高亮
16 不展示 leadStatusReason text ai 为什么是这个状态(数据存储但前端不展示)
17 Profile Lead Objections leadObjections jsonb ai 犹豫中的顾虑标签(amber 标签展示,仅 leadStatus = Connected / Booked 时显示)
18 Profile Lead Rejection Reasons leadRejectionReasons jsonb ai 条件性拒绝的原因标签(red 标签展示,仅 leadStatus = Bad Timing 时显示)
19 Profile Purchase Intent purchaseIntent text ai high / medium / low(仅 Lead)
20 不展示 purchaseIntentReason text ai 为什么是这个意向等级(数据存储但前端不展示)
21a Profile Goal goals[].goal jsonb ai 客户目标(仅 Lead)
21b 不展示 goals[].reason jsonb ai 为什么判断是这个目标(数据存储但前端不展示)
22 Profile Customer Summary customerSummary text ai 综合所有通话和 SMS 的整体画像摘要
23 不展示 lastContactAnalysisAt timestamp 代码 Pipeline 2 最后分析时间(cooldown gate 内部使用)
24 不展示 doNotContactUpdatedBy text 代码 DNC 来源:staff / ai / system(TCPA 合规审计)
25 Table + Filter + Profile Open Complaint hasOpenComplaint boolean ai+代码 当前是否有未解决投诉
26 Table + Profile Acquired createdAt timestamp 代码 首次创建时间 = 客户进入系统时间
27 不展示 updatedAt timestamp 代码 最后更新时间(Drizzle 自动刷新)

不展示说明

所有 Reason 类数据后端存储但前端不展示,供 AI 内部追溯使用,未来可考虑以 tooltip 或展开方式呈现:

  • 不展示的独立字段(7 个):#7 lifecycleState、#13 actionNeededReason、#16 leadStatusReason、#20 purchaseIntentReason、#23 lastContactAnalysisAt、#24 doNotContactUpdatedBy、#27 updatedAt
  • 不展示的 jsonb 内部属性(3 个)suggestedActions[].reasonsuggestedActions[].priorityReasongoals[].reason
  • 不展示的 leadStatus 枚举值(3 个)showedtrialedconverted — 当前系统无线下数据(门店签到、课程管理、POS),V1 暂不支持

二、contact_timeline 表(事件查询)

前端展示位置 前端展示名 查询方式 event_type
Table + Profile Last Complaint MAX(occurred_at) contact.complaint_opened

三、跨表派生(calls / leads / messages)

前端展示位置 前端展示名 来源表 查询方式
Profile First Attempted calls MIN(start_time) WHERE contact_phone=? AND direction='Outbound'
Profile First Connected calls MIN(start_time) WHERE contact_phone=? AND call_state='human_conversation'
Table Calls calls COUNT(*) WHERE contact_phone=? AND direction='Outbound'
Table SMS messages COUNT(*) WHERE from/to_phone_number=?
Profile Communication Log calls + messages 通话和 SMS 记录按时间倒序合并展示

四、前端计算(不存 DB)

Lead Temp 不存数据库,前端根据 contacts.createdAt + contacts.leadStatus + 固定阈值直接判断:

leadStatus 判断逻辑 结果
new / attempted now - createdAt ≤ 1 天 🔥 Hot
new / attempted now - createdAt ≤ 5 天 ☀️ Warm
neglected / unreachable now - createdAt > 5 天 ❄️ Cold
其他(connected / booked / badtiming / notinterested / lost_contact) 固定, Connected 及之后由 Task 系统管理,温度不再适用。详见 Lead Temperature N/A

温度仅在 pre-contact 阶段适用。neglectedunreachable 是温度系统的终态(温度冷掉后自动判定),固定 Cold。