package income import ( "context" "fmt" "sort" "strconv" "time" model "go-common/app/admin/main/growup/model/income" "go-common/library/log" "go-common/library/xstr" ) // ArchiveStatis archive income statis func (s *Service) ArchiveStatis(c context.Context, categoryID []int64, typ, groupType int, fromTime, toTime int64) (data interface{}, err error) { table := setArchiveTableByGroup(typ, groupType) from := getDateByGroup(groupType, time.Unix(fromTime, 0)) to := getDateByGroup(groupType, time.Unix(toTime, 0)) query := formatArchiveQuery(categoryID, from, to) if typ == _lottery { data, err = s.lotteryStatis(c, categoryID, from, addDayByGroup(groupType, to).AddDate(0, 0, -1), groupType) if err != nil { log.Error("s.lotteryStatis error(%v)", err) } return } avs, err := s.GetArchiveStatis(c, table, query) if err != nil { log.Error("s.GetArchiveStatis error(%v)", err) return } data = archiveStatis(avs, from, to, groupType) return } func archiveStatis(avs []*model.ArchiveStatis, from, to time.Time, groupType int) interface{} { avsMap := make(map[string]*model.ArchiveStatis) ctgyMap := make(map[string]bool) for _, av := range avs { date := formatDateByGroup(av.CDate.Time(), groupType) ctgykey := date + strconv.FormatInt(av.CategroyID, 10) if val, ok := avsMap[date]; ok { val.Avs += av.Avs if !ctgyMap[ctgykey] { val.Income += av.Income ctgyMap[ctgykey] = true } } else { avsMap[date] = &model.ArchiveStatis{ Avs: av.Avs, Income: av.Income, } ctgyMap[ctgykey] = true } } return parseArchiveStatis(avsMap, from, to, groupType) } func parseArchiveStatis(avsMap map[string]*model.ArchiveStatis, from, to time.Time, groupType int) interface{} { income, counts, xAxis := []string{}, []int64{}, []string{} // get result by date to = to.AddDate(0, 0, 1) for from.Before(to) { dateStr := formatDateByGroup(from, groupType) xAxis = append(xAxis, dateStr) if val, ok := avsMap[dateStr]; ok { income = append(income, fmt.Sprintf("%.2f", float64(val.Income)/float64(100))) counts = append(counts, val.Avs) } else { income = append(income, "0") counts = append(counts, int64(0)) } from = addDayByGroup(groupType, from) } return map[string]interface{}{ "counts": counts, "incomes": income, "xaxis": xAxis, } } // ArchiveSection get av/column income section func (s *Service) ArchiveSection(c context.Context, categoryID []int64, typ, groupType int, fromTime, toTime int64) (data interface{}, err error) { table := setArchiveTableByGroup(typ, groupType) from := getDateByGroup(groupType, time.Unix(fromTime, 0)) to := getDateByGroup(groupType, time.Unix(toTime, 0)) query := formatArchiveQuery(categoryID, from, to) avs, err := s.GetArchiveStatis(c, table, query) if err != nil { log.Error("s.GetArchiveStatis error(%v)", err) return } data = archiveSection(avs, from, to, groupType) return } func archiveSection(avs []*model.ArchiveStatis, from, to time.Time, groupType int) interface{} { ret := make([]map[string]interface{}, 0) avsMap := make(map[string][]int64) for _, av := range avs { date := formatDateByGroup(av.CDate.Time(), groupType) if val, ok := avsMap[date]; ok { val[av.MoneySection] += av.Avs } else { avsMap[date] = make([]int64, 12) avsMap[date][av.MoneySection] = av.Avs ret = append(ret, map[string]interface{}{ "date_format": date, "sections": avsMap[date], }) } } return ret } // ArchiveDetail archive detail (av column) func (s *Service) ArchiveDetail(c context.Context, mid int64, typ, groupType int, fromTime, toTime int64) (archives []*model.ArchiveIncome, err error) { archives = make([]*model.ArchiveIncome, 0) from := getDateByGroup(groupType, time.Unix(fromTime, 0)) to := getDateByGroup(groupType, time.Unix(toTime, 0)) to = addDayByGroup(groupType, to).AddDate(0, 0, -1) if typ == _video || typ == _up { var avs []*model.ArchiveIncome avs, err = s.archiveDetail(c, _video, groupType, mid, from, to) if err != nil { log.Error("s.archiveDetail error(%v)", err) return } archives = append(archives, avs...) } if typ == _column || typ == _up { var columns []*model.ArchiveIncome columns, err = s.archiveDetail(c, _column, groupType, mid, from, to) if err != nil { log.Error("s.archiveDetail error(%v)", err) return } archives = append(archives, columns...) } if typ == _bgm || typ == _up { var bgms []*model.ArchiveIncome bgms, err = s.archiveDetail(c, _bgm, groupType, mid, from, to) if err != nil { log.Error("s.archiveDetail error(%v)", err) return } archives = append(archives, bgms...) } return } func (s *Service) archiveDetail(c context.Context, typ, groupType int, mid int64, from, to time.Time) (archives []*model.ArchiveIncome, err error) { archives = make([]*model.ArchiveIncome, 0) query := fmt.Sprintf("mid = %d", mid) origins, err := s.GetArchiveIncome(c, typ, query, from.Format(_layout), to.Format(_layout)) if err != nil { log.Error("s.GetArchiveIncome error(%v)", err) return } var black map[int64]struct{} black, err = s.dao.GetAvBlackListByMID(c, mid, typ) if err != nil { log.Error("s.dao.GetAvBlackListByMID error(%v)", err) return } archives = calArchiveDetail(origins, black, groupType) return } func calArchiveDetail(archives []*model.ArchiveIncome, blackMap map[int64]struct{}, groupType int) []*model.ArchiveIncome { avsMap := make(map[string]*model.ArchiveIncome) for _, av := range archives { if _, ok := blackMap[av.AvID]; ok { continue } date := formatDateByGroup(av.Date.Time(), groupType) key := date + strconv.FormatInt(av.AvID, 10) if val, ok := avsMap[key]; ok { val.Income += av.Income } else { av.DateFormat = date avsMap[key] = av } } list := make([]*model.ArchiveIncome, 0) for _, av := range avsMap { list = append(list, av) } sort.Slice(list, func(i, j int) bool { if list[i].DateFormat == list[j].DateFormat { return list[i].Income > list[j].Income } return list[i].DateFormat > list[j].DateFormat }) return list } // ArchiveTop archive_income top func (s *Service) ArchiveTop(c context.Context, aIDs []int64, typ int, groupType int, fromTime, toTime int64, from, limit int) (data []*model.ArchiveIncome, total int, err error) { query := "" if len(aIDs) != 0 { switch typ { case _video, _lottery: query = fmt.Sprintf("av_id IN (%s)", xstr.JoinInts(aIDs)) case _column: query = fmt.Sprintf("aid IN (%s)", xstr.JoinInts(aIDs)) case _bgm: query = fmt.Sprintf("sid IN (%s)", xstr.JoinInts(aIDs)) } } if query == "" && typ != _lottery { query = fmt.Sprintf("income >= %d", _leastAvIncome) } avs, err := s.GetArchiveIncome(c, typ, query, time.Unix(fromTime, 0).Format(_layout), time.Unix(toTime, 0).Format(_layout)) if err != nil { log.Error("s.GetArchiveIncome error(%v)", err) return } if typ == _lottery { typ = _video } avBMap, err := s.GetAvBlackListByAvIds(c, avs, typ) if err != nil { log.Error("s.GetAvBlackListByAvIds error(%v)", err) return } data, total = archiveTop(avs, avBMap, from, limit) upInfo, err := s.GetUpInfoByAIDs(c, data) if err != nil { log.Error("s.GetUpInfoByAIDs error(%v)", err) return } for i := 0; i < len(data); i++ { data[i].Nickname = upInfo[data[i].MID] } return } func archiveTop(avs []*model.ArchiveIncome, avBlack map[int64]struct{}, from, limit int) ([]*model.ArchiveIncome, int) { nAvs := make([]*model.ArchiveIncome, 0) for _, av := range avs { if _, ok := avBlack[av.AvID]; ok { continue } av.DateFormat = av.Date.Time().Format(_layout) nAvs = append(nAvs, av) } sort.Slice(nAvs, func(i, j int) bool { if nAvs[i].Date == nAvs[j].Date { return nAvs[i].Income > nAvs[j].Income } return nAvs[i].Date > nAvs[j].Date }) if limit+from > len(nAvs) { limit = len(nAvs) } total := len(nAvs) return nAvs[from:limit], total } // BgmDetail bgm detail func (s *Service) BgmDetail(c context.Context, sid int64, fromTime, toTime int64, from, limit int) (avs []*model.ArchiveIncome, total int, err error) { avs = make([]*model.ArchiveIncome, 0) fromDate := time.Unix(fromTime, 0).Format(_layout) toDate := time.Unix(toTime, 0).Format(_layout) avMap, err := s.dao.GetAvByBgm(c, sid, fromDate, toDate) if err != nil { log.Error("s.dao.GetAvByBgm error(%v)", err) return } if len(avMap) == 0 { return } avIDs := make([]int64, 0, len(avMap)) for avID := range avMap { avIDs = append(avIDs, avID) } avs, err = s.GetArchiveIncome(c, _video, fmt.Sprintf("av_id in (%s)", xstr.JoinInts(avIDs)), fromDate, toDate) if err != nil { log.Error("s.GetArchiveIncome error(%v)", err) return } if limit > len(avs) { limit = len(avs) } total = len(avs) avs = avs[from:limit] return } // GetArchiveStatis get up income func (s *Service) GetArchiveStatis(c context.Context, table, query string) (avs []*model.ArchiveStatis, err error) { offset, size := 0, 2000 for { av, err := s.dao.GetArchiveStatis(c, table, query, offset, size) if err != nil { return nil, err } avs = append(avs, av...) if len(av) < size { break } offset += len(av) } return } // GetArchiveIncome get archive income func (s *Service) GetArchiveIncome(c context.Context, typ int, query string, from, to string) (archs []*model.ArchiveIncome, err error) { var id int64 limit := 2000 for { var arch []*model.ArchiveIncome arch, err = s.dao.GetArchiveIncome(c, id, query, from, to, limit, typ) if err != nil { return } archs = append(archs, arch...) if len(arch) < limit { break } id = arch[len(arch)-1].ID } if typ == _bgm { bgms := make(map[string]*model.ArchiveIncome) for _, bgm := range archs { key := bgm.Date.Time().Format(_layout) + strconv.FormatInt(bgm.AvID, 10) if b, ok := bgms[key]; !ok { bgms[key] = bgm } else { b.Income += bgm.Income b.TotalIncome += bgm.TotalIncome b.TaxMoney += bgm.TaxMoney } bgms[key].Avs++ } archs = make([]*model.ArchiveIncome, 0, len(bgms)) for _, b := range bgms { archs = append(archs, b) } } return } func formatDateByGroup(date time.Time, groupType int) string { str := "" if groupType == _groupWeek { date = getStartWeekDate(date) str = date.Format(_layout) + "~" + date.AddDate(0, 0, 6).Format(_layout) } else if groupType == _groupMonth { date = getStartMonthDate(date) str = date.Format(_layoutMonth) } else { str = date.Format(_layout) } return str } func formatArchiveQuery(categoryID []int64, from, to time.Time) string { query := "cdate >= '" + from.Format(_layout) + "'" query += " AND " query += "cdate <= '" + to.Format(_layout) + "'" if len(categoryID) != 0 { query += " AND " query += "category_id in (" + xstr.JoinInts(categoryID) + ")" } return query }