Files
shanxia2.0/docs/crm-migration/plans/clue/05-special.md
T
2026-06-01 08:21:21 +08:00

179 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 线索管理模块迁移方案 — 05 业务逻辑与特殊场景
> **原则(第六步)**:本节为开发门禁文档。未在本节逐条对照 Java 实现前,**不得**修改 `backend/app/crud/crm/clue*.py` 或新增路由。
---
## 1. 定时任务 / 触发器 / 监听器
| 类型 | 线索模块 | 说明 |
|------|----------|------|
| MySQL 触发器 | 无 | `sx.sql` 无 `crm_clue` 触发器 |
| Quartz / SnailJob | 无 | 无 `*Clue*Job` |
| Spring 事件监听 | 无 | 转化/跟进均在 Service 同步事务内完成 |
**结论**:线索无独立后台任务;与 **公海池规则定时回收** 无关。
---
## 2. 线索状态机
```
new(新线索)
→ follow(跟进中) # 首次新增跟进记录时自动切换
→ invalid(无效) # 手动标记无效
→ converted(已转化) # 转化客户成功
```
| 规则 | Java 行为(须对齐) |
|------|---------------------|
| 已转化 | `is_converted=1`,不可再编辑/删除/分配/再转化 |
| 无效 | `status=invalid`,不可转化 |
| 转化条件 | `checkConvertible`:至少 1 次跟进、非 invalid、未转化 |
| 删除 | 已转化线索校验不通过则拒绝(`deleteWithValidByIds`) |
---
## 3. 新增线索 `insertByBo`
- 校验手机号租户内唯一
- 默认 `status=new`,`level=unrated`(若未传)
- 填充 `owner_user_id`:未传时取当前登录用户
- 冗余 `owner_user_name`(UserService 翻译)
- **数据权限**:列表查询带 `@DataPermission`(门户用角色数据范围 union)
---
## 4. 修改线索 `updateByBo`
- 已转化不可改
- 改手机号时排除自身查重
- 更新 `update_by` / `update_time`
---
## 5. 批量分配 `assignClues`
- 参数:`ids[]`、`ownerUserId`、`remark`(可选)
- 已转化线索跳过或整批失败(以 Java 异常信息为准,实施时读 `assignClues` 源码定稿)
- 写 `assign_time`、`assign_by`,更新负责人姓名冗余
---
## 6. 转化客户 `convertToCustomer`(事务)
**必须在同一事务内:**
1. 校验 `checkConvertible`
2. 创建 `crm_customer`(字段映射见 `CrmClueConvertBo` + 客户模块既有逻辑)
3. 创建主联系人 `crm_contact`(姓名、手机等从线索带出)
4. 更新线索:`status=converted`、`is_converted=1`、`converted_time`、`customer_id`、`converted_by`
5. 客户表回写 `clue_id` 关联来源线索
**禁止**:只更新线索不建客户,或先 commit 客户后更新线索。
---
## 7. 标记无效 `markAsInvalid`
- 支持批量 `ids[]` + `reason`
- 已转化不可标记无效
---
## 8. 新增跟进 `CrmClueFollowServiceImpl.insertByBo`(关键)
新增跟进后 **级联更新线索**(门户 CRUD 必须保持一致):
| 线索字段 | 更新规则 |
|----------|----------|
| `last_time` | 当前时间 |
| `follow_count` | +1 |
| `next_time` | 跟进记录的 `next_time`(若有) |
| `status` | 若当前为 `new` → 改为 `follow` |
修改跟进时:若 `next_time` 变更,同步回写线索 `next_time`。
删除跟进:是否回减 `follow_count` —— **以 Java `deleteWithValidByIds` 为准**(实施前读源码)。
---
## 9. 列表视图(多 Tab)
| 视图 | Java 方法 | 过滤要点 |
|------|-----------|----------|
| 全部 | `queryPageList` | 租户 + 数据权限 |
| 我的 | `queryMyClues` | `owner_user_id = 当前用户` |
| 待跟进 | `queryToFollowClues` | `next_time <= now` 且状态 in (new,follow) |
| 今日新增 | 原 GET `/todayNew` 或列表加日期条件 | `create_time` 当天 |
| 已转化 | 前端筛 `status=converted` 或 `is_converted=1` | 与 Java 筛选项一致 |
门户 API 建议:`POST /web/crm/clue/list` + `viewType` 枚举,与现 Python `list_clues` 对齐。
---
## 10. 导入导出
| 能力 | Java | 门户现状 |
|------|------|----------|
| 导出 Excel | `POST /export`,`*Vo` + `@ExcelDictFormat` | ✅ `POST /web/crm/clue/export`,经 **`CLUE_EXPORT_COLUMNS` + `export_rows_to_xlsx_response`** 字典翻译 |
| 导入模板 | `POST /importTemplate` | ✅ |
| 批量导入 | `POST /import` + MultipartFile | ✅ |
**线索导出字典列(须与列表展示一致)**:
| 列 | dict_type |
|----|-----------|
| 客户类型 | `crm_customer_type` |
| 线索来源 | `crm_clue_source` |
| 线索等级 | `crm_clue_level` |
| 线索状态 | `crm_clue_status` |
| 所属行业 | `crm_industry` |
| 所在园区 | `crm_customer_park` |
Java 对照:`shanxia/crm/.../vo/CrmClueVo.java`。门户列定义:`backend/app/utils/crm_export_columns.py` → `CLUE_EXPORT_COLUMNS`。
---
## 11. 统计分析(5 接口)
后端五路由已实现;**前端统计菜单隐藏**(`sqxp.ts` `isHide: true`),页面保留供后续启用。
---
## 12. 查重 `checkDuplicate`
- 入参:`mobile`、`company`、`excludeId`
- 返回可能重复的线索列表
- 门户 **未实现**;表单失焦/保存前可选对接
---
## 13. 跨模块依赖
| 依赖 | 说明 |
|------|------|
| 客户模块 | 转化时复用 `create customer` / `create contact` |
| 用户下拉 | `GET /web/admin/users/options` 或 `fetchUserList` |
| 字典 | `useDictStore` / `dictStore.getOptions('crm_clue_*')` |
| 附件 | MinIO;跟进 `attachments` 逗号分隔 URL |
| 园区 | Java 已废弃 `parkAreaList` API,改用字典 `crm_customer_park` |
---
## 14. 权限标识(sys_menu)
与公海池/客户一致:`crm:clue:list|query|add|edit|remove|export|import|assign|follow|convert|invalid`。
`v-auth` 使用动作短码:`add`、`edit`、`remove` 等(门户 `auth.ts`)。
---
## 15. 开发顺序建议
1. 读本节 + `04-api-spec.md`
2. 对照 `CrmClueServiceImpl.java` 逐方法打勾
3. 先写/改 CRUD 单测或 Postman 集合
4. 再挂 `api/crm.py` 路由
5. 最后适配前端(step-03)