forked from erp-dev/erp
156 lines
4.0 KiB
Plaintext
156 lines
4.0 KiB
Plaintext
@startuml
|
||
title Notifier 模块一期类图
|
||
|
||
skinparam shadowing false
|
||
skinparam class {
|
||
BackgroundColor #F8FBFF
|
||
BorderColor #4C6A92
|
||
ArrowColor #4C6A92
|
||
FontName Noto Sans CJK SC
|
||
}
|
||
skinparam note {
|
||
BackgroundColor #FFF7E6
|
||
BorderColor #B7791F
|
||
FontName Noto Sans CJK SC
|
||
}
|
||
skinparam defaultFontName Noto Sans CJK SC
|
||
|
||
class "Notifier\n通知器配置" as Notifier {
|
||
+id: BigAutoField
|
||
+merchant: Merchant
|
||
+name: CharField
|
||
+event_key: CharField
|
||
+channel: CharField
|
||
+template_key: CharField
|
||
+is_enabled: Boolean = true
|
||
+config: JSON
|
||
+description: Text?
|
||
+created_at: DateTime
|
||
+updated_at: DateTime
|
||
}
|
||
|
||
class "Merchant\nbasic_info.Merchant" as Merchant {
|
||
+id: BigAutoField
|
||
+name: CharField
|
||
}
|
||
|
||
class "Mission Signals\n领域信号" as MissionSignals <<service>> {
|
||
+mission_created
|
||
+mission_replied
|
||
+mission_completed
|
||
+mission_reply_rejected
|
||
+mission_reopened
|
||
+mission_cancelled
|
||
}
|
||
|
||
class "MissionHandlers\n信号处理器" as MissionHandlers <<service>> {
|
||
+on_mission_created(...)
|
||
+on_mission_replied(...)
|
||
+on_mission_completed(...)
|
||
+on_mission_reply_rejected(...)
|
||
+on_mission_reopened(...)
|
||
+on_mission_cancelled(...)
|
||
}
|
||
|
||
class "NotifierDispatcher\n通知分发器" as NotifierDispatcher <<service>> {
|
||
+dispatch(event_key, merchant_id, payload)
|
||
}
|
||
|
||
class "TemplateRenderer\n模板渲染器" as TemplateRenderer <<service>> {
|
||
+render(template_key, payload): dict
|
||
}
|
||
|
||
abstract class "BaseNotifier\n渠道后端抽象" as BaseNotifier {
|
||
+channel: str
|
||
+notify(endpoint, event_key, payload, rendered): dict
|
||
}
|
||
|
||
class "WeComWebhookNotifier\n企业微信通知器" as WeComWebhookNotifier {
|
||
+channel = \"wecom_webhook\"
|
||
+notify(endpoint, event_key, payload, rendered): dict
|
||
}
|
||
|
||
class "EmailNotifier\n邮件通知器" as EmailNotifier {
|
||
+channel = \"email\"
|
||
+notify(endpoint, event_key, payload, rendered): dict
|
||
}
|
||
|
||
class "NotifierRegistry\n通知器注册表" as NotifierRegistry <<service>> {
|
||
+get(channel): BaseNotifier
|
||
}
|
||
|
||
class "NotifierTask\n异步任务入口" as NotifierTask <<task>> {
|
||
+dispatch_notification_event(...)
|
||
}
|
||
|
||
MissionSignals ..> MissionHandlers : connect
|
||
MissionHandlers ..> NotifierTask : on_commit + delay
|
||
NotifierTask ..> NotifierDispatcher : dispatch(...)
|
||
NotifierDispatcher --> "0..*" Notifier : query by\nmerchant + event_key + is_enabled
|
||
NotifierDispatcher ..> TemplateRenderer : render(...)
|
||
NotifierDispatcher ..> NotifierRegistry : get(channel)
|
||
NotifierRegistry ..> BaseNotifier
|
||
BaseNotifier <|-- WeComWebhookNotifier
|
||
BaseNotifier <|-- EmailNotifier
|
||
Notifier "0..*" --> "1" Merchant : merchant
|
||
|
||
note right of Notifier
|
||
一期简化设计:
|
||
- 不拆 Endpoint / Subscription
|
||
- 直接把 event_key 绑定在 Notifier 对象上
|
||
- 直接把 template_key 配置在 Notifier 对象上
|
||
|
||
适合通过 Django Admin 做:
|
||
- 添加 / 删除
|
||
- 启用 / 禁用
|
||
- 编辑渠道参数
|
||
end note
|
||
|
||
note bottom of Notifier
|
||
config 为 JSON:
|
||
企业微信示例可包含:
|
||
- webhook_key
|
||
- mentioned_list
|
||
- mentioned_mobile_list
|
||
|
||
同一商户下可配置多个 Notifier,
|
||
同一个 event_key 可命中多个 Notifier。
|
||
end note
|
||
|
||
note right of TemplateRenderer
|
||
模板文件不落数据库。
|
||
Notifier 仅保存 template_key。
|
||
|
||
模板集中存放在固定目录,例如:
|
||
notifier/templates/
|
||
end note
|
||
|
||
note left of MissionHandlers
|
||
handler 不直接拼企业微信内容,
|
||
也不直接读取 settings.py 中的静态 key。
|
||
|
||
handler 只负责把领域事件
|
||
转成 event_key + payload,
|
||
再交给 notifier 模块。
|
||
end note
|
||
|
||
note bottom of NotifierDispatcher
|
||
一期暂不引入 NotificationDelivery 表。
|
||
发送结果通过日志记录即可,
|
||
不做数据库级发送审计。
|
||
|
||
风险:
|
||
- 无法在数据库中重放 / 检索历史发送记录
|
||
- 排查依赖日志系统
|
||
end note
|
||
|
||
note left of Notifier
|
||
设计取舍风险:
|
||
把 template_key 配到 Notifier 对象上,
|
||
会让“同一渠道目标用于多个事件”时产生配置重复。
|
||
|
||
但这能显著降低一期复杂度,
|
||
且更贴合 Admin 直接维护。
|
||
end note
|
||
@enduml
|