You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

22 KiB

线索业务 PRD

版本:v0.1(chart 阶段收敛稿) 范围:crm-lead(线索业务)· crm-rule/线索规则(公海池配置)· crm-preference(列偏好平台能力) 目的:把线索域端到端业务流程写成产品可验证的规格;不确定点用 ⚠ 待确认 标出。


0. 阅读约定

  • ⚠ 待确认(编号):产品/UX 尚未拍板的点,见文末《待确认事项索引》。
  • 术语沿用 crm-auth 既有:主部门、兼职部门、部门集合、数据范围档位。
  • 实体名用于对齐:线索(Lead)、公海池(LeadPool)、反馈(Feedback)、关注(Follow)、附件(Attachment)、行历史(History)、区划(Region)。

1. 全景:线索一生

一条线索从进入系统到**转化为商机(或作废/失效)**的完整生命周期:

                     ┌──────────── 管理员导入/新建 ────────────┐
                     ▼                                          ▼
              [未分发]──分配到池──▶[待领取]                 [销售新增]
                                       │                        │
                                       ▼ 领取/分配               ▼
                                   [已领取]────首次反馈────▶[跟进中]
                                       │                        │  ▲
                                       │ 释放 / 超时回收         │  │ 再次反馈(重置N)
                                       ▼                        │  │
                                   [待领取]◀────释放/回收 N ────┘  │
                                                                  │
                                       转商机(已领取/跟进中) ──────┘
                                             │
                                             ▼
                                        [已转商机] ← 终态

              失效M计时(创建时起持续跑) ──到期──▶[过期失效]──管理员激活──▶恢复原态

四把标尺贯穿始终:

  1. 状态(7 态单字段,见 §3)
  2. 归属(哪个池 / 哪个部门 / 哪个销售,见 §4)
  3. 两把计时器(回收 N 天 / 失效 M 天,见 §5)
  4. 可见性(谁能看到、谁能操作,见 §9 ⚠ 待权限 PRD)

2. 模块架构(后端)

模块 职责 关键实体
crm-lead 线索业务:CRUD、领取/反馈/释放/转商机、四视图列表、统计、附件 lead, lead_history, lead_follow, lead_attachment
crm-rule(线索规则子域) 公海池配置与规则参数 lead_pool, lead_pool_province, lead_pool_region, lead_pool_member
crm-preference(新平台模块) 用户级 UI 列偏好(显隐 + 顺序) user_column_preference
crm-auth(既有,消费) 用户/部门/角色/数据范围/行级授权(新增) sys_user, sys_dept, sys_role_data_scope, sys_row_grant ⚠ 待 PRD
crm-dict(既有,消费) 字典:渠道/品牌/需求产品/需求场景 dict_group, dict_item
crm-region(新建,02 定稿) 行政区划:省/市/区,国标 code sys_region
crm-file(既有,消费) 附件文件 file
商机模块 不存在,crm-lead 通过 outbound port 契约声明依赖

依赖关系crm-lead → crm-rule / crm-preference / crm-auth / crm-dict / crm-region / crm-file;单向,无回边。


3. 线索状态机(7 态单字段 leadStatus

3.1 状态定义

# 状态 含义 有领取人 回收计时 N 失效计时 M
1 未分发 管理员新建/导入且未指定归属池;悬于池外
2 待领取 已归池;池内成员可自领
3 已领取 某销售持有,尚未反馈
4 跟进中 持有销售已产生至少一次反馈 跑(每次反馈重置)
5 已转商机 已通过转商机操作创建对应商机;终态 保留(历史) 冻结 冻结
6 过期失效 失效计时 M 到期;可发生在任何非终态 保留(若失效前被持有) 冻结 冻结(除激活重置)
7 线索作废 ⚠ 待确认(A)

反馈情况(有效 / 无效 / 未反馈)是独立字段 feedbackStatus,不进状态机;仅供筛选/展示。

3.2 合法迁移边

# from 触发 to 副作用
1 (无) 管理员新建/导入且未指定池 未分发 启动 M(起点=创建时刻)
2 (无) 销售在"我的线索"新增(自动带出本人池)或管理员指定池 待领取 启动 M
3 待领取 销售新增时勾"是否领取" 已领取 领取人=本人;启动 N
4 未分发 管理员分配到池 待领取 归池,M 继续
5 未分发 / 待领取 管理员分配并指定销售 已领取 领取人=被指派销售;启动 N
6 待领取 池内成员点【领取】 已领取 领取人=本人;启动 N
7 已领取 首次反馈 跟进中 写反馈;N 重置(起点=反馈时刻)
8 跟进中 再次反馈 跟进中(自环) 写反馈;N 重置
9 已领取 / 跟进中 转商机 已转商机 调 OpportunityCreationPort;写 CONVERT 历史;冻结 N、M
10 已领取 / 跟进中 手动【释放】 待领取 清领取人;N 停
11 已领取 / 跟进中 超时回收(N 到期无跟进) 待领取 清领取人;N 停
12 未分发 / 待领取 / 已领取 / 跟进中 失效计时 M 到期 过期失效 若被持有则保留领取人;只读
13 过期失效 管理员【激活】 恢复失效前状态与原领取人 M 重置(起点=激活时刻)
C 线索作废 ⚠ 待确认(A)

3.3 状态 × 操作 权威矩阵

操作 未分发 待领取 已领取 跟进中 已转商机 过期失效 线索作废
详情
编辑 ✓(管理) ✓(管理) ✓(持有人) ✓(持有人)
领取 ✓(池成员)
分配 ✓(管理) ✓(管理)
反馈 ✓(持有人) ✓(持有人)
转商机 ✓(持有人) ✓(持有人)
释放 ✓(持有人) ✓(持有人)
关注/取关
删除 ✓(管理) ✓(管理) ✓(管理·强确认) ✓(管理·强确认) ✓(管理·强确认) ✗ 不可删
激活 ✓(管理)

「管理」= 具有该线索所属数据范围的管理权限;具体谁是"管理"随 §9 权限 PRD 定。


4. 归属模型

4.1 三层归属

一条线索的归属由三层表达,各有用途:

字段 由什么决定 变化时机
池归属 pool_id 建线索时指定(或后续分配) 分配变更
部门归属 dept_id(冗余 = 池的 dept_id) 池所属部门;一部门一池 → 线索的 dept_id 恒等于池的 dept_id 池不变则永不变
销售归属 owner_user_id 领取/分配到销售 领取/释放/回收/分配

4.2 快照策略

以下字段在 lead 主表以快照形式冗余,避免关联查询:

字段 快照源 刷新时机
pool_name_snapshot lead_pool.pool_name 池改名时批量刷
dept_id 池的 dept_id 一部门一池 → 永不变
team_dept_id 池的 team_dept_id 同上
owner_name_snapshot 领取人姓名 领取/分配时快照,释放时清空
owner_dept_id_snapshot 领取时销售所属部门 领取/分配时快照(用于审计"这条线索历史属于哪个部门")
feedback_*(5 列) 最新一条反馈 每次反馈时刷

⚠ 待确认(B):销售换部门后,owner_dept_id_snapshot 是否需要刷新?当前定为不刷(快照即历史)。

4.3 公海池(lead_pool,crm-rule 定义)

一个公海池 = 一个部门的线索容器 + 一组规则参数

字段组 内容
归属 dept_id(UNIQUE,一部门一池)、team_dept_id(冗余,团队 = 部门上溯节点)
负责市场 多省(lead_pool_province)+ 多市/区(lead_pool_region);用国标 region_code 前缀 LIKE 支持祖先查询
人员 lead_pool_member(pool_id, user_id, role_type) role=OWNER(1)/COLLABORATOR(多);部门成员 = 部门全体动态推导,不落库
规则参数 recycle_days(N,默认 7)、expire_days(M,默认 180)、hold_limit(持有上限,默认 200)、daily_claim_limit(每日领取上限,默认 10,0=无限)、claim_rule(1=成员可领+管理员分配 / 2=仅管理员分配)

池名全局 UNIQUE;删除软删且必须"池下无非终态线索"。


5. 双计时器

两把独立计时器,各管各的(对齐产品最新口径):

5.1 回收计时 N(recycle_deadline

  • 计什么:销售领取到线索后,多久没跟进就退回公海。
  • 起点:领取时刻。
  • 重置:每次新增反馈时重置为 now + N
  • 停止:释放 / 回收 / 转商机 / 失效。
  • 到期动作:定时任务扫 WHERE recycle_deadline < now AND status IN ('已领取','跟进中') → 状态回到"待领取"、清领取人、写 RECYCLE 历史。
  • 存储lead.recycle_deadline datetime,加索引。

5.2 失效计时 M(expire_deadline

  • 计什么:一条线索从入库起多久后自动失效。
  • 起点创建时刻,不随领取/释放变化。
  • 重置管理员激活时(now + M)。
  • 停止:转商机 / 已失效。
  • 到期动作:定时任务扫 WHERE expire_deadline < now AND status IN ('未分发','待领取','已领取','跟进中') → 状态置"过期失效"(保留领取人若有)、写 EXPIRE 历史。
  • 存储lead.expire_deadline datetime,加索引。

5.3 池规则参数变更时的批量刷新

管理员改了池的 N 或 M:

  • N 改动 → 批量 UPDATE lead SET recycle_deadline = claim_time + new_N WHERE pool_id=? AND status IN ('已领取','跟进中')(对跟进中的按最后反馈时刻算:last_feedback_time + new_N
  • M 改动 → 批量 UPDATE lead SET expire_deadline = create_time + new_M WHERE pool_id=? AND status != '已转商机'

当日不批量清算已超时的——只改截止时刻,实际状态转移交给次日定时任务自然执行(对齐原型 A7-3-1 口径)。


6. 关键业务流程

6.1 新增线索(销售侧 · a2-1-2-2)

入口:【我的线索】列表 → 【新增线索】按钮。

表单字段(必填标 *):

分组 字段 类型 校验
基础 线索名称 文本
联系电话 文本 手机/座机通用正则(单字段)
微信 文本 微信号正则;无效提示"无效微信号"
电子邮箱 文本 通用邮箱正则;无效提示"无效邮箱号"
省份 * 下拉 联动城市
城市 * 下拉 依赖省份;未选省份不可选城市
详细地址 文本
业务 渠道 * 字典 dict group=lead.channel
品牌 * 字典 dict group=lead.brand
需求产品 * 字典 dict group=lead.product
需求场景 字典 dict group=lead.scene
核心 咨询内容 * 多行文本
只读回填 线索状态 展示"待领取" 不可编辑
线索公海池 自动带出本人所属池 不可编辑
销售团队 / 销售部门 / 销售人员 / 新增时间 自动回填 不可编辑
标记 是否加急 单选是/否,默认否
是否领取 复选,勾则新增即领
是否关注 复选,勾则加我的关注

底部:连续新增(复选)· 新增线索(主按钮)· 关闭(二次确认放弃)。

副作用

  • lead 行 → 状态 = 待领取(勾"是否领取"则一步转已领取,走边 #3)
  • lead_history CREATE 记录
  • 勾"是否关注" → 落 lead_follow
  • 触发失效计时 M(起点=create_time);若同步领取,触发回收计时 N

6.2 领取线索(池成员 · a2-1-1 系列)

入口:【线索公海】列表 → 单条【领取】 / 批量勾选后【批量领取】。 前置(应用层校验):

  1. 当前用户在池的可领取成员集合内(claim_rule=1 时=部门全员;claim_rule=2销售不可自领,按钮隐藏)
  2. 未超"每日领取上限"daily_claim_limit(0=无限)
  3. 未超"个人持有上限"hold_limit
  4. 目标线索状态 = 待领取 副作用:设 owner_user_id;快照 owner 姓名/部门;状态转 已领取(边 #6);启动 N;写 CLAIM 历史。

6.3 分配线索(管理侧 · A7 相关,部分在 A2 管理视图)

入口:管理员在【线索管理】/【线索公海】的管理视图选中线索 → 【分配】。 两种分配深度

  • 仅分配到池(未分发 → 待领取,边 #4)
  • 分配到销售(未分发/待领取 → 已领取,边 #5) 权限:仅管理员 + 池 OWNER + 池 COLLABORATOR 可执行(对齐 04-3 语义)。

6.4 反馈(持有人 · a2-1-2 系列)

入口:详情页 / 列表操作【反馈】按钮。 表单:反馈情况(有效/无效/未反馈)· 反馈内容 · 需求产品(可切换)· ⚠ 待确认(C):反馈是否可上传附件? 副作用

  • lead_history FEEDBACK 记录
  • 主表更新 5 列反馈快照(feedback_status/content/time/by/product_code
  • 状态:已领取 → 跟进中(边 #7);跟进中 → 跟进中(边 #8)
  • 回收计时 N 重置(起点=now

6.5 转商机(持有人 · a2-1-2 转商机弹窗)

入口:详情页 / 列表【转商机】按钮。 前置status IN (已领取, 跟进中);当前用户=持有人;反馈情况不参与判定(对齐产品最新口径,⚠ 已推翻原型"仅有效/跟进中/已联系"文案,UX 修订清单见 §11)。 表单:商机名称* · 行业*(字典 opportunity.industry,⚠ 待商机模块创建)· 甲方 · 意向客户* · 地区*(region_code)· 备注。 **副作用(同一本地事务)**:

  1. OpportunityCreationPort#createOpportunity(cmd) → 拿商机 id
  2. UPDATE lead SET status='已转商机' WHERE id=? AND status IN ('已领取','跟进中');行数=0 抛并发异常
  3. lead_history CONVERT 记录,detail 含 opportunityId + opportunityName
  4. 冻结 N/M(靠定时任务 WHERE status != '已转商机' 天然实现,无需 UPDATE 截止字段) 幂等:状态终态保护(crm-lead 侧) + opportunityUNIQUE(source_lead_id)(商机侧契约要求)。 失败:本地事务性回滚,线索状态不变。

6.6 释放(持有人 · a2-1-2)

前置status IN (已领取, 跟进中);当前用户=持有人。 副作用:清 owner_user_id;状态转"待领取"(边 #10);N 停;写 RELEASE 历史。线索回到池内待领取,原持有人失去所有非查看权限。

6.7 定时任务:超时回收 & 失效

回收 Job(每日凌晨 / 或按配置节奏):

SELECT id, pool_id, owner_user_id FROM lead
WHERE recycle_deadline < now() AND status IN ('已领取','跟进中');

逐行:清领取人,状态→待领取,写 RECYCLE 历史。

失效 Job(同上):

SELECT id, status FROM lead
WHERE expire_deadline < now() AND status IN ('未分发','待领取','已领取','跟进中');

逐行:状态→过期失效(若在私海则保留 owner_user_id 作历史记录),写 EXPIRE 历史。

⚠ 待确认(D):两个 Job 的执行节奏(每日凌晨?每小时?按公海池独立?)。当前定为统一每日 02:00 全库扫

6.8 激活失效线索(管理员)

入口:过期失效线索详情 → 【激活】。 副作用:状态恢复为失效前状态、owner 保留;expire_deadline = now + pool.expire_days(M 重新计);写 ACTIVATE 历史。


7. 四视图(前端列表页)

视图 路径 数据集 关键操作
线索公海(a2-1-1) /lead/pool 池内非私海(待领取 + 已被别人领取的观察态?⚠ 待确认(E)) 领取、关注
我的线索(a2-1-2) /lead/mine owner_user_id = 当前用户(含已转商机、过期失效) 反馈、转商机、释放、编辑、删除
我的关注(a2-1-3) /lead/follow 我在 lead_follow 里关注的线索 取消关注、跳转详情
线索管理(a2-1-4) /lead/manage 数据可见范围内全部线索 分配、导入/导出、批量释放、删除、激活

列偏好:每视图独立一套字段显隐 + 顺序(scope_key 各不同:lead.public_pool / lead.my_lead / lead.my_follow / lead.manage),互不同步(对齐 07 定稿,⚠ 已推翻原型"共用一套"文案,UX 修订清单见 §11)。

⚠ 待确认(E):线索公海视图是否只显示 status='待领取' 的线索,还是把"已被别人领取的"(已领取/跟进中)也展示为只读观察?原型混合展示,产品需明确。


8. crm-preference 契约(列偏好,07 定稿)

user_column_preference(id, user_id, scope_key varchar(64), visible_keys json, column_order json, updated_at)UNIQUE(user_id, scope_key)

接口(仅 2 方法):

Optional<ColumnPreference> get(Long userId, String scopeKey);
void save(Long userId, String scopeKey, ColumnPreference preference);

record ColumnPreference(List<String> visibleKeys, List<String> columnOrder) {}

scope_key:由业务方(crm-lead)约定的稳定字符串(不是路由、不是主键)。线索域 4 个:

  • lead.public_pool · lead.my_lead · lead.my_follow · lead.manage

字段池归属:业务方(crm-lead)拥有字段元数据、校验、未知 key 兜底;preference 只存"勾了哪些 key + 什么顺序",无感知语义。

保存时机点【保存】按钮才落库;拖拽临时顺序仅前端本地保留,关页面/刷新即丢。

明确不做:跨用户默认模板、管理员强制列、多租户 scope 隔离、偏好版本历史、字段池注册表、scopeKey 注册表校验。


9. 数据可见性与权限

⚠ 整个 §9 待产品拍板权限 PRD(权限与数据可见性-PRD.md

已升级为三机制模型(升级动因:团队成员/线索池协作人这类"行级授权"必须能越过部门天花板,纯 AND 不够表达):

  1. 功能权限(既有):权限点管理运行期配置按钮/API 开关
  2. 数据可见范围(既有,四档天花板):SELF / DEPT / DEPT_AND_CHILDREN / ALL,多角色取最宽
  3. 行级授权(通行证,新增)sys_row_grant(resource_type, resource_id, user_id, grant_source, grant_level) 通用表;拦截器统一 OR/EXISTS 注入

组合公式

能否看到某数据 = 页面业务条件 AND (落在数据可见范围 OR 已被行级授权)

5 项待产品拍板(PRD-1/2/3/D/E,详见待确认索引):见 §11《待确认事项索引》。


10. 依赖与集成

目标 依赖模块 依赖形态
用户/部门/角色 crm-auth 消费既有 API
数据范围拦截 crm-auth @DataScope 注解 + 拦截器
行级授权 crm-auth(待加强 sys_row_grant 通用表 + 拦截器 OR/EXISTS 注入(⚠ 待权限 PRD)
字典 crm-dict 4 个 group:lead.channel/brand/product/scene
行政区划 crm-region(新建,02 定稿) sys_region.code 国标前缀 LIKE 查询
附件 crm-file 关联表 lead_attachment(lead_id, file_id)
列偏好 crm-preference(新建,07 定稿) 2-方法接口
商机模块 不存在 crm-lead 定 outbound port OpportunityCreationPort,实现待商机模块落地

11. 待确认事项索引

11.1 产品拍板类(阻塞 spec 收尾)

编号 事项 阻塞对象 优先级
⚠ (A) 线索作废:触发方(自动/手动)、入口状态、可逆性、归属处理 03 收尾 P1
⚠ (B) 销售换部门后 owner_dept_id_snapshot 是否刷新?(当前定"不刷") 04 完善 P2
⚠ (C) 反馈是否可上传附件? 06 完善 P2
⚠ (D) 回收/失效 Job 执行节奏(每日 02:00?每小时?按池独立?) §6.7 P2
⚠ (E) 线索公海视图是否显示"已被别人领取"的线索(只读观察态) §7 P2
⚠ PRD-1 行级授权触发动作清单是否完整 05、§9 P0
⚠ PRD-2 被授权者权限边界:只读/可操作,是否分级 05、§9 P0
⚠ PRD-3 移除授权后即时失效行为确认 05、§9 P0
⚠ PRD-D 线索是否存在跨部门逐条指派(决定是否需 resource_type=lead 直接授权通道) 05、§9 P0
⚠ PRD-E 池负责人/协作人的授权范围(仅池内线索/兼池配置管理) 05、§9 P0

11.2 UX 修订类(不阻塞后端,但上线前必改,详见 待确认事项清单.md

编号 事项 处数
⚠ UX-1 列表字段"共用一套/同步生效" → "每菜单独立" 7 处
⚠ UX-2 "拖拽实时保存" → "点保存才落库" 2 处
⚠ UX-3 公海池"江苏 1/2/3" → 合并为 1 池 数据行
⚠ UX-4 转商机触发条件"跟进中/已联系/有效" → "已领取/跟进中" 3 处 4 行

12. 附:字段清单速查

见各 ticket Answer:

  • lead 主表 → issues/06-线索实体与字段模型.md
  • lead_pool + 3 关联表 → issues/04-公海池实体与归属建模.md
  • sys_regionissues/02-行政区划数据源调研.md
  • user_column_preferenceissues/07-preference列偏好scope模型与契约.md
  • OpportunityCreationPortissues/08-转商机outbound-port契约.md