mirror of
https://github.com/TeaOSLab/EdgeAPI.git
synced 2025-12-25 06:26:35 +08:00
优化代码/删除不需要的代码
This commit is contained in:
@@ -1,134 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
)
|
||||
|
||||
const (
|
||||
NodePriceItemStateEnabled = 1 // 已启用
|
||||
NodePriceItemStateDisabled = 0 // 已禁用
|
||||
|
||||
NodePriceTypeTraffic = "traffic" // 价格类型之流量
|
||||
)
|
||||
|
||||
type NodePriceItemDAO dbs.DAO
|
||||
|
||||
func NewNodePriceItemDAO() *NodePriceItemDAO {
|
||||
return dbs.NewDAO(&NodePriceItemDAO{
|
||||
DAOObject: dbs.DAOObject{
|
||||
DB: Tea.Env,
|
||||
Table: "edgeNodePriceItems",
|
||||
Model: new(NodePriceItem),
|
||||
PkName: "id",
|
||||
},
|
||||
}).(*NodePriceItemDAO)
|
||||
}
|
||||
|
||||
var SharedNodePriceItemDAO *NodePriceItemDAO
|
||||
|
||||
func init() {
|
||||
dbs.OnReady(func() {
|
||||
SharedNodePriceItemDAO = NewNodePriceItemDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// EnableNodePriceItem 启用条目
|
||||
func (this *NodePriceItemDAO) EnableNodePriceItem(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NodePriceItemStateEnabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// DisableNodePriceItem 禁用条目
|
||||
func (this *NodePriceItemDAO) DisableNodePriceItem(tx *dbs.Tx, id int64) error {
|
||||
_, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Set("state", NodePriceItemStateDisabled).
|
||||
Update()
|
||||
return err
|
||||
}
|
||||
|
||||
// FindEnabledNodePriceItem 查找启用中的条目
|
||||
func (this *NodePriceItemDAO) FindEnabledNodePriceItem(tx *dbs.Tx, id int64) (*NodePriceItem, error) {
|
||||
result, err := this.Query(tx).
|
||||
Pk(id).
|
||||
Attr("state", NodePriceItemStateEnabled).
|
||||
Find()
|
||||
if result == nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.(*NodePriceItem), err
|
||||
}
|
||||
|
||||
// FindNodePriceItemName 根据主键查找名称
|
||||
func (this *NodePriceItemDAO) FindNodePriceItemName(tx *dbs.Tx, id int64) (string, error) {
|
||||
return this.Query(tx).
|
||||
Pk(id).
|
||||
Result("name").
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreateItem 创建价格
|
||||
func (this *NodePriceItemDAO) CreateItem(tx *dbs.Tx, name string, itemType string, bitsFrom, bitsTo int64) (int64, error) {
|
||||
var op = NewNodePriceItemOperator()
|
||||
op.Name = name
|
||||
op.Type = itemType
|
||||
op.BitsFrom = bitsFrom
|
||||
op.BitsTo = bitsTo
|
||||
op.IsOn = true
|
||||
op.State = NodePriceItemStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdateItem 修改价格
|
||||
func (this *NodePriceItemDAO) UpdateItem(tx *dbs.Tx, itemId int64, name string, bitsFrom, bitsTo int64) error {
|
||||
if itemId <= 0 {
|
||||
return errors.New("invalid itemId")
|
||||
}
|
||||
var op = NewNodePriceItemOperator()
|
||||
op.Id = itemId
|
||||
op.Name = name
|
||||
op.BitsFrom = bitsFrom
|
||||
op.BitsTo = bitsTo
|
||||
return this.Save(tx, op)
|
||||
}
|
||||
|
||||
// FindAllEnabledRegionPrices 列出某个区域的所有价格
|
||||
func (this *NodePriceItemDAO) FindAllEnabledRegionPrices(tx *dbs.Tx, priceType string) (result []*NodePriceItem, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("type", priceType).
|
||||
State(NodePriceItemStateEnabled).
|
||||
Asc("bitsFrom").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindAllEnabledAndOnRegionPrices 列出某个区域的所有启用的价格
|
||||
func (this *NodePriceItemDAO) FindAllEnabledAndOnRegionPrices(tx *dbs.Tx, priceType string) (result []*NodePriceItem, err error) {
|
||||
_, err = this.Query(tx).
|
||||
Attr("type", priceType).
|
||||
State(NodePriceItemStateEnabled).
|
||||
Attr("isOn", true).
|
||||
Asc("bitsFrom").
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// SearchItemsWithBytes 根据字节查找付费项目
|
||||
func (this *NodePriceItemDAO) SearchItemsWithBytes(items []*NodePriceItem, bytes int64) int64 {
|
||||
bytes *= 8
|
||||
|
||||
for _, item := range items {
|
||||
if bytes >= int64(item.BitsFrom) && (bytes < int64(item.BitsTo) || item.BitsTo == 0) {
|
||||
return int64(item.Id)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
@@ -11,20 +11,20 @@ type NodeRegion struct {
|
||||
Description string `field:"description"` // 描述
|
||||
Order uint32 `field:"order"` // 排序
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
Prices dbs.JSON `field:"prices"` // 价格
|
||||
Prices dbs.JSON `field:"prices"` // 流量价格
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type NodeRegionOperator struct {
|
||||
Id interface{} // ID
|
||||
AdminId interface{} // 管理员ID
|
||||
IsOn interface{} // 是否启用
|
||||
Name interface{} // 名称
|
||||
Description interface{} // 描述
|
||||
Order interface{} // 排序
|
||||
CreatedAt interface{} // 创建时间
|
||||
Prices interface{} // 价格
|
||||
State interface{} // 状态
|
||||
Id any // ID
|
||||
AdminId any // 管理员ID
|
||||
IsOn any // 是否启用
|
||||
Name any // 名称
|
||||
Description any // 描述
|
||||
Order any // 排序
|
||||
CreatedAt any // 创建时间
|
||||
Prices any // 流量价格
|
||||
State any // 状态
|
||||
}
|
||||
|
||||
func NewNodeRegionOperator() *NodeRegionOperator {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
//go:build !plus
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@@ -79,129 +80,6 @@ func (this *PlanDAO) FindPlanName(tx *dbs.Tx, id int64) (string, error) {
|
||||
FindStringCol("")
|
||||
}
|
||||
|
||||
// CreatePlan 创建套餐
|
||||
func (this *PlanDAO) CreatePlan(tx *dbs.Tx,
|
||||
name string,
|
||||
clusterId int64,
|
||||
trafficLimitJSON []byte,
|
||||
featuresJSON []byte,
|
||||
priceType serverconfigs.PlanPriceType,
|
||||
trafficPriceJSON []byte,
|
||||
bandwidthPriceJSON []byte,
|
||||
monthlyPrice float32,
|
||||
seasonallyPrice float32,
|
||||
yearlyPrice float32) (int64, error) {
|
||||
var op = NewPlanOperator()
|
||||
op.Name = name
|
||||
op.ClusterId = clusterId
|
||||
if len(trafficLimitJSON) > 0 {
|
||||
op.TrafficLimit = trafficLimitJSON
|
||||
}
|
||||
if len(featuresJSON) > 0 {
|
||||
op.Features = featuresJSON
|
||||
}
|
||||
op.PriceType = priceType
|
||||
if len(trafficPriceJSON) > 0 {
|
||||
op.TrafficPrice = trafficPriceJSON
|
||||
}
|
||||
if len(bandwidthPriceJSON) > 0 {
|
||||
op.BandwidthPrice = bandwidthPriceJSON
|
||||
}
|
||||
if monthlyPrice >= 0 {
|
||||
op.MonthlyPrice = monthlyPrice
|
||||
}
|
||||
if seasonallyPrice >= 0 {
|
||||
op.SeasonallyPrice = seasonallyPrice
|
||||
}
|
||||
if yearlyPrice >= 0 {
|
||||
op.YearlyPrice = yearlyPrice
|
||||
}
|
||||
op.IsOn = true
|
||||
op.State = PlanStateEnabled
|
||||
return this.SaveInt64(tx, op)
|
||||
}
|
||||
|
||||
// UpdatePlan 修改套餐
|
||||
func (this *PlanDAO) UpdatePlan(tx *dbs.Tx,
|
||||
planId int64,
|
||||
name string,
|
||||
isOn bool,
|
||||
clusterId int64,
|
||||
trafficLimitJSON []byte,
|
||||
featuresJSON []byte,
|
||||
priceType serverconfigs.PlanPriceType,
|
||||
trafficPriceJSON []byte,
|
||||
bandwidthPriceJSON []byte,
|
||||
monthlyPrice float32,
|
||||
seasonallyPrice float32,
|
||||
yearlyPrice float32) error {
|
||||
if planId <= 0 {
|
||||
return errors.New("invalid planId")
|
||||
}
|
||||
|
||||
// 检查集群有无变化
|
||||
oldClusterId, err := this.Query(tx).
|
||||
Pk(planId).
|
||||
Result("clusterId").
|
||||
FindInt64Col(0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var op = NewPlanOperator()
|
||||
op.Id = planId
|
||||
op.Name = name
|
||||
op.IsOn = isOn
|
||||
op.ClusterId = clusterId
|
||||
if len(trafficLimitJSON) > 0 {
|
||||
op.TrafficLimit = trafficLimitJSON
|
||||
}
|
||||
if len(featuresJSON) > 0 {
|
||||
op.Features = featuresJSON
|
||||
}
|
||||
op.PriceType = priceType
|
||||
if len(trafficPriceJSON) > 0 {
|
||||
op.TrafficPrice = trafficPriceJSON
|
||||
}
|
||||
if len(bandwidthPriceJSON) > 0 {
|
||||
op.BandwidthPrice = bandwidthPriceJSON
|
||||
}
|
||||
if monthlyPrice >= 0 {
|
||||
op.MonthlyPrice = monthlyPrice
|
||||
} else {
|
||||
op.MonthlyPrice = 0
|
||||
}
|
||||
if seasonallyPrice >= 0 {
|
||||
op.SeasonallyPrice = seasonallyPrice
|
||||
} else {
|
||||
op.SeasonallyPrice = 0
|
||||
}
|
||||
if yearlyPrice >= 0 {
|
||||
op.YearlyPrice = yearlyPrice
|
||||
} else {
|
||||
op.YearlyPrice = 0
|
||||
}
|
||||
err = this.Save(tx, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if oldClusterId != clusterId {
|
||||
// 修改服务所属集群
|
||||
err = SharedServerDAO.UpdateServersClusterIdWithPlanId(tx, planId, clusterId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedNodeClusterDAO.NotifyUpdate(tx, oldClusterId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return this.NotifyUpdate(tx, planId)
|
||||
}
|
||||
|
||||
// CountAllEnabledPlans 计算套餐的数量
|
||||
func (this *PlanDAO) CountAllEnabledPlans(tx *dbs.Tx) (int64, error) {
|
||||
return this.Query(tx).
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
@@ -1,38 +1 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
)
|
||||
|
||||
// DecodeTrafficPrice 流量价格配置
|
||||
func (this *Plan) DecodeTrafficPrice() *serverconfigs.PlanTrafficPriceConfig {
|
||||
var config = &serverconfigs.PlanTrafficPriceConfig{}
|
||||
|
||||
if len(this.TrafficPrice) == 0 {
|
||||
return config
|
||||
}
|
||||
|
||||
err := json.Unmarshal(this.TrafficPrice, config)
|
||||
if err != nil {
|
||||
// 忽略错误
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
// DecodeBandwidthPrice 带宽价格配置
|
||||
func (this *Plan) DecodeBandwidthPrice() *serverconfigs.PlanBandwidthPriceConfig {
|
||||
var config = &serverconfigs.PlanBandwidthPriceConfig{}
|
||||
|
||||
if len(this.BandwidthPrice) == 0 {
|
||||
return config
|
||||
}
|
||||
|
||||
err := json.Unmarshal(this.BandwidthPrice, config)
|
||||
if err != nil {
|
||||
// 忽略错误
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
@@ -14,7 +15,6 @@ import (
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"math"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -218,11 +218,10 @@ func (this *ServerBandwidthStatDAO) FindBandwidthStatsBetweenDays(tx *dbs.Tx, se
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var dayReg = regexp.MustCompile(`^\d{8}$`)
|
||||
if !dayReg.MatchString(dayFrom) {
|
||||
if !regexputils.YYYYMMDD.MatchString(dayFrom) {
|
||||
return nil, errors.New("invalid dayFrom '" + dayFrom + "'")
|
||||
}
|
||||
if !dayReg.MatchString(dayTo) {
|
||||
if !regexputils.YYYYMMDD.MatchString(dayTo) {
|
||||
return nil, errors.New("invalid dayTo '" + dayTo + "'")
|
||||
}
|
||||
|
||||
|
||||
@@ -5,18 +5,20 @@ type ServerBandwidthStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
ServerId uint64 `field:"serverId"` // 服务ID
|
||||
RegionId uint32 `field:"regionId"` // 区域ID
|
||||
Day string `field:"day"` // 日期YYYYMMDD
|
||||
TimeAt string `field:"timeAt"` // 时间点HHMM
|
||||
Bytes uint64 `field:"bytes"` // 带宽字节
|
||||
}
|
||||
|
||||
type ServerBandwidthStatOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
ServerId interface{} // 服务ID
|
||||
Day interface{} // 日期YYYYMMDD
|
||||
TimeAt interface{} // 时间点HHMM
|
||||
Bytes interface{} // 带宽字节
|
||||
Id any // ID
|
||||
UserId any // 用户ID
|
||||
ServerId any // 服务ID
|
||||
RegionId any // 区域ID
|
||||
Day any // 日期YYYYMMDD
|
||||
TimeAt any // 时间点HHMM
|
||||
Bytes any // 带宽字节
|
||||
}
|
||||
|
||||
func NewServerBandwidthStatOperator() *ServerBandwidthStatOperator {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
@@ -195,7 +196,7 @@ func (this *ServerDailyStatDAO) SumUserMonthlyPeek(tx *dbs.Tx, userId int64, reg
|
||||
// SumUserDaily 获取某天流量总和
|
||||
// day 格式为YYYYMMDD
|
||||
func (this *ServerDailyStatDAO) SumUserDaily(tx *dbs.Tx, userId int64, regionId int64, day string) (int64, error) {
|
||||
query := this.Query(tx)
|
||||
var query = this.Query(tx)
|
||||
if regionId > 0 {
|
||||
query.Attr("regionId", regionId)
|
||||
}
|
||||
@@ -205,6 +206,27 @@ func (this *ServerDailyStatDAO) SumUserDaily(tx *dbs.Tx, userId int64, regionId
|
||||
SumInt64("bytes", 0)
|
||||
}
|
||||
|
||||
// SumUserTrafficBytesBetweenDays 获取用户某个日期段内的流量总和
|
||||
func (this *ServerDailyStatDAO) SumUserTrafficBytesBetweenDays(tx *dbs.Tx, userId int64, regionId int64, dayFrom string, dayTo string) (int64, error) {
|
||||
if !regexputils.YYYYMMDD.MatchString(dayFrom) {
|
||||
return 0, errors.New("invalid 'dayFrom':" + dayFrom)
|
||||
}
|
||||
if !regexputils.YYYYMMDD.MatchString(dayTo) {
|
||||
return 0, errors.New("invalid 'dayTo':" + dayTo)
|
||||
}
|
||||
|
||||
var query = this.Query(tx)
|
||||
if regionId > 0 {
|
||||
query.Attr("regionId", regionId)
|
||||
} else if regionId < 0 { // 表示没有分配区域的流量
|
||||
query.Attr("regionId", 0)
|
||||
}
|
||||
return query.
|
||||
Attr("userId", userId).
|
||||
Between("day", dayFrom, dayTo).
|
||||
SumInt64("bytes", 0)
|
||||
}
|
||||
|
||||
// SumUserMonthly 获取某月流量总和
|
||||
// month 格式为YYYYMM
|
||||
func (this *ServerDailyStatDAO) SumUserMonthly(tx *dbs.Tx, userId int64, month string) (int64, error) {
|
||||
@@ -299,18 +321,17 @@ func (this *ServerDailyStatDAO) SumHourlyStat(tx *dbs.Tx, serverId int64, hour s
|
||||
// SumDailyStat 获取某天内的流量
|
||||
// dayFrom 格式为YYYYMMDD
|
||||
// dayTo 格式为YYYYMMDD
|
||||
func (this *ServerDailyStatDAO) SumDailyStat(tx *dbs.Tx, userId int64, serverId int64, dayFrom string, dayTo string) (stat *pb.ServerDailyStat, err error) {
|
||||
func (this *ServerDailyStatDAO) SumDailyStat(tx *dbs.Tx, userId int64, serverId int64, regionId int64, dayFrom string, dayTo string) (stat *pb.ServerDailyStat, err error) {
|
||||
stat = &pb.ServerDailyStat{}
|
||||
|
||||
if userId <= 0 && serverId <= 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var reg = regexp.MustCompile(`^\d{8}$`)
|
||||
if !reg.MatchString(dayFrom) {
|
||||
if !regexputils.YYYYMMDD.MatchString(dayFrom) {
|
||||
return nil, errors.New("invalid dayFrom '" + dayFrom + "'")
|
||||
}
|
||||
if !reg.MatchString(dayTo) {
|
||||
if !regexputils.YYYYMMDD.MatchString(dayTo) {
|
||||
return nil, errors.New("invalid dayTo '" + dayTo + "'")
|
||||
}
|
||||
|
||||
@@ -329,6 +350,10 @@ func (this *ServerDailyStatDAO) SumDailyStat(tx *dbs.Tx, userId int64, serverId
|
||||
query.Attr("serverId", serverId)
|
||||
}
|
||||
|
||||
if regionId > 0 {
|
||||
query.Attr("regionId", regionId)
|
||||
}
|
||||
|
||||
if dayFrom == dayTo {
|
||||
query.Attr("day", dayFrom)
|
||||
} else {
|
||||
@@ -360,7 +385,7 @@ func (this *ServerDailyStatDAO) SumDailyStat(tx *dbs.Tx, userId int64, serverId
|
||||
func (this *ServerDailyStatDAO) SumDailyStatBeforeMinute(tx *dbs.Tx, serverId int64, day string, minute string) (stat *pb.ServerDailyStat, err error) {
|
||||
stat = &pb.ServerDailyStat{}
|
||||
|
||||
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
|
||||
if !regexputils.YYYYMMDD.MatchString(day) {
|
||||
return nil, errors.New("invalid day '" + day + "'")
|
||||
}
|
||||
|
||||
@@ -392,7 +417,7 @@ func (this *ServerDailyStatDAO) SumDailyStatBeforeMinute(tx *dbs.Tx, serverId in
|
||||
func (this *ServerDailyStatDAO) SumMonthlyStat(tx *dbs.Tx, serverId int64, month string) (stat *pb.ServerDailyStat, err error) {
|
||||
stat = &pb.ServerDailyStat{}
|
||||
|
||||
if !regexp.MustCompile(`^\d{6}$`).MatchString(month) {
|
||||
if !regexputils.YYYYMM.MatchString(month) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -421,7 +446,7 @@ func (this *ServerDailyStatDAO) SumMonthlyStat(tx *dbs.Tx, serverId int64, month
|
||||
// SumMonthlyBytes 获取某月内的流量
|
||||
// month 格式为YYYYMM
|
||||
func (this *ServerDailyStatDAO) SumMonthlyBytes(tx *dbs.Tx, serverId int64, month string) (result int64, err error) {
|
||||
if !regexp.MustCompile(`^\d{6}$`).MatchString(month) {
|
||||
if !regexputils.YYYYMM.MatchString(month) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -467,15 +492,18 @@ func (this *ServerDailyStatDAO) FindDailyStats(tx *dbs.Tx, serverId int64, dayFr
|
||||
|
||||
// FindStatsWithDay 按天查找5分钟级统计
|
||||
// day YYYYMMDD
|
||||
// timeFrom HHII00
|
||||
// timeTo HHII59
|
||||
func (this *ServerDailyStatDAO) FindStatsWithDay(tx *dbs.Tx, serverId int64, day string, timeFrom string, timeTo string) (result []*ServerDailyStat, err error) {
|
||||
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
|
||||
if !regexputils.YYYYMMDD.MatchString(day) {
|
||||
return
|
||||
}
|
||||
|
||||
var query = this.Query(tx).
|
||||
Result("SUM(bytes) AS bytes", "SUM(cachedBytes) AS cachedBytes", "SUM(countRequests) AS countRequests", "SUM(countCachedRequests) AS countCachedRequests", "SUM(countAttackRequests) AS countAttackRequests", "SUM(attackBytes) AS attackBytes", "day", "timeFrom", "MIN(timeTo) AS timeTo").
|
||||
Attr("serverId", serverId).
|
||||
Attr("day", day).
|
||||
DescPk()
|
||||
Group("day").Group("timeFrom", dbs.QueryOrderDesc)
|
||||
|
||||
if len(timeFrom) > 0 {
|
||||
query.Gte("timeFrom", timeFrom)
|
||||
@@ -487,13 +515,17 @@ func (this *ServerDailyStatDAO) FindStatsWithDay(tx *dbs.Tx, serverId int64, day
|
||||
_, err = query.
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FindStatsBetweenDays 查找日期段内的5分钟统计
|
||||
func (this *ServerDailyStatDAO) FindStatsBetweenDays(tx *dbs.Tx, userId int64, serverId int64, dayFrom string, dayTo string) (result []*ServerDailyStat, err error) {
|
||||
var dayReg = regexp.MustCompile(`^\d{8}$`)
|
||||
if !dayReg.MatchString(dayFrom) || !dayReg.MatchString(dayTo) {
|
||||
func (this *ServerDailyStatDAO) FindStatsBetweenDays(tx *dbs.Tx, userId int64, serverId int64, regionId int64, dayFrom string, dayTo string) (result []*ServerDailyStat, err error) {
|
||||
if !regexputils.YYYYMMDD.MatchString(dayFrom) || !regexputils.YYYYMMDD.MatchString(dayTo) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -514,7 +546,13 @@ func (this *ServerDailyStatDAO) FindStatsBetweenDays(tx *dbs.Tx, userId int64, s
|
||||
query.Attr("serverId", serverId)
|
||||
} else {
|
||||
query.Result("SUM(bytes) AS bytes", "SUM(cachedBytes) AS cachedBytes", "SUM(countRequests) AS countRequests", "SUM(countCachedRequests) AS countCachedRequests", "SUM(countAttackRequests) AS countAttackRequests", "SUM(attackBytes) AS attackBytes", "MIN(day) AS day", "MIN(timeFrom) AS timeFrom", "MIN(timeTo) AS timeTo")
|
||||
query.Group("CONCAT(day,timeFrom)")
|
||||
query.Group("day").Group("timeFrom")
|
||||
}
|
||||
|
||||
if regionId > 0 {
|
||||
query.Attr("regionId", regionId)
|
||||
} else if regionId < 0 { // 表示未分配区域的流量
|
||||
query.Attr("regionId", 0)
|
||||
}
|
||||
|
||||
// 不需要排序
|
||||
@@ -528,7 +566,18 @@ func (this *ServerDailyStatDAO) FindStatsBetweenDays(tx *dbs.Tx, userId int64, s
|
||||
|
||||
var m = map[string]*ServerDailyStat{} // day @ timeFrom => *ServerDailyStat
|
||||
for _, stat := range result {
|
||||
m[stat.Day+"@"+stat.TimeFrom] = stat
|
||||
var key = stat.Day + "@" + stat.TimeFrom
|
||||
mStat, ok := m[key]
|
||||
if ok {
|
||||
mStat.Bytes += stat.Bytes
|
||||
mStat.CachedBytes += stat.CachedBytes
|
||||
mStat.AttackBytes += stat.AttackBytes
|
||||
mStat.CountRequests += stat.CountRequests
|
||||
mStat.CountAttackRequests += stat.CountAttackRequests
|
||||
mStat.CountCachedRequests += stat.CountCachedRequests
|
||||
} else {
|
||||
m[key] = stat
|
||||
}
|
||||
}
|
||||
|
||||
// 填充空白
|
||||
@@ -649,6 +698,23 @@ func (this *ServerDailyStatDAO) FindDistinctServerIds(tx *dbs.Tx, dayFrom string
|
||||
return serverIds, nil
|
||||
}
|
||||
|
||||
// FindDistinctUserIds 查找所有有流量的用户ID
|
||||
func (this *ServerDailyStatDAO) FindDistinctUserIds(tx *dbs.Tx, dayFrom string, dayTo string) (userIds []int64, err error) {
|
||||
dayFrom = strings.ReplaceAll(dayFrom, "-", "")
|
||||
dayTo = strings.ReplaceAll(dayTo, "-", "")
|
||||
ones, _, err := this.Query(tx).
|
||||
Result("DISTINCT(userId) AS userId").
|
||||
Between("day", dayFrom, dayTo).
|
||||
FindOnes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, one := range ones {
|
||||
userIds = append(userIds, one.GetInt64("userId"))
|
||||
}
|
||||
return userIds, nil
|
||||
}
|
||||
|
||||
// UpdateStatFee 设置费用
|
||||
func (this *ServerDailyStatDAO) UpdateStatFee(tx *dbs.Tx, statId int64, fee float32) error {
|
||||
return this.Query(tx).
|
||||
|
||||
@@ -87,7 +87,7 @@ func TestServerDailyStatDAO_FindDistinctPlanServerIdsBetweenDay(t *testing.T) {
|
||||
|
||||
func TestServerDailyStatDAO_FindStatsBetweenDays(t *testing.T) {
|
||||
var tx *dbs.Tx
|
||||
stats, err := NewServerDailyStatDAO().FindStatsBetweenDays(tx, 1, 0, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)), timeutil.Format("Ymd"))
|
||||
stats, err := NewServerDailyStatDAO().FindStatsBetweenDays(tx, 1, 0, 0, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -1)), timeutil.Format("Ymd"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -95,3 +95,15 @@ func TestServerDailyStatDAO_FindStatsBetweenDays(t *testing.T) {
|
||||
t.Log(stat.Day, stat.TimeFrom, stat.TimeTo, stat.Bytes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerDailyStatDAO_FindStatsWithDay(t *testing.T) {
|
||||
var dao = NewServerDailyStatDAO()
|
||||
var tx *dbs.Tx
|
||||
stats, err := dao.FindStatsWithDay(tx, 23, timeutil.Format("Ymd"), "000000", "235900")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, stat := range stats {
|
||||
t.Log(stat.TimeFrom, stat.TimeTo, stat.Bytes)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2617,11 +2617,29 @@ func (this *ServerDAO) UpdateServerBandwidth(tx *dbs.Tx, serverId int64, fullTim
|
||||
if bandwidthBytes < 0 {
|
||||
bandwidthBytes = 0
|
||||
}
|
||||
return this.Query(tx).
|
||||
|
||||
bandwidthTime, err := this.Query(tx).
|
||||
Pk(serverId).
|
||||
Set("bandwidthTime", fullTime).
|
||||
Set("bandwidthBytes", bandwidthBytes).
|
||||
UpdateQuickly()
|
||||
Result("bandwidthTime").
|
||||
FindStringCol("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if bandwidthTime != fullTime {
|
||||
return this.Query(tx).
|
||||
Pk(serverId).
|
||||
Set("bandwidthTime", fullTime).
|
||||
Set("bandwidthBytes", bandwidthBytes).
|
||||
UpdateQuickly()
|
||||
} else {
|
||||
return this.Query(tx).
|
||||
Pk(serverId).
|
||||
Set("bandwidthTime", fullTime).
|
||||
Set("bandwidthBytes", dbs.SQL("bandwidthBytes+:bytes")).
|
||||
Param("bytes", bandwidthBytes).
|
||||
UpdateQuickly()
|
||||
}
|
||||
}
|
||||
|
||||
// NotifyUpdate 同步服务所在的集群
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -322,6 +323,15 @@ func TestServerDAO_FindBool(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerDAO_UpdateServerBandwidth(t *testing.T) {
|
||||
var dao = models.NewServerDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.UpdateServerBandwidth(tx, 1, timeutil.FormatTime("YmdHi", time.Now().Unix()/300*300), 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkServerDAO_CountAllEnabledServers(b *testing.B) {
|
||||
models.SharedServerDAO = models.NewServerDAO()
|
||||
|
||||
|
||||
@@ -142,42 +142,6 @@ func (this *SysSettingDAO) ReadGlobalConfig(tx *dbs.Tx) (*serverconfigs.GlobalCo
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// ReadUserServerConfig 读取用户服务配置
|
||||
func (this *SysSettingDAO) ReadUserServerConfig(tx *dbs.Tx) (*userconfigs.UserServerConfig, error) {
|
||||
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeUserServerConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(valueJSON) == 0 {
|
||||
return userconfigs.DefaultUserServerConfig(), nil
|
||||
}
|
||||
|
||||
var config = userconfigs.DefaultUserServerConfig()
|
||||
err = json.Unmarshal(valueJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// ReadUserFinanceConfig 读取用户服务配置
|
||||
func (this *SysSettingDAO) ReadUserFinanceConfig(tx *dbs.Tx) (*userconfigs.UserFinanceConfig, error) {
|
||||
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeUserFinanceConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(valueJSON) == 0 {
|
||||
return userconfigs.DefaultUserFinanceConfig(), nil
|
||||
}
|
||||
|
||||
var config = userconfigs.DefaultUserFinanceConfig()
|
||||
err = json.Unmarshal(valueJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// ReadAdminUIConfig 读取管理员界面配置
|
||||
func (this *SysSettingDAO) ReadAdminUIConfig(tx *dbs.Tx, cacheMap *utils.CacheMap) (*systemconfigs.AdminUIConfig, error) {
|
||||
var cacheKey = this.Table + ":ReadAdminUIConfig"
|
||||
@@ -228,3 +192,21 @@ func (this *SysSettingDAO) NotifyUpdate(tx *dbs.Tx, code string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadUserServerConfig 读取用户服务配置
|
||||
func (this *SysSettingDAO) ReadUserServerConfig(tx *dbs.Tx) (*userconfigs.UserServerConfig, error) {
|
||||
valueJSON, err := this.ReadSetting(tx, systemconfigs.SettingCodeUserServerConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(valueJSON) == 0 {
|
||||
return userconfigs.DefaultUserServerConfig(), nil
|
||||
}
|
||||
|
||||
var config = userconfigs.DefaultUserServerConfig()
|
||||
err = json.Unmarshal(valueJSON, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ type SysSetting struct {
|
||||
}
|
||||
|
||||
type SysSettingOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
Code interface{} // 代号
|
||||
Value interface{} // 配置值
|
||||
Id any // ID
|
||||
UserId any // 用户ID
|
||||
Code any // 代号
|
||||
Value any // 配置值
|
||||
}
|
||||
|
||||
func NewSysSettingOperator() *SysSettingOperator {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils/regexputils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
@@ -14,7 +15,7 @@ import (
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"math"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
@@ -60,7 +61,7 @@ func init() {
|
||||
}
|
||||
|
||||
// UpdateUserBandwidth 写入数据
|
||||
func (this *UserBandwidthStatDAO) UpdateUserBandwidth(tx *dbs.Tx, userId int64, day string, timeAt string, bytes int64) error {
|
||||
func (this *UserBandwidthStatDAO) UpdateUserBandwidth(tx *dbs.Tx, userId int64, regionId int64, day string, timeAt string, bytes int64) error {
|
||||
if userId <= 0 {
|
||||
// 如果用户ID不大于0,则说明服务不属于任何用户,此时不需要处理
|
||||
return nil
|
||||
@@ -70,10 +71,11 @@ func (this *UserBandwidthStatDAO) UpdateUserBandwidth(tx *dbs.Tx, userId int64,
|
||||
Table(this.partialTable(userId)).
|
||||
Param("bytes", bytes).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"userId": userId,
|
||||
"day": day,
|
||||
"timeAt": timeAt,
|
||||
"bytes": bytes,
|
||||
"userId": userId,
|
||||
"regionId": regionId,
|
||||
"day": day,
|
||||
"timeAt": timeAt,
|
||||
"bytes": bytes,
|
||||
}, maps.Map{
|
||||
"bytes": dbs.SQL("bytes+:bytes"),
|
||||
})
|
||||
@@ -84,9 +86,12 @@ func (this *UserBandwidthStatDAO) UpdateUserBandwidth(tx *dbs.Tx, userId int64,
|
||||
func (this *UserBandwidthStatDAO) FindUserPeekBandwidthInMonth(tx *dbs.Tx, userId int64, month string) (*UserBandwidthStat, error) {
|
||||
one, err := this.Query(tx).
|
||||
Table(this.partialTable(userId)).
|
||||
Result("MIN(id) AS id", "MIN(userId) AS userId", "day", "timeAt", "SUM(bytes) AS bytes").
|
||||
Attr("userId", userId).
|
||||
Between("day", month+"01", month+"31").
|
||||
Desc("bytes").
|
||||
Group("day").
|
||||
Group("timeAt").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
@@ -95,7 +100,8 @@ func (this *UserBandwidthStatDAO) FindUserPeekBandwidthInMonth(tx *dbs.Tx, userI
|
||||
}
|
||||
|
||||
// FindPercentileBetweenDays 获取日期段内内百分位
|
||||
func (this *UserBandwidthStatDAO) FindPercentileBetweenDays(tx *dbs.Tx, userId int64, dayFrom string, dayTo string, percentile int32) (result *UserBandwidthStat, err error) {
|
||||
// regionId 如果为 -1 表示没有区域的带宽;如果为 0 表示所有区域的带宽
|
||||
func (this *UserBandwidthStatDAO) FindPercentileBetweenDays(tx *dbs.Tx, userId int64, regionId int64, dayFrom string, dayTo string, percentile int32) (result *UserBandwidthStat, err error) {
|
||||
if dayFrom > dayTo {
|
||||
dayFrom, dayTo = dayTo, dayFrom
|
||||
}
|
||||
@@ -106,11 +112,20 @@ func (this *UserBandwidthStatDAO) FindPercentileBetweenDays(tx *dbs.Tx, userId i
|
||||
|
||||
// 如果是100%以上,则快速返回
|
||||
if percentile >= 100 {
|
||||
one, err := this.Query(tx).
|
||||
Table(this.partialTable(userId)).
|
||||
var query = this.Query(tx).
|
||||
Table(this.partialTable(userId))
|
||||
if regionId > 0 {
|
||||
query.Attr("regionId", regionId)
|
||||
} else if regionId < 0 {
|
||||
query.Attr("regionId", 0)
|
||||
}
|
||||
one, err := query.
|
||||
Result("MIN(id) AS id", "MIN(userId) AS userId", "day", "timeAt", "SUM(bytes) AS bytes").
|
||||
Attr("userId", userId).
|
||||
Between("day", dayFrom, dayTo).
|
||||
Desc("bytes").
|
||||
Group("day").
|
||||
Group("timeAt").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
@@ -120,11 +135,17 @@ func (this *UserBandwidthStatDAO) FindPercentileBetweenDays(tx *dbs.Tx, userId i
|
||||
}
|
||||
|
||||
// 总数量
|
||||
total, err := this.Query(tx).
|
||||
Table(this.partialTable(userId)).
|
||||
var totalQuery = this.Query(tx).
|
||||
Table(this.partialTable(userId))
|
||||
if regionId > 0 {
|
||||
totalQuery.Attr("regionId", regionId)
|
||||
} else if regionId < 0 {
|
||||
totalQuery.Attr("regionId", 0)
|
||||
}
|
||||
total, err := totalQuery.
|
||||
Attr("userId", userId).
|
||||
Between("day", dayFrom, dayTo).
|
||||
Count()
|
||||
CountAttr("DISTINCT day, timeAt")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -139,11 +160,20 @@ func (this *UserBandwidthStatDAO) FindPercentileBetweenDays(tx *dbs.Tx, userId i
|
||||
}
|
||||
|
||||
// 查询 nth 位置
|
||||
one, err := this.Query(tx).
|
||||
Table(this.partialTable(userId)).
|
||||
var query = this.Query(tx).
|
||||
Table(this.partialTable(userId))
|
||||
if regionId > 0 {
|
||||
query.Attr("regionId", regionId)
|
||||
} else if regionId < 0 {
|
||||
query.Attr("regionId", 0)
|
||||
}
|
||||
one, err := query.
|
||||
Result("MIN(id) AS id", "MIN(userId) AS userId", "day", "timeAt", "SUM(bytes) AS bytes").
|
||||
Attr("userId", userId).
|
||||
Between("day", dayFrom, dayTo).
|
||||
Desc("bytes").
|
||||
Group("day").
|
||||
Group("timeAt").
|
||||
Offset(offset).
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
@@ -158,9 +188,11 @@ func (this *UserBandwidthStatDAO) FindPercentileBetweenDays(tx *dbs.Tx, userId i
|
||||
func (this *UserBandwidthStatDAO) FindUserPeekBandwidthInDay(tx *dbs.Tx, userId int64, day string) (*UserBandwidthStat, error) {
|
||||
one, err := this.Query(tx).
|
||||
Table(this.partialTable(userId)).
|
||||
Result("MIN(id) AS id", "MIN(userId) AS userId", "MIN(day) AS day", "timeAt", "SUM(bytes) AS bytes").
|
||||
Attr("userId", userId).
|
||||
Attr("day", day).
|
||||
Desc("bytes").
|
||||
Group("timeAt").
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
@@ -171,16 +203,15 @@ func (this *UserBandwidthStatDAO) FindUserPeekBandwidthInDay(tx *dbs.Tx, userId
|
||||
// FindUserBandwidthStatsBetweenDays 查找日期段内的带宽峰值
|
||||
// dayFrom YYYYMMDD
|
||||
// dayTo YYYYMMDD
|
||||
func (this *UserBandwidthStatDAO) FindUserBandwidthStatsBetweenDays(tx *dbs.Tx, userId int64, dayFrom string, dayTo string) (result []*pb.FindDailyServerBandwidthStatsBetweenDaysResponse_Stat, err error) {
|
||||
func (this *UserBandwidthStatDAO) FindUserBandwidthStatsBetweenDays(tx *dbs.Tx, userId int64, regionId int64, dayFrom string, dayTo string) (result []*pb.FindDailyServerBandwidthStatsBetweenDaysResponse_Stat, err error) {
|
||||
if userId <= 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var dayReg = regexp.MustCompile(`^\d{8}$`)
|
||||
if !dayReg.MatchString(dayFrom) {
|
||||
if !regexputils.YYYYMMDD.MatchString(dayFrom) {
|
||||
return nil, errors.New("invalid dayFrom '" + dayFrom + "'")
|
||||
}
|
||||
if !dayReg.MatchString(dayTo) {
|
||||
if !regexputils.YYYYMMDD.MatchString(dayTo) {
|
||||
return nil, errors.New("invalid dayTo '" + dayTo + "'")
|
||||
}
|
||||
|
||||
@@ -188,11 +219,17 @@ func (this *UserBandwidthStatDAO) FindUserBandwidthStatsBetweenDays(tx *dbs.Tx,
|
||||
dayFrom, dayTo = dayTo, dayFrom
|
||||
}
|
||||
|
||||
ones, _, err := this.Query(tx).
|
||||
Table(this.partialTable(userId)).
|
||||
Result("bytes", "day", "timeAt").
|
||||
var query = this.Query(tx).
|
||||
Table(this.partialTable(userId))
|
||||
if regionId > 0 {
|
||||
query.Attr("regionId", regionId)
|
||||
}
|
||||
ones, _, err := query.
|
||||
Result("SUM(bytes) AS bytes", "day", "timeAt").
|
||||
Attr("userId", userId).
|
||||
Between("day", dayFrom, dayTo).
|
||||
Group("day").
|
||||
Group("timeAt").
|
||||
FindOnes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -248,6 +285,33 @@ func (this *UserBandwidthStatDAO) FindUserBandwidthStatsBetweenDays(tx *dbs.Tx,
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// FindDistinctUserIds 获取所有有带宽的用户ID
|
||||
// dayFrom YYYYMMDD
|
||||
// dayTo YYYYMMDD
|
||||
func (this *UserBandwidthStatDAO) FindDistinctUserIds(tx *dbs.Tx, dayFrom string, dayTo string) (userIds []int64, err error) {
|
||||
dayFrom = strings.ReplaceAll(dayFrom, "-", "")
|
||||
dayTo = strings.ReplaceAll(dayTo, "-", "")
|
||||
|
||||
err = this.runBatch(func(table string, locker *sync.Mutex) error {
|
||||
ones, err := this.Query(tx).
|
||||
Table(table).
|
||||
Between("day", dayFrom, dayTo).
|
||||
Result("DISTINCT userId").
|
||||
FindAll()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, one := range ones {
|
||||
locker.Lock()
|
||||
userIds = append(userIds, int64(one.(*UserBandwidthStat).UserId))
|
||||
locker.Unlock()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Clean 清理过期数据
|
||||
func (this *UserBandwidthStatDAO) Clean(tx *dbs.Tx) error {
|
||||
var day = timeutil.Format("Ymd", time.Now().AddDate(0, 0, -100)) // 保留大约3个月的数据
|
||||
|
||||
@@ -5,15 +5,38 @@ import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/logs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestUserBandwidthStatDAO_FindUserPeekBandwidthInMonth(t *testing.T) {
|
||||
var dao = models.NewUserBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
stat, err := dao.FindUserPeekBandwidthInMonth(tx, 1, timeutil.Format("Ym"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
logs.PrintAsJSON(stat, t)
|
||||
}
|
||||
|
||||
func TestUserBandwidthStatDAO_FindUserPeekBandwidthInDay(t *testing.T) {
|
||||
var dao = models.NewUserBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
stat, err := dao.FindUserPeekBandwidthInDay(tx, 1, timeutil.Format("Ymd"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
logs.PrintAsJSON(stat, t)
|
||||
}
|
||||
|
||||
func TestUserBandwidthStatDAO_UpdateServerBandwidth(t *testing.T) {
|
||||
var dao = models.NewUserBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
err := dao.UpdateUserBandwidth(tx, 1, timeutil.Format("Ymd"), timeutil.Format("Hi"), 1024)
|
||||
err := dao.UpdateUserBandwidth(tx, 1, 0, timeutil.Format("Ymd"), timeutil.Format("Hi"), 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -33,7 +56,7 @@ func TestUserBandwidthStatDAO_Clean(t *testing.T) {
|
||||
func TestUserBandwidthStatDAO_FindBandwidthStatsBetweenDays(t *testing.T) {
|
||||
var dao = models.NewUserBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
stats, err := dao.FindUserBandwidthStatsBetweenDays(tx, 1, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -2)), timeutil.Format("Ymd"))
|
||||
stats, err := dao.FindUserBandwidthStatsBetweenDays(tx, 1, 0, timeutil.Format("Ymd", time.Now().AddDate(0, 0, -2)), timeutil.Format("Ymd"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -46,3 +69,13 @@ func TestUserBandwidthStatDAO_FindBandwidthStatsBetweenDays(t *testing.T) {
|
||||
}
|
||||
t.Log("data count:", dataCount)
|
||||
}
|
||||
|
||||
func TestUserBandwidthStatDAO_FindPercentileBetweenDays(t *testing.T) {
|
||||
var dao = models.NewUserBandwidthStatDAO()
|
||||
var tx *dbs.Tx
|
||||
stat, err := dao.FindPercentileBetweenDays(tx, 1, 0, timeutil.Format("Ymd"), timeutil.Format("Ymd"), 95)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
logs.PrintAsJSON(stat, t)
|
||||
}
|
||||
|
||||
@@ -2,19 +2,21 @@ package models
|
||||
|
||||
// UserBandwidthStat 用户月带宽峰值
|
||||
type UserBandwidthStat struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
Day string `field:"day"` // 日期YYYYMMDD
|
||||
TimeAt string `field:"timeAt"` // 时间点HHII
|
||||
Bytes uint64 `field:"bytes"` // 带宽
|
||||
Id uint64 `field:"id"` // ID
|
||||
UserId uint64 `field:"userId"` // 用户ID
|
||||
Day string `field:"day"` // 日期YYYYMMDD
|
||||
TimeAt string `field:"timeAt"` // 时间点HHII
|
||||
Bytes uint64 `field:"bytes"` // 带宽
|
||||
RegionId uint32 `field:"regionId"` // 区域ID
|
||||
}
|
||||
|
||||
type UserBandwidthStatOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
Day interface{} // 日期YYYYMMDD
|
||||
TimeAt interface{} // 时间点HHII
|
||||
Bytes interface{} // 带宽
|
||||
Id any // ID
|
||||
UserId any // 用户ID
|
||||
Day any // 日期YYYYMMDD
|
||||
TimeAt any // 时间点HHII
|
||||
Bytes any // 带宽
|
||||
RegionId any // 区域ID
|
||||
}
|
||||
|
||||
func NewUserBandwidthStatOperator() *UserBandwidthStatOperator {
|
||||
|
||||
@@ -1,50 +1,9 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/lists"
|
||||
"github.com/iwind/TeaGo/maps"
|
||||
"github.com/iwind/TeaGo/rands"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
dbs.OnReadyDone(func() {
|
||||
var generatedMonths = []string{}
|
||||
|
||||
goman.New(func() {
|
||||
// 自动生成账单任务
|
||||
var ticker = time.NewTicker(1 * time.Hour)
|
||||
for range ticker.C {
|
||||
// 是否已经生成了,如果已经生成了就跳过
|
||||
var lastMonth = timeutil.Format("Ym", time.Now().AddDate(0, -1, 0))
|
||||
if lists.ContainsString(generatedMonths, lastMonth) {
|
||||
continue
|
||||
}
|
||||
|
||||
err := SharedUserBillDAO.GenerateBills(nil, lastMonth)
|
||||
if err != nil {
|
||||
remotelogs.Error("UserBillDAO", "generate bills failed: "+err.Error())
|
||||
} else {
|
||||
generatedMonths = append(generatedMonths, lastMonth)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
type BillType = string
|
||||
|
||||
const (
|
||||
BillTypeTraffic BillType = "traffic" // 按流量计费
|
||||
)
|
||||
|
||||
type UserBillDAO dbs.DAO
|
||||
@@ -67,415 +26,3 @@ func init() {
|
||||
SharedUserBillDAO = NewUserBillDAO()
|
||||
})
|
||||
}
|
||||
|
||||
// FindUserBill 查找单个账单
|
||||
func (this *UserBillDAO) FindUserBill(tx *dbs.Tx, billId int64) (*UserBill, error) {
|
||||
one, err := this.Query(tx).
|
||||
Pk(billId).
|
||||
Find()
|
||||
if err != nil || one == nil {
|
||||
return nil, err
|
||||
}
|
||||
return one.(*UserBill), nil
|
||||
}
|
||||
|
||||
// CountAllUserBills 计算账单数量
|
||||
func (this *UserBillDAO) CountAllUserBills(tx *dbs.Tx, isPaid int32, userId int64, month string) (int64, error) {
|
||||
query := this.Query(tx)
|
||||
if isPaid == 0 {
|
||||
query.Attr("isPaid", 0)
|
||||
} else if isPaid > 0 {
|
||||
query.Attr("isPaid", 1)
|
||||
}
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
if len(month) > 0 {
|
||||
query.Attr("month", month)
|
||||
}
|
||||
return query.Count()
|
||||
}
|
||||
|
||||
// ListUserBills 列出单页账单
|
||||
func (this *UserBillDAO) ListUserBills(tx *dbs.Tx, isPaid int32, userId int64, month string, offset, size int64) (result []*UserBill, err error) {
|
||||
query := this.Query(tx)
|
||||
if isPaid == 0 {
|
||||
query.Attr("isPaid", 0)
|
||||
} else if isPaid > 0 {
|
||||
query.Attr("isPaid", 1)
|
||||
}
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
}
|
||||
if len(month) > 0 {
|
||||
query.Attr("month", month)
|
||||
}
|
||||
_, err = query.
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
DescPk().
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// FindUnpaidBills 查找未支付订单
|
||||
func (this *UserBillDAO) FindUnpaidBills(tx *dbs.Tx, size int64) (result []*UserBill, err error) {
|
||||
if size <= 0 {
|
||||
size = 10000
|
||||
}
|
||||
_, err = this.Query(tx).
|
||||
Attr("isPaid", false).
|
||||
Lt("month", timeutil.Format("Ym")). //当月的不能支付,因为当月还没过完
|
||||
Limit(size).
|
||||
DescPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
// CreateBill 创建账单
|
||||
func (this *UserBillDAO) CreateBill(tx *dbs.Tx, userId int64, billType BillType, description string, amount float64, month string, canPay bool) error {
|
||||
code, err := this.GenerateBillCode(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return this.Query(tx).
|
||||
InsertOrUpdateQuickly(maps.Map{
|
||||
"userId": userId,
|
||||
"type": billType,
|
||||
"description": description,
|
||||
"amount": amount,
|
||||
"month": month,
|
||||
"code": code,
|
||||
"isPaid": amount == 0,
|
||||
"canPay": canPay,
|
||||
}, maps.Map{
|
||||
"amount": amount,
|
||||
"canPay": canPay,
|
||||
})
|
||||
}
|
||||
|
||||
// ExistBill 检查是否有当月账单
|
||||
func (this *UserBillDAO) ExistBill(tx *dbs.Tx, userId int64, billType BillType, month string) (bool, error) {
|
||||
return this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
Attr("month", month).
|
||||
Attr("type", billType).
|
||||
Exist()
|
||||
}
|
||||
|
||||
// GenerateBills 生成账单
|
||||
// month 格式YYYYMM
|
||||
func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error {
|
||||
// 区域价格
|
||||
regions, err := SharedNodeRegionDAO.FindAllEnabledRegionPrices(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var priceItems []*NodePriceItem
|
||||
if len(regions) > 0 {
|
||||
priceItems, err = SharedNodePriceItemDAO.FindAllEnabledRegionPrices(tx, NodePriceTypeTraffic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 默认计费方式
|
||||
userFinanceConfig, err := SharedSysSettingDAO.ReadUserFinanceConfig(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 计算服务套餐费用
|
||||
plans, err := SharedPlanDAO.FindAllEnabledPlans(tx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var planMap = map[int64]*Plan{}
|
||||
for _, plan := range plans {
|
||||
planMap[int64(plan.Id)] = plan
|
||||
}
|
||||
|
||||
var dayFrom = month + "01"
|
||||
var dayTo = month + "32"
|
||||
serverIds, err := SharedServerDailyStatDAO.FindDistinctServerIds(tx, dayFrom, dayTo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var cacheMap = utils.NewCacheMap()
|
||||
var userIds = []int64{}
|
||||
for _, serverId := range serverIds {
|
||||
// 套餐类型
|
||||
userPlanId, userId, err := SharedServerDAO.FindServerLastUserPlanIdAndUserId(tx, serverId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if userId == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
userIds = append(userIds, userId)
|
||||
if userPlanId == 0 {
|
||||
// 总流量
|
||||
totalTrafficBytes, err := SharedServerDailyStatDAO.SumMonthlyBytes(tx, serverId, month)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 默认计费方式
|
||||
if userFinanceConfig != nil && userFinanceConfig.IsOn { // 默认计费方式
|
||||
switch userFinanceConfig.PriceType {
|
||||
case serverconfigs.PlanPriceTypeTraffic:
|
||||
var config = userFinanceConfig.TrafficPriceConfig
|
||||
var fee float64 = 0
|
||||
if config != nil && config.Base > 0 {
|
||||
fee = float64(totalTrafficBytes) / 1024 / 1024 / 1024 * float64(config.Base)
|
||||
}
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, userId, serverId, month, userPlanId, 0, totalTrafficBytes, percentileBytes, percentile, userFinanceConfig.PriceType, fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case serverconfigs.PlanPriceTypeBandwidth:
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
var config = userFinanceConfig.BandwidthPriceConfig
|
||||
if config != nil {
|
||||
percentile = config.Percentile
|
||||
if percentile <= 0 {
|
||||
percentile = 95
|
||||
} else if percentile > 100 {
|
||||
percentile = 100
|
||||
}
|
||||
}
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var mb = float32(percentileBytes) / 1024 / 1024
|
||||
var price float32
|
||||
if config != nil {
|
||||
price = config.LookupPrice(mb)
|
||||
}
|
||||
var fee = float64(price)
|
||||
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, userId, serverId, month, userPlanId, 0, totalTrafficBytes, percentileBytes, percentile, userFinanceConfig.PriceType, fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else { // 区域流量计费
|
||||
var fee float64
|
||||
|
||||
for _, region := range regions {
|
||||
var regionId = int64(region.Id)
|
||||
var pricesMap = region.DecodePriceMap()
|
||||
if len(pricesMap) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
trafficBytes, err := SharedServerDailyStatDAO.SumServerMonthlyWithRegion(tx, serverId, regionId, month)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if trafficBytes == 0 {
|
||||
continue
|
||||
}
|
||||
var itemId = SharedNodePriceItemDAO.SearchItemsWithBytes(priceItems, trafficBytes)
|
||||
if itemId == 0 {
|
||||
continue
|
||||
}
|
||||
price, ok := pricesMap[itemId]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if price <= 0 {
|
||||
continue
|
||||
}
|
||||
var regionFee = float64(trafficBytes) / 1000 / 1000 / 1000 * 8 * price
|
||||
fee += regionFee
|
||||
}
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, userId, serverId, month, userPlanId, 0, totalTrafficBytes, percentileBytes, percentile, "", fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
userPlan, err := SharedUserPlanDAO.FindUserPlanWithoutState(tx, userPlanId, cacheMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if userPlan == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
plan, ok := planMap[int64(userPlan.PlanId)]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// 总流量
|
||||
totalTrafficBytes, err := SharedServerDailyStatDAO.SumMonthlyBytes(tx, serverId, month)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch plan.PriceType {
|
||||
case serverconfigs.PlanPriceTypePeriod:
|
||||
// 已经在购买套餐的时候付过费,这里不再重复计费
|
||||
var fee float64 = 0
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, plan.PriceType, fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case serverconfigs.PlanPriceTypeTraffic:
|
||||
var config = plan.DecodeTrafficPrice()
|
||||
var fee float64 = 0
|
||||
if config != nil && config.Base > 0 {
|
||||
fee = float64(totalTrafficBytes) / 1024 / 1024 / 1024 * float64(config.Base)
|
||||
}
|
||||
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, plan.PriceType, fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case serverconfigs.PlanPriceTypeBandwidth:
|
||||
// 百分位
|
||||
var percentile = 95
|
||||
var config = plan.DecodeBandwidthPrice()
|
||||
if config != nil {
|
||||
percentile = config.Percentile
|
||||
if percentile <= 0 {
|
||||
percentile = 95
|
||||
} else if percentile > 100 {
|
||||
percentile = 100
|
||||
}
|
||||
}
|
||||
percentileBytes, err := SharedServerBandwidthStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var mb = float32(percentileBytes) / 1024 / 1024
|
||||
var price float32
|
||||
if config != nil {
|
||||
price = config.LookupPrice(mb)
|
||||
}
|
||||
var fee = float64(price)
|
||||
err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, plan.PriceType, fee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 计算用户费用
|
||||
for _, userId := range userIds {
|
||||
if userId == 0 {
|
||||
continue
|
||||
}
|
||||
amount, err := SharedServerBillDAO.SumUserMonthlyAmount(tx, userId, month)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = SharedUserBillDAO.CreateBill(tx, userId, BillTypeTraffic, "流量带宽费用", amount, month, month < timeutil.Format("Ym"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateUserBillIsPaid 设置账单已支付
|
||||
func (this *UserBillDAO) UpdateUserBillIsPaid(tx *dbs.Tx, billId int64, isPaid bool) error {
|
||||
return this.Query(tx).
|
||||
Pk(billId).
|
||||
Set("isPaid", isPaid).
|
||||
UpdateQuickly()
|
||||
}
|
||||
|
||||
// BillTypeName 获取账单类型名称
|
||||
func (this *UserBillDAO) BillTypeName(billType BillType) string {
|
||||
switch billType {
|
||||
case BillTypeTraffic:
|
||||
return "流量带宽"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GenerateBillCode 生成账单编号
|
||||
func (this *UserBillDAO) GenerateBillCode(tx *dbs.Tx) (string, error) {
|
||||
var code = timeutil.Format("YmdHis") + types.String(rands.Int(100000, 999999))
|
||||
exists, err := this.Query(tx).
|
||||
Attr("code", code).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !exists {
|
||||
return code, nil
|
||||
}
|
||||
return this.GenerateBillCode(tx)
|
||||
}
|
||||
|
||||
// CheckUserBill 检查用户账单
|
||||
func (this *UserBillDAO) CheckUserBill(tx *dbs.Tx, userId int64, billId int64) error {
|
||||
if userId <= 0 || billId <= 0 {
|
||||
return ErrNotFound
|
||||
}
|
||||
exists, err := this.Query(tx).
|
||||
Pk(billId).
|
||||
Attr("userId", userId).
|
||||
Exist()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SumUnpaidUserBill 计算某个用户未支付总额
|
||||
func (this *UserBillDAO) SumUnpaidUserBill(tx *dbs.Tx, userId int64) (float32, error) {
|
||||
sum, err := this.Query(tx).
|
||||
Attr("userId", userId).
|
||||
Attr("isPaid", 0).
|
||||
Sum("amount", 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return float32(sum), nil
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUserBillDAO_GenerateBills(t *testing.T) {
|
||||
dbs.NotifyReady()
|
||||
|
||||
var tx *dbs.Tx
|
||||
|
||||
err := SharedUserBillDAO.GenerateBills(tx, timeutil.Format("Ym"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log("ok")
|
||||
}
|
||||
@@ -15,22 +15,26 @@ type UserBill struct {
|
||||
PaidAt uint64 `field:"paidAt"` // 支付时间
|
||||
Code string `field:"code"` // 账单编号
|
||||
CreatedAt uint64 `field:"createdAt"` // 创建时间
|
||||
PricePeriod string `field:"pricePeriod"` // 计费周期
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type UserBillOperator struct {
|
||||
Id interface{} // ID
|
||||
UserId interface{} // 用户ID
|
||||
Type interface{} // 消费类型
|
||||
Description interface{} // 描述
|
||||
Amount interface{} // 消费数额
|
||||
DayFrom interface{} // YYYYMMDD
|
||||
DayTo interface{} // YYYYMMDD
|
||||
Month interface{} // 帐期YYYYMM
|
||||
CanPay interface{} // 是否可以支付
|
||||
IsPaid interface{} // 是否已支付
|
||||
PaidAt interface{} // 支付时间
|
||||
Code interface{} // 账单编号
|
||||
CreatedAt interface{} // 创建时间
|
||||
Id any // ID
|
||||
UserId any // 用户ID
|
||||
Type any // 消费类型
|
||||
Description any // 描述
|
||||
Amount any // 消费数额
|
||||
DayFrom any // YYYYMMDD
|
||||
DayTo any // YYYYMMDD
|
||||
Month any // 帐期YYYYMM
|
||||
CanPay any // 是否可以支付
|
||||
IsPaid any // 是否已支付
|
||||
PaidAt any // 支付时间
|
||||
Code any // 账单编号
|
||||
CreatedAt any // 创建时间
|
||||
PricePeriod any // 计费周期
|
||||
State any // 状态
|
||||
}
|
||||
|
||||
func NewUserBillOperator() *UserBillOperator {
|
||||
|
||||
@@ -28,6 +28,8 @@ type User struct {
|
||||
IsVerified bool `field:"isVerified"` // 是否验证通过
|
||||
RequirePlans uint8 `field:"requirePlans"` // 是否需要购买套餐
|
||||
Modules dbs.JSON `field:"modules"` // 用户模块
|
||||
PriceType string `field:"priceType"` // 计费类型:traffic|bandwidth
|
||||
PricePeriod string `field:"pricePeriod"` // 结算周期
|
||||
}
|
||||
|
||||
type UserOperator struct {
|
||||
@@ -55,6 +57,8 @@ type UserOperator struct {
|
||||
IsVerified any // 是否验证通过
|
||||
RequirePlans any // 是否需要购买套餐
|
||||
Modules any // 用户模块
|
||||
PriceType any // 计费类型:traffic|bandwidth
|
||||
PricePeriod any // 结算周期
|
||||
}
|
||||
|
||||
func NewUserOperator() *UserOperator {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !plus
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
@@ -7,8 +9,6 @@ import (
|
||||
"github.com/iwind/TeaGo/Tea"
|
||||
"github.com/iwind/TeaGo/dbs"
|
||||
"github.com/iwind/TeaGo/types"
|
||||
timeutil "github.com/iwind/TeaGo/utils/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -112,59 +112,11 @@ func (this *UserPlanDAO) FindUserPlanWithoutState(tx *dbs.Tx, userPlanId int64,
|
||||
|
||||
// CountAllEnabledUserPlans 计算套餐数量
|
||||
func (this *UserPlanDAO) CountAllEnabledUserPlans(tx *dbs.Tx, userId int64, isAvailable bool, isExpired bool, expiringDays int32) (int64, error) {
|
||||
var query = this.Query(tx).
|
||||
State(UserPlanStateEnabled).
|
||||
Where("planId IN (SELECT id FROM " + SharedPlanDAO.Table + " WHERE state=1)")
|
||||
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
} else {
|
||||
query.Where("userId IN (SELECT id FROM " + SharedUserDAO.Table + " WHERE state=1)")
|
||||
}
|
||||
|
||||
var today = timeutil.Format("Y-m-d")
|
||||
if isAvailable {
|
||||
query.Gte("dayTo", today)
|
||||
}
|
||||
if isExpired {
|
||||
query.Lt("dayTo", today)
|
||||
}
|
||||
if expiringDays > 0 {
|
||||
var expiringDay = timeutil.Format("Y-m-d", time.Now().AddDate(0, 0, int(expiringDays)))
|
||||
query.Gte("dayTo", today)
|
||||
query.Lte("dayTo", expiringDay)
|
||||
}
|
||||
return query.Count()
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// ListEnabledUserPlans 列出单页套餐
|
||||
func (this *UserPlanDAO) ListEnabledUserPlans(tx *dbs.Tx, userId int64, isAvailable bool, isExpired bool, expiringDays int32, offset int64, size int64) (result []*UserPlan, err error) {
|
||||
var query = this.Query(tx).
|
||||
State(UserPlanStateEnabled).
|
||||
Where("planId IN (SELECT id FROM " + SharedPlanDAO.Table + " WHERE state=1)")
|
||||
if userId > 0 {
|
||||
query.Attr("userId", userId)
|
||||
} else {
|
||||
query.Where("userId IN (SELECT id FROM " + SharedUserDAO.Table + " WHERE state=1)")
|
||||
}
|
||||
var today = timeutil.Format("Y-m-d")
|
||||
if isAvailable {
|
||||
query.Gte("dayTo", today)
|
||||
}
|
||||
if isExpired {
|
||||
query.Lt("dayTo", today)
|
||||
}
|
||||
if expiringDays > 0 {
|
||||
var expiringDay = timeutil.Format("Y-m-d", time.Now().AddDate(0, 0, int(expiringDays)))
|
||||
query.Gte("dayTo", today)
|
||||
query.Lte("dayTo", expiringDay)
|
||||
}
|
||||
_, err = query.
|
||||
DescPk().
|
||||
Offset(offset).
|
||||
Limit(size).
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -215,20 +167,6 @@ func (this *UserPlanDAO) UpdateUserPlanDayTo(tx *dbs.Tx, userPlanId int64, dayTo
|
||||
|
||||
// FindAllEnabledPlansForServer 列出服务可用的套餐
|
||||
func (this *UserPlanDAO) FindAllEnabledPlansForServer(tx *dbs.Tx, userId int64, serverId int64) (result []*UserPlan, err error) {
|
||||
var query = this.Query(tx).
|
||||
State(UserPlanStateEnabled).
|
||||
Attr("userId", userId).
|
||||
Where("planId IN (SELECT id FROM " + SharedPlanDAO.Table + " WHERE state=1)")
|
||||
if serverId > 0 {
|
||||
query.Where("id NOT IN (SELECT userPlanId FROM " + SharedServerDAO.Table + " WHERE state=1 AND id!=:serverId)")
|
||||
query.Param("serverId", serverId)
|
||||
} else {
|
||||
query.Where("id NOT IN (SELECT userPlanId FROM " + SharedServerDAO.Table + " WHERE state=1)")
|
||||
}
|
||||
_, err = query.
|
||||
DescPk().
|
||||
Slice(&result).
|
||||
FindAll()
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/iwind/TeaGo/bootstrap"
|
||||
)
|
||||
30
internal/db/models/user_traffic_bill_model.go
Normal file
30
internal/db/models/user_traffic_bill_model.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package models
|
||||
|
||||
// UserTrafficBill 用户流量/带宽账单
|
||||
type UserTrafficBill struct {
|
||||
Id uint64 `field:"id"` // ID
|
||||
BillId uint64 `field:"billId"` // 主账单ID
|
||||
RegionId uint32 `field:"regionId"` // 区域ID
|
||||
Amount float64 `field:"amount"` // 金额
|
||||
BandwidthMB float64 `field:"bandwidthMB"` // 带宽MB
|
||||
TrafficGB float64 `field:"trafficGB"` // 流量GB
|
||||
PricePerUnit float64 `field:"pricePerUnit"` // 单位价格
|
||||
PriceType string `field:"priceType"` // 计费方式:traffic|bandwidth
|
||||
State uint8 `field:"state"` // 状态
|
||||
}
|
||||
|
||||
type UserTrafficBillOperator struct {
|
||||
Id any // ID
|
||||
BillId any // 主账单ID
|
||||
RegionId any // 区域ID
|
||||
Amount any // 金额
|
||||
BandwidthMB any // 带宽MB
|
||||
TrafficGB any // 流量GB
|
||||
PricePerUnit any // 单位价格
|
||||
PriceType any // 计费方式:traffic|bandwidth
|
||||
State any // 状态
|
||||
}
|
||||
|
||||
func NewUserTrafficBillOperator() *UserTrafficBillOperator {
|
||||
return &UserTrafficBillOperator{}
|
||||
}
|
||||
1
internal/db/models/user_traffic_bill_model_ext.go
Normal file
1
internal/db/models/user_traffic_bill_model_ext.go
Normal file
@@ -0,0 +1 @@
|
||||
package models
|
||||
Reference in New Issue
Block a user