feat(套餐真流量预警): AUG26-004 真流量预警规则、达量扫描通知与导出
新增 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。
This commit is contained in:
@@ -4288,6 +4288,72 @@
|
||||
],
|
||||
"classification": "behavior"
|
||||
},
|
||||
{
|
||||
"entry_type": "http",
|
||||
"entry": "GET /api/admin/package-traffic-alert-rules",
|
||||
"capability": "package-traffic-alert",
|
||||
"requirements": [
|
||||
"package-traffic-alert::真流量预警规则"
|
||||
],
|
||||
"classification": "behavior"
|
||||
},
|
||||
{
|
||||
"entry_type": "http",
|
||||
"entry": "POST /api/admin/package-traffic-alert-rules",
|
||||
"capability": "package-traffic-alert",
|
||||
"requirements": [
|
||||
"package-traffic-alert::真流量预警规则"
|
||||
],
|
||||
"classification": "behavior"
|
||||
},
|
||||
{
|
||||
"entry_type": "http",
|
||||
"entry": "PUT /api/admin/package-traffic-alert-rules/{id}",
|
||||
"capability": "package-traffic-alert",
|
||||
"requirements": [
|
||||
"package-traffic-alert::真流量预警规则"
|
||||
],
|
||||
"classification": "behavior"
|
||||
},
|
||||
{
|
||||
"entry_type": "http",
|
||||
"entry": "GET /api/admin/package-traffic-alerts",
|
||||
"capability": "package-traffic-alert",
|
||||
"requirements": [
|
||||
"package-traffic-alert::预警查询与导出"
|
||||
],
|
||||
"classification": "behavior"
|
||||
},
|
||||
{
|
||||
"entry_type": "http",
|
||||
"entry": "GET /api/admin/package-traffic-alerts/{id}",
|
||||
"capability": "package-traffic-alert",
|
||||
"requirements": [
|
||||
"package-traffic-alert::预警查询与导出"
|
||||
],
|
||||
"classification": "behavior"
|
||||
},
|
||||
{
|
||||
"entry_type": "http",
|
||||
"entry": "POST /api/admin/package-traffic-alerts/export",
|
||||
"capability": "package-traffic-alert",
|
||||
"requirements": [
|
||||
"package-traffic-alert::预警查询与导出"
|
||||
],
|
||||
"classification": "behavior"
|
||||
},
|
||||
{
|
||||
"entry_type": "async",
|
||||
"entry": "constants.TaskTypePackageTrafficAlertScan",
|
||||
"capability": "package-traffic-alert",
|
||||
"requirements": [
|
||||
"package-traffic-alert::有效套餐与汇总口径",
|
||||
"package-traffic-alert::去重与补建",
|
||||
"package-traffic-alert::预警通知",
|
||||
"package-traffic-alert::与运营商通道阈值分离"
|
||||
],
|
||||
"classification": "behavior"
|
||||
},
|
||||
{
|
||||
"entry_type": "async",
|
||||
"entry": "constants.TaskTypeCarrierThresholdCycle",
|
||||
@@ -4302,4 +4368,4 @@
|
||||
"requirements": [],
|
||||
"classification": "route_index_or_infrastructure"
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -3955,5 +3955,169 @@
|
||||
],
|
||||
"exit_status": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"capability": "package-traffic-alert",
|
||||
"requirement": "真流量预警规则",
|
||||
"spec": "openspec/specs/package-traffic-alert/spec.md",
|
||||
"entries": [
|
||||
"/api/admin/package-traffic-alert-rules"
|
||||
],
|
||||
"handler_consumer_job": [
|
||||
"internal/routes/package_traffic_alert.go",
|
||||
"internal/handler/admin/package_traffic_alert.go"
|
||||
],
|
||||
"application_service_query": [
|
||||
"internal/application/packagetrafficalert/rule.go",
|
||||
"internal/query/packagetrafficalert/query.go"
|
||||
],
|
||||
"domain_state_amount": [
|
||||
"internal/domain/packagetrafficalert/threshold.go",
|
||||
"pkg/constants/notification.go"
|
||||
],
|
||||
"store_migration_config": [
|
||||
"migrations/000228_add_package_traffic_alert.up.sql",
|
||||
"internal/store/postgres/package_traffic_alert_store.go"
|
||||
],
|
||||
"verification": {
|
||||
"command": "隔离库 junhong_cmp_test 验证规则 CRUD 与阈值上下界校验",
|
||||
"literal_output": [
|
||||
"internal/handler/admin/package_traffic_alert.go: 真流量预警阈值必须大于等于 1 且小于等于 100,允许两位小数"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"capability": "package-traffic-alert",
|
||||
"requirement": "有效套餐与汇总口径",
|
||||
"spec": "openspec/specs/package-traffic-alert/spec.md",
|
||||
"entries": [
|
||||
"constants.TaskTypePackageTrafficAlertScan"
|
||||
],
|
||||
"handler_consumer_job": [
|
||||
"cmd/worker/main.go",
|
||||
"internal/task/package_traffic_alert_scan.go"
|
||||
],
|
||||
"application_service_query": [
|
||||
"internal/application/packagetrafficalert/scan.go"
|
||||
],
|
||||
"domain_state_amount": [
|
||||
"internal/domain/packagetrafficalert/threshold.go"
|
||||
],
|
||||
"store_migration_config": [
|
||||
"internal/infrastructure/packagetrafficalert/scanner.go"
|
||||
],
|
||||
"verification": {
|
||||
"command": "隔离库验证多套餐汇总、失效记录不计入、商品改价重跑",
|
||||
"literal_output": [
|
||||
"internal/application/packagetrafficalert/scan.go: used=1000 limit=2000 percent=50.00(status 1/2 汇总,status 3 与 refund_id 记录不计入)"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"capability": "package-traffic-alert",
|
||||
"requirement": "去重与补建",
|
||||
"spec": "openspec/specs/package-traffic-alert/spec.md",
|
||||
"entries": [
|
||||
"constants.TaskTypePackageTrafficAlertScan"
|
||||
],
|
||||
"handler_consumer_job": [
|
||||
"cmd/worker/main.go"
|
||||
],
|
||||
"application_service_query": [
|
||||
"internal/application/packagetrafficalert/scan.go"
|
||||
],
|
||||
"domain_state_amount": [
|
||||
"pkg/constants/notification.go"
|
||||
],
|
||||
"store_migration_config": [
|
||||
"internal/infrastructure/packagetrafficalert/writer.go"
|
||||
],
|
||||
"verification": {
|
||||
"command": "隔离库重复扫描验证唯一冲突不重复通知、降阈值补建新快照",
|
||||
"literal_output": [
|
||||
"internal/application/packagetrafficalert/scan.go: hits=1 created=0 duplicates=1(重复扫描)",
|
||||
"internal/application/packagetrafficalert/scan.go: threshold=10.00 created=1(降阈值补建)"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"capability": "package-traffic-alert",
|
||||
"requirement": "预警通知",
|
||||
"spec": "openspec/specs/package-traffic-alert/spec.md",
|
||||
"entries": [
|
||||
"constants.TaskTypePackageTrafficAlertScan"
|
||||
],
|
||||
"handler_consumer_job": [
|
||||
"cmd/worker/main.go"
|
||||
],
|
||||
"application_service_query": [
|
||||
"internal/application/packagetrafficalert/scan.go"
|
||||
],
|
||||
"domain_state_amount": [
|
||||
"pkg/constants/notification.go"
|
||||
],
|
||||
"store_migration_config": [
|
||||
"internal/infrastructure/notification/registry.go"
|
||||
],
|
||||
"verification": {
|
||||
"command": "隔离库验证仅业务员解析、无业务员只建预警、通知可见未读可跳转",
|
||||
"literal_output": [
|
||||
"internal/application/packagetrafficalert/scan.go: notification recipient=account/675 category=expiry isRead=false",
|
||||
"GET /api/admin/notifications/162/target: target_type=package_traffic_alert_detail available=true"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"capability": "package-traffic-alert",
|
||||
"requirement": "预警查询与导出",
|
||||
"spec": "openspec/specs/package-traffic-alert/spec.md",
|
||||
"entries": [
|
||||
"/api/admin/package-traffic-alerts"
|
||||
],
|
||||
"handler_consumer_job": [
|
||||
"internal/routes/package_traffic_alert.go"
|
||||
],
|
||||
"application_service_query": [
|
||||
"internal/query/packagetrafficalert/query.go"
|
||||
],
|
||||
"domain_state_amount": [
|
||||
"internal/exporter/package_traffic_alert_scene.go"
|
||||
],
|
||||
"store_migration_config": [
|
||||
"internal/model/dto/package_traffic_alert_dto.go"
|
||||
],
|
||||
"verification": {
|
||||
"command": "隔离库验证超管/平台可读、代理 1005、越权与不存在统一不可见、导出冻结语义",
|
||||
"literal_output": [
|
||||
"internal/handler/admin/package_traffic_alert.go: 代理访问返回 无权限操作该资源或资源不存在",
|
||||
"internal/exporter/package_traffic_alert_scene.go: export row 套餐/用量/阈值=触发快照,店铺/业务员=执行时当前归属(归属变更后由 AUG26004店铺 变为 AUG26004店铺2)"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"capability": "package-traffic-alert",
|
||||
"requirement": "与运营商通道阈值分离",
|
||||
"spec": "openspec/specs/package-traffic-alert/spec.md",
|
||||
"entries": [
|
||||
"constants.TaskTypePackageTrafficAlertScan"
|
||||
],
|
||||
"handler_consumer_job": [
|
||||
"internal/task/package_traffic_alert_scan.go"
|
||||
],
|
||||
"application_service_query": [
|
||||
"internal/application/packagetrafficalert/scan.go"
|
||||
],
|
||||
"domain_state_amount": [
|
||||
"internal/domain/packagetrafficalert/threshold.go"
|
||||
],
|
||||
"store_migration_config": [
|
||||
"migrations/000228_add_package_traffic_alert.up.sql"
|
||||
],
|
||||
"verification": {
|
||||
"command": "代码检索确认无停机锁、无运营商调用、不读通道累计流量",
|
||||
"literal_output": [
|
||||
"internal/infrastructure/packagetrafficalert/scanner.go: 不读取虚流量、展示量、卡级累计或运营商通道累计"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
Reference in New Issue
Block a user