Files
junhong_cmp_fiber/internal/domain/packagetrafficalert/threshold.go
邹进 25c081fe60
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Failing after 8h37m36s
fix: 第1批 M2、M3、M16、M23 导入与展示类缺陷
- M2 批量换绑表头改为“平台登录账号”,只认手机号,细分格式、不存在、多匹配、非平台、已禁用失败原因
- M3 后台订单列表与详情返回 C 端在线购买的交易流水号、支付渠道、商户名称,详情新增全部支付单 payments
- M16 预警规则不再返回 real_data_mb,预警列表/详情新增 threshold_mb,导出末列追加“阈值流量(MB)”
- M23 设备导入 IMEI 必填,空 IMEI 行记为失败
- OpenSpec Change fix-august-iteration-follow-up-gaps:13/18,导入任务、导出任务的 Worker 端到端验证与前端/运营通知待部署后完成
2026-10-11 23:49:29 +09:00

58 lines
2.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package packagetrafficalert 提供套餐真流量达量预警的领域判定规则。
//
// 判定口径固定为「真流量」:分子取套餐使用记录的真已用量,分母取套餐使用记录的真总量快照,
// 二者按资产汇总后再与主套餐规则阈值比较;全部使用整数万分比比较,不使用浮点判定,
// 避免边界(例如恰好等于阈值)因二进制浮点误差产生错误结论。
package packagetrafficalert
import "math"
// ratioScale 是万分比刻度:1% = 100,0.01% = 1。
const ratioScale = 10000
// MinThresholdPercent 与 MaxThresholdPercent 是可配置阈值百分比的闭区间端点。
const (
MinThresholdPercent = 1.0
MaxThresholdPercent = 100.0
)
// ThresholdBasisPoints 把百分比阈值换算为整数万分比(0.01% = 1)。
// 数据库以 NUMERIC(5,2) 保存两位小数,读取后先四舍五入到两位再换算,保证 1.25% 恒等于 125。
func ThresholdBasisPoints(percent float64) int64 {
return int64(math.Round(NormalizeThresholdPercent(percent) * 100))
}
// NormalizeThresholdPercent 把百分比四舍五入到两位小数,与 NUMERIC(5,2) 的存储精度一致。
func NormalizeThresholdPercent(percent float64) float64 {
return math.Round(percent*100) / 100
}
// IsValidThresholdPercent 判断百分比是否落在 1%~100% 闭区间内。
func IsValidThresholdPercent(percent float64) bool {
normalized := NormalizeThresholdPercent(percent)
return normalized >= MinThresholdPercent && normalized <= MaxThresholdPercent
}
// Decide 按资产的汇总真流量判定是否达到阈值,并返回向下取整的汇总比例万分比。
//
// usedMB 为该资产全部当前有效套餐的真已用量之和,limitMB 为同集合的真总量快照之和。
// 分母不大于零属于不可判定资产,调用方必须先跳过;此处返回未命中以避免除零。
func Decide(usedMB, limitMB, thresholdBasisPoints int64) (bool, int64) {
if limitMB <= 0 || thresholdBasisPoints <= 0 {
return false, 0
}
ratioBasisPoints := usedMB * ratioScale / limitMB
hit := usedMB*ratioScale >= thresholdBasisPoints*limitMB
return hit, ratioBasisPoints
}
// ThresholdMB 返回阈值对应流量:真流量额度汇总 × 阈值百分比 ÷ 100,保留两位小数,口径与额度一致(含加油包)。
func ThresholdMB(limitMB int64, thresholdPercent float64) float64 {
return math.Round(float64(limitMB)*NormalizeThresholdPercent(thresholdPercent)) / 100
}
// PercentFromBasisPoints 把万分比换算为保留两位小数的百分比展示值。
func PercentFromBasisPoints(basisPoints int64) float64 {
return float64(basisPoints) / 100
}