diff --git a/internal/db/models/server_bill_dao.go b/internal/db/models/server_bill_dao.go index f292fecd..54c1cc0c 100644 --- a/internal/db/models/server_bill_dao.go +++ b/internal/db/models/server_bill_dao.go @@ -31,13 +31,24 @@ func init() { } // CreateOrUpdateServerBill 创建账单 -func (this *ServerBillDAO) CreateOrUpdateServerBill(tx *dbs.Tx, userId int64, serverId int64, month string, userPlanId int64, planId int64, totalTrafficBytes int64, bandwidthPercentileBytes int64, bandwidthPercentile int, fee float64) error { +func (this *ServerBillDAO) CreateOrUpdateServerBill(tx *dbs.Tx, + userId int64, + serverId int64, + month string, + userPlanId int64, + planId int64, + totalTrafficBytes int64, + bandwidthPercentileBytes int64, + bandwidthPercentile int, + priceType string, + fee float64) error { fee = math.Floor(fee*100) / 100 return this.Query(tx). InsertOrUpdateQuickly(maps.Map{ "userId": userId, "serverId": serverId, "month": month, + "priceType": priceType, "amount": fee, "userPlanId": userPlanId, "planId": planId, @@ -47,6 +58,7 @@ func (this *ServerBillDAO) CreateOrUpdateServerBill(tx *dbs.Tx, userId int64, se "createdAt": time.Now().Unix(), }, maps.Map{ "userId": userId, + "priceType": priceType, "amount": fee, "userPlanId": userPlanId, "planId": planId, diff --git a/internal/db/models/server_bill_dao_test.go b/internal/db/models/server_bill_dao_test.go index 49cae31f..68ba56f4 100644 --- a/internal/db/models/server_bill_dao_test.go +++ b/internal/db/models/server_bill_dao_test.go @@ -12,7 +12,7 @@ func TestServerBillDAO_CreateOrUpdateServerBill(t *testing.T) { var dao = NewServerBillDAO() var tx *dbs.Tx var month = timeutil.Format("Y02") - err := dao.CreateOrUpdateServerBill(tx, 1, 2, month, 4, 5, 6, 7, 95, 100) + err := dao.CreateOrUpdateServerBill(tx, 1, 2, month, 4, 5, 6, 7, 95, "", 100) if err != nil { t.Fatal(err) } diff --git a/internal/db/models/server_bill_model.go b/internal/db/models/server_bill_model.go index 8c74027c..92cf7eaa 100644 --- a/internal/db/models/server_bill_model.go +++ b/internal/db/models/server_bill_model.go @@ -13,6 +13,7 @@ type ServerBill struct { TotalTrafficBytes uint64 `field:"totalTrafficBytes"` // 总流量 BandwidthPercentileBytes uint64 `field:"bandwidthPercentileBytes"` // 带宽百分位字节 BandwidthPercentile uint8 `field:"bandwidthPercentile"` // 带宽百分位 + PriceType string `field:"priceType"` // 计费类型 } type ServerBillOperator struct { @@ -27,6 +28,7 @@ type ServerBillOperator struct { TotalTrafficBytes interface{} // 总流量 BandwidthPercentileBytes interface{} // 带宽百分位字节 BandwidthPercentile interface{} // 带宽百分位 + PriceType interface{} // 计费类型 } func NewServerBillOperator() *ServerBillOperator { diff --git a/internal/db/models/sys_setting_dao.go b/internal/db/models/sys_setting_dao.go index 04d0d3ef..0971d8be 100644 --- a/internal/db/models/sys_setting_dao.go +++ b/internal/db/models/sys_setting_dao.go @@ -158,6 +158,24 @@ func (this *SysSettingDAO) ReadUserServerConfig(tx *dbs.Tx) (*userconfigs.UserSe 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" diff --git a/internal/db/models/user_bill_dao.go b/internal/db/models/user_bill_dao.go index c698ef18..f8938169 100644 --- a/internal/db/models/user_bill_dao.go +++ b/internal/db/models/user_bill_dao.go @@ -182,6 +182,12 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error { } } + // 默认计费方式 + userFinanceConfig, err := SharedSysSettingDAO.ReadUserFinanceConfig(tx) + if err != nil { + return err + } + // 计算服务套餐费用 plans, err := SharedPlanDAO.FindAllEnabledPlans(tx) if err != nil { @@ -212,52 +218,103 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error { userIds = append(userIds, userId) if userPlanId == 0 { - 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 - } - // 总流量 totalTrafficBytes, err := SharedServerDailyStatDAO.SumMonthlyBytes(tx, serverId, month) if err != nil { return err } - // 百分位 - var percentile = 95 - percentileBytes, err := SharedServerDailyStatDAO.FindMonthlyPercentile(tx, serverId, month, percentile) - 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) + } - err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, userId, serverId, month, userPlanId, 0, totalTrafficBytes, percentileBytes, percentile, fee) - if err != nil { - return err + // 百分位 + var percentile = 95 + percentileBytes, err := SharedServerDailyStatDAO.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 := SharedServerDailyStatDAO.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 := SharedServerDailyStatDAO.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) @@ -291,7 +348,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error { return err } - err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, fee) + err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, plan.PriceType, fee) if err != nil { return err } @@ -309,7 +366,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error { return err } - err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, fee) + err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, plan.PriceType, fee) if err != nil { return err } @@ -335,7 +392,7 @@ func (this *UserBillDAO) GenerateBills(tx *dbs.Tx, month string) error { price = config.LookupPrice(mb) } var fee = float64(price) - err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, fee) + err = SharedServerBillDAO.CreateOrUpdateServerBill(tx, int64(userPlan.UserId), serverId, month, userPlanId, int64(userPlan.PlanId), totalTrafficBytes, percentileBytes, percentile, plan.PriceType, fee) if err != nil { return err } diff --git a/internal/rpc/services/service_server_bill.go b/internal/rpc/services/service_server_bill.go index 59f4af5b..e43e3517 100644 --- a/internal/rpc/services/service_server_bill.go +++ b/internal/rpc/services/service_server_bill.go @@ -114,6 +114,7 @@ func (this *ServerBillService) ListServerBills(ctx context.Context, req *pb.List UserId: int64(bill.UserId), ServerId: int64(bill.ServerId), Amount: float32(bill.Amount), + PriceType: bill.PriceType, CreatedAt: int64(bill.CreatedAt), UserPlanId: int64(bill.UserPlanId), PlanId: int64(bill.PlanId),