package period_profit import ( "app/commons/constant" "app/commons/core" "app/commons/model/entity" "app/commons/utils" "fmt" "github.com/shopspring/decimal" ) // 计算等级奖励 // 根据等级配置 计算每个等级可获得比例 // 统计各等级人数 // 平均分配计算 -- 生成待发放奖励记录 // 加权分配计算 -- 生成待发放奖励记录 -- 以真实小区业绩加权 func (s *Service) calLevelProfit(periodNo string) error { levelMap, err := s.LevelConfigMapFromCache() if err != nil { return err } nowPeriodJob, err := s.FirstStakePeriodJob(s.DB(). Where("job_state", entity.PeriodJobStateRunning). Where("period_no", periodNo). Where("level_profit_is_cal", false)) if err != nil { return err } if nowPeriodJob.StaticSymbolProfit.LessThanOrEqual(decimal.Zero) { core.JobLog.Warnf("期:%s 静态收益为:%s,跳过等级收益计算", periodNo, nowPeriodJob.StaticSymbolProfit) return nil } periodProfit := nowPeriodJob.StaticSymbolProfit periodUsdProfit := nowPeriodJob.StaticUsdProfit price := nowPeriodJob.Price profitRecords := make([]*entity.UserProfitRecord, 0) for k, v := range levelMap { core.JobLog.Infof("计算等级:%d 收益", k) records, err := s.avgWeightedLevelProfit(periodNo, v, periodUsdProfit, price, periodProfit) if err != nil { return err } if len(records) > 0 { profitRecords = append(profitRecords, records...) } } if len(profitRecords) > 0 { txDb := s.DB().Begin() err = txDb.CreateInBatches(profitRecords, 200).Error if err != nil { txDb.Rollback() return err } txDb.Commit() } return nil } // 根据等级计算均分收益 func (s *Service) avgWeightedLevelProfit(periodNo string, levelConfig *entity.SysLevelConfig, usdProfit, symbolProfit, price decimal.Decimal) ([]*entity.UserProfitRecord, error) { dailyJobDate, err := utils.PeriodNoToDailyDate(periodNo) // 期任务格式转化为 日任务格式 if err != nil { return nil, err } profitRecords := make([]*entity.UserProfitRecord, 0) levelSymbolProfit := symbolProfit.Mul(levelConfig.StaticRatio) // 当期该等级可分配总数量 levelUsdAmount := usdProfit.Mul(levelConfig.StaticRatio) // 当期该等级可分配总U数 // 等级均分总数 totalAvgProfit := levelSymbolProfit.Mul(levelConfig.AvgRatio) totalAvgUsdProfit := levelUsdAmount.Mul(levelConfig.AvgRatio) // 加权分配总数 totalWeightedProfit := levelSymbolProfit.Mul(levelConfig.WeightedRatio) totalWeightedUsdProfit := levelUsdAmount.Mul(levelConfig.WeightedRatio) allLevelUserQuota, err := s.BatchUserQuota(s.DB().Where("level", levelConfig.Level)) if err != nil { return profitRecords, err } // 均分计算 countUser := len(allLevelUserQuota) core.JobLog.Infof("等级:%d 用户数:%d", levelConfig.Level, countUser) if countUser == 0 { return profitRecords, nil } avgRatio := decimal.NewFromFloat(1).Div(decimal.NewFromInt(int64(countUser))) // 每人可获得均分比例 avgPerUserSymbolProfit := totalAvgProfit.Mul(avgRatio) // 当前等级每人可获得SYMBOL数量 == 拆分为 均分与加权 avgPerUserUsdProfit := totalAvgUsdProfit.Mul(avgRatio) // 当前等级每人可获得USD数量 == 拆分为 均分与加权 // 计算加权分配数量 allFewAc := decimal.Zero // 等级达标总小区业绩 for _, quota := range allLevelUserQuota { allFewAc = allFewAc.Add(quota.FewTeamAchievement) } weightedPerAcSymbolRatio := totalWeightedProfit.Mul(allFewAc) // 1U 业绩可获得 加权奖励比例 weightedPerAcUsdRatio := totalWeightedUsdProfit.Mul(allFewAc) // 1U 业绩可获得 加权奖励比例 for _, userQuota := range allLevelUserQuota { // 均分记录 avgBs := constant.BsById(constant.BsDynamicLevelAvgProfit) avgBs.ContextValue = fmt.Sprintf("%d", userQuota.UserId) avgBs.ContextName = userQuota.TableName() avgBs.Desc = fmt.Sprintf("%s-期:%s-Level:%d-perUserSymbolProfit:%s", avgBs.BusinessName, periodNo, levelConfig.Level, avgPerUserSymbolProfit) profitInfo := &entity.ProfitInfo{ RawUserId: userQuota.UserId, RawUserUid: userQuota.Uid, RewardUserId: userQuota.UserId, RewardUserUid: userQuota.Uid, RewardSymbol: constant.CoinSymbolTD, SymbolUsdPrice: price, CapitalUsd: totalAvgUsdProfit, RewardRatio: avgRatio, RewardUsdValue: avgPerUserUsdProfit, RewardQuantity: avgPerUserSymbolProfit, RewardPeriod: periodNo, RewardDate: dailyJobDate, } profitRecord := s.BuildUserProfitRecord(profitInfo, avgBs) profitRecords = append(profitRecords, profitRecord) // 加权分配 weightedBs := constant.BsById(constant.BsDynamicLevelWeightedProfit) weightedBs.ContextValue = fmt.Sprintf("%d", userQuota.UserId) weightedBs.ContextName = userQuota.TableName() userWeightedProfit := userQuota.FewTeamAchievement.Mul(weightedPerAcSymbolRatio) userWeightedUsdProfit := userQuota.FewTeamAchievement.Mul(weightedPerAcUsdRatio) weightedBs.Desc = fmt.Sprintf("%s-期:%s-Level:%d-userWeightedProfit:%s", avgBs.BusinessName, periodNo, levelConfig.Level, userWeightedProfit) weightedProfitInfo := &entity.ProfitInfo{ RawUserId: userQuota.UserId, RawUserUid: userQuota.Uid, RewardUserId: userQuota.UserId, RewardUserUid: userQuota.Uid, RewardSymbol: constant.CoinSymbolTD, SymbolUsdPrice: price, CapitalUsd: userQuota.FewTeamAchievement, RewardRatio: weightedPerAcUsdRatio, RewardUsdValue: userWeightedUsdProfit, RewardQuantity: userWeightedProfit, RewardPeriod: periodNo, RewardDate: dailyJobDate, } weightedProfitRecord := s.BuildUserProfitRecord(weightedProfitInfo, weightedBs) profitRecords = append(profitRecords, weightedProfitRecord) } return profitRecords, nil }