# Notifier 管理人员配置说明

本文档面向后台管理人员，说明如何在 Django Admin 中配置 `Notifier` 与 `NotifierRoute`，让系统在指定业务事件发生时自动发送通知，并支持按任务分类分发。

## 1. 两层结构

当前通知配置分成两层：

- `Notifier`：通知器本体，负责“发到哪里、用什么模板、走什么渠道”
- `NotifierRoute`：通知路由，负责“什么事件、什么任务分类，应该命中哪个 Notifier”

可以这样理解：

- `Notifier` 是“发信工具”
- `NotifierRoute` 是“分发规则”

## 2. 当前已支持的 mission 事件

目前 `mission` 模块已接入以下事件：

- `mission.created`
- `mission.replied`
- `mission.completed`
- `mission.unreplied`
- `mission.reply_rejected`
- `mission.reopened`
- `mission.cancelled`

所有这些事件都支持通过 `NotifierRoute` 进行分类路由。

## 3. 当前支持的分类路由能力

路由匹配规则如下：

1. 先按 `merchant + event_key + is_enabled=True` 匹配启用中的路由
2. 如果当前任务带有分类：
   - 优先匹配该分类的专用路由
   - 同时允许匹配“任务分类为空”的通配路由
3. 如果同一个 `Notifier` 同时命中了专用路由和通配路由，只发送一次，优先使用专用路由

这意味着你可以实现：

- 某个分类发到专门群
- 未单独配置的分类发到通用群
- 同一事件同时发多个群

## 4. Admin 中的两个入口

进入 Django Admin 后，主要会看到两个对象：

- `通知器`
- `通知路由`

推荐的管理方式：

1. 先创建 `Notifier`
2. 再创建或维护它的 `NotifierRoute`

在 `Notifier` 详情页中，也可以直接通过 inline 管理该通知器下的路由。

## 5. Notifier 字段说明

### 5.1 merchant

所属商户。

通知器只会服务于该商户下的路由和事件。

### 5.2 name

通知器名称，仅用于后台识别和管理。

建议命名方式：

- `任务通知-生产群`
- `任务通知-售后群`
- `任务通知-管理群`

同一商户下名称不能重复。

### 5.3 channel

通知渠道。

当前固定选：

- `wecom_webhook`

### 5.4 template_key

模板标识。

系统会根据这个字段去固定目录查找模板文件。  
当前模板目录：

`notifier/templates/notifier/events/`

例如：

- `template_key = mission_completed`
- 对应模板文件：`notifier/templates/notifier/events/mission_completed.md`

### 5.5 is_enabled

是否启用通知器本体。

- 勾选：该通知器可被路由命中
- 不勾选：即使路由存在，也不会发送

### 5.6 config

渠道配置，JSON 格式。

当前企业微信机器人建议配置：

```json
{
  "key": "你的企业微信机器人key",
  "msgtype": "markdown",
  "timeout_seconds": 10
}
```

### 5.7 description

备注说明，非必填。

## 6. NotifierRoute 字段说明

### 6.1 merchant

所属商户。

必须与关联的 `Notifier` 属于同一商户。

### 6.2 notifier

要使用的通知器。

### 6.3 event_key

要监听的业务事件。

例如：

- `mission.created`
- `mission.completed`
- `mission.unreplied`

### 6.4 mission_category

任务分类路由条件。

- 为空：表示该事件的通配路由，适用于所有未被更具体路由覆盖的任务分类
- 不为空：表示只处理该任务分类下的任务事件

### 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`: `任务完成通知-管理群`
- `channel`: `wecom_webhook`
- `template_key`: `mission_completed`
- `is_enabled`: 勾选

`NotifierRoute`

- `event_key`: `mission.completed`
- `mission_category`: 留空
- `is_enabled`: 勾选

### 8.2 示例二：售后分类任务创建发售后群

`Notifier`

- `name`: `任务创建通知-售后群`
- `channel`: `wecom_webhook`
- `template_key`: `mission_created`
- `is_enabled`: 勾选

`NotifierRoute`

- `event_key`: `mission.created`
- `mission_category`: `售后`
- `is_enabled`: 勾选

### 8.3 示例三：同一个事件同时发多个群

例如 `mission.cancelled` 同时发客服群和管理群：

- 创建两个不同的 `Notifier`
- 分别为它们配置两条 `event_key = mission.cancelled` 的路由
- 两条路由都可以是 `mission_category` 为空的通配路由

系统会分别发送到两个群。

## 9. 模板如何对应

当前系统已内置以下模板：

- `mission_created`
- `mission_replied`
- `mission_completed`
- `mission_unreplied`
- `mission_reply_rejected`
- `mission_reopened`
- `mission_cancelled`

管理人员通常只需要填 `template_key`，不需要改代码。  
如果后续要新增模板内容或调整文案，需要由开发人员修改模板文件。

## 10. 未回复提醒的 admin 配置要点

`mission.unreplied` 和其它事件不同，它不是在某个瞬时动作发生时触发，而是由后台每分钟扫描一次“仍未回复的任务”后触发。

这意味着 admin 需要同时确认两件事：

1. 任务本身开启了未回复提醒
2. 通知系统中存在 `mission.unreplied` 对应的 `NotifierRoute`

如果只配置了路由，但任务没有开启提醒，则不会发送。

如果任务开启了提醒，但没有配置 `mission.unreplied` 路由，也不会发送到任何群。

### 10.1 推荐配置方式

1. 创建一个 `Notifier`
   - `name = 任务未回复提醒-管理群`
   - `channel = wecom_webhook`
   - `template_key = mission_unreplied`
   - `is_enabled = True`
2. 创建一条 `NotifierRoute`
   - `event_key = mission.unreplied`
   - `mission_category = 留空` 或选择具体任务分类
   - `is_enabled = True`

### 10.2 什么时候会持续提醒

只有满足以下条件才会持续发送 `mission.unreplied`：

1. 任务开启了“未回复提醒”
2. 任务还没完成
3. 任务还没取消
4. 当前没有任何有效回复
5. 没超过任务自身设置的最大提醒次数

### 10.3 为什么任务开启了提醒，但还是没收到群通知

优先检查：

1. 是否已配置 `mission.unreplied` 的路由
2. 该路由是否启用
3. 对应的 `Notifier` 是否启用
4. `template_key` 是否写成 `mission_unreplied`
5. Celery worker / beat 是否都在运行

## 11. 如何停用

### 停用整个通知器

适用于：

- 这个群临时不用
- 机器人 key 暂时不可用
- 该通知器下的所有路由都不想生效

操作方式：

1. 打开 `Notifier`
2. 取消勾选 `is_enabled`
3. 保存

### 停用某一条路由

适用于：

- 只是不想处理某个事件
- 只是不想处理某个任务分类

操作方式：

1. 打开对应 `NotifierRoute`
2. 取消勾选 `is_enabled`
3. 保存

## 12. 常见问题

### 11.1 为什么事件发生了，但没有收到通知

请依次检查：

1. `Notifier` 是否启用
2. `NotifierRoute` 是否启用
3. `event_key` 是否选对
4. `mission_category` 是否与实际任务分类匹配
5. `template_key` 是否对应现有模板
6. `config.key` 是否填写正确
7. Celery worker 是否已启动

### 11.2 为什么某个任务分类没有走专门群

常见原因：

1. 没有为该分类配置专用路由
2. 专用路由被停用
3. 该任务分类本身不是你以为的那个分类

### 11.3 为什么同一个事件发了多次

通常是因为配置了多个不同的 `NotifierRoute`，分别绑定到了不同的 `Notifier`。  
这不一定是错误，也可能是有意发往多个群。

### 11.4 同一个通知器会不会因为“专用路由 + 通配路由”重复发送两次

不会。  
系统会自动去重，并优先使用更具体的分类路由。

## 13. 管理建议

- 先建 `Notifier`，再建 `NotifierRoute`
- 通知器名称中写清楚目标群
- 路由备注中写清楚事件和分类用途
- 先停用再删除
- 先配置一条路由做验证，再批量扩展

## 14. 最简操作结论

如果你只想快速配置一条通知，记住这 6 个关键点就够了：

1. 先创建 `Notifier`
2. 填好 `channel`
3. 填好 `template_key`
4. 在 `config` 中填好企业微信机器人 `key`
5. 再创建 `NotifierRoute`
6. 选对 `event_key` 和 `mission_category`

这样保存后，对应任务事件发生时就会自动按路由发送。
