新增 000228 迁移:规则表 tb_package_traffic_alert_rule(每套餐商品至多一条,无软删除,package_id 非部分唯一约束)、达量预警快照表 tb_package_traffic_alert(以主套餐使用记录 + 阈值快照为唯一键, 触发时冻结用量、额度、比例、阈值、到期时间、归属与资产快照),并为 tb_package_usage 新增扫描 范围部分索引 idx_package_usage_alert_scope;down 在预警表存在数据时阻断回滚。 新增规则维护接口 GET/POST/PUT /api/admin/package-traffic-alert-rules(仅超级管理员与平台账号): 创建校验套餐存在且真流量额度大于零,阈值为 1%~100% 的两位小数;修改只影响后续扫描,不回填也 不改写既有预警快照;全部写操作记录操作者、前后值与时间。 新增每日 06:00(Asia/Shanghai)扫描任务 package:traffic:alert:scan,与套餐临期扫描共用 data_cleanup 队列:按资产汇总当前有效套餐的真流量,分子取使用记录真已用量、分母取使用记录真总量快照,命中 主套餐规则阈值时在同一事务创建预警与可靠通知事件;重复执行以唯一冲突视为已处理,不重复投递, 不建停机锁、不调用运营商。 新增预警列表、详情与异步导出 GET /api/admin/package-traffic-alerts、GET /api/admin/package-traffic-alerts/:id、 POST /api/admin/package-traffic-alerts/export,列表与详情一律读冻结快照;新增通知类型 package.traffic.alert 与受控目标 package_traffic_alert_detail,目标解析仅对超级管理员与平台账号 返回可跳转,越权与不存在统一按资源不可见处理。 同步 OpenAPI(cmd/gendocs、cmd/api/docs.go、pkg/openapi/handlers.go)、审计动作与资源注册、上下文 健康检查证据;归档变更并同步 package-traffic-alert 主 Spec。
87 lines
3.7 KiB
Go
87 lines
3.7 KiB
Go
package constants
|
||
|
||
// 套餐真流量达量预警的通知投递结果常量。
|
||
//
|
||
// 该结果不落库为独立列,而是由「预警行的可靠通知事件 + tb_outbox_event 状态 + tb_notification 事实」
|
||
// 交叉推导,因此枚举值一旦发布不得调整含义。1~4 表示已写入通知事件后的四种结果,
|
||
// 5 表示触发时店铺没有有效业务员,预警只保存事实不产生通知,也不在未来补发。
|
||
const (
|
||
// PackageTrafficAlertNotifyNotified 表示通知事件已生成站内通知,接收人可读。
|
||
PackageTrafficAlertNotifyNotified = 1
|
||
// PackageTrafficAlertNotifyPending 表示通知事件已写入但尚未完成投递。
|
||
PackageTrafficAlertNotifyPending = 2
|
||
// PackageTrafficAlertNotifyFailed 表示通知事件投递达到最终失败或等待人工重放。
|
||
PackageTrafficAlertNotifyFailed = 3
|
||
// PackageTrafficAlertNotifyRecipientGone 表示事件已投递但接收人已失效,未生成站内通知。
|
||
PackageTrafficAlertNotifyRecipientGone = 4
|
||
// PackageTrafficAlertNotifyNoBusinessOwner 表示触发时店铺无有效业务员,只保存预警。
|
||
PackageTrafficAlertNotifyNoBusinessOwner = 5
|
||
)
|
||
|
||
// GetPackageTrafficAlertNotifyStatusName 返回通知投递结果的中文名称。
|
||
func GetPackageTrafficAlertNotifyStatusName(status int) string {
|
||
switch status {
|
||
case PackageTrafficAlertNotifyNotified:
|
||
return "已通知"
|
||
case PackageTrafficAlertNotifyPending:
|
||
return "待投递"
|
||
case PackageTrafficAlertNotifyFailed:
|
||
return "投递失败"
|
||
case PackageTrafficAlertNotifyRecipientGone:
|
||
return "未通知(接收人已失效)"
|
||
case PackageTrafficAlertNotifyNoBusinessOwner:
|
||
return "未通知(无有效业务员)"
|
||
default:
|
||
return "未知"
|
||
}
|
||
}
|
||
|
||
// IsValidPackageTrafficAlertNotifyStatus 判断通知投递结果枚举是否受支持。
|
||
func IsValidPackageTrafficAlertNotifyStatus(status int) bool {
|
||
switch status {
|
||
case PackageTrafficAlertNotifyNotified,
|
||
PackageTrafficAlertNotifyPending,
|
||
PackageTrafficAlertNotifyFailed,
|
||
PackageTrafficAlertNotifyRecipientGone,
|
||
PackageTrafficAlertNotifyNoBusinessOwner:
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
// ResolvePackageTrafficAlertNotifyStatus 由通知事件、Outbox 状态与站内通知事实推导投递结果。
|
||
// 判断顺序必须与读侧列表、详情与导出保持完全一致,因此该口径只在此处实现一次。
|
||
// - hasEvent=false:触发时无有效业务员,只保存预警;
|
||
// - hasNotification=true:通知已生成,接收人可读;
|
||
// - Outbox 为最终失败/已投递但无通知/其余未终结状态,分别对应失败、接收人已失效与待投递。
|
||
func ResolvePackageTrafficAlertNotifyStatus(hasEvent bool, outboxStatus *int, hasNotification bool) int {
|
||
if !hasEvent {
|
||
return PackageTrafficAlertNotifyNoBusinessOwner
|
||
}
|
||
if hasNotification {
|
||
return PackageTrafficAlertNotifyNotified
|
||
}
|
||
if outboxStatus == nil {
|
||
return PackageTrafficAlertNotifyPending
|
||
}
|
||
switch *outboxStatus {
|
||
case OutboxStatusFailed:
|
||
return PackageTrafficAlertNotifyFailed
|
||
case OutboxStatusDelivered:
|
||
// 事件已投递却没有生成通知:接收人在投递期已失效;本能力不允许改投他人。
|
||
return PackageTrafficAlertNotifyRecipientGone
|
||
default:
|
||
return PackageTrafficAlertNotifyPending
|
||
}
|
||
}
|
||
|
||
// PackageTrafficAlertRuleMaxRemarkLength 是预警规则备注的最大长度。
|
||
const PackageTrafficAlertRuleMaxRemarkLength = 500
|
||
|
||
// PackageTrafficAlertScanAggregateType 与 Outbox 事件的聚合类型,标识事件由达量扫描产生。
|
||
const PackageTrafficAlertScanAggregateType = "package_traffic_alert"
|
||
|
||
// PackageTrafficAlertEventIDPrefix 是可靠通知事件ID前缀:pta:<package_usage_id>:<阈值万分比>。
|
||
const PackageTrafficAlertEventIDPrefix = "pta"
|