forked from erp-dev/erp
feat: mission category
This commit is contained in:
@@ -1,84 +1,83 @@
|
||||
# Notifier 管理人员配置说明
|
||||
|
||||
本文档面向后台管理人员,说明如何在 Django Admin 中配置 `Notifier`,让系统在指定业务事件发生时自动发送通知。
|
||||
本文档面向后台管理人员,说明如何在 Django Admin 中配置 `Notifier` 与 `NotifierRoute`,让系统在指定业务事件发生时自动发送通知,并支持按任务分类分发。
|
||||
|
||||
## 1. Notifier 是什么
|
||||
## 1. 两层结构
|
||||
|
||||
`Notifier` 可以理解为一条“通知规则”。
|
||||
当前通知配置分成两层:
|
||||
|
||||
当某个业务事件发生时,系统会根据以下条件查找可用的通知器:
|
||||
- `Notifier`:通知器本体,负责“发到哪里、用什么模板、走什么渠道”
|
||||
- `NotifierRoute`:通知路由,负责“什么事件、什么任务分类,应该命中哪个 Notifier”
|
||||
|
||||
- 商户一致
|
||||
- `event_key` 一致
|
||||
- `is_enabled=True`
|
||||
可以这样理解:
|
||||
|
||||
找到后,系统会自动:
|
||||
- `Notifier` 是“发信工具”
|
||||
- `NotifierRoute` 是“分发规则”
|
||||
|
||||
1. 使用对应模板渲染消息内容
|
||||
2. 按配置的渠道发送
|
||||
3. 记录发送日志
|
||||
|
||||
当前已支持的渠道:
|
||||
|
||||
- 企业微信机器人 `wecom_webhook`
|
||||
|
||||
## 2. 当前已支持的事件
|
||||
## 2. 当前已支持的 mission 事件
|
||||
|
||||
目前 `mission` 模块已接入以下事件:
|
||||
|
||||
- `mission.created`:任务创建
|
||||
- `mission.replied`:任务有新回应
|
||||
- `mission.completed`:任务完成
|
||||
- `mission.reply_rejected`:任务回应被撤销
|
||||
- `mission.reopened`:任务被重新打开
|
||||
- `mission.cancelled`:任务被取消
|
||||
- `mission.created`
|
||||
- `mission.replied`
|
||||
- `mission.completed`
|
||||
- `mission.reply_rejected`
|
||||
- `mission.reopened`
|
||||
- `mission.cancelled`
|
||||
|
||||
如果要让某个事件发送通知,只需要在后台新增对应 `event_key` 的 `Notifier`。
|
||||
所有这些事件都支持通过 `NotifierRoute` 进行分类路由。
|
||||
|
||||
## 3. 在哪里配置
|
||||
## 3. 当前支持的分类路由能力
|
||||
|
||||
进入 Django Admin 后,找到:
|
||||
路由匹配规则如下:
|
||||
|
||||
1. 先按 `merchant + event_key + is_enabled=True` 匹配启用中的路由
|
||||
2. 如果当前任务带有分类:
|
||||
- 优先匹配该分类的专用路由
|
||||
- 同时允许匹配“任务分类为空”的通配路由
|
||||
3. 如果同一个 `Notifier` 同时命中了专用路由和通配路由,只发送一次,优先使用专用路由
|
||||
|
||||
这意味着你可以实现:
|
||||
|
||||
- 某个分类发到专门群
|
||||
- 未单独配置的分类发到通用群
|
||||
- 同一事件同时发多个群
|
||||
|
||||
## 4. Admin 中的两个入口
|
||||
|
||||
进入 Django Admin 后,主要会看到两个对象:
|
||||
|
||||
- `通知器`
|
||||
- `通知路由`
|
||||
|
||||
然后点击“新增”即可。
|
||||
推荐的管理方式:
|
||||
|
||||
## 4. 字段说明
|
||||
1. 先创建 `Notifier`
|
||||
2. 再创建或维护它的 `NotifierRoute`
|
||||
|
||||
创建 `Notifier` 时,需要填写以下字段。
|
||||
在 `Notifier` 详情页中,也可以直接通过 inline 管理该通知器下的路由。
|
||||
|
||||
### 4.1 merchant
|
||||
## 5. Notifier 字段说明
|
||||
|
||||
### 5.1 merchant
|
||||
|
||||
所属商户。
|
||||
|
||||
通知器只会匹配当前商户下发生的事件。
|
||||
不同商户如果都需要通知,需要分别创建各自的 `Notifier`。
|
||||
通知器只会服务于该商户下的路由和事件。
|
||||
|
||||
### 4.2 name
|
||||
### 5.2 name
|
||||
|
||||
通知器名称,仅用于后台识别和管理。
|
||||
|
||||
建议命名方式:
|
||||
|
||||
- `任务创建通知-生产群`
|
||||
- `任务完成通知-老板群`
|
||||
- `任务取消通知-客服群`
|
||||
- `任务通知-生产群`
|
||||
- `任务通知-售后群`
|
||||
- `任务通知-管理群`
|
||||
|
||||
同一商户下名称不能重复。
|
||||
|
||||
### 4.3 event_key
|
||||
|
||||
要监听的业务事件标识。
|
||||
|
||||
这是最核心的绑定字段。
|
||||
它决定这条 `Notifier` 绑定到哪个业务信号。
|
||||
|
||||
例如:
|
||||
|
||||
- `mission.completed` 表示“任务完成时发送”
|
||||
- `mission.cancelled` 表示“任务取消时发送”
|
||||
|
||||
### 4.4 channel
|
||||
### 5.3 channel
|
||||
|
||||
通知渠道。
|
||||
|
||||
@@ -86,12 +85,12 @@
|
||||
|
||||
- `wecom_webhook`
|
||||
|
||||
### 4.5 template_key
|
||||
### 5.4 template_key
|
||||
|
||||
消息模板标识。
|
||||
模板标识。
|
||||
|
||||
系统会根据这个字段去固定目录查找模板文件。
|
||||
当前模板目录为:
|
||||
当前模板目录:
|
||||
|
||||
`notifier/templates/notifier/events/`
|
||||
|
||||
@@ -100,18 +99,18 @@
|
||||
- `template_key = mission_completed`
|
||||
- 对应模板文件:`notifier/templates/notifier/events/mission_completed.md`
|
||||
|
||||
### 4.6 is_enabled
|
||||
### 5.5 is_enabled
|
||||
|
||||
是否启用。
|
||||
是否启用通知器本体。
|
||||
|
||||
- 勾选:该 `Notifier` 生效
|
||||
- 不勾选:该 `Notifier` 不会参与匹配和发送
|
||||
- 勾选:该通知器可被路由命中
|
||||
- 不勾选:即使路由存在,也不会发送
|
||||
|
||||
### 4.7 config
|
||||
### 5.6 config
|
||||
|
||||
渠道配置,使用 JSON 格式填写。
|
||||
渠道配置,JSON 格式。
|
||||
|
||||
当前企业微信机器人建议配置如下:
|
||||
当前企业微信机器人建议配置:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -121,105 +120,134 @@
|
||||
}
|
||||
```
|
||||
|
||||
字段说明:
|
||||
|
||||
- `key`:企业微信机器人 webhook key
|
||||
- `msgtype`:消息类型,建议用 `markdown`
|
||||
- `timeout_seconds`:请求超时时间,单位秒
|
||||
|
||||
### 4.8 description
|
||||
### 5.7 description
|
||||
|
||||
备注说明,非必填。
|
||||
|
||||
建议写清楚这条通知器的用途,例如:
|
||||
## 6. NotifierRoute 字段说明
|
||||
|
||||
- `用于生产部任务完成通知`
|
||||
- `用于客服查看任务取消`
|
||||
### 6.1 merchant
|
||||
|
||||
## 5. 配置步骤
|
||||
所属商户。
|
||||
|
||||
以“任务完成时发送企业微信通知”为例:
|
||||
必须与关联的 `Notifier` 属于同一商户。
|
||||
|
||||
1. 进入 Admin 的 `通知器`
|
||||
2. 点击“新增”
|
||||
3. 选择 `merchant`
|
||||
4. 填写 `name`
|
||||
5. 选择 `event_key = mission.completed`
|
||||
6. 选择 `channel = wecom_webhook`
|
||||
7. 填写 `template_key = mission_completed`
|
||||
8. 在 `config` 中填写 webhook 参数
|
||||
9. 勾选 `is_enabled`
|
||||
10. 保存
|
||||
### 6.2 notifier
|
||||
|
||||
保存后,只要该商户下发生“任务完成”事件,系统就会自动尝试发送通知。
|
||||
要使用的通知器。
|
||||
|
||||
## 6. 推荐配置示例
|
||||
### 6.3 event_key
|
||||
|
||||
### 6.1 示例一:任务创建通知
|
||||
要监听的业务事件。
|
||||
|
||||
适合发到内部任务协作群。
|
||||
例如:
|
||||
|
||||
字段建议:
|
||||
- `mission.created`
|
||||
- `mission.completed`
|
||||
|
||||
- `name`: `任务创建通知-协作群`
|
||||
- `event_key`: `mission.created`
|
||||
- `channel`: `wecom_webhook`
|
||||
- `template_key`: `mission_created`
|
||||
- `is_enabled`: 勾选
|
||||
### 6.4 mission_category
|
||||
|
||||
`config` 示例:
|
||||
任务分类路由条件。
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
|
||||
"msgtype": "markdown",
|
||||
"timeout_seconds": 10
|
||||
}
|
||||
```
|
||||
- 为空:表示该事件的通配路由,适用于所有未被更具体路由覆盖的任务分类
|
||||
- 不为空:表示只处理该任务分类下的任务事件
|
||||
|
||||
### 6.2 示例二:任务完成通知
|
||||
### 6.5 is_enabled
|
||||
|
||||
适合发到管理群或老板群。
|
||||
是否启用该路由。
|
||||
|
||||
字段建议:
|
||||
- 勾选:路由参与匹配
|
||||
- 不勾选:路由不会命中
|
||||
|
||||
### 6.6 description
|
||||
|
||||
备注说明,建议写清楚用途,例如:
|
||||
|
||||
- `任务创建-生产分类专用路由`
|
||||
- `任务完成-所有分类默认路由`
|
||||
|
||||
## 7. 推荐配置步骤
|
||||
|
||||
以“任务创建时,生产分类发生产群,其他分类发管理群”为例:
|
||||
|
||||
### 第一步:创建两个 Notifier
|
||||
|
||||
1. 创建 `Notifier A`
|
||||
- `name = 任务通知-生产群`
|
||||
- `channel = wecom_webhook`
|
||||
- `template_key = mission_created`
|
||||
- `config` 填生产群机器人 key
|
||||
- `is_enabled = True`
|
||||
|
||||
2. 创建 `Notifier B`
|
||||
- `name = 任务通知-管理群`
|
||||
- `channel = wecom_webhook`
|
||||
- `template_key = mission_created`
|
||||
- `config` 填管理群机器人 key
|
||||
- `is_enabled = True`
|
||||
|
||||
### 第二步:创建路由
|
||||
|
||||
1. 创建 `NotifierRoute A1`
|
||||
- `notifier = Notifier A`
|
||||
- `event_key = mission.created`
|
||||
- `mission_category = 生产`
|
||||
- `is_enabled = True`
|
||||
|
||||
2. 创建 `NotifierRoute B1`
|
||||
- `notifier = Notifier B`
|
||||
- `event_key = mission.created`
|
||||
- `mission_category = 空`
|
||||
- `is_enabled = True`
|
||||
|
||||
这样配置后:
|
||||
|
||||
- 生产分类任务创建时,优先命中生产群路由
|
||||
- 其他分类任务创建时,走管理群的通配路由
|
||||
|
||||
## 8. 典型配置示例
|
||||
|
||||
### 8.1 示例一:所有任务完成统一发管理群
|
||||
|
||||
`Notifier`
|
||||
|
||||
- `name`: `任务完成通知-管理群`
|
||||
- `event_key`: `mission.completed`
|
||||
- `channel`: `wecom_webhook`
|
||||
- `template_key`: `mission_completed`
|
||||
- `is_enabled`: 勾选
|
||||
|
||||
### 6.3 示例三:任务取消通知
|
||||
`NotifierRoute`
|
||||
|
||||
适合发到客服或跟单群。
|
||||
|
||||
字段建议:
|
||||
|
||||
- `name`: `任务取消通知-客服群`
|
||||
- `event_key`: `mission.cancelled`
|
||||
- `channel`: `wecom_webhook`
|
||||
- `template_key`: `mission_cancelled`
|
||||
- `event_key`: `mission.completed`
|
||||
- `mission_category`: 留空
|
||||
- `is_enabled`: 勾选
|
||||
|
||||
## 7. 一个事件是否可以绑定多个 Notifier
|
||||
### 8.2 示例二:售后分类任务创建发售后群
|
||||
|
||||
可以。
|
||||
`Notifier`
|
||||
|
||||
例如同一个商户下,`mission.completed` 可以同时配置:
|
||||
- `name`: `任务创建通知-售后群`
|
||||
- `channel`: `wecom_webhook`
|
||||
- `template_key`: `mission_created`
|
||||
- `is_enabled`: 勾选
|
||||
|
||||
- 一条发到生产群
|
||||
- 一条发到老板群
|
||||
- 一条发到客服群
|
||||
`NotifierRoute`
|
||||
|
||||
只要它们满足:
|
||||
- `event_key`: `mission.created`
|
||||
- `mission_category`: `售后`
|
||||
- `is_enabled`: 勾选
|
||||
|
||||
- `merchant` 相同
|
||||
- `event_key` 相同
|
||||
- `is_enabled=True`
|
||||
### 8.3 示例三:同一个事件同时发多个群
|
||||
|
||||
系统就会逐条发送。
|
||||
例如 `mission.cancelled` 同时发客服群和管理群:
|
||||
|
||||
## 8. 模板如何对应
|
||||
- 创建两个不同的 `Notifier`
|
||||
- 分别为它们配置两条 `event_key = mission.cancelled` 的路由
|
||||
- 两条路由都可以是 `mission_category` 为空的通配路由
|
||||
|
||||
系统会分别发送到两个群。
|
||||
|
||||
## 9. 模板如何对应
|
||||
|
||||
当前系统已内置以下模板:
|
||||
|
||||
@@ -233,61 +261,84 @@
|
||||
管理人员通常只需要填 `template_key`,不需要改代码。
|
||||
如果后续要新增模板内容或调整文案,需要由开发人员修改模板文件。
|
||||
|
||||
## 9. 如何停用某条通知
|
||||
## 10. 如何停用
|
||||
|
||||
如果暂时不想让某条通知继续发送,不需要删除,只需要:
|
||||
### 停用整个通知器
|
||||
|
||||
1. 打开该 `Notifier`
|
||||
适用于:
|
||||
|
||||
- 这个群临时不用
|
||||
- 机器人 key 暂时不可用
|
||||
- 该通知器下的所有路由都不想生效
|
||||
|
||||
操作方式:
|
||||
|
||||
1. 打开 `Notifier`
|
||||
2. 取消勾选 `is_enabled`
|
||||
3. 保存
|
||||
|
||||
这样最安全,也方便后续恢复。
|
||||
### 停用某一条路由
|
||||
|
||||
## 10. 常见问题
|
||||
适用于:
|
||||
|
||||
### 10.1 为什么事件发生了,但没有收到通知
|
||||
- 只是不想处理某个事件
|
||||
- 只是不想处理某个任务分类
|
||||
|
||||
操作方式:
|
||||
|
||||
1. 打开对应 `NotifierRoute`
|
||||
2. 取消勾选 `is_enabled`
|
||||
3. 保存
|
||||
|
||||
## 11. 常见问题
|
||||
|
||||
### 11.1 为什么事件发生了,但没有收到通知
|
||||
|
||||
请依次检查:
|
||||
|
||||
1. `Notifier` 是否已勾选 `is_enabled`
|
||||
2. `merchant` 是否配置正确
|
||||
1. `Notifier` 是否启用
|
||||
2. `NotifierRoute` 是否启用
|
||||
3. `event_key` 是否选对
|
||||
4. `template_key` 是否与现有模板匹配
|
||||
5. `config.key` 是否填写正确
|
||||
6. Celery worker 是否已启动
|
||||
4. `mission_category` 是否与实际任务分类匹配
|
||||
5. `template_key` 是否对应现有模板
|
||||
6. `config.key` 是否填写正确
|
||||
7. Celery worker 是否已启动
|
||||
|
||||
### 10.2 为什么同一个事件发了多次
|
||||
### 11.2 为什么某个任务分类没有走专门群
|
||||
|
||||
通常是因为配置了多条相同 `merchant + event_key` 的启用状态通知器。
|
||||
常见原因:
|
||||
|
||||
1. 没有为该分类配置专用路由
|
||||
2. 专用路由被停用
|
||||
3. 该任务分类本身不是你以为的那个分类
|
||||
|
||||
### 11.3 为什么同一个事件发了多次
|
||||
|
||||
通常是因为配置了多个不同的 `NotifierRoute`,分别绑定到了不同的 `Notifier`。
|
||||
这不一定是错误,也可能是有意发往多个群。
|
||||
|
||||
如果不希望多发,请检查是否存在重复配置。
|
||||
### 11.4 同一个通知器会不会因为“专用路由 + 通配路由”重复发送两次
|
||||
|
||||
### 10.3 是否建议删除 Notifier
|
||||
不会。
|
||||
系统会自动去重,并优先使用更具体的分类路由。
|
||||
|
||||
一般不建议优先删除,建议先停用:
|
||||
## 12. 管理建议
|
||||
|
||||
- 更安全
|
||||
- 方便回滚
|
||||
- 方便排查历史配置
|
||||
|
||||
## 11. 管理建议
|
||||
|
||||
建议按下面的方式维护:
|
||||
|
||||
- 名称中写清楚用途和群目标
|
||||
- 先建 `Notifier`,再建 `NotifierRoute`
|
||||
- 通知器名称中写清楚目标群
|
||||
- 路由备注中写清楚事件和分类用途
|
||||
- 先停用再删除
|
||||
- 一个事件先配一条验证,确认无误后再扩展到多个群
|
||||
- `description` 中注明负责人或用途
|
||||
- 先配置一条路由做验证,再批量扩展
|
||||
|
||||
## 12. 给管理人员的最简操作结论
|
||||
## 13. 最简操作结论
|
||||
|
||||
如果你只想快速配置一条通知,记住这 5 个关键点就够了:
|
||||
如果你只想快速配置一条通知,记住这 6 个关键点就够了:
|
||||
|
||||
1. 选对 `merchant`
|
||||
2. 选对 `event_key`
|
||||
3. 选 `channel = wecom_webhook`
|
||||
4. 填对 `template_key`
|
||||
5. 在 `config` 填正确的企业微信机器人 `key`
|
||||
1. 先创建 `Notifier`
|
||||
2. 填好 `channel`
|
||||
3. 填好 `template_key`
|
||||
4. 在 `config` 中填好企业微信机器人 `key`
|
||||
5. 再创建 `NotifierRoute`
|
||||
6. 选对 `event_key` 和 `mission_category`
|
||||
|
||||
这样保存后,对应事件发生时就会自动发送。
|
||||
这样保存后,对应任务事件发生时就会自动按路由发送。
|
||||
|
||||
@@ -2,131 +2,118 @@
|
||||
|
||||
本文档面向后端维护者,描述 `notifier` 模块当前的实现决策、已落地范围与后续扩展注意事项。
|
||||
|
||||
## 1. 背景与目标
|
||||
## 1. 当前阶段
|
||||
|
||||
项目原有的通知能力主要以企业微信机器人为主,并且配置集中在 `settings.py` 中,属于静态配置方案。
|
||||
新的 `mission` 模块希望从一开始就采用:
|
||||
`notifier` 现已从第一阶段的“`Notifier` 直接绑定 `event_key`”升级为第二阶段的“`Notifier + NotifierRoute`”结构。
|
||||
|
||||
- 独立 Django app
|
||||
- task 化投递
|
||||
- 后台可配置
|
||||
- signal 与 notifier 动态绑定
|
||||
- 为后续增加其它通知渠道预留统一接口
|
||||
这样做的原因是:
|
||||
|
||||
因此本次新增独立模块 `notifier`,并先将 `mission` 的新信号通知接入该模块。
|
||||
- 一个通知器可能需要绑定多个事件
|
||||
- 同一事件需要支持按任务分类路由
|
||||
- 同一事件可能同时发往多个不同通知器
|
||||
- 后续还可能出现更多路由维度
|
||||
|
||||
因此当前模块职责被拆成两层:
|
||||
|
||||
- `Notifier`:通知渠道配置、模板配置、启停控制
|
||||
- `NotifierRoute`:事件匹配与业务路由规则
|
||||
|
||||
## 2. 当前范围
|
||||
|
||||
本次实现属于 Phase 1,范围有意收敛:
|
||||
本阶段已实现:
|
||||
|
||||
- 已新增独立 app:`notifier`
|
||||
- 已支持后台配置 `Notifier`
|
||||
- 已支持按 `event_key` + `merchant` 动态匹配通知器
|
||||
- 已支持 Celery task 化派发
|
||||
- 已支持模板化内容渲染
|
||||
- 已支持第一种渠道:企业微信机器人 webhook
|
||||
- 已接入 `mission` 的 6 个业务信号
|
||||
- 独立 app:`notifier`
|
||||
- Celery task 化投递
|
||||
- 企业微信 webhook 渠道
|
||||
- 模板化内容渲染
|
||||
- Admin 可配置
|
||||
- `NotifierRoute` 事件路由
|
||||
- `mission` 相关事件按任务分类路由
|
||||
|
||||
本次**没有**做的内容:
|
||||
本阶段仍未做:
|
||||
|
||||
- 没有改造旧模块的静态通知逻辑
|
||||
- 没有引入通知订阅/端点拆表
|
||||
- 没有引入通知投递明细表(如 `NotificationDelivery`)
|
||||
- 没有做数据库级别审计
|
||||
- 没有提供对外 API
|
||||
- 旧模块静态通知逻辑迁移
|
||||
- 外部 API
|
||||
- 通知投递明细表
|
||||
- 数据库级别审计
|
||||
|
||||
## 3. 核心模型
|
||||
|
||||
当前模型只有一个主模型:`notifier.Notifier`
|
||||
### 3.1 Notifier
|
||||
|
||||
字段职责如下:
|
||||
`Notifier` 负责“怎么发”:
|
||||
|
||||
- `merchant`: 多商户隔离
|
||||
- `name`: 通知器名称,仅要求在同商户内唯一
|
||||
- `event_key`: 事件标识,用于和业务 signal 对接
|
||||
- `channel`: 通知渠道,当前仅实现 `wecom_webhook`
|
||||
- `template_key`: 模板标识,对应固定目录中的模板文件
|
||||
- `is_enabled`: 启用/停用
|
||||
- `config`: 渠道配置,当前主要存放企业微信 webhook key、msgtype、timeout 等
|
||||
- `description`: 备注
|
||||
- `merchant`
|
||||
- `name`
|
||||
- `channel`
|
||||
- `template_key`
|
||||
- `is_enabled`
|
||||
- `config`
|
||||
- `description`
|
||||
|
||||
当前将 `event_key` 直接放在 `Notifier` 上,而没有拆成“事件订阅 + 通知端点”两层,原因是现阶段追求低复杂度、可快速上线。
|
||||
后续如果一个通知端点需要订阅多个事件,或者一个事件需要更复杂的启停/优先级/路由策略,再考虑拆模。
|
||||
当前 `Notifier` 已不再直接持有 `event_key`。
|
||||
|
||||
## 4. 目录结构
|
||||
### 3.2 NotifierRoute
|
||||
|
||||
关键文件如下:
|
||||
`NotifierRoute` 负责“何时发、发给谁”:
|
||||
|
||||
- `notifier/models.py`
|
||||
- `notifier/admin.py`
|
||||
- `notifier/services.py`
|
||||
- `notifier/tasks.py`
|
||||
- `notifier/backends.py`
|
||||
- `notifier/registry.py`
|
||||
- `notifier/templates/notifier/events/`
|
||||
- `merchant`
|
||||
- `notifier`
|
||||
- `event_key`
|
||||
- `mission_category`
|
||||
- `is_enabled`
|
||||
- `description`
|
||||
|
||||
模板固定目录为:
|
||||
其中:
|
||||
|
||||
`notifier/templates/notifier/events/`
|
||||
- `mission_category = null` 表示该事件的通配路由
|
||||
- `mission_category != null` 表示任务分类专用路由
|
||||
|
||||
当前已提供的模板:
|
||||
### 3.3 约束设计
|
||||
|
||||
- `mission_created.md`
|
||||
- `mission_replied.md`
|
||||
- `mission_completed.md`
|
||||
- `mission_reply_rejected.md`
|
||||
- `mission_reopened.md`
|
||||
- `mission_cancelled.md`
|
||||
当前约束:
|
||||
|
||||
`template_key` 与模板文件名一一对应,例如:
|
||||
- `Notifier` 在同商户下 `name` 唯一
|
||||
- `NotifierRoute` 在同一 `notifier + event_key + mission_category` 下唯一
|
||||
- `NotifierRoute` 额外限制同一 `notifier + event_key` 只能有一条通配路由
|
||||
|
||||
- `template_key="mission_created"`
|
||||
- 模板路径 `notifier/events/mission_created.md`
|
||||
## 4. 路由匹配规则
|
||||
|
||||
## 5. 调用链路
|
||||
当前 `dispatch_notification_event(...)` 的匹配规则为:
|
||||
|
||||
当前通知链路为:
|
||||
1. 先按 `merchant + event_key + route.is_enabled=True + notifier.is_enabled=True` 查路由
|
||||
2. 如果 payload 中带有 `category_id`
|
||||
- 匹配该分类的专用路由
|
||||
- 也允许匹配通配路由
|
||||
3. 如果 payload 中没有 `category_id`
|
||||
- 只匹配通配路由
|
||||
4. 如果同一个 `Notifier` 同时命中专用路由和通配路由
|
||||
- 只保留一条
|
||||
- 优先保留专用路由
|
||||
|
||||
1. `mission.services` 在事务提交后发送业务 signal
|
||||
2. `mission.handlers` 监听 signal
|
||||
3. handler 将业务对象整理为纯字典 payload
|
||||
4. handler 调用 `notifier.services.enqueue_notification_event(...)`
|
||||
5. notifier 通过 Celery task 异步执行投递
|
||||
6. task 内部调用 `dispatch_notification_event(...)`
|
||||
7. 按 `merchant_id + event_key + is_enabled=True` 查询匹配的 `Notifier`
|
||||
8. 逐个渲染模板并调用对应 backend 的 `notify(...)`
|
||||
9. 写详细日志
|
||||
这样可以同时满足:
|
||||
|
||||
这里有两个关键约束:
|
||||
- 分类专用通知
|
||||
- 默认兜底通知
|
||||
- 多群并发通知
|
||||
- 同一通知器不重复发送
|
||||
|
||||
- handler 只做 payload 组装和入队,不做实际发送
|
||||
- task 层才做真正的通知投递
|
||||
## 5. 当前调用链
|
||||
|
||||
这样可以保持业务事务与外部通知解耦。
|
||||
通知链路如下:
|
||||
|
||||
## 6. 渠道抽象
|
||||
1. `mission.services` 在事务提交后发 signal
|
||||
2. `mission.handlers` 构造 payload
|
||||
3. payload 中已包含 `category_id`、`category_name`
|
||||
4. handler 调用 `enqueue_notification_event(...)`
|
||||
5. Celery task 调用 `dispatch_notification_event(...)`
|
||||
6. notifier 根据 route 匹配命中的 `Notifier`
|
||||
7. 渲染模板并调用 backend 发送
|
||||
8. 记录路由日志和发送日志
|
||||
|
||||
当前 backend 接口约定为:
|
||||
## 6. 已接入的事件
|
||||
|
||||
- `BaseNotifierBackend.notify(notifier, content, context) -> dict`
|
||||
|
||||
当前已实现:
|
||||
|
||||
- `WeComWebhookNotifierBackend`
|
||||
|
||||
其复用了现有工具:
|
||||
|
||||
- `api_v1.utils.wecom_webhook.send_wecom_webhook_message`
|
||||
|
||||
这样做的原因:
|
||||
|
||||
- 避免重复实现 webhook 发送逻辑
|
||||
- 保持旧工具可复用
|
||||
- 新模块只负责“编排”和“动态配置”
|
||||
|
||||
## 7. Mission 已接入事件
|
||||
|
||||
当前 `mission` 已接入以下事件:
|
||||
当前 `mission` 已接入:
|
||||
|
||||
- `mission.created`
|
||||
- `mission.replied`
|
||||
@@ -135,95 +122,89 @@
|
||||
- `mission.reopened`
|
||||
- `mission.cancelled`
|
||||
|
||||
对应 handler 在:
|
||||
这些事件全部支持按任务分类路由。
|
||||
|
||||
- `mission/handlers.py`
|
||||
|
||||
当前 handler 不再只是打日志,而是会构造 payload 并投递到 notifier task。
|
||||
|
||||
## 8. Admin 配置方式
|
||||
|
||||
`Notifier` 已接入 Django Admin,可进行:
|
||||
|
||||
- 添加
|
||||
- 编辑
|
||||
- 删除
|
||||
- 启用/停用
|
||||
|
||||
当前推荐的使用方式:
|
||||
|
||||
1. 在 admin 中新建 `Notifier`
|
||||
2. 选择所属商户
|
||||
3. 选择 `event_key`
|
||||
4. 选择 `channel=wecom_webhook`
|
||||
5. 填写 `template_key`
|
||||
6. 在 `config` 中填写 webhook key 等参数
|
||||
7. 启用 `is_enabled`
|
||||
|
||||
当前 `config` 示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"key": "企业微信机器人key",
|
||||
"msgtype": "markdown",
|
||||
"timeout_seconds": 10
|
||||
}
|
||||
```
|
||||
|
||||
## 9. 日志策略
|
||||
|
||||
本阶段没有引入数据库投递明细表,因此发送明细主要依赖日志。
|
||||
## 7. 日志策略
|
||||
|
||||
当前日志覆盖以下节点:
|
||||
|
||||
- 任务入队
|
||||
- 事件入队
|
||||
- 没有命中任何可用路由
|
||||
- 路由命中成功
|
||||
- backend 发送成功
|
||||
- 单个 notifier 发送成功
|
||||
- 单个 notifier 发送失败
|
||||
- 某事件无匹配 notifier
|
||||
- 单个通知发送失败
|
||||
|
||||
这满足当前“先可用、后增强”的目标,也符合“暂不做数据库级审计”的约束。
|
||||
当前已增加 route 维度日志,重点字段包括:
|
||||
|
||||
## 10. 当前风险与注意点
|
||||
- `event_key`
|
||||
- `merchant_id`
|
||||
- `route_id`
|
||||
- `route_mission_category_id`
|
||||
- `notifier_id`
|
||||
|
||||
### 10.1 配置合法性主要依赖管理规范
|
||||
## 8. Admin 现状
|
||||
|
||||
当前 `config` 是自由 JSON,没有做更强的结构化校验。
|
||||
优点是灵活,缺点是后台录入错误会在发送时才暴露。
|
||||
当前后台提供两个对象:
|
||||
|
||||
### 10.2 模板标识依赖文件存在
|
||||
- `Notifier`
|
||||
- `NotifierRoute`
|
||||
|
||||
`template_key` 对应的模板文件如果不存在,会在发送阶段报错并记录日志。
|
||||
这在当前阶段是可接受的,但后续可以考虑在 admin 或 model clean 中增加校验。
|
||||
并且:
|
||||
|
||||
### 10.3 目前仍是“单对象订阅”模型
|
||||
- `Notifier` 页面支持 inline 维护其下路由
|
||||
- `NotifierRoute` 也支持单独管理
|
||||
|
||||
一个 `Notifier` 对应一个 `event_key`。
|
||||
如果后续出现“一个群同时订阅多个事件”的强需求,可以考虑抽象出 Subscription 层。
|
||||
在 `Notifier` inline 场景下,route 的 `merchant` 会自动同步为当前 notifier 的商户,避免管理人员重复录入。
|
||||
|
||||
### 10.4 旧通知逻辑尚未迁移
|
||||
## 9. 迁移策略
|
||||
|
||||
当前仅 `mission` 新通知走 `notifier`。
|
||||
`printing`、`shipment` 等旧逻辑仍保留原来的静态方式,不应在本次改动中混改。
|
||||
本次从旧结构迁到新结构时,做了自动回填:
|
||||
|
||||
## 11. 后续建议
|
||||
- 对每条旧 `Notifier(event_key=...)`
|
||||
- 自动创建一条 `NotifierRoute`
|
||||
- `event_key` 原样继承
|
||||
- `mission_category = null`
|
||||
- `description` 标记为自动迁移生成
|
||||
|
||||
按优先级建议如下:
|
||||
这样旧配置不会因为结构调整而丢失。
|
||||
|
||||
1. 在 admin 使用中观察 `config` 和 `template_key` 是否已足够稳定
|
||||
2. 若 notifier 数量增多,再决定是否拆分“通知端点”与“事件订阅”
|
||||
3. 若需要追踪投递历史,再增加 `NotificationDelivery`
|
||||
4. 当 mission 通知稳定后,再考虑逐步迁移新业务节点到 notifier
|
||||
## 10. 测试覆盖重点
|
||||
|
||||
当前测试已覆盖:
|
||||
|
||||
- 模板渲染
|
||||
- backend 发送
|
||||
- 路由按事件匹配
|
||||
- 分类专用路由优先于通配路由
|
||||
- 无专用路由时回退到通配路由
|
||||
- 任务事件 handler 正常入队
|
||||
|
||||
## 11. 当前风险与注意点
|
||||
|
||||
### 11.1 当前只对 mission 做了分类路由
|
||||
|
||||
当前 `mission_category` 是显式写进 `NotifierRoute` 的业务字段。
|
||||
这适合当前目标,但如果未来要扩展到其它业务模型的复杂路由,可能需要更抽象的路由条件模型。
|
||||
|
||||
### 11.2 config 仍是自由 JSON
|
||||
|
||||
后台录入错误仍可能在发送时才暴露。
|
||||
当前依赖日志排查,后续可增加更强校验。
|
||||
|
||||
### 11.3 模板校验仍在发送期暴露
|
||||
|
||||
`template_key` 如果写错,会在渲染阶段报错并记录日志。
|
||||
后续可在 admin 或 model clean 中增强校验。
|
||||
|
||||
## 12. 当前结论
|
||||
|
||||
当前方案已经满足:
|
||||
当前 `notifier` 已具备:
|
||||
|
||||
- 独立模块
|
||||
- admin 配置
|
||||
- task 化通知
|
||||
- 模板化内容
|
||||
- 动态 signal -> notifier 路由
|
||||
- 后续可扩展到多渠道
|
||||
- 通知器配置
|
||||
- 路由配置
|
||||
- 分类分发
|
||||
- 任务事件按分类路由
|
||||
- 管理后台操作支持
|
||||
- 日志与测试保障
|
||||
|
||||
同时复杂度仍控制在较低水平,适合作为第一阶段正式实现。
|
||||
这已经足以支撑你当前提出的“所有任务事件都支持按任务分类路由”的要求。
|
||||
|
||||
Reference in New Issue
Block a user