From d768080ed796c061187ff9566df5b0658817c208 Mon Sep 17 00:00:00 2001 From: luoweijian <1329394916@qq.com> Date: Sat, 22 Aug 2026 12:07:03 +0800 Subject: [PATCH] commit --- .../产品待确认清单.md | 52 +++++---- .../opportunity-module/商机业务-PRD.md | 104 ++++++++++++++---- crm-opportunity/CONTEXT.md | 46 ++++++-- 3 files changed, 148 insertions(+), 54 deletions(-) diff --git a/.scratch/opportunity-module/产品待确认清单.md b/.scratch/opportunity-module/产品待确认清单.md index e8888cd..88ae6a3 100644 --- a/.scratch/opportunity-module/产品待确认清单.md +++ b/.scratch/opportunity-module/产品待确认清单.md @@ -69,27 +69,33 @@ - **依据**:原型 line 1745 给的是行为类别(字段变更/状态流转/附件/推送)非字段白名单;白名单是长期负债(加字段易漏审计),商机低频写全记扛得住且审计更全。 - **已落**:票 09(P6 写入点 + 待核项)。 -### ⚠ P1-6 归属起点计时初始化(E1/E2/两入口创建)— 挂起,待产品确认 -- **来源**:票 03/04/05 交叉缝隙(grill 20260821 发现,PRD §2.2/§3.2 已标注 ⚠) -- **问题**:回收公式 = `now − last_valid_follow_time ≥ recycle_days`,但该锚点在三处归属起点未统一初始化: - 1. **E1 领取**:已设 `claim_time` + 刷锚点=now(票 04) - 2. **E2 分配**:只设 `claim_time`,**不刷锚点**(票 04 疏漏) - 3. **两入口新建(线索转入/直接新建)**:出生即「推进中」+有负责人,不经过领取边,两字段均未定义(票 02 未提) -- **后果**:锚点为 NULL 时回收公式失效——分配/新建的商机若接手人从不跟进,将**永远不被回收**,回收机制有漏洞。 -- **候选方案**: - - A:四场景统一设 `claim_time=now` + 锚点=now(归属起点口径,锚点永不空,公式不改) - - B:只补 `claim_time`,公式改 `now − COALESCE(锚点, claim_time)` - - C:不补,锚点空不回收(有漏洞,不建议) -- **不阻塞建模**:两字段均已建表,仅侧效口径待定。 - -### ⚠ P1-7 暂缓期间子表可写范围 — 挂起,待产品确认 -- **来源**:票 04/09 缝隙(grill 20260821;原型 A3-1-1-2-6 只说「暂停部分推进动作和常规跟进提醒」,未枚举具体项) -- **问题**:暂缓中(3) 的流转限制已定(票 04:允许 E5 取消暂缓/E6 关闭/E9 移交;推进节点/转项目/抛公海需先取消暂缓),但**写跟进、方案卡/勘察/附件/关联客户/团队成员等子表写**是否允许,原型未明确。 -- **候选方案**: - - A:写跟进 + 子表写全部允许(仅推进节点/转项目/抛公海受限)——「暂停推进动作」≠禁记录留痕 - - B:写跟进允许、子表写禁 - - C:全禁只读(同关闭口径)——与原型「保留已有业务数据、暂停部分动作」不符 -- **已关闭(4) 不在此项内**:原型 A3-1-1-2-9 已明确(推进类隐藏/置灰/禁止、只读操作保留),已回填 PRD §3.3。 +### ✅ P1-6 归属起点计时初始化(E1/E2/两入口创建)— 已拍板(产品回复 20260821) +- **来源**:票 03/04/05 交叉缝隙(grill 20260821 发现) +- **问题**:回收公式 = `now − last_valid_follow_time ≥ recycle_days`,但该锚点在三处归属起点未统一初始化:E1 领取已设两者;E2 分配只设 `claim_time` 不刷锚点(票 04 疏漏);两入口新建(线索转入/直接新建)出生即「推进中」+有负责人,不经过领取边,两字段均未定义(票 02 未提)。 +- **产品回复**:① 回收按最近一次有效跟进时间判断;② 领取、分配**重置**回收计时;③ 首次进入名下(新建/转商机)时不存在跟进记录,**以进入名下的时间作为起点**。 +- **结论**:E1 领取/E2 分配均 `claim_time=now` + 锚点重置=now;两入口创建时 `claim_time=now` + 锚点=now(「进入名下时间」即创建时刻)。锚点永不空,回收公式维持 `now − 锚点` 不改。 +- **已落**:PRD §2.2/§3.2 去 ⚠、侧效口径固化。 + +### ✅ P1-7 暂缓期间子表可写范围 — 已拍板(产品回复 20260821) +- **来源**:票 04/09 缝隙(原型 A3-1-1-2-6 只说「暂停部分推进动作」,未枚举)。 +- **产品回复**:**暂缓/关闭状态:先解除状态,才能编辑操作。** +- **结论**:暂缓中(3) 与已关闭(4) 同口径——一切编辑操作(写跟进/方案卡/勘察/附件/关联客户/团队成员等子表写)全禁,必须先 取消暂缓/重启 回到推进中才能写。暂缓中(3) 允许的只有 E5 取消暂缓/E6 关闭/E9 移交。 +- **已落**:PRD §3.3 暂缓行去 ⚠、口径固化;CONTEXT「暂缓」术语。 + +### ✅ P1-8 有效跟进定义修订 + 配置化 — 已拍板(产品二次修订 20260821) +- **来源**:票 05/09 原定义「写跟进记录/上附件/编辑字段(非浏览)」。 +- **产品回复(首次)**:暂定为【推进中 + 写跟进、工作计划、标记完成、新增方案卡、新增现场勘察】五类。 +- **产品回复(二次修订 20260821)**:动作收缩——**本期只有「写跟进」才算有效跟进**;配置机制保留,以后可能新增动作。 +- **结论**:有效跟进 = **商机状态推进中(2) 且动作 = 写跟进**;上附件/编辑字段不计(已移出);「工作计划/标记完成/新增方案卡/新增现场勘察」本期不计(后续经配置新增)。 +- **配置落地(已拍板 20260821)**:`crm-rule` 第四族「有效跟进规则」`opportunity_follow_rule`(V-CONFIG 同族,动作类型多选子表,本期默认仅含「写跟进」),回收 Job 按商机 `owner_dept_id` 实时匹配当前发布中规则。 +- **已落**:PRD §5.3 有效跟进定义更新。 + +### 🅿️ P1-9 公海视图可见范围 — 暂定口径(按产品意见,PRD 定稿后终审,grill 20260821) +- **来源**:票 05 line 106「谁能看/领某条公海商机 = 按匹配到的公海规则适用范围判定」与 PRD §2.4 索引注释「公海视图 + 部门天花板」两处口径缝隙。 +- **问题**:公海视图(A3-3-1)查询时,可见范围是纯规则适用范围,还是叠加查看者自身 DataScope? +- **产品意见(20260821)**:公海视图与管理视图**同口径**——DataScope 按模块配置自动生效(配「本部门及以下」则公海也是本部门及以下),无需规则额外过滤。 +- **暂定结论**:**公海可见 = `@DataScope` 自动叠加**(按 `owner_dept_id` 部门锚点,同管理视图口径);**公海规则适用范围管「谁能领」(领取资格)+ 规则参数匹配**,不管可见性。「看得到但领不了」场景领取按钮置灰提示。 +- **已落**:PRD §5.4(专属规则管领取不辖可见)/§6.1(公海工作区数据范围);待产品终审后固化 CONTEXT「抛公海」相关术语与票 05 原文差异说明。 ## P2 — 展示/交互口径 + 字典选项(可后置,不影响核心模型) @@ -138,6 +144,10 @@ - **暂缓到期提醒渠道**:提醒对象=当前领取人已定(CONTEXT),到期不自动恢复、提醒后人工选 取消暂缓/继续暂缓/关闭已定;提醒发送渠道(站内信/短信/邮件)属平台通知基础设施,待平台通知能力确定时拍板。不阻塞建模。 - 今日已拍板(已回填 PRD/CONTEXT):直接新建必填主要意向客户;公海规则锚点=商机 `owner_dept_id`、实时匹配当前发布版、已执行动作不回溯(版本快照写 oplog,PRD 补 §5.4);公海商机在管理视图按 DataScope 档位自然判定可见性;商机无删除动作;recent 视图任意详情皮肤都算访问;customer_role 全部选填;附件仅跟进限 10。 +### ✅ P2-9 跟进记录编辑/删除 — 已拍板(grill 20260821) +- **拍板**:**支持删除、删除不回退回收锚点**(`last_valid_follow_time` 保持不变,防「写了又删」刷锚点);「最近跟进」按删除后最新留存行自然变化;删除入 oplog。**编辑本期不做**——写错以删除+补写修正。 +- **已落**:PRD §7.4、CONTEXT「跟进记录」。 + --- ## 实现票(非 spec,待其他模块/编码阶段) diff --git a/.scratch/opportunity-module/商机业务-PRD.md b/.scratch/opportunity-module/商机业务-PRD.md index 477ce09..d0cacf8 100644 --- a/.scratch/opportunity-module/商机业务-PRD.md +++ b/.scratch/opportunity-module/商机业务-PRD.md @@ -40,7 +40,7 @@ | 角色 | 定义 | 字段 | |---|---|---| | **负责人(领取人)** | 当前持有该商机的销售,归属 + 默认可见性双重含义 | `owner_user_id` | -| **团队成员** | 负责人拉入协作的人员,带项目角色(商机负责人 / 方案工程师 / 招标专员 / 现场工程师等)与权限(读写 / 只读 / 可写跟进 / 可推进节点等);是行级授权白名单,绕开 DataScope 部门天花板 | `opportunity_team`(关联表) | +| **团队成员** | 负责人拉入协作的人员,带项目角色(商机负责人 / 方案工程师 / 招标专员 / 现场工程师等)与权限(读写 / 只读 / 可写跟进 / 可推进节点等);是行级授权白名单,绕开 DataScope 部门天花板——**生效边界 = 详情/子表读 + 个人工作区视图;管理/公海工作区严格按 DataScope 不混白名单**(grill 补拍 20260821) | `opportunity_team`(关联表) | | **创建人** | 全生命周期不变 | `creator_user_id` | - 抛公海只清空负责人,**不动团队成员**(产品明确,票 01)。 @@ -59,6 +59,28 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 商机规则(阶段模板 / 方案卡模板 / 公海规则 / 字典)住 `crm-rule`,商机模块只消费。 +### 1.5 权限点需求清单(grill 梳理 20260821,编码实现阶段按平台规范登记) + +权限模型(§1.3):按钮可见即可点,权限全由权限点配置决定。以下为**需要权限点的动作全集**: + +| 类 | 权限点动作 | +|---|---| +| 入口 | 销售机会工作区 / 商机管理工作区 / 商机公海工作区 | +| 商机主表 | 新增商机 / 编辑商机 / 关闭 / 重启 | +| 归属流转 | 领取(公海)/ 分配(管理)/ 抛公海(个人主动)/ 领导释放(管理强制)/ 暂缓 / 取消暂缓 / 移交 | +| 跟进 | 写跟进 / 删除跟进 | +| 方案卡 | 新增 / 编辑 / 提交 / 推送 | +| 团队成员 | 添加 / 调整角色与权限 / 移除(成员行上的读写/只读/可写跟进/可推进节点 = **行级角色配置,不走全局权限点**) | +| 关联客户 | 新增 / 编辑 / 删除 | +| 现场勘察 | 新增 / 编辑 / 删除 | +| 附件 | 上传 / 删除 | +| 视图 | 关注 / 取关;自定义视图新增/编辑/删除;批量领取/分配/关注/领导释放(同单条动作权限点,批量不加新点) | +| 审计 | 操作日志查看 | +| 后台(crm-rule 侧) | 阶段模板管理 / 方案卡模板管理 / 公海规则管理 / 有效跟进规则管理 | + +- **颗粒度口径**:动作级(一个动作一个点),不按「视图 × 动作」拆——同一动作在个人/管理/公海共用一个权限点,界面差异由视角 + 状态驱动(§6.7)。 +- **催办/督办本期不做**(§6.6 spin-out 留白),不登记权限点。 + --- ## §2 商机主表 @@ -92,8 +114,8 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 | `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 时回收公式失效) | +| `claim_time` 领取时间 | datetime | 领取/分配/两入口创建时=now(「进入名下时间」,P1-6 拍板) | +| `last_valid_follow_time` 最近有效跟进时间 | datetime | 自动回收计时锚点(票 05);领取/分配**重置**=now;两入口创建以进入名下时间(=创建时刻)为起点;有效跟进时刷新(§5.3 定义,配置化 P1-8) | | `current_stage_id` 当前阶段 | bigint | 指向 `opportunity_stage_node.id`(版本绑定,票 06) | | `stage_template_id` 阶段模板版本 | bigint | 存模板版本行 id,锁死,发新版不自动迁移(票 06) | | `stage_template_version` 模板版本号冗余 | varchar(20) | 展示用,免 join(如 V1.2) | @@ -146,15 +168,15 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 | # | 动作 | 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(管理页分配) | +| E2 | 分配 | `AssignToUserCmd` | 1→2 | 设 owner=指派对象 + 快照 + `claim_time`;重置 `last_valid_follow_time`=now(P1-6 拍板) | A3-2-1(管理页分配) | | E3 | 抛公海 | `ReleaseToPoolCmd` | 2→1 | 清 `owner_user_id` + `owner_name_snapshot` + `claim_time`;**`owner_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(转项目) | +| E8 | 转项目 | `ConvertToProjectCmd` | 2→5 | **触发源 = ① 标准路径:推送方案卡成功(系统自动创建项目);② 特殊路径:项目侧建项目关联商机后回调**(grill 补拍 20260821),无独立「转项目」动作;保留 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_time`;`owner_dept_id` 保留定公海可见范围;`pool_reason`=超期回收;保留 `current_stage_id` 快照;暂缓中(3)**不参与回收**;实际执行的规则版本快照写 `opportunity_oplog`(§5.4) | 后台 Job | +| E10 | 超时回收 | `executeRecycle` | 2→1(批量) | 清 `owner_user_id` + `owner_name_snapshot` + `claim_time`;`owner_dept_id` 保留定公海可见范围;`pool_reason`=超期回收;保留 `current_stage_id` 快照;暂缓中(3)**不参与回收**;实际执行的规则版本快照写 `opportunity_oplog`(§5.4) | **crm-opportunity 自建 `@Scheduled` 单 Job**(先提醒后回收串行,对齐线索域 ADR-0019 竞态规避;cron 配置占位符默认每日凌晨,grill 补拍 20260821) | > **「领导释放」**(E3 变体)= 管理侧强制抛公海,操作人 ≠ owner,`pool_reason`=领导释放(原型 A3-2-1 管理页)。 @@ -164,7 +186,7 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 |---|---| | 已关闭(4) | 仅允许 E7 重启;暂缓/抛公海/关闭/转项目/写跟进/推进节点 全禁;**整商机只读、所有子表写全禁**(原型 A3-1-1-2-9:推进类隐藏/置灰/禁止,只读操作保留) | | 已转项目(5) | **无任何出边**,全禁 | -| 暂缓中(3) | 允许 E5/E6/E9;推进节点/转项目 受限(需先取消暂缓);⚠ 写跟进/子表写是否允许待产品确认(P1-7) | +| 暂缓中(3) | 允许 E5/E6/E9;推进节点/转项目 受限(需先取消暂缓);**一切编辑操作全禁,必须先取消暂缓回到推进中才能写**(写跟进/子表写同禁,P1-7 拍板) | > **无删除动作**(grill 补拍 20260821):商机不提供删除接口,终法只有关闭(→4)/转项目(→5),历史数据(含子表)永不删。 @@ -223,7 +245,7 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 ### 4.4 「已转项目」固定节点 × 轴 1 联动 - 「已转项目」是每个模板的**固定节点**(`is_fixed=1`,字典值固定 `OPP_STAGE_05`),配模板时自带、**不可删**(原型校验「除固定节点外至少创建一个阶段节点」),且**不可拖到非末位**(语义要求,落地校验)。 -- 商机中任一方案卡转项目 → 触发轴 1 转项目终态(E8)+ 轴 2 落到固定节点。 +- **推送方案卡成功(系统自动创建项目)→ 触发轴 1 转项目终态(E8)+ 轴 2 落到固定节点**(标准路径,grill 补拍 20260821);无独立「转项目」动作,列表「转项目」按钮 = 推送流程快捷入口。 ### 4.5 绑定与不迁移(V-CONFIG 12) @@ -270,9 +292,9 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 | `allow_free_claim=0` | 无自领入口,只能管理员分配(E2) | | `auto_recycle_enabled=1` | 回收锚点 = `last_valid_follow_time`;连续未有效跟进天数 = now − 锚点,≥ `recycle_days` 触发 E10 自动回收 | | 暂缓中(3) | **不参与回收**,回收计时暂停;取消暂缓回推进中后按剩余天数续算 | -| `recycle_remind_enabled=1` | 提醒时间 = 预计回收时间 − `remind_days` | +| `recycle_remind_enabled=1` | 提醒时间 = 预计回收时间 − `remind_days`;**由回收 Job 同一 `@Scheduled` 内先扫提醒再扫回收**(提醒先于回收,对齐线索域 ADR-0019;grill 补拍 20260821) | -- **有效跟进**(刷新锚点)= 写跟进记录 / 上附件 / 编辑字段(非浏览),票 09 联动。 +- **有效跟进**(刷新锚点,P1-8 拍板)= **商机状态为推进中(2) 且动作 = 写跟进**(本期唯一动作;上附件/编辑字段/方案卡/勘察等不计,产品二次修订 20260821)。动作类型集合是**配置项**:落 `crm-rule` 第四族「有效跟进规则」`opportunity_follow_rule`(V-CONFIG 同族,动作类型多选子表,本期默认仅「写跟进」,以后经配置新增),回收 Job 按商机 `owner_dept_id` 实时匹配当前发布中规则拿动作集合(与公海规则同匹配引擎)。领取/分配重置锚点=now;两入口创建锚点=进入名下时间(P1-6)。 ### 5.4 规则版本:实时匹配 vs 锅版本(关键区分) @@ -286,7 +308,7 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 **口径(产品拍板,原型 A7-3-2-5):** -1. **“谁能看/谁能领”判断→用当前发布中的版本。** 池里商机无需“迁移”:拿 `owner_dept_id` 实时匹配当前发布中规则。管理员发新版(如关掉自由领取 / 新增部门专属规则圈进该商机)→ **立即对存量公海商机生效**。 +1. **「谁能领」判断→用当前发布中的版本**(可见性归 `@DataScope`,见下节 grill 补拍口径)。池里商机无需“迁移”:拿 `owner_dept_id` 实时匹配当前发布中规则。管理员发新版(如关掉自由领取 / 新增部门专属规则圈进该商机)→ **立即对存量公海商机生效**。 2. **历史动作不重算(原型明写):** 已完成的领取/回收/提醒**锁旧版快照**,发新版不回溯。例:旧规则下已被领走的商机,不因发新版而撤销。 3. **版本快照落操作日志(已定):** 领取/回收时把实际执行的规则版本写进 `opportunity_oplog`(票 09),**不上主表**(一商机多次领/回收,主表存不下历史)。作用:查旧账(说清“当时凭哪版规则领/回收”)+ 落实口径 2 “历史不重算”。 @@ -297,7 +319,7 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 ### 5.4 规则匹配与执行语义(票 05「三」补抄,grill 20260821 核对) -- **匹配锚点 = 商机自身的 `owner_dept_id`**(规则跟着商机走,不跟查看人部门走):按该部门匹配 `apply_scope=2 且部门命中` 的发布中规则;匹配不到 → 发布中的所有部门通用默认规则兑底;部门专用 > 通用默认,发布约束保证唯一命中。专属规则同时决定该商机在公海**谁能看到、谁能领**(适用部门外不可见不可领)。 +- **匹配锚点 = 商机自身的 `owner_dept_id`**(规则跟着商机走,不跟查看人部门走):按该部门匹配 `apply_scope=2 且部门命中` 的发布中规则;匹配不到 → 发布中的所有部门通用默认规则兑底;部门专用 > 通用默认,发布约束保证唯一命中。专属规则决定该商机在公海**谁能领**(适用部门外不可领,grill 补拍 20260821 暂定,待产品终审);**可见性归 `@DataScope`**——公海视图查询自动叠加部门过滤(同管理视图口径),「看得到但领不了」场景领取按钮置灰提示。 - **实时匹配,不锁版本**:公海规则**不存于商机主表**,查看/领取/回收时拿 `owner_dept_id` 实时匹配**当前发布中**版本。管理员发新版立即对在池商机生效(如关掉「允许自由领取」→ 立刻不能自领)。⚠ 与阶段模板口径相反(阶段模板主表存 `stage_template_id` 锁死版本不迁移;公海规则实时匹配)。 - **已完成的动作不重算,不回溯**:旧规则下已领走/已回收的记录继续关联原规则版本(原型 A7-3-2-5 明写)。 - **落库手段**:每笔领取/回收把当时实际执行的**规则版本快照写操作日志 `opportunity_oplog`**,不上主表(一条商机会多次领/回收,主表只能存最新一次;存档 research-a7325 line 533/1097/1832)。 @@ -314,18 +336,20 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 |---|---|---|---| | **销售机会**(个人) | 见 6.2 内置视图 + 自定义视图 | A3-1-1 | ✅ 本期开 | | **商机管理** | 按 `@DataScope` 可见范围(复用 crm-auth,不自建数据权限) | A3-2-1 | 本期不开 | -| **商机公海** | `opp_status=1 且 owner 空` 逻辑视图 + 匹配公海规则适用范围 | A3-3-1 | 本期不开 | +| **商机公海** | `opp_status=1 且 owner 空` 逻辑视图;**可见性 = `@DataScope` 自动叠加**(按 `owner_dept_id` 部门锚点,同管理视图口径);公海规则适用范围管**领取资格**(grill 补拍 20260821,待产品终审) | A3-3-1 | 本期不开 | > **公海商机在管理视图的可见性**(grill 补拍 20260821):owner 空但 `owner_dept_id` 保留作 DataScope 部门锚点,按查看者档位自然判定——全部档可见;部门档看 `owner_dept_id` 是否在其可见部门集合;仅本人档永不可见(owner 空 ≠ 本人)。故 E2 分配入口(管理页)对全部/部门档管理员数据可达,无需去公海页。 +> **详情聚合接口可见性**(grill 补拍 20260821)= **DataScope 可见 OR 团队成员白名单命中**——保证「我参与的」视图点进详情链路闭环;写操作再按成员自身权限点校验。 + > 视图不是状态切片:同一商机可同时出现在多视图(如自己负责 + 最近访问过)。 ### 6.2 销售机会工作区 — 内置四视图(「常用检索」Tab,固定不可删/改) | code | 名称 | 数据范围 | |---|---|---| -| `recent` | 最近访问 | 当前用户打开过详情的商机,访问时间倒序、按商机 id 去重留最新,上限可配置(本期默认 50);「访问」= 调用详情聚合接口,任意皮肤(个人/管理/公海)都算(grill 补拍 20260821) | -| `mine` | 我负责的销售机会 | `owner_user_id = 当前用户` | +| `recent` | 最近访问 | 当前用户打开过详情的商机,访问时间倒序、按商机 id 去重留最新,上限可配置(本期默认 50);「访问」= 调用详情聚合接口,任意皮肤(个人/管理/公海)都算(grill 补拍 20260821);**落库 `opportunity_view_log`**(§7.9,访问即 upsert) | +| `mine` | 我负责的销售机会 | `owner_user_id = 当前用户`;**不按状态切片**(已关闭/已转项目仍在列——原型样例首行即「已转项目」商机;需只看活跃的用自定义视图按状态过滤,grill 补拍 20260821) | | `participated` | 我参与的销售机会 | **团队成员且非负责人**:`EXISTS(opportunity_team WHERE opportunity_id=? AND user_id=当前用户) AND owner_user_id <> 当前用户`;与 `mine` 互斥 | | `followed` | 我关注的销售机会 | 当前用户关注表 `opportunity_focus` 命中(§7.8) | @@ -374,21 +398,41 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 | 视图 | 专属列 | 操作按钮 | 新增入口 | |---|---|---|---| | 个人 A3-1-1 | 负责人默认隐藏 | 详情 / 写跟进 | **有**「+新增商机」(默认归当前用户) | -| 管理 A3-2-1 | 负责人显示 | 详情 / 分配 / 催办 / 关闭 + 批量催办/分配/关注/领导释放 | 无 | +| 管理 A3-2-1 | 负责人显示 | 详情 / 分配 / 关闭 + 批量分配/关注/领导释放;**催办/批量催办本期不做**(spin-out 留白,grill 补拍 20260821) | 无 | | 公海 A3-3-1 | 入池前工作节点 / 进入公海原因 / 当前负责人 | 详情 / 关注 / 领取 + 批量领取/关注 | 无 | | 最近访问 A3-0-1 | 按访问时间排序 | 详情 / 写跟进 / 关注 / 领取(按角色+商机态动态) | 无 | +> **批量操作语义**(grill 拍板 20260821):批量领取/关注/分配/领导释放 = **逐条处理、部分成功**——成功的成功,失败的逐条给出失败原因,前端展示「成功 x 条,失败 y 条 + 失败明细」;无全批回滚、无长事务。 + ### 6.7 详情三皮肤 同一详情聚合,按视角展示不同操作区,**非三套数据**。Tab 结构一致(概览/客户信息/方案卡/现场勘察/相关附件/跟进记录/工作计划/团队成员/操作日志);差异在头部操作按钮 + 进入权限: - 个人 A3-1-1-1:写跟进/编辑/暂缓/抛公海/关闭/新增方案卡 -- 管理 A3-2-1-1:+ 分配/催办/关闭/督办 +- 管理 A3-2-1-1:+ 分配/关闭;**催办/督办本期不做**(A3-2-1-1-1 督办功能 spin-out,催办随督办,grill 补拍 20260821) - 公海 A3-3-1-1:领取/关注,无跟进/推进入口(未领取不可推进) ⚠ P2-4:管理视角「领导 ▾」层级数据范围与 `@DataScope` 精确映射待实现阶段定。 + +⚠ **spin-out 留白(grill 补拍 20260821)**:**催办/督办** = 管理侧督促功能(A3-2-1-1-1),**本期不实现**——催办本质是向负责人发通知,而平台通知基础设施未建(暂缓到期提醒的发送渠道同因挂起);留白待平台通知能力就绪后与督办功能一并规划落地,本期管理视图隐藏催办/督办相关按钮。 ⚠ P2-7:自定义视图数量上限 / 多组条件开放时机 / 是否支持共享 待产品定。 +### 6.8 视图形态(正交于视图内容,grill 补拍 20260821) + +**出处**:原型 line 1281「分屏 split / 列表 list / 看板 board——展示模式切换,与『哪个视图/检索』正交」;A3-2-1「标题栏左侧视图切换 [ 列表、分屏、看板 ]」;票 10/14 均未定义此维度。 + +三种**展示形态**,与「哪个视图/检索」(6.2/6.3)正交——同一份列表数据三种渲染,**后端列表接口不变**(同一查询、同一 DataScope、同一分页),形态 = 前端渲染维度: + +| 形态 | code | 定义 | 默认 | +|---|---|---|---| +| 列表视图 | `list` | 传统表格(§6.5 基础列 + 列偏好) | **默认形态** | +| 分屏视图 | `split` | 左列表 + 右详情面板;面板复用详情聚合接口,非新数据源 | — | +| 看板视图 | `board` | 按「当前工作节点」分列的卡片流(列 = 阶段节点,列头带「共 N 条」计数;卡片 = 商机;底部「已展示 X/共 Y + 加载更多」——按列 or 整体加载的实现粒度留实现阶段定) | — | + +- **适用范围**:三个工作区(销售机会/商机管理/商机公海)+ 最近访问入口均支持三形态切换;切换入口 = 标题栏左侧,切换即刷新数据展示,操作按钮随工作区口径(原型 A3-2-1「切换不同入口时,标题栏、列表数据及可操作按钮同步刷新」)。 +- **列配置仅列表视图生效**(grill 拍板 20260821):自定义字段配置 / 列偏好只作用于列表视图;看板卡片字段与分屏面板字段为固定口径,不跟列偏好。 +- **形态偏好落 `crm-preference`**(与自定义视图同族,scope=`opportunity.sales`):用户切换后记住,下次打开该工作区保持上次形态;未设 → `list`。 + --- ## §7 详情子表族 @@ -413,7 +457,8 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 - **一客户一卡**:`UNIQUE(opportunity_id, customer_id)`;每张卡必挂一个当前商机下的关联客户(无孤立卡)。 - **状态机**:`草稿1 / 已提交2 / 已推送3`(「未创建」= 0 卡展示态,不入库)。 - - 保存草稿 → 草稿;确认 → 已提交(核心字段锁);推送 A7-3-2-3 → 已推送。 + - 保存草稿 → 草稿;确认 → 已提交(核心字段锁);推送 A7-3-2-3 → 已推送(**本期可达**,推送方案补票,grill 补拍 20260821)。 + - **推送成功 → 系统自动创建项目 → 商机转终态 5 + 落「已转项目」固定节点**(E8 触发源,grill 补拍 20260821)。 - **可编辑性**:草稿(1)/已提交(2) 均可改全部字段;仅已推送(3) 整卡只读(`card_status < 3` 可编辑),要改新建卡。不做字段级锁。 | 关键字段 | 说明 | @@ -442,7 +487,7 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 | `engineer_user_id` 主要工程师 | ✅ | 引用 crm-auth SysUser;列表展姓名/部门/联系方式(脱敏,反查不冗余存) | | `apply_way` 申请方式 | — | 引用字典 | | `survey_seq` 勘察次数 | — | 引用字典 | -| `apply_no` 申请单号 | — | | +| `apply_no` 申请单号 | ✕ | **人工录入、选填**(外部勘察申请流程未对接,单号线下拿到后补录;grill 拍板 20260821) | - 勘察附件走统一附件表(`biz_type=SITE_SURVEY` + `biz_id`)。 @@ -453,6 +498,7 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 - 字段 + `opp_id` + BaseEntity(create_by/create_time = 记录人/时间)。 - 跟进附件 → 附件子表 `biz_type=FOLLOW_UP`,最多 10 个。 - **保存跟进 → 刷新商机「最近跟进」 + `last_valid_follow_time`**(回收锚点刷新点,票 05 联动)。 +- **支持删除,删除不回退回收锚点**(grill 拍板 20260821):删除后 `last_valid_follow_time` 保持不变(不回退重算,防「写了又删」刷锚点);「最近跟进」计算列按删除后最新留存行自然变化;删除动作入 oplog。**编辑本期不做**(见清单 P2-9,写错以删除+补写方式修正)。 ### 7.5 附件 `opportunity_attachment`(统一表) @@ -487,6 +533,16 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 - 关注/取关无需原因、物理删行即可(关注不是审计对象,不入 oplog)。 - 「我关注的」视图 = 该表命中当前用户;管理/公海/最近访问视图的「关注」按钮读写此表。 +### 7.9 最近访问 `opportunity_view_log` + +**出处**:grill 补拍 20260821(票 10 recent 视图落库方式未定,拍板新建)。 + +- 字段:`user_id` + `opportunity_id` + `last_view_time` + BaseEntity;约束 `UNIQUE(user_id, opportunity_id)`。 +- 写入时机 = **调用详情聚合接口即 upsert**(刷新 `last_view_time`);个人/管理/公海任意皮肤都算(§6.2)。 +- **不写 `opportunity_oplog`**:访问是高频行为数据,oplog 是审计轨迹(行为类别不含浏览,票 09),两者分离。 +- 裁剪:recent 视图只取上限条数(本期默认 50),表内历史行靠后台 Job 按容量/时间裁剪(超出视图范围的历史无业务用途)。 +- 「最近访问」视图 = 该表命中当前用户,按 `last_view_time` 倒序取上限。 + --- ## §8 上下游集成 @@ -513,7 +569,9 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 ### 8.3 商机 → 项目(转项目端口占位) - E8 转项目:对接 A5 项目模块(本模块只占端口,转项目后商机锁死终态 5)。 -- 触发源:商机中任一方案卡转项目 → 轴 1 终态 + 轴 2 固定节点「已转项目」。 +- **标准路径(grill 补拍 20260821)**:创建商机 → 填写方案卡 → **推送方案卡 → 系统自动创建项目** → 商机触发轴 1 终态 + 轴 2 固定节点「已转项目」。列表「转项目」按钮 = 推送流程快捷入口。 +- **特殊路径(grill 补拍 20260821)**:跳过商机录入,项目侧直接创建项目,可关联方案卡(选填)——归 A5 项目模块定义。**关联即联动(grill 补拍 20260821)**:项目创建成功且关联了商机(或商机下的方案卡)时,A5 **回调商机模块触发 E8**(2→5)+ 落「已转项目」固定节点;本模块暴露回调端口(入参 = 商机 id 或方案卡 id),校验关联合法性后执行 E8 侧效(幂等:商机已终态则拒绝/跳过)。 +- **推送方案本期做(grill 补拍 20260821,票 07 边界修订)**:推送流程页 A3-1-1-2-5 + 方案推送规则 A7-3-2-3 + **项目查重规则 A7-3-2-4 一并纳入**,**补一张推送票**(流程/规则细则待该票定;原型推送链路 = 选卡 → 查重校验 → 创建项目);推送成功 → A5 建项目 → 触发 E8。E8 两个触发源(标准/特殊)本期均真实可达。 ### 8.4 商机 ↔ 客户(A4 客户模块) @@ -533,6 +591,7 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 | 阶段模板 | `opportunity_stage_template` | `OPP_GUIDE_*` | | 公海规则 | `opportunity_pool_rule` | `POOL_RULE_*` | | 方案卡模板 | `opportunity_scheme_card_template` | — | +| 有效跟进规则 | `opportunity_follow_rule` | `FOLLOW_RULE_*` | **V-CONFIG 公共约定:** @@ -586,8 +645,9 @@ crm-opportunity → crm-rule(阶段模板 / 方案卡模板 / 公海规则 | P2-6 | 公海规则数值样例 | P2 | 样例非验收值,规则配置录入 | | P2-7 | 自定义视图:数量上限 / 多组条件(AND/OR)+高级公式开放时机 / 是否支持共享 / 管理·公海是否开 | P2 | 本期私有、1 组条件、只销售机会开 | | P1-4 | 工作计划精确状态枚举 | 🅿️ | 归 A1X 独立模块,本期挂起 | -| P1-6 | 归属起点计时初始化(E1/E2/两入口创建统一口径,候选方案见清单) | P1 | 挂起待产品确认(grill 20260821) | -| P1-7 | 暂缓期间子表可写范围(写跟进/方案卡/勘察/附件/客户/团队) | P1 | 挂起待产品确认(grill 20260821) | +| P1-6 | 归属起点计时初始化(领取/分配重置、两入口创建=进入名下时间) | P1 | ✅ 已拍板(产品回复 20260821) | +| P1-7 | 暂缓期间子表可写范围 | P1 | ✅ 已拍板(暂缓/关闭先解除状态才能编辑) | +| P1-8 | 有效跟进定义修订+配置化 | P1 | ✅ 已拍板(本期仅写跟进;配置化保留可新增) | **已拍板存档(备查):** 预计成交时间归属(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)。 diff --git a/crm-opportunity/CONTEXT.md b/crm-opportunity/CONTEXT.md index c601732..c880b3a 100644 --- a/crm-opportunity/CONTEXT.md +++ b/crm-opportunity/CONTEXT.md @@ -15,7 +15,7 @@ _Avoid_: opportunity(英文单说)、线索(线索是上游实体)、项 _Avoid_: 阶段(阶段是另一条轴)、进度、stage、中止(不存在) **阶段(oppStage)**: -商机的**业务阶段轴**,`OpportunityStage`。表达按公司标准打法走到第几步:客户圈定 → 关系摸排 → 资料采集 → 方案卡 → 已转项目(原型详情页进度条 A3-1-1-1-1)。阶段序列由 `crm-rule` 的**商机阶段模板**配置(原型 A7-3-2-1,票 06)。商机绑定模板时锁死具体版本(`stage_template_id`=版本行 id),发新版不自动迁移。除「已转项目」外其余阶段**可自由切换(连跳/回退)**,每次写 `opportunity_stage_history` 快照。「已转项目」为固定末节点(`is_fixed`,不可删、不可手动点),仅由**商机下任一方案卡转项目创建成功**触发,同时驱动轴1 已转项目终态(联动)。与状态正交。 +商机的**业务阶段轴**,`OpportunityStage`。表达按公司标准打法走到第几步:客户圈定 → 关系摸排 → 资料采集 → 方案卡 → 已转项目(原型详情页进度条 A3-1-1-1-1)。阶段序列由 `crm-rule` 的**商机阶段模板**配置(原型 A7-3-2-1,票 06)。商机绑定模板时锁死具体版本(`stage_template_id`=版本行 id),发新版不自动迁移。除「已转项目」外其余阶段**可自由切换(连跳/回退)**,每次写 `opportunity_stage_history` 快照。「已转项目」为固定末节点(`is_fixed`,不可删、不可手动点),仅由**推送方案卡成功(系统自动创建项目)**触发,同时驱动轴1 已转项目终态(联动;grill 补拍 20260821,替代票 06「任一方案卡转项目」口径)。与状态正交。 _Avoid_: 状态(状态是另一条轴)、节点(口语可叫「节点」,字段用 stage)、status **领取人**: @@ -27,7 +27,7 @@ _Avoid_: 负责人(负责人是公海池概念)、持有者、owner(英文 _Avoid_: 录入人、owner(owner 是领取人) **团队成员**: -领取人拉入协作的人员,存于独立关联(原型「添加团队成员&一键拉群」A3-1-1-2-8、团队成员 Tab A3-1-1-1-8)。每人配**项目角色**(商机负责人 / 方案工程师 / 招标专员 / 现场工程师 等)与**权限**(读写 / 只读 / 可写跟进 / 可推进节点 等)。团队成员是**行级授权白名单**——绕开 DataScope 部门天花板给出可见性,但能否写取决于其自身权限点。**抛公海只清空领取人,不动团队成员**(产品明确)。**转商机时自动插一条团队成员:领取人 = 商机负责人(票 02 拍板)**。 +领取人拉入协作的人员,存于独立关联(原型「添加团队成员&一键拉群」A3-1-1-2-8、团队成员 Tab A3-1-1-1-8)。每人配**项目角色**(商机负责人 / 方案工程师 / 招标专员 / 现场工程师 等)与**权限**(读写 / 只读 / 可写跟进 / 可推进节点 等)。团队成员是**行级授权白名单**——绕开 DataScope 部门天花板给出可见性,但能否写取决于其自身权限点。**生效边界(grill 补拍 20260821)**:详情/子表读 + 个人工作区视图(我参与的/recent);管理/公海工作区严格按 DataScope 不混白名单;详情可见 = DataScope OR 白名单命中。**抛公海只清空领取人,不动团队成员**(产品明确)。**转商机时自动插一条团队成员:领取人 = 商机负责人(票 02 拍板)**。 _Avoid_: 协作人、参与者、观察者(团队成员带角色与权限,不只是「能看」) **商机来源**: @@ -43,7 +43,7 @@ _Avoid_: 商机来源(那是 oppSource 渠道)、线索 id、parent _Avoid_: 客户(客户是 A4 域的实体)、甲方(甲方是快照里的一个字段)、customer **暂缓**: -商机流转动作(原型 A3-1-1-2-6):短期推不动、但仍有价值时挂起。选**暂缓原因**(字典)+ **预计重启日期**(必填,不早于今天)+ 补充说明 → 状态「暂缓中」。**保留领取人+团队、不进公海、冻结回收计时**(暂缓期间不被超时回收;取消暂缓后按剩余天数续算,票 05)。保留暂缓前阶段/节点。到期不自动恢复——系统提醒领取人,人工选 取消暂缓(恢复推进)/ 继续暂缓 / 关闭。按钮可见性由权限点配置,可见即可点,与是否领取人无关。原型 A3-1-1-2-6 原文「暂停部分推进动作和常规跟进提醒」未枚举具体项:推进节点/转项目/抛公海受限(需先取消暂缓)已定(票 04);⚠ 写跟进/子表写是否允许待产品确认(P1-7)。 +商机流转动作(原型 A3-1-1-2-6):短期推不动、但仍有价值时挂起。选**暂缓原因**(字典)+ **预计重启日期**(必填,不早于今天)+ 补充说明 → 状态「暂缓中」。**保留领取人+团队、不进公海、冻结回收计时**(暂缓期间不被超时回收;取消暂缓后按剩余天数续算,票 05)。保留暂缓前阶段/节点。到期不自动恢复——系统提醒领取人,人工选 取消暂缓(恢复推进)/ 继续暂缓 / 关闭。按钮可见性由权限点配置,可见即可点,与是否领取人无关。**暂缓期间一切编辑操作全禁,必须先取消暂缓回到推进中才能写**(写跟进/子表写同禁;P1-7 产品拍板 20260821)。暂缓中(3) 允许的只有 E5 取消暂缓/E6 关闭/E9 移交。 _Avoid_: 中止(不存在)、挂起、冻结、关闭(关闭是明确无价值) **取消暂缓**: @@ -51,7 +51,7 @@ _Avoid_: 中止(不存在)、挂起、冻结、关闭(关闭是明确无 _Avoid_: 恢复(口语)、重启(重启是关闭的逆动作)、激活 **抛公海**: -商机流转动作(原型 A3-1-1-2-7):不想继续做,退回商机公海让他人领取。**只清空领取人**,回公海,**不动其他团队成员**(产品明确)。**无池实体**——公海 = `opp_status=1 且 owner 为空` 的逻辑视图,`owner_dept_id` 保留决定谁能看到(票 05 原型 A7-3-2-5 定稿,推翻初稿的 `pool_id` 回池模型)。人工抛公海入口受公海规则 `allow_manual_pool` 开关控制;此外连续 `recycle_days` 天无**有效跟进**会被**超时回收**自动回公海(票 05 `executeRecycle`,锚点 `last_valid_follow_time`)。 +商机流转动作(原型 A3-1-1-2-7):不想继续做,退回商机公海让他人领取。**只清空领取人**,回公海,**不动其他团队成员**(产品明确)。**无池实体**——公海 = `opp_status=1 且 owner 为空` 的逻辑视图,`owner_dept_id` 保留作 **DataScope 部门锚点**(公海可见性按查看者档位自然判定,同管理视图口径;grill 补拍 20260821 暂定,待产品终审)。人工抛公海入口受公海规则 `allow_manual_pool` 开关控制;此外连续 `recycle_days` 天无**有效跟进**会被**超时回收**自动回公海(票 05 `executeRecycle`,锚点 `last_valid_follow_time`)。 _Avoid_: 释放(线索用「释放」)、退回、放弃 **关闭**: @@ -67,7 +67,7 @@ _Avoid_: 恢复、取消暂缓(取消暂缓是暂缓的逆动作)、激活 _Avoid_: 转让(无此独立动作)、转移、指派(分配才是指派) **转项目**: -商机的下游终态动作:商机推到最后转成项目,商机进入「已转项目」终态、锁死不可回退(对称线索的「已转商机」)。**转项目端口**名字先占位——项目实体、项目查重规则(原型 A7-3-2-4)归 A5 项目模块,本域只承认终态、定占位契约。 +商机的下游终态动作:商机推到最后转成项目,商机进入「已转项目」终态、锁死不可回退(对称线索的「已转商机」)。**无独立「转项目」按钮动作**(grill 补拍 20260821)——标准路径 = 创建商机 → 填写方案卡 → **推送方案卡 → 系统自动创建项目**,推送成功即触发轴1 终态(E8)+ 轴2 固定节点;列表「转项目」按钮只是**推送流程快捷入口**。特殊路径 = 跳过商机录入、项目侧直接创建项目,可关联方案卡(选填,归 A5)。**关联即联动**(grill 补拍 20260821):项目创建成功且关联了商机(或商机下的方案卡)时,A5 回调商机模块触发 E8(2→5)+ 落固定节点;本模块暴露回调端口(入参 = 商机 id 或方案卡 id),校验关联合法性后执行 E8 侧效(幂等:已终态则拒绝/跳过)。**转项目端口**名字先占位——项目实体、项目查重规则(原型 A7-3-2-4)归 A5 项目模块,本域只承认终态、定占位契约。 _Avoid_: 成交、转化、结项、CreateProject(具体接口名留给 A5) **已转项目**: @@ -83,15 +83,15 @@ _Avoid_: 方案预算(方案卡字段,不同层次)、预计金额(旧 _Avoid_: 项目金额(商机主表字段,不同层次)、预计金额(旧名,已弃) **方案卡**: -商机推进过程中沉淀「客户需求/预算/招标形式/介入阶段/方案状态」的业务单据,转项目的**基础档案**。住 `crm-opportunity` 的 `opportunity_scheme_card`(票 07,原型 A3-1-1-1-3)。**一商机可多张、一客户一卡**(`UNIQUE(opportunity_id, customer_id)`),每张必关联商机下一个关联客户(无孤立方案卡);字段集由绑定的**方案卡模板**版本驱动(动态字段);单卡状态 `草稿1/已提交2/已推送3`(「未创建」=0卡展示态,P0-4)。列表「方案卡状态/方案预算」列取**主要意向客户那张卡**(票 13,非主卡)。**商机下任一方案卡转项目创建成功 = 「已转项目」联动触发源**(票 06)。 -_Avoid_: 推送方案/方案推送规则(A7-3-2-3,out of scope)、查重规则(A7-3-2-4,out of scope) +商机推进过程中沉淀「客户需求/预算/招标形式/介入阶段/方案状态」的业务单据,转项目的**基础档案**。住 `crm-opportunity` 的 `opportunity_scheme_card`(票 07,原型 A3-1-1-1-3)。**一商机可多张、一客户一卡**(`UNIQUE(opportunity_id, customer_id)`),每张必关联商机下一个关联客户(无孤立方案卡);字段集由绑定的**方案卡模板**版本驱动(动态字段);单卡状态 `草稿1/已提交2/已推送3`(「未创建」=0卡展示态,P0-4)。列表「方案卡状态/方案预算」列取**主要意向客户那张卡**(票 13,非主卡)。**推送方案卡成功 → 系统自动创建项目 = 「已转项目」联动触发源**(grill 补拍 20260821,替代票 06「任一方案卡转项目」口径)。 +_Avoid_: 推送规则(A7-3-2-3)、查重规则(A7-3-2-4)——均随推送票本期做(grill 补拍 20260821),但与方案卡本体/字段模板分层,不混入本票范畴 **现场勘察**: -记录商机某次到客户现场勘察的**结果单据**(现场条件/客户需求/安装环境/工程师建议 + 附件)。住 `crm-opportunity` 的 `opportunity_site_survey`(票 08,原型 A3-1-1-1-4)。**一商机可多条**(多次勘察保留历史不覆盖);**无状态机**(区别于方案卡);**不绑阶段节点**(自由记录);主要工程师从 **`crm-auth` 组织架构**选(`engineer_user_id`,非自由文本);附件**复用 `crm-file`**商机附件子表(`biz_type=SITE_SURVEY`+`biz_id`,票 09),不独立建表。 +记录商机某次到客户现场勘察的**结果单据**(现场条件/客户需求/安装环境/工程师建议 + 附件)。住 `crm-opportunity` 的 `opportunity_site_survey`(票 08,原型 A3-1-1-1-4)。**一商机可多条**(多次勘察保留历史不覆盖);**无状态机**(区别于方案卡);**不绑阶段节点**(自由记录);主要工程师从 **`crm-auth` 组织架构**选(`engineer_user_id`,非自由文本);**`apply_no` 申请单号人工录入选填**(外部勘察申请流程未对接,grill 拍板 20260821);附件**复用 `crm-file`**商机附件子表(`biz_type=SITE_SURVEY`+`biz_id`,票 09),不独立建表。 _Avoid_: 工程师=操作人(工程师是被选执行人,可跨部门;操作人是当前登录销售) **跟进记录**: -商机的客户沟通记录,`opportunity_follow`(票 09,原型 A3-1-1-1-6)。**无草稿态**(确认即提交,异于线索反馈记录);字段:跟进内容/时间/方式/关联客户/联系人/结果标签/下次跟进时间/附件。**保存跟进→刷新 `last_valid_follow_time`**(票 05 回收锚点刷新点之一);与阶段推进**不联动**。 +商机的客户沟通记录,`opportunity_follow`(票 09,原型 A3-1-1-1-6)。**无草稿态**(确认即提交,异于线索反馈记录);字段:跟进内容/时间/方式/关联客户/联系人/结果标签/下次跟进时间/附件。**保存跟进→刷新 `last_valid_follow_time`**(票 05 回收锚点刷新点之一);与阶段推进**不联动**。**支持删除、删除不回退回收锚点(grill 拍板 20260821)**:`last_valid_follow_time` 保持不变(防「写了又删」刷锚点),「最近跟进」按删除后最新留存行自然变化,删除入 oplog;**编辑本期不做**(写错以删除+补写修正)。 _Avoid_: 线索反馈记录(有草稿态,机制不同) **商机附件**: @@ -106,14 +106,34 @@ _Avoid_: 中央工作计划模块(A1X,跨域,本票不定读写) 商机的**字段级变更审计** `opportunity_oplog`(票 09,原型 A3-1-1-1-9):实体对象/字段名称/旧值/新值/操作说明/来源(系统自动 vs 人工)/时间/操作人。普通用户只读。**与线索 `lead_history` 口径不同**:线索是动作类型枚举(CLAIM/ASSIGN…)+JSON,商机是字段级旧新值审计。状态/阶段迁移另有专用快照表(`opportunity_status_history`/`opportunity_stage_history`),与本通用审计并存不重。 _Avoid_: 线索 history 模型(动作枚举,口径不同)、状态/阶段快照表(专用表,非通用审计) +**催办/督办**: +管理侧督促功能(原型 A3-2-1-1-1 督办功能;管理列表/详情的「催办/批量催办」入口)。**本期不实现(spin-out 留白,grill 补拍 20260821)**——催办本质是向负责人发通知,平台通知基础设施未建(暂缓到期提醒发送渠道同因挂起);留白待通知能力就绪后与督办一并规划落地,本期管理视图隐藏相关按钮。 +_Avoid_: 写跟进(催办是督促不是跟进记录)、站内信自建(通知属平台能力,商机域不自建) + **视图(内置 + 自定义)**: -销售机会工作区下的视图组织(票 14 推翻票 10「单一我负责的」,以 demo 0803 为准)。**内置视图四个**(「常用检索」Tab,固定不可删/改):**最近访问**(打开过详情的商机,时间倒序、按 id 去重留最新,上限可配 默认 50)/ **我负责的** `owner=当前用户` / **我参与的**(团队成员且非负责人,见下)/ **我关注的**(关注表 `opportunity_focus` 命中,见下)。**自定义视图**(「自定义检索」Tab)= 用户保存的检索:检索名称 + 条件列表(字段∈列表可筛选列 + 操作符 等于/不等于/包含/不包含/为空/不为空 + 值)+ 排序(字段+asc/desc),可编辑/重命名/删除/图钉设默认——**落 `crm-preference` 平台能力**(用户私有、按 `scope_key` 分组,本期 scope=`opportunity.sales`,后续菜单加 scope 即复用)。**商机管理**(按 `@DataScope`)/ **商机公海**(`opp_status=1 且 owner 空` 逻辑视图)仍是独立 workspace、不进销售机会视图下拉、本期不开自定义视图。计算列不冗余存:节点停留=今−进入当前节点日(stage_history)、最近跟进=最新 follow、预计金额=`project_amount`。详情三皮肤(个人/管理/公海)=同一聚合按视角展不同操作区,非三套数据。 +销售机会工作区下的视图组织(票 14 推翻票 10「单一我负责的」,以 demo 0803 为准)。**内置视图四个**(「常用检索」Tab,固定不可删/改):**最近访问**(打开过详情的商机,时间倒序、按 id 去重留最新,上限可配 默认 50,落 `opportunity_view_log`)/ **我负责的** `owner=当前用户` / **我参与的**(团队成员且非负责人,见下)/ **我关注的**(关注表 `opportunity_focus` 命中,见下)。**自定义视图**(「自定义检索」Tab)= 用户保存的检索:检索名称 + 条件列表(字段∈列表可筛选列 + 操作符 等于/不等于/包含/不包含/为空/不为空 + 值)+ 排序(字段+asc/desc),可编辑/重命名/删除/图钉设默认——**落 `crm-preference` 平台能力**(用户私有、按 `scope_key` 分组,本期 scope=`opportunity.sales`,后续菜单加 scope 即复用)。**商机管理**(按 `@DataScope`)/ **商机公海**(`opp_status=1 且 owner 空` 逻辑视图)仍是独立 workspace、不进销售机会视图下拉、本期不开自定义视图。计算列不冗余存:节点停留=今−进入当前节点日(stage_history)、最近跟进=最新 follow、预计金额=`project_amount`。详情三皮肤(个人/管理/公海)=同一聚合按视角展不同操作区,非三套数据。 _Avoid_: 视图=状态切片(同一商机可跨视图)、预计成交时间(产品二次拍板:商机列表删除该列、不上主表;仅方案卡内部字段票07)、自定义视图绑死商机(落 crm-preference 按 scope 通用,票 14)、内置视图可编辑(内置固定,只自定义视图可增删改) +**视图形态**: +与「哪个视图/检索」**正交**的展示形态维度(原型 line 1281,票 10/14 未定义;grill 补拍 20260821):**列表 list(默认)/ 分屏 split / 看板 board**,标题栏左侧切换。同一份列表数据三种渲染,**后端列表接口不变**(同查询、同 DataScope、同分页),形态 = 纯前端渲染维度;三个工作区 + 最近访问均支持。看板 = 按「当前工作节点」分列的卡片流(列头带「共 N 条」计数),分屏 = 左列表 + 右详情面板(复用详情聚合接口)。**列配置(自定义字段/列偏好)仅列表视图生效**(grill 拍板 20260821),看板卡片与分屏面板字段固定不跟列偏好。形态偏好落 `crm-preference`(scope=`opportunity.sales`,未设 → list)。 +_Avoid_: 形态=视图内容(两轴正交)、后端为形态单开接口(同一接口前端渲染)、列配置对看板/分屏生效 + +**最近访问**: +商机级个人浏览行为数据,落 `opportunity_view_log`(`user_id`+`opportunity_id`+`last_view_time`,`UNIQUE(user_id, opportunity_id)`;grill 补拍 20260821,票 10 未定落库方式)。**调用详情聚合接口即 upsert**,个人/管理/公海任意皮肤都算。**不写 `opportunity_oplog`**——访问是高频行为数据,oplog 是字段级审计轨迹(票 09 行为类别不含浏览),两者分离。表内历史行后台 Job 按容量/时间裁剪。「最近访问」视图 = 命中当前用户按 `last_view_time` 倒序取上限(默认 50)。 +_Avoid_: 操作日志(访问不入审计)、浏览记录(统一叫最近访问) + **关注**: 商机级个人收藏动作,落 `opportunity_focus`(`opportunity_id`+`user_id`,`UNIQUE(opportunity_id, user_id)`;grill 补拍 20260821,票 14 视图引用前此表未定义)。**纯收藏夹语义,不带通知**(通知属平台通知基础设施,未建)。关注/取关无需原因、物理删行、不入操作日志。「我关注的」视图 = 该表命中当前用户;管理/公海/最近访问视图的「关注」按钮读写此表。 _Avoid_: 团队成员(成员是行级授权白名单,关注是个人收藏)、收藏(统一叫关注) +**批量操作**: +视图列表的批量领取/关注/分配/领导释放 = **逐条处理、部分成功**(grill 拍板 20260821):成功的成功,失败的逐条给失败原因,前端展「成功 x 条,失败 y 条 + 失败明细」;无全批回滚、无长事务。 +_Avoid_: 全有或全无(批量不允许整批回滚) + +**权限点**: +商机模块权限模型 = **按钮可见即可点,权限全由权限点配置决定,与「是否负责人」无关**(票 01 产品明确)。权限点**动作级**颗粒度(一个动作一个点,不按视图 × 动作拆),全集见 PRD §1.5;编码实现阶段按平台规范登记。团队成员行上的读写/只读/可写跟进/可推进节点 = **行级角色配置,不走全局权限点**。 +_Avoid_: owner guard(无「操作人==负责人」拦截,可见即可点)、视图×动作拆分(颗粒度过细) + **我参与的**: 销售机会内置视图之一(票 14):**我是该商机团队成员但不是负责人** —— `EXISTS(团队成员 WHERE opportunity_id=? AND user_id=当前用户) AND owner_user_id <> 当前用户`。团队成员表 = 票 02/04 建商机落的领取人=负责人 + 后续「添加团队成员」加入者。与「我负责的」互斥不重叠(负责人走 `mine`,非负责成员走 `participated`)。 _Avoid_: 参与=含负责人(负责人归「我负责的」,参与专指非负责成员)、参与=仅能看(团队成员带角色权限,非观察者) @@ -137,9 +157,13 @@ _Avoid_: 阶段字典项(被引用方)、current_stage(运行时指针) _Avoid_: 商机公海池(无池实体)、商机池、线索池 **回收天数**: -商机公海规则字段 `recycle_days`(`auto_recycle_enabled` 时必填):连续 `recycle_days` 天无**有效跟进**(跟进/附件/字段编辑,非浏览;锚点 `last_valid_follow_time`)则超时回收→待领取,清 owner(票 05 `executeRecycle`)。回收前 `remind_days` 天提醒当前负责人(`remind_days` < `recycle_days` 硬校验)。**无失效天数 M**(商机无失效态,票 04/05)。 +商机公海规则字段 `recycle_days`(`auto_recycle_enabled` 时必填):连续 `recycle_days` 天无**有效跟进**则超时回收→待领取,清 owner(票 05 `executeRecycle`)。回收前 `remind_days` 天提醒当前负责人(`remind_days` < `recycle_days` 硬校验)。**回收/提醒由 crm-opportunity 自建 `@Scheduled` 单 Job 串行**(先扫提醒再扫回收,对齐线索域 ADR-0019 竞态规避;cron 配置占位符默认每日凌晨,grill 补拍 20260821)。**无失效天数 M**(商机无失效态,票 04/05)。 _Avoid_: 失效天数(商机无)、超时天数、N +**有效跟进**: +商机公海回收计时的**刷新动作**(刷新锚点 `last_valid_follow_time`)。P1-8 产品拍板(20260821):**商机状态为推进中(2) 且动作 = 写跟进**(本期唯一动作;上附件/编辑字段/方案卡/勘察等不计,产品二次修订)。动作类型集合是**配置项**——落 `crm-rule` 第四族「有效跟进规则」`opportunity_follow_rule`(V-CONFIG 同族:`rule_code`+`version_no`+草稿/发布中/已停用+适用范围两档+动作类型多选子表),回收 Job 按商机 `owner_dept_id` 实时匹配当前发布中规则(与公海规则同匹配引擎)。领取/分配重置锚点=now;两入口创建锚点=进入名下时间(P1-6)。 +_Avoid_: 浏览(不算有效跟进)、编辑主表字段(不计)、上传附件(不计) + ## 待细化(后续票) - 「移交」按钮原型位置、「取消暂缓/重启」独立页存否 —— 见 `issues/01` 的 To-verify,以产品口径为准。 - 商机主表 + 子表(团队成员 / 方案卡 / 现场勘察 / 跟进 / 附件 / 操作日志)字段(票 03/07/08/09)。