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.
 
 
 
 
 

40 KiB

商机业务 PRD

版本:V1.0(冻结自 spec effort .scratch/opportunity-module,票 01–14 全部 resolved) 用途:给其他智能体 / 产品 / 开发按原型页逐条核对,每条决策挂原型页码。 原型基准:蓝湖 V1.0-20260815;demo nginx/html/保伦CRM系统demo-重构版-S1_0803.html范围:spec-only,不含实现代码。⚠ = 实现前须产品拍板的待确认项。


§1 领域定义

出处:票 01 domain-vocab-boundary,原型 A3-x-x 总览。

1.1 什么是商机

商机(Opportunity)= 一条正在推进、准备转成项目的销售机会。

两条入口,进系统后完全平权(同样的流程 / 公海 / 视图,不因来路不同而区别对待):

入口 说明 原型页
线索转入 销售在线索里跟进成熟后转成商机 A3-1-1(线索详情转商机入口)
直接新建 销售跳过线索,直接建一条商机 A3-1-1-2-1

直接新建时默认负责人 = 当前操作人(原型 A3-1-1-2-1 明证)。

1.2 两条正交轴

商机同时有两个独立维度,不互相干扰

字段 通俗解释 原型对应
轴 1 归属流转状态 opp_status(tinyint,5 态) 这条商机归谁、现在处于什么归属处境 详情顶部「商机状态:推进中」A3-1-1-1-1
轴 2 业务阶段 current_stage_id(指向节点) 业务打法走到第几步 详情进度条 A3-1-1-1-1;阶段设置 A7-3-2-1

一句话:「状态」管归属,「阶段」管业务打法

1.3 核心角色

角色 定义 字段
负责人(领取人) 当前持有该商机的销售,归属 + 默认可见性双重含义 owner_user_id
团队成员 负责人拉入协作的人员,带项目角色(商机负责人 / 方案工程师 / 招标专员 / 现场工程师等)与权限(读写 / 只读 / 可写跟进 / 可推进节点等);是行级授权白名单,绕开 DataScope 部门天花板 opportunity_team(关联表)
创建人 全生命周期不变 creator_user_id
  • 抛公海只清空负责人,不动团队成员(产品明确,票 01)。
  • 转商机时自动插一条团队成员:领取人 = 商机负责人(票 02)。
  • 权限模型:按钮可见即可点,权限全由权限点配置决定,与「是否负责人」无关(票 01 产品明确)。

1.4 模块边界

crm-opportunity  →  crm-rule(阶段模板 / 方案卡模板 / 公海规则,零反依赖)
                 →  crm-auth(DataScope / SysUser)
                 →  crm-dict(字典码)
                 →  crm-file(附件上传)
                 →  crm-preference(列偏好 / 自定义视图)

商机规则(阶段模板 / 方案卡模板 / 公海规则 / 字典)住 crm-rule,商机模块只消费。


§2 商机主表

出处:票 03 opportunity-main-table,原型 A3-1-1-2-1(新增表单)。

2.1 新增必填字段(原型 A3-1-1-2-1)

字段 类型 必填 说明
opp_name 商机名称 varchar(200)
opp_source 商机来源 varchar(64) 字典码 渠道归因;线索转入时默认置「线索转入」
opp_type 商机类型 varchar(64) 字典码
industry_code 行业 varchar(64) 字典码
bid_form 招标形式 varchar(64) 字典码
locality_type 项目属地 varchar(64) 字典码 本地/异地分类标签,非地理坐标
party_a_clear 甲方是否明确 tinyint 0/1
party_a 甲方名称 varchar(200) 条件必填 party_a_clear=1 时必填
province_code 省份 varchar(12)
city_code 市/区 varchar(12) 既可填市码也可填区/县码,不单建 district_code
remark 备注 text
project_amount 项目金额 decimal(14,2) 项目整体总包金额,选填可后补;默认人民币元,不建币种字段(Amendment 1)
意向客户(主要意向客户) 表单项,落 opportunity_customer 首条(is_primary_intended=1)+ 主表冗余快照;两条入口均必填(grill 补拍 20260821,与票 02 customerId 必填对齐);数据源依赖 A4 ⚠

2.2 系统生成字段

字段 类型 说明
opp_status tinyint 归属流转状态(轴 1),见 §3
owner_user_id 负责人 bigint 抛公海后清空
owner_name_snapshot 负责人姓名快照 varchar(100) 调岗不自动更新
owner_dept_id 负责人部门快照 bigint 公海可见范围锚点;调岗不变
creator_user_id 创建人 bigint 全生命周期不变
claim_time 领取时间 datetime 领取/分配时设;⚠ 两入口新建是否初始化待产品确认(P1-6)
last_valid_follow_time 最近有效跟进时间 datetime 自动回收计时锚点(票 05);有效跟进(写跟进记录/上附件/编辑字段)时刷新;⚠ 分配/新建/转入是否刷锚点待产品确认(P1-6,锚点为 NULL 时回收公式失效)
current_stage_id 当前阶段 bigint 指向 opportunity_stage_node.id(版本绑定,票 06)
stage_template_id 阶段模板版本 bigint 存模板版本行 id,锁死,发新版不自动迁移(票 06)
stage_template_version 模板版本号冗余 varchar(20) 展示用,免 join(如 V1.2)
source_lead_id 来源线索 bigint UNIQUE 幂等键;NULL 不参与唯一(直接创建可多条 NULL)
pool_reason 进入公海原因 varchar(32) 抛公海/回收时写(见 §3.2);公海列表筛选
primary_customer_id 主要意向客户 id bigint 冗余快查,= 关联客户表 is_primary_intended=1 那条
primary_customer_name_snapshot 主客户名快照 varchar(200) 列表/详情顶部免 join

继承 BaseEntity(id / create_time / update_time / creator / updater / 逻辑删除)。

2.3 DataScope 注解

@DataScope(module = "opportunity", ownerColumn = "owner_user_id", deptColumn = "owner_dept_id")

2.4 核心索引

索引 用途
UNIQUE idx_source_lead (source_lead_id) 一条线索只能关联一条商机(幂等键)
idx_owner_status (owner_user_id, opp_status) 「我负责的」视图
idx_owner_dept_status (owner_dept_id, opp_status) 公海视图 + 部门天花板

2.5 不建的字段(已明确排除)

  • pool_id:票 05 定稿删——商机域无独立池实体,公海 = 逻辑视图
  • dept_id:只用 owner_dept_id 快照做 DataScope 天花板
  • recycle_deadline:票 05 推翻,改为 last_valid_follow_time 实时算
  • 预计成交时间:产品二次拍板——商机主表不建、商机列表不展示;仅方案卡内部字段(票 07/10)

§3 归属流转状态机(轴 1)

出处:票 04 ownership-state-machine,原型 A3-1-1-1-1 / A3-1-1-2-x。

3.1 状态取值域(opp_status tinyint)

常量 名称 说明 终态
1 STATUS_IN_POOL 待领取(在公海) 无人持有,躺在商机公海
2 STATUS_ADVANCING 推进中 有负责人、正常推进
3 STATUS_PAUSED 暂缓中 短期挂起,保留负责人
4 STATUS_CLOSED 已关闭 只读锁定,可重启 半终态
5 STATUS_CONVERTED 已转项目 锁死,无任何出边 终态

3.2 迁移边全图

# 动作 Cmd 起始态→目标态 侧效摘要 原型页
E1 领取 ClaimCmd 1→2 设 owner + 部门/姓名快照 + claim_time;刷新 last_valid_follow_time=now A3-3-1-1(公海领取)
E2 分配 AssignToUserCmd 1→2 设 owner=指派对象 + 快照 + claim_time;⚠ 是否刷 last_valid_follow_time 待产品确认(P1-6) A3-2-1(管理页分配)
E3 抛公海 ReleaseToPoolCmd 2→1 owner_user_id + owner_name_snapshot + claim_timeowner_dept_id 保留(公海可见范围锚点,票 05);记 pool_reason(销售主动释放/特殊原因暂停/领导释放);保留 current_stage_id 供公海展示;不动团队成员;入口受规则 allow_manual_pool 开关控制 A3-1-1-2-7
E4 暂缓 PauseCmd 2→3 保留 owner + 团队;记暂缓原因(字典) + 预计重启日期(必填≥今天) + 补充说明 A3-1-1-2-6
E5 取消暂缓 ResumeCmd 3→2 保留 owner;回暂缓前阶段(阶段字段未动);清暂缓附加字段 A3-1-1-2-6(取消按钮)
E6 关闭 CloseCmd 2,3→4 保留 owner(只读锁定);记关闭原因(字典) + 补充说明(选「其他」时必填) + 确认勾选 A3-1-1-2-9
E7 重启 ReopenCmd 4→2 保留 owner;记重开原因(必填);统一回「推进中」 A3-1-1(重新开启入口)
E8 转项目 ConvertToProjectCmd 2→5 保留 owner(锁死);对接 A5 项目模块(本模块只占端口) A3-1-1-2-x(转项目)
E9 移交 HandoverCmd 2,3→自环 换 owner = 移交对象 + 姓名/部门快照同步刷新(owner_dept_id 换为移交对象部门,公海规则匹配锚点跟人走,grill 补拍 20260821);claim_time 不重置;入口在团队成员页 A3-1-1-1-8(团队成员 Tab)
E10 超时回收 executeRecycle 2→1(批量) owner_user_id + owner_name_snapshot + claim_timeowner_dept_id 保留定公海可见范围;pool_reason=超期回收;保留 current_stage_id 快照;暂缓中(3)不参与回收;实际执行的规则版本快照写 opportunity_oplog(§5.4) 后台 Job

「领导释放」(E3 变体)= 管理侧强制抛公海,操作人 ≠ owner,pool_reason=领导释放(原型 A3-2-1 管理页)。

3.3 受限态出边约束

状态 禁止的动作
已关闭(4) 仅允许 E7 重启;暂缓/抛公海/关闭/转项目/写跟进/推进节点 全禁;整商机只读、所有子表写全禁(原型 A3-1-1-2-9:推进类隐藏/置灰/禁止,只读操作保留)
已转项目(5) 无任何出边,全禁
暂缓中(3) 允许 E5/E6/E9;推进节点/转项目 受限(需先取消暂缓);⚠ 写跟进/子表写是否允许待产品确认(P1-7)

无删除动作(grill 补拍 20260821):商机不提供删除接口,终法只有关闭(→4)/转项目(→5),历史数据(含子表)永不删。

3.4 守卫与 CAS

  • 无「操作人==负责人」guard:商机侧详情页顶部操作区动作可见即可点,权限全由权限点决定(票 01 产品明确)。
  • CAS 乐观锁:每条迁移边在 WHERE id=? AND opp_status IN (合法起始态) 执行;更新 0 行抛 CODE_STATUS_NOT_ALLOWED
  • 移交 E9 CAS:WHERE id=? AND opp_status IN (2,3) AND owner_user_id=?原owner(防并发移交/抛公海竞态)。
  • 操作日志(P6):每条 Cmd 执行后 INSERT 一条 opportunity_oplog,含动作类型/操作人/时间/附加说明。

3.5 pool_reason 枚举(进入公海原因)

触发边 说明
销售主动释放 E3(销售本人操作)
特殊原因暂停 E3(销售本人操作,特殊原因)
领导释放 E3(管理侧操作,操作人≠owner)
超期回收 E10 executeRecycle 自动 Job

公海列表可按 pool_reason 筛选(原型 A3-3-1 筛选项)。


§4 业务阶段轴(轴 2)

出处:票 06 stage-template-versioning,原型 A7-3-2-1(商机阶段设置,列表/详情/新增 3 页)。

4.1 模型分层

  • 模板 + 节点住 crm-rule(版本化配置,遵 V-CONFIG 范式,见 §9)。
  • 运行时位置 + 版本快照住 crm-opportunity(主表 current_stage_id + stage_template_id + stage_template_version)。

4.2 阶段模板头表 opportunity_stage_template(crm-rule)

字段 类型 必填 说明
template_code 模板编码 varchar(64) 系统生成(如 OPP_GUIDE_01),同模板多版本共用,只读
version_no 版本号 varchar(20) 系统生成(V1.0/V1.1…),只读
status 状态 tinyint 1=草稿 / 2=发布中 / 3=已停用
apply_scope 适用范围 tinyint 1=所有商机 / 2=指定部门(两档单选,本期不做「指定业务类型」档)
is_default 是否默认 tinyint 同「适用范围+适用对象」内唯一
template_desc 模板说明 varchar
  • 适用对象子表 opportunity_stage_template_dept(apply_scope=2 时,适用部门多值)。apply_scope=1 → 无适用对象(原型「适用对象展示 --」)。

4.3 阶段节点表 opportunity_stage_node(crm-rule,从属模板版本)

字段 类型 必填 说明
template_id 所属模板版本 bigint opportunity_stage_template.id(版本级,每版本一套节点快照)
seq_no 阶段序号 int 推进顺序(轨道图左→右),增删/拖拽后系统重算
stage_dict_code 阶段字典值 varchar(64) 引用「商机阶段」字典分组项(如 OPP_STAGE_04),引用关系,自定义名不反写字典
custom_node_name 自定义节点名称 varchar(100) 本模板实际展示名,空则带入字典名
is_fixed 固定节点 tinyint 1=固定(「已转项目」)/ 0=普通

4.4 「已转项目」固定节点 × 轴 1 联动

  • 「已转项目」是每个模板的固定节点is_fixed=1,字典值固定 OPP_STAGE_05),配模板时自带、不可删(原型校验「除固定节点外至少创建一个阶段节点」),且不可拖到非末位(语义要求,落地校验)。
  • 商机中任一方案卡转项目 → 触发轴 1 转项目终态(E8)+ 轴 2 落到固定节点。

4.5 绑定与不迁移(V-CONFIG 12)

  • 商机绑定模板时记录具体版本stage_template_id = 版本行 id)。
  • 模板发新版后,在途商机继续用原版本,不自动迁移;新建/重新匹配的商机用当时最新发布版本(按适用范围匹配)。
  • 新建默认落首节点(客户圈定)。

⚠ P2-5:默认排序维度待产品定(建议最近跟进时间倒序)。


§5 商机公海规则

出处:票 05 opportunity-pool-rules,原型 A7-3-2-5(3 页一手正文)。

重要:商机公海规则 = 版本化规则配置(遵 V-CONFIG),非线索的 lead_pool 池实体。商机域无独立池实体——「公海」= opp_status=1 且 owner 为空 的逻辑视图,可见范围由 owner_dept_id + 匹配规则适用范围判定。

5.1 规则表 opportunity_pool_rule(crm-rule,版本化)

同一 rule_code 一套规则、多版本,每版本一行。核心配置五项:

字段 类型 必填 说明
rule_code 规则编码 varchar(64) 系统生成(如 POOL_RULE_01),同规则多版本共用
version_no 版本号 varchar(20) 系统生成,只读
apply_scope 适用范围 tinyint 1=所有商机 / 2=指定部门
allow_manual_pool 允许负责人手动转入公海 tinyint 0/1,控制「抛公海」入口是否对负责人开放
auto_recycle_enabled 启用自动回收 tinyint 0/1
  recycle_days 自动回收天数 N int auto_recycle_enabled=1 时必填;>0;连续未有效跟进达 N 天回收
allow_free_claim 允许自由领取 tinyint 0/1,控制适用范围内销售能否自领
recycle_remind_enabled 回收前提醒 tinyint 0/1,仅 auto_recycle_enabled=1 时可开
  remind_days 提前提醒天数 int recycle_remind_enabled=1 时必填;>0 且 < recycle_days(原型硬校验)

5.2 版本约束

  • 同一 rule_code 同时仅一个草稿 + 仅一个发布中
  • 复制 = 生成独立新规则(新 rule_code,非后续版本)。

5.3 领取 / 回收行为

场景 行为
allow_free_claim=1 适用范围内且具备公海权限的销售可自领;领取成功 owner=领取人,记录领取时间/人/规则版本(E1)
allow_free_claim=0 无自领入口,只能管理员分配(E2)
auto_recycle_enabled=1 回收锚点 = last_valid_follow_time;连续未有效跟进天数 = now − 锚点,≥ recycle_days 触发 E10 自动回收
暂缓中(3) 不参与回收,回收计时暂停;取消暂缓回推进中后按剩余天数续算
recycle_remind_enabled=1 提醒时间 = 预计回收时间 − remind_days
  • 有效跟进(刷新锚点)= 写跟进记录 / 上附件 / 编辑字段(非浏览),票 09 联动。

5.4 规则版本:实时匹配 vs 锅版本(关键区分)

公海规则与阶段模板的版本口径不同,核对时切勿混淆:

阶段模板(§4) 公海规则(本节)
绑定方式 主表存 stage_template_id(版本行 id),锁死版本 商机不存规则 id,只存 owner_dept_id
发新版 在途商机继续用原版本,不迁移(V-CONFIG 12) 待处理判断实时按当前发布中的版本
典型场景 商机“走什么打法”,中途换会打乱在途流程→锁版 “谁能碰这个部门公海”的当下策略,改规则就是要立刻生效→实时

口径(产品拍板,原型 A7-3-2-5):

  1. “谁能看/谁能领”判断→用当前发布中的版本。 池里商机无需“迁移”:拿 owner_dept_id 实时匹配当前发布中规则。管理员发新版(如关掉自由领取 / 新增部门专属规则圈进该商机)→ 立即对存量公海商机生效
  2. 历史动作不重算(原型明写): 已完成的领取/回收/提醒锁旧版快照,发新版不回溯。例:旧规则下已被领走的商机,不因发新版而撤销。
  3. 版本快照落操作日志(已定): 领取/回收时把实际执行的规则版本写进 opportunity_oplog(票 09),不上主表(一商机多次领/回收,主表存不下历史)。作用:查旧账(说清“当时凭哪版规则领/回收”)+ 落实口径 2 “历史不重算”。

一句记忆:公海规则跟着商机的部门、按当下发布中版本实时算;阶段模板锁版不迁移。

⚠ P2-6:原型 recycle_days/remind_days 样例值(30/7、45/7、20/5)非验收值,由规则配置录入。

5.4 规则匹配与执行语义(票 05「三」补抄,grill 20260821 核对)

  • 匹配锚点 = 商机自身的 owner_dept_id(规则跟着商机走,不跟查看人部门走):按该部门匹配 apply_scope=2 且部门命中 的发布中规则;匹配不到 → 发布中的所有部门通用默认规则兑底;部门专用 > 通用默认,发布约束保证唯一命中。专属规则同时决定该商机在公海谁能看到、谁能领(适用部门外不可见不可领)。
  • 实时匹配,不锁版本:公海规则不存于商机主表,查看/领取/回收时拿 owner_dept_id 实时匹配当前发布中版本。管理员发新版立即对在池商机生效(如关掉「允许自由领取」→ 立刻不能自领)。⚠ 与阶段模板口径相反(阶段模板主表存 stage_template_id 锁死版本不迁移;公海规则实时匹配)。
  • 已完成的动作不重算,不回溯:旧规则下已领走/已回收的记录继续关联原规则版本(原型 A7-3-2-5 明写)。
  • 落库手段:每笔领取/回收把当时实际执行的规则版本快照写操作日志 opportunity_oplog,不上主表(一条商机会多次领/回收,主表只能存最新一次;存档 research-a7325 line 533/1097/1832)。

§6 视图体系

出处:票 10 four-views-query + 票 14 custom-views-and-builtin-view-family,原型 A3-1-1/A3-2-1/A3-3-1/A3-0-1;demo 0803 oppModule

6.1 三个工作区(workspace)

工作区 数据范围 原型 自定义视图
销售机会(个人) 见 6.2 内置视图 + 自定义视图 A3-1-1 本期开
商机管理 @DataScope 可见范围(复用 crm-auth,不自建数据权限) A3-2-1 本期不开
商机公海 opp_status=1 且 owner 空 逻辑视图 + 匹配公海规则适用范围 A3-3-1 本期不开

公海商机在管理视图的可见性(grill 补拍 20260821):owner 空但 owner_dept_id 保留作 DataScope 部门锚点,按查看者档位自然判定——全部档可见;部门档看 owner_dept_id 是否在其可见部门集合;仅本人档永不可见(owner 空 ≠ 本人)。故 E2 分配入口(管理页)对全部/部门档管理员数据可达,无需去公海页。

视图不是状态切片:同一商机可同时出现在多视图(如自己负责 + 最近访问过)。

6.2 销售机会工作区 — 内置四视图(「常用检索」Tab,固定不可删/改)

code 名称 数据范围
recent 最近访问 当前用户打开过详情的商机,访问时间倒序、按商机 id 去重留最新,上限可配置(本期默认 50);「访问」= 调用详情聚合接口,任意皮肤(个人/管理/公海)都算(grill 补拍 20260821)
mine 我负责的销售机会 owner_user_id = 当前用户
participated 我参与的销售机会 团队成员且非负责人EXISTS(opportunity_team WHERE opportunity_id=? AND user_id=当前用户) AND owner_user_id <> 当前用户;与 mine 互斥
followed 我关注的销售机会 当前用户关注表 opportunity_focus 命中(§7.8)

6.3 销售机会工作区 — 自定义视图(「自定义检索」Tab)

用户保存的检索,加入常用检索列表(排在内置四视图之后)。一个自定义视图 =:

  • 检索名称(同一用户同一 scope 内唯一)
  • 检索条件:条件列表 [{field, operator, value}, …]
    • field列表所有可筛选列(字段池归商机模块定义)
    • operator等于 / 不等于 / 包含 / 不包含 / 为空 / 不为空
    • 本期前端只提交 1 组条件;契约按列表建模,预留多组(AND/OR)/ 高级公式扩展位
  • 排序条件:排序字段(∈字段池)+ 方向(asc/desc)

生命周期动作(用户私有):保存为常用检索 / 另存为新检索 / 编辑保存 / 重命名 / 删除(删当前视图回落 mine)。

默认视图(图钉):每个视图(内置四 + 自定义任一)可图钉设为该用户在此 scope 的默认视图,用户级单值;未设默认 → mine

6.4 落 crm-preference 平台能力

  • 自定义视图 = crm-preference 平台级能力(与「列偏好」并列),按 scope_key 分组、用户私有,对齐 ADR-0024「每菜单独立」。
  • 新实体 user_saved_view(user_id, scope_key, view_id, name, filter_json, sort_field, sort_direction, is_default, seq_no)filter_json 序列化条件列表;crm-preference 不校验字段合法性(字段池归业务方)。
  • 本期 scope = opportunity.sales(单一);后续菜单加 scope 即复用(产品确认「目前只销售机会、但要灵活性」)。
  • 内置视图不入库——口径硬编码在业务方,本表只存用户自建视图。
  • 契约:现有列偏好 get/save 之外,为自定义视图加 list / save / delete / setDefault(方法签名留实现阶段定)。

6.5 列表字段(个人/管理/最近访问共用基础列)

序号 / 选择框 / 商机名称 / 甲方 / 意向客户 / 行业 / 地区 / 预计金额 / 当前工作节点 / 节点停留时间 / 最近跟进 / 下一节点 / 方案卡状态 / 操作。

计算列口径(不冗余存,实时算/join):

口径
当前工作节点 current_stage_id 对应节点名
下一节点 模板中当前节点的下一 seq_no 节点(展示用「建议下一步」)
节点停留时间 今 − 进入当前节点日期(opportunity_stage_history 最新 to_time)
最近跟进 最新 opportunity_follow.create_time;无则 --
方案卡状态 主要意向客户is_primary_intended=1)那张方案卡的 card_status;无 → 「未创建」
方案预算 取主要意向客户那张方案卡的 scheme_budget;无则空
预计金额 主表 project_amount
当前负责人 owner_user_id 反查;个人页默认隐藏,管理/公海显示

6.6 各视图差异

视图 专属列 操作按钮 新增入口
个人 A3-1-1 负责人默认隐藏 详情 / 写跟进 「+新增商机」(默认归当前用户)
管理 A3-2-1 负责人显示 详情 / 分配 / 催办 / 关闭 + 批量催办/分配/关注/领导释放
公海 A3-3-1 入池前工作节点 / 进入公海原因 / 当前负责人 详情 / 关注 / 领取 + 批量领取/关注
最近访问 A3-0-1 按访问时间排序 详情 / 写跟进 / 关注 / 领取(按角色+商机态动态)

6.7 详情三皮肤

同一详情聚合,按视角展示不同操作区,非三套数据。Tab 结构一致(概览/客户信息/方案卡/现场勘察/相关附件/跟进记录/工作计划/团队成员/操作日志);差异在头部操作按钮 + 进入权限:

  • 个人 A3-1-1-1:写跟进/编辑/暂缓/抛公海/关闭/新增方案卡
  • 管理 A3-2-1-1:+ 分配/催办/关闭/督办
  • 公海 A3-3-1-1:领取/关注,无跟进/推进入口(未领取不可推进)

⚠ P2-4:管理视角「领导 ▾」层级数据范围与 @DataScope 精确映射待实现阶段定。 ⚠ P2-7:自定义视图数量上限 / 多组条件开放时机 / 是否支持共享 待产品定。


§7 详情子表族

7.1 关联客户 opportunity_customer

出处:票 13 opportunity-customer-relation,原型 A3-1-1-2-4。

字段 类型 必填 说明
opportunity_id bigint 所属商机
customer_id bigint 引用客户(A4 客户模块,⚠ 未建)
customer_role varchar(32) 客户角色(机电总包/工程商/集成商…)→ crm-dict「客户角色」分组;全部选填(grill 补拍 20260821)
is_primary_intended tinyint 0/1 是否主要意向客户,一商机唯一 =1
  • 线索转商机填的「意向客户」→ 落 is_primary_intended=1;商机侧添加普通关联客户 → is_primary_intended=0
  • 约束:UNIQUE(opportunity_id, customer_id)(一客户一商机只关联一次);主要意向客户唯一(应用层事务 + 部分唯一索引)。

7.2 方案卡 opportunity_scheme_card

出处:票 07 scheme-card,原型 A3-1-1-1-3 / A7-3-2-2/3。

  • 一客户一卡UNIQUE(opportunity_id, customer_id);每张卡必挂一个当前商机下的关联客户(无孤立卡)。
  • 状态机草稿1 / 已提交2 / 已推送3(「未创建」= 0 卡展示态,不入库)。
    • 保存草稿 → 草稿;确认 → 已提交(核心字段锁);推送 A7-3-2-3 → 已推送。
  • 可编辑性:草稿(1)/已提交(2) 均可改全部字段;仅已推送(3) 整卡只读(card_status < 3 可编辑),要改新建卡。不做字段级锁。
关键字段 说明
card_status 草稿1/已提交2/已推送3(tinyint)
scheme_budget 方案预算金额 decimal(14,2);商机列表「方案预算」列取主要意向客户卡的此值

模板驱动动态字段

  • 模板头 opportunity_scheme_card_template(版本行,遵 V-CONFIG)+ 适用对象子表 _template_dept + 字段项 opportunity_scheme_card_field(有序)。
  • 字段定义库 opportunity_scheme_field_def(crm-rule,自建不复用 crm-dict):field_key/field_name/field_type(控件类型)/option_source/ref_target/autofill_source/default_value/is_deletable组合式:单选下拉类字段的选项集可 option_source=dict_group_code 引用 crm-dict 分组。
  • 运行时值 opportunity_scheme_card_value(card_id, field_key, field_value)(随模板字段)。
  • 「预计成交时间」是方案卡内部字段(非商机主表、非列表列,票 10)。

模板选择与锁定(grill 补拍 20260821)

  • 创建方案卡时手动选模板版本(不自动匹配,产品明确)。
  • 候选范围 = 模板适用范围命中商机 owner_dept_id(所有商机档 + 指定部门命中档)的**「发布中」版本**;草稿/停用版本不可选。
  • 选定后卡存 card_template_id(版本行 id)锁版本,模板发新版后在途卡继续用原版(V-CONFIG 7),不自动迁移。

7.3 现场勘察 opportunity_site_survey

出处:票 08 site-survey,原型 A3-1-1-1-4。

字段 必填 说明
survey_date 现场勘察日期
engineer_user_id 主要工程师 引用 crm-auth SysUser;列表展姓名/部门/联系方式(脱敏,反查不冗余存)
apply_way 申请方式 引用字典
survey_seq 勘察次数 引用字典
apply_no 申请单号
  • 勘察附件走统一附件表(biz_type=SITE_SURVEY + biz_id)。

7.4 跟进记录 opportunity_follow

出处:票 09 P2,原型 A3-1-1-1-6 / 写跟进 A3-1-1-2-2。

  • 字段 + opp_id + BaseEntity(create_by/create_time = 记录人/时间)。
  • 跟进附件 → 附件子表 biz_type=FOLLOW_UP,最多 10 个。
  • 保存跟进 → 刷新商机「最近跟进」 + last_valid_follow_time(回收锚点刷新点,票 05 联动)。

7.5 附件 opportunity_attachment(统一表)

出处:票 09 P4,原型 A3-1-1-1-5,复用 crm-file。

  • 一张附件表 + biz_type + biz_id 定位,不为每个子表各建附件表。
  • biz_type 枚举:OPP(商机通用) / FOLLOW_UP(跟进) / SITE_SURVEY(勘察) / SCHEME_CARD(方案卡) …
  • 数量上限:仅跟进附件限 10 个/条(原型明画);其余 biz_type 不设业务上限,由 crm-file 层统一管控(grill 补拍 20260821)。
  • 附件归属商机(无孤立附件,硬约束);文件本体走 crm-file,本表存资料类型/说明/上传人/时间。

7.6 工作计划 opportunity_work_plan(结构 only)

出处:票 09 P5,原型 A3-1-1-1-7。

  • 🅿️ 工作计划 = 独立业务模块 A1X,本期挂起(产品拍板 P1-4)。本商机模块只保留子表结构与归属契约(多条/归属商机/内容/deadline/plan_status/finish_time)。
  • plan_status:未完成0/已完成1(逾期=未完成且 now>deadline,实时算)。精确态枚举、状态机、与跟进联动、Tab 读中央模块 全归 A1X 模块定。

7.7 操作日志 opportunity_oplog

出处:票 09 P6,原型 A3-1-1-1-9。

  • 字段级变更审计:实体对象/字段名称/旧值/新值/操作说明/来源(系统自动 vs 人工)/时间/操作人。普通用户只读。
  • 与线索 lead_history 口径不同:线索是动作枚举+JSON,商机是字段级旧新值审计。
  • 状态/阶段迁移另有专用快照表 opportunity_status_history / opportunity_stage_history,与本通用审计并存不重。

7.8 关注 opportunity_focus

出处:票 14 视图引用,grill 补拍 20260821(新建,PRD 此前引用未定义的表)。

  • 纯收藏夹语义,不带通知(通知属平台通知基础设施,未建;后续要通知再加字段,grill 补拍 20260821)。
  • 字段:opportunity_id + user_id + BaseEntity;约束 UNIQUE(opportunity_id, user_id)
  • 关注/取关无需原因、物理删行即可(关注不是审计对象,不入 oplog)。
  • 「我关注的」视图 = 该表命中当前用户;管理/公海/最近访问视图的「关注」按钮读写此表。

§8 上下游集成

8.1 线索 → 商机(消费线索侧 port)

出处:票 02 lead-port-consumer-contract,原型 A3-1-1(线索转商机)。

  • 线索侧提供 CreateOpportunityCmd(out-port),商机模块消费,转商机时自动带 source_lead_id
  • 契约变更(票 02 拍板,票 11 实现)CreateOpportunityCmd 新增 customerId(Long,必填);intendedCustomer 保留为客户名快照(走法 B:引用 + 快照并存)。
  • 线索转商机弹窗:意向客户改为下拉选客户(选中拿到 customer_id);线索转商机前置要求「必须有意向客户」。
  • 转商机时商机侧动作:建主表 + 建团队成员一条(领取人=商机负责人)+ 建关联客户一条(is_primary_intended=1customer_id=cmd.customerId)。
  • 幂等UNIQUE(source_lead_id) 保证一条线索只能关联一条商机。

8.2 商机侧新增入口 → 关联线索校验

出处:票 12 related-lead-validation,原型 A3-1-1-2-1。

  • 商机侧新增入口当用户选「商机来源 = 线索转入」时,手选一条【关联线索】写 source_lead_id(复用票 02 字段,不新建 related_lead_id)。
  • 候选线索范围 = 线索 status IN (已领取, 跟进中)source_lead_id 未被占用(与线索侧转商机准入对称)。
  • 命中已占用 → 返回错误码 opp.related_lead.taken;靠 UNIQUE(source_lead_id) 保唯一。
  • 直接创建且来源非「线索转入」→ source_lead_id NULL(可多条 NULL)。

8.3 商机 → 项目(转项目端口占位)

  • E8 转项目:对接 A5 项目模块(本模块只占端口,转项目后商机锁死终态 5)。
  • 触发源:商机中任一方案卡转项目 → 轴 1 终态 + 轴 2 固定节点「已转项目」。

8.4 商机 ↔ 客户(A4 客户模块)

  • A4 客户模块未建。关联客户 customer_idprimary_customer_id、线索转商机「下拉选客户」均引用 A4。
  • 票 11(customerId 契约字段)、票 13(关联客户表)已定契约;「下拉选客户」UI 数据源待 A4 到达。

§9 商机规则三族 · 版本化配置范式(V-CONFIG)

出处:票 06 抽出,票 05/07 复用。

crm-rule 三族配置共享同一版本化范式:

编码前缀样例
阶段模板 opportunity_stage_template OPP_GUIDE_*
公海规则 opportunity_pool_rule POOL_RULE_*
方案卡模板 opportunity_scheme_card_template

V-CONFIG 公共约定:

  1. 同一 code 多版本,每版本一行。
  2. version_no 系统生成(V1.0/V1.1/V2.0…),只读。
  3. status:1=草稿 / 2=发布中 / 3=已停用。
  4. 同一 code 同时仅一个草稿 + 仅一个发布中
  5. apply_scope:1=所有商机 / 2=指定部门(两档单选,本期不做「指定业务类型」);apply_scope=2 配适用对象子表(部门多值)。
  6. is_default:同「适用范围+适用对象」内唯一;发布新默认 → 原默认自动取消。
  7. 绑定快照:业务实体绑定配置时记录具体版本;新版本发布后原绑定实体继续用原版本不自动迁移;新建/重新匹配用最新发布版本。
  8. 复制 = 生成独立新规则(新 code,非后续版本)。
  9. 列表按版本维度展示:同 code 的草稿/发布中/停用各占一行,不合并。

crm-rule 对上层零反依赖:规则表不知道 opportunity 实体,靠 apply_scope/部门 + code 弱关联。


§10 字典清单(走 crm-dict,选项值由产品录入)

⚠ P2-1:本模块只定「要做字典」,具体选项值由产品提供。

字典分组 用途 出处
商机来源 opp_source 渠道归因(含「线索转入」) 票 03
商机类型 opp_type 票 03
行业 industry_code 票 03
招标形式 bid_form 票 03
项目属地 locality_type 本地/异地分类 票 03
商机阶段 OPP_STAGE_* 客户圈定/关系摸排/资料采集/方案卡/已转项目… 票 06
进入公海原因 pool_reason 销售主动释放/特殊原因暂停/领导释放/超期回收 票 04/10
暂缓原因 票 04
关闭原因 票 04
客户角色 机电总包/工程商/集成商… 票 13
跟进方式 电话/上门/微信/线上会议/展会… 票 09
跟进结果标签 暂无进展/需求确认/方案推进… 票 09
商机资料类型 现场资料/设计清单·图纸/客户需求资料/招投标相关资料/其它 票 09
申请方式(勘察) 工单申请/线下申请… 票 08
勘察次数 票 08

§11 待确认清单索引(实现前须产品拍板)

完整版见 .scratch/opportunity-module/产品待确认清单.md。以下均不阻塞建模/表结构(各票已给默认处置)。

编号 待确认项 现状
P2-1 各字典具体选项集 P2 走 crm-dict,产品录入
P2-4 管理视角「领导 ▾」层级数据范围 vs @DataScope 精确映射 P2 复用 crm-auth,映射待实现阶段定
P2-5 内置视图默认排序维度 P2 建议最近跟进倒序,待定
P2-6 公海规则数值样例 P2 样例非验收值,规则配置录入
P2-7 自定义视图:数量上限 / 多组条件(AND/OR)+高级公式开放时机 / 是否支持共享 / 管理·公海是否开 P2 本期私有、1 组条件、只销售机会开
P1-4 工作计划精确状态枚举 🅿️ 归 A1X 独立模块,本期挂起
P1-6 归属起点计时初始化(E1/E2/两入口创建统一口径,候选方案见清单) P1 挂起待产品确认(grill 20260821)
P1-7 暂缓期间子表可写范围(写跟进/方案卡/勘察/附件/客户/团队) P1 挂起待产品确认(grill 20260821)

已拍板存档(备查): 预计成交时间归属(P0-1,方案卡内部/不上主表/列表删除)、阶段模板适用范围两档(P0-2)、字段定义库自建不复用 crm-dict(P0-3)、方案卡状态枚举+多卡取值锚点(P0-4)、方案卡可编辑性(P1-1,card_status<3)、勘察次数生成(P1-2)、勘察补充说明必填(P1-3)、操作日志关键字段(P1-5)、最近访问去重+上限(P2-2)、方案卡状态列多卡口径(P2-3)。


附:原型事实出处索引

原型页 内容
A3-1-1 商机个人视图列表 / 线索转商机入口
A3-1-1-1-1 商机详情概览(状态条 + 进度条)
A3-1-1-1-3~9 详情 Tab:方案卡/勘察/附件/跟进/工作计划/团队成员/操作日志
A3-1-1-2-1 新增商机表单
A3-1-1-2-2 写跟进
A3-1-1-2-4 添加关联客户
A3-1-1-2-6/7/9 暂缓 / 抛公海 / 关闭
A3-2-1 商机管理视图
A3-3-1 商机公海视图
A3-0-1 最近访问视图
A7-3-2-1 商机阶段设置(阶段模板)
A7-3-2-2/3 方案卡模板 / 方案推送
A7-3-2-5 商机公海与提醒规则
demo 0803 oppModule 视图体系(内置四视图 + 自定义视图交互)

票映射总表:

主题 PRD 章节
01 领域词汇与边界 §1
02 线索侧 port 消费契约 §8.1
03 商机主表 §2
04 归属流转状态机 §3
05 商机公海规则 §5
06 阶段模板版本化 §4 §9
07 方案卡 §7.2
08 现场勘察 §7.3
09 子表族(跟进/附件/工作计划/日志) §7.4–7.7
10 四视图与列表/详情查询 §6
11 CreateOpportunityCmd + customerId §8.1(实现票)
12 商机侧关联线索校验 §8.2(实现票)
13 商机-关联客户 §7.1
14 自定义视图 + 内置视图族 §6.2–6.4

(本 PRD 冻结自 spec,如与原型有出入,以原型 + 票正文为准并回填对应票。)