Files
go-common/app/interface/main/growup/service/income.go
2019-04-22 18:49:16 +08:00

835 lines
22 KiB
Go

package service
import (
"context"
"crypto/md5"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"sort"
"strconv"
"time"
"go-common/app/interface/main/growup/model"
"go-common/library/log"
xtime "go-common/library/time"
"go-common/library/xstr"
)
const (
_video = iota
_audio
_column
_bgm
_up
)
var (
_layout = "2006-01-02"
)
// GetUpCharge get up daily sum(charge) last 30 days
func (s *Service) GetUpCharge(c context.Context, mid int64, t time.Time) (total int, err error) {
begin := t.AddDate(0, 0, -30).Format(_layout)
incs, err := s.dao.GetUpDailyCharge(c, mid, begin)
if err != nil {
return
}
for _, inc := range incs {
total += inc
}
total = int(float64(total) * float64(0.6))
return
}
// ArchiveIncome get archive income by mid
func (s *Service) ArchiveIncome(c context.Context, mid int64, typ, page, size, all int) (data map[string]interface{}, err error) {
redisKey := fmt.Sprintf("growup-archive-income:%d+%d+%d+%d+%d", typ, mid, all, page, size)
data, err = s.dao.GetIncomeCache(c, redisKey)
if err != nil {
log.Error("s.dao.GetIncomeCache error(%v)", err)
return
}
if data != nil {
return
}
data, err = s.archiveIncome(c, mid, typ, page, size, all)
if err != nil {
log.Error("s.archiveIncome error(%v)", err)
return
}
err = s.dao.SetIncomeCache(c, redisKey, data)
if err != nil {
log.Error("s.dao.SetIncomeCache error(%v)", err)
}
return
}
// archiveIncome get archive income by mid
func (s *Service) archiveIncome(c context.Context, mid int64, typ, page, size, all int) (data map[string]interface{}, err error) {
data = make(map[string]interface{})
if page == 0 {
page = 1
}
start, end := (page-1)*size, page*size
date := time.Now().AddDate(0, 0, -2)
startMonth := time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, time.Local).Format(_layout)
if all == 1 {
startMonth = "2017-12-01"
}
var (
archives []*model.ArchiveIncome
total int
)
switch typ {
case _video:
archives, total, err = s.listAvIncome(c, mid, startMonth, date.Format(_layout), start, end)
case _audio:
case _column:
archives, total, err = s.listColumnIncome(c, mid, startMonth, date.Format(_layout), start, end)
case _bgm:
archives, total, err = s.listBgmIncome(c, mid, startMonth, date.Format(_layout), start, end)
}
if err != nil {
log.Error("s.archiveIncome error(%v)", err)
return nil, err
}
data["data"] = archives
data["total_count"] = total
data["page"] = page
return
}
func (s *Service) listAvIncome(c context.Context, mid int64, startTime, endTime string, start, end int) (archiveList []*model.ArchiveIncome, total int, err error) {
avs, err := s.dao.ListAvIncome(c, mid, startTime, endTime)
if err != nil {
log.Error("s.dao.ListAvIncome error(%v)", err)
return
}
return s.handleArchiveIncome(c, avs, start, end, _video)
}
func (s *Service) listColumnIncome(c context.Context, mid int64, startTime, endTime string, start, end int) (archiveList []*model.ArchiveIncome, total int, err error) {
columns, err := s.dao.ListColumnIncome(c, mid, startTime, endTime)
if err != nil {
log.Error("s.dao.ListColumnIncome error(%v)", err)
return
}
return s.handleArchiveIncome(c, columns, start, end, _column)
}
func (s *Service) listBgmIncome(c context.Context, mid int64, startTime, endTime string, start, end int) (archiveList []*model.ArchiveIncome, total int, err error) {
bgms, err := s.dao.ListBgmIncome(c, mid, startTime, endTime)
if err != nil {
log.Error("s.dao.ListBgmIncome error(%v)", err)
return
}
return s.handleArchiveIncome(c, bgms, start, end, _bgm)
}
func calArchiveIncome(archives []*model.ArchiveIncome, avBMap map[int64]struct{}) (archiveMap map[int64]*model.ArchiveIncome) {
endTime := time.Now().AddDate(0, 0, -2)
archiveMap = make(map[int64]*model.ArchiveIncome)
archMonthIncome := make(map[int64]int64)
for _, arch := range archives {
if _, ok := avBMap[arch.ArchiveID]; ok {
continue
}
archiveDate := arch.Date.Time()
// cal month income
if archiveDate.Month() == endTime.Month() {
archMonthIncome[arch.ArchiveID] += arch.Income
}
if archiveDate.Format(_layout) != endTime.Format(_layout) {
arch.Income = 0
}
if old, ok := archiveMap[arch.ArchiveID]; !ok {
archiveMap[arch.ArchiveID] = arch
} else {
if old.Date < arch.Date {
archiveMap[arch.ArchiveID] = arch
}
}
archiveMap[arch.ArchiveID].MonthIncome = archMonthIncome[arch.ArchiveID]
}
return
}
func (s *Service) handleArchiveIncome(c context.Context, archives []*model.ArchiveIncome, start, end, typ int) (archiveList []*model.ArchiveIncome, total int, err error) {
archiveList = make([]*model.ArchiveIncome, 0)
if len(archives) == 0 {
return
}
aIDMap := make(map[int64]struct{})
aIDList := []int64{}
for _, arch := range archives {
if _, ok := aIDMap[arch.ArchiveID]; !ok {
aIDMap[arch.ArchiveID] = struct{}{}
aIDList = append(aIDList, arch.ArchiveID)
}
}
avBMap, err := s.dao.ListAvBlackList(c, aIDList, typ)
if err != nil {
log.Error("s.dao.ListAvBlackList error(%v)", err)
return
}
avsMap := calArchiveIncome(archives, avBMap)
for _, av := range avsMap {
archiveList = append(archiveList, av)
}
sort.Slice(archiveList, func(i, j int) bool {
if archiveList[i].Income == archiveList[j].Income {
if archiveList[i].MonthIncome == archiveList[j].MonthIncome {
return archiveList[i].TotalIncome > archiveList[j].TotalIncome
}
return archiveList[i].MonthIncome > archiveList[j].MonthIncome
}
return archiveList[i].Income > archiveList[j].Income
})
total = len(archiveList)
if end > total {
end = total
}
if start >= total || start > end {
return
}
archiveList = archiveList[start:end]
avIDs := []int64{}
for _, av := range archiveList {
avIDs = append(avIDs, av.ArchiveID)
}
titles := make(map[int64]string)
switch typ {
case _video:
titles, err = s.getAvTitle(c, avIDs)
if err != nil {
log.Error("s.getAvTitle error(%v)", err)
return
}
case _column:
titles, err = s.getColumnTitle(c, avIDs)
if err != nil {
log.Error("s.getColumnTitle error(%v)", err)
return
}
case _bgm:
titles, err = s.getBgmTitle(c, avIDs)
if err != nil {
log.Error("s.getBgmTitle error(%v)", err)
return
}
}
icons, err := s.getAvIcon(c, avIDs)
if err != nil {
log.Error("s.getAvIcon error(%v)", err)
return
}
breachs, err := s.getAvBreach(c, avIDs, typ)
if err != nil {
log.Error("s.getAvBreach error(%v)", err)
return
}
for _, av := range archiveList {
av.Title = titles[av.ArchiveID]
av.Icon = icons[av.ArchiveID]
av.Breach = breachs[av.ArchiveID]
}
return
}
func (s *Service) getColumnTitle(c context.Context, avs []int64) (titles map[int64]string, err error) {
return s.dao.GetColumnTitle(c, avs)
}
func (s *Service) getBgmTitle(c context.Context, avs []int64) (titles map[int64]string, err error) {
return s.dao.GetBgmTitle(c, avs)
}
func (s *Service) getAvTitle(c context.Context, avs []int64) (titles map[int64]string, err error) {
req, err := http.NewRequest("GET", s.conf.Host.ArchiveURI, nil)
if err != nil {
log.Error("http.NewRequest error(%v)", err)
return
}
q := req.URL.Query()
q.Add("aids", xstr.JoinInts(avs))
q.Add("appkey", s.conf.AppConf.Key)
now := time.Now().Unix()
q.Add("ts", strconv.FormatInt(now, 10))
sign := q.Encode() + s.conf.AppConf.Secret
q.Add("sign", fmt.Sprintf("%x", md5.Sum([]byte(sign))))
req.URL.RawQuery = q.Encode()
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Error("http.DefaultClient.Do error(%v)", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Error("ioutil.ReadAll error(%v)", err)
return
}
res := model.ArchiveRes{}
err = json.Unmarshal(body, &res)
if err != nil {
log.Error("json.Unmarshal body %s error(%v)", string(body), err)
return
}
titles = make(map[int64]string)
for _, archive := range res.Data {
titles[archive.AID] = archive.Title
}
return
}
func (s *Service) getAvIcon(c context.Context, avs []int64) (acM map[int64]string, err error) {
if len(avs) == 0 {
return
}
activeM, err := s.dao.ListActiveInfo(c, avs)
if err != nil {
log.Error("s.dao.ListActiveInfo error(%v)", err)
return
}
tagIDM := make(map[int64]struct{})
for _, tagID := range activeM {
tagIDM[tagID] = struct{}{}
}
tagIDList := make([]int64, 0)
for tagID := range tagIDM {
tagIDList = append(tagIDList, tagID)
}
if len(tagIDList) == 0 {
return
}
tagIconM, err := s.dao.ListTagInfo(c, tagIDList)
if err != nil {
log.Error("s.dao.ListTagInfo error(%v)", err)
return
}
acM = make(map[int64]string)
for avID, tagID := range activeM {
if _, ok := tagIconM[tagID]; ok {
acM[avID] = tagIconM[tagID].Icon
}
}
return
}
func (s *Service) getAvBreach(c context.Context, avs []int64, typ int) (breachs map[int64]*model.AvBreach, err error) {
if len(avs) == 0 {
return
}
return s.dao.GetAvBreachs(c, avs, typ)
}
// UpSummary summary up income
func (s *Service) UpSummary(c context.Context, mid int64) (data interface{}, err error) {
redisKey := fmt.Sprintf("growup-up-summary:%d", mid)
res, err := s.dao.GetIncomeCache(c, redisKey)
if err != nil {
log.Error("s.dao.GetIncomeCache error(%v)", err)
return
}
if res != nil {
data = res["data"]
return
}
data, err = s.upSummary(c, mid)
if err != nil {
log.Error("s.upSummary error(%v)", err)
return
}
err = s.dao.SetIncomeCache(c, redisKey, map[string]interface{}{"data": data})
if err != nil {
log.Error("s.dao.SetIncomeCache error(%v)", err)
}
return
}
func (s *Service) upSummary(c context.Context, mid int64) (data interface{}, err error) {
summary := new(struct {
DayIncome string `json:"day_income"`
Date string `json:"date"`
Income string `json:"income"`
TotalIncome string `json:"total_income"`
WaitWithdraw string `json:"wait_withdraw"`
BreachMoney string `json:"breach_money"`
UnwithdrawDate string `json:"unwithdraw_date"`
})
summary.DayIncome, summary.Income, summary.TotalIncome, summary.WaitWithdraw, summary.BreachMoney = "0", "0", "0", "0", "0"
now := time.Now().AddDate(0, 0, -2)
nowMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.Local)
count, err := s.dao.GetUpIncomeCount(c, now.Format(_layout))
if err != nil {
log.Error("s.dao.GetUpIncomeCount error(%v)", err)
return
}
if count <= 0 {
summary.DayIncome, summary.Income, summary.TotalIncome, summary.WaitWithdraw, summary.BreachMoney = "-1", "-1", "-1", "-1", "-1"
data = summary
return
}
upIncomes, err := s.dao.ListUpIncome(c, mid, "up_income", nowMonth.Format(_layout), now.AddDate(0, 0, 1).Format(_layout))
if err != nil {
log.Error("s.dao.ListUpIncome error(%v)", err)
return
}
var monthIncome, lastDayIncome, dayIncome int64
for _, up := range upIncomes {
if up.Date.Time().Format(_layout) == now.Format(_layout) {
dayIncome = up.Income
}
if up.Date.Time().Format(_layout) == now.AddDate(0, 0, 1).Format(_layout) {
lastDayIncome = up.Income
}
monthIncome += up.Income
}
upAccount, err := s.dao.ListUpAccount(c, mid)
if err != nil {
log.Error("s.dao.ListUpAccount error(%v)", err)
return
}
if upAccount == nil {
data = summary
return
}
breachs, err := s.dao.ListAvBreach(c, mid, nowMonth.Format(_layout), time.Now().Format(_layout))
if err != nil {
log.Error("s.dao.ListAvBreach error(%v)", err)
return
}
var breachMoney int64
for _, b := range breachs {
breachMoney += b.Money
}
summary.DayIncome = fmt.Sprintf("%.2f", fromYuanToFen(dayIncome))
summary.BreachMoney = fmt.Sprintf("%.2f", fromYuanToFen(breachMoney))
summary.TotalIncome = fmt.Sprintf("%.2f", fromYuanToFen(upAccount.TotalIncome-lastDayIncome))
summary.Date = now.Format(_layout)
wdv, err := time.Parse("2006-01", upAccount.WithdrawDateVersion)
if err != nil {
log.Error("time.Parse error(%v)", err)
return
}
summary.UnwithdrawDate = time.Date(wdv.Year(), wdv.Month()+1, 1, 0, 0, 0, 0, time.Local).Format("2006-01")
// 如果T-1的month不等于T-2的month 当月新增不需要减去那一天的收入:lastDayIncome = 0
if now.AddDate(0, 0, 1).Month() == now.Month() {
monthIncome -= lastDayIncome
}
summary.Income = fmt.Sprintf("%.2f", fromYuanToFen(monthIncome))
// 当月未提现,待结算不能减去昨天收入,当月已提现,需要减去昨日收入
preMonth := time.Date(nowMonth.Year(), nowMonth.Month()-1, 1, 0, 0, 0, 0, time.Local).Format("2006-01")
if preMonth != upAccount.WithdrawDateVersion || now.AddDate(0, 0, 1).Month() != now.Month() {
lastDayIncome = 0
}
summary.WaitWithdraw = fmt.Sprintf("%.2f", fromYuanToFen(upAccount.TotalUnwithdrawIncome-lastDayIncome))
data = summary
return
}
func fromYuanToFen(income int64) float64 {
return float64(income) / float64(100)
}
// ArchiveSummary get archive summary
func (s *Service) ArchiveSummary(c context.Context, typ int, mid int64) (data interface{}, err error) {
redisKey := fmt.Sprintf("growup-archive-summary:%d+%d", typ, mid)
res, err := s.dao.GetIncomeCache(c, redisKey)
if err != nil {
log.Error("s.dao.GetIncomeCache error(%v)", err)
return
}
if res != nil {
data = res["data"]
return
}
data, err = s.archiveSummary(c, typ, mid)
if err != nil {
log.Error("s.archiveSummary error(%v)", err)
return
}
err = s.dao.SetIncomeCache(c, redisKey, map[string]interface{}{"data": data})
if err != nil {
log.Error("s.dao.SetIncomeCache error(%v)", err)
}
return
}
func (s *Service) archiveSummary(c context.Context, typ int, mid int64) (data interface{}, err error) {
date := time.Now().AddDate(0, 0, -2)
startMonth := xtime.Time(time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, time.Local).Unix())
upIncomes, err := s.dao.ListUpIncome(c, mid, "up_income", "2017-12-01", date.Format(_layout))
if err != nil {
log.Error("s.dao.ListUpIncome error(%v)", err)
return
}
summary := new(struct {
DayIncome int64 `json:"day_income"`
Date string `json:"date"`
MonthIncome int64 `json:"income"`
TotalIncome int64 `json:"total_income"`
Breach int64 `json:"breach_money"`
})
if len(upIncomes) == 0 {
data = summary
return
}
sort.Slice(upIncomes, func(i, j int) bool {
return upIncomes[i].Date > upIncomes[j].Date
})
summary.Date = date.Format(_layout)
if upIncomes[0].Date.Time().Format(_layout) == summary.Date {
switch typ {
case _video:
summary.DayIncome = upIncomes[0].AvIncome
case _column:
summary.DayIncome = upIncomes[0].ColumnIncome
case _bgm:
summary.DayIncome = upIncomes[0].BgmIncome
}
}
var breachType []int64
for _, up := range upIncomes {
if up.Date >= startMonth {
switch typ {
case _video:
summary.MonthIncome += up.AvIncome
case _column:
summary.MonthIncome += up.ColumnIncome
case _bgm:
summary.MonthIncome += up.BgmIncome
}
}
switch typ {
case _video:
breachType = []int64{0}
summary.TotalIncome += up.AvIncome
case _column:
breachType = []int64{2}
summary.TotalIncome += up.ColumnIncome
case _bgm:
breachType = []int64{3}
summary.TotalIncome += up.BgmIncome
}
}
breach, err := s.dao.GetAvBreachByType(c, mid, "2017-12-01", time.Now().Format(_layout), breachType)
if err != nil {
log.Error("s.dao.GetAvBreachByType error(%v)", err)
return
}
for d, money := range breach {
if d >= startMonth {
summary.Breach += money
}
summary.TotalIncome -= money
}
if summary.TotalIncome < 0 {
summary.TotalIncome = 0
}
data = summary
return
}
// ArchiveDetail cal archive detail
func (s *Service) ArchiveDetail(c context.Context, typ int, archiveID int64) (data interface{}, err error) {
redisKey := fmt.Sprintf("growup-archive-detail:%d+%d", typ, archiveID)
res, err := s.dao.GetIncomeCache(c, redisKey)
if err != nil {
log.Error("s.dao.GetIncomeCache error(%v)", err)
return
}
if res != nil {
data = res["data"]
return
}
data, err = s.archiveDetail(c, typ, archiveID)
if err != nil {
log.Error("s.archiveDetail error(%v)", err)
return
}
err = s.dao.SetIncomeCache(c, redisKey, map[string]interface{}{"data": data})
if err != nil {
log.Error("s.dao.SetIncomeCache error(%v)", err)
}
return
}
func (s *Service) archiveDetail(c context.Context, typ int, archiveID int64) (archives []*model.ArchiveIncome, err error) {
archives = make([]*model.ArchiveIncome, 0)
endTime := time.Now().AddDate(0, 0, -2).Format(_layout)
switch typ {
case _video:
archives, err = s.dao.ListAvIncomeByID(c, archiveID, endTime)
if err != nil {
log.Error("s.dao.ListAvIncomeByID error(%v)", err)
return
}
case _audio:
case _column:
archives, err = s.dao.ListColumnIncomeByID(c, archiveID, endTime)
if err != nil {
log.Error("s.dao.ListColumnIncomeByID error(%v)", err)
return
}
case _bgm:
archives, err = s.listBgmIncomeByID(c, archiveID, endTime)
if err != nil {
return
}
}
sort.Slice(archives, func(i, j int) bool {
return archives[i].Date > archives[j].Date
})
return
}
func (s *Service) listBgmIncomeByID(c context.Context, archiveID int64, endTime string) (archives []*model.ArchiveIncome, err error) {
as, err := s.dao.ListBgmIncomeByID(c, archiveID, endTime)
if err != nil {
log.Error("s.dao.ListBgmIncomeByID error(%v)", err)
return
}
am := make(map[xtime.Time][]*model.ArchiveIncome)
for _, a := range as {
if _, ok := am[a.Date]; ok {
am[a.Date] = append(am[a.Date], a)
} else {
am[a.Date] = []*model.ArchiveIncome{a}
}
}
archives = make([]*model.ArchiveIncome, 0)
for date, ars := range am {
a := &model.ArchiveIncome{}
a.Date = date
for _, ar := range ars {
a.Income += ar.Income
a.Avs = append(a.Avs, ar.ArchiveID)
}
archives = append(archives, a)
}
return
}
// ArchiveBreach get av_breach_record
func (s *Service) ArchiveBreach(c context.Context, mid int64, typ, page, size, all int) (data interface{}, err error) {
if page == 0 {
page = 1
}
start, end := (page-1)*size, page*size
date := time.Now().AddDate(0, 0, -2)
startMonth := time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, time.Local).Format(_layout)
if all == 1 {
startMonth = "2017-12-01"
}
archives, err := s.dao.ListAvBreach(c, mid, startMonth, date.Format(_layout))
if err != nil {
log.Error("s.dao.ListAvBreach error(%v)", err)
return
}
typBreach := make([]*model.AvBreach, 0)
for _, arch := range archives {
if arch.CType == typ {
typBreach = append(typBreach, arch)
}
}
if len(typBreach) == 0 {
return
}
breachs, err := s.breachInBlacklist(c, typBreach, typ)
if err != nil {
log.Error("s.breachInBlacklist error(%v)", err)
return
}
sort.Slice(breachs, func(i, j int) bool {
return breachs[i].CDate > breachs[j].CDate
})
if end > len(breachs) {
end = len(breachs)
}
list := breachs[start:end]
aIDs := make([]int64, 0)
for _, b := range list {
aIDs = append(aIDs, b.AvID)
}
var titles map[int64]string
switch typ {
case _video:
titles, err = s.getAvTitle(c, aIDs)
if err != nil {
log.Error("s.getAvTitle error(%v)", err)
return
}
case _column:
titles, err = s.getColumnTitle(c, aIDs)
if err != nil {
log.Error("s.getColumnTitle error(%v)", err)
return
}
case _bgm:
titles, err = s.getBgmTitle(c, aIDs)
if err != nil {
log.Error("s.getBgmTitle error(%v)", err)
return
}
}
for _, b := range list {
b.Title = titles[b.AvID]
}
data = map[string]interface{}{
"data": list,
"total_count": len(breachs),
"page": page,
}
return
}
func (s *Service) breachInBlacklist(c context.Context, avs []*model.AvBreach, typ int) (breachs []*model.AvBreach, err error) {
aIDList := make([]int64, 0)
for _, a := range avs {
aIDList = append(aIDList, a.AvID)
}
avBMap, err := s.dao.ListAvBlackList(c, aIDList, typ)
if err != nil {
return
}
breachs = make([]*model.AvBreach, 0)
for _, av := range avs {
if _, ok := avBMap[av.AvID]; ok {
breachs = append(breachs, av)
}
}
return
}
// UpIncomeStat get up income stat by month
func (s *Service) UpIncomeStat(c context.Context, typ int, mid int64, date time.Time) (data interface{}, err error) {
redisKey := fmt.Sprintf("growup-income-stat:%d+%d", typ, mid)
res, err := s.dao.GetIncomeCache(c, redisKey)
if err != nil {
log.Error("s.dao.GetIncomeCache error(%v)", err)
return
}
if res != nil {
data = res["data"]
return
}
data, err = s.upIncomeStat(c, typ, mid, date)
if err != nil {
return
}
err = s.dao.SetIncomeCache(c, redisKey, map[string]interface{}{"data": data})
if err != nil {
log.Error("s.dao.SetIncomeCache error(%v)", err)
}
return
}
func (s *Service) upIncomeStat(c context.Context, typ int, mid int64, date time.Time) (stats []*model.UpIncomeStat, err error) {
et := date.AddDate(0, 0, -2)
end := et.Format(_layout)
// last 30 days
begin := et.AddDate(0, 0, -30).Format(_layout)
upIncomes, err := s.dao.ListUpIncome(c, mid, "up_income", begin, end)
if err != nil {
log.Error("s.dao.ListUpIncome error(%v)", err)
return
}
stats = make([]*model.UpIncomeStat, 0)
if len(upIncomes) == 0 {
return
}
var breachType []int64
for _, up := range upIncomes {
var income, baseIncome int64
switch typ {
case _video:
income, baseIncome = up.AvIncome, up.AvBaseIncome
breachType = []int64{0}
case _column:
income, baseIncome = up.ColumnIncome, up.ColumnBaseIncome
breachType = []int64{2}
case _bgm:
income, baseIncome = up.BgmIncome, up.BgmBaseIncome
breachType = []int64{3}
case _up:
income, baseIncome = up.Income, up.BaseIncome
breachType = []int64{0, 1, 2, 3}
}
extra := income - baseIncome
if extra < 0 {
extra = 0
}
stats = append(stats, &model.UpIncomeStat{
MID: up.MID,
Income: income,
BaseIncome: baseIncome,
ExtraIncome: extra,
Date: up.Date,
})
}
rs, err := s.dao.GetAvBreachByType(c, mid, begin, end, breachType)
if err != nil {
log.Error("s.dao.GetAvBreachByType error(%v)", err)
return
}
for _, stat := range stats {
if _, ok := rs[stat.Date]; ok {
stat.Breach = rs[stat.Date]
delete(rs, stat.Date)
}
}
for date, breach := range rs {
stats = append(stats, &model.UpIncomeStat{
MID: mid,
Date: date,
Breach: breach,
})
}
sort.Slice(stats, func(i, j int) bool {
return stats[i].Date < stats[j].Date
})
return
}