179 lines
5.7 KiB
Markdown
179 lines
5.7 KiB
Markdown
# 线索管理模块迁移方案 — 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)
|