You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
8.6 KiB
272 lines
8.6 KiB
package income |
|
|
|
import ( |
|
"bytes" |
|
"context" |
|
"fmt" |
|
"math" |
|
"strconv" |
|
"time" |
|
|
|
incomeD "go-common/app/job/main/growup/dao/income" |
|
model "go-common/app/job/main/growup/model/income" |
|
|
|
"go-common/library/log" |
|
xtime "go-common/library/time" |
|
) |
|
|
|
var ( |
|
_avIncomeDailyStatis = "av_income_daily_statis" |
|
_avIncomeWeeklyStatis = "av_income_weekly_statis" |
|
_avIncomeMonthlyStatis = "av_income_monthly_statis" |
|
|
|
_cmIncomeDailyStatis = "column_income_daily_statis" |
|
_cmIncomeWeeklyStatis = "column_income_weekly_statis" |
|
_cmIncomeMonthlyStatis = "column_income_monthly_statis" |
|
|
|
_bgmIncomeDailyStatis = "bgm_income_daily_statis" |
|
_bgmIncomeWeeklyStatis = "bgm_income_weekly_statis" |
|
_bgmIncomeMonthlyStatis = "bgm_income_monthly_statis" |
|
) |
|
|
|
// SectionEntries section entries |
|
type SectionEntries struct { |
|
avDaily []*model.DateStatis |
|
avWeekly []*model.DateStatis |
|
avMonthly []*model.DateStatis |
|
} |
|
|
|
// DateStatis income date statistics |
|
type DateStatis struct { |
|
dao *incomeD.Dao |
|
} |
|
|
|
// NewDateStatis new income date statistics service |
|
func NewDateStatis(dao *incomeD.Dao) *DateStatis { |
|
return &DateStatis{dao: dao} |
|
} |
|
|
|
func initIncomeSections(income, tagID int64, date xtime.Time) []*model.DateStatis { |
|
incomeSections := make([]*model.DateStatis, 12) |
|
incomeSections[0] = initIncomeSection(0, 1, 0, income, tagID, date) |
|
incomeSections[1] = initIncomeSection(1, 5, 1, income, tagID, date) |
|
incomeSections[2] = initIncomeSection(5, 10, 2, income, tagID, date) |
|
incomeSections[3] = initIncomeSection(10, 30, 3, income, tagID, date) |
|
incomeSections[4] = initIncomeSection(30, 50, 4, income, tagID, date) |
|
incomeSections[5] = initIncomeSection(50, 100, 5, income, tagID, date) |
|
incomeSections[6] = initIncomeSection(100, 200, 6, income, tagID, date) |
|
incomeSections[7] = initIncomeSection(200, 500, 7, income, tagID, date) |
|
incomeSections[8] = initIncomeSection(500, 1000, 8, income, tagID, date) |
|
incomeSections[9] = initIncomeSection(1000, 3000, 9, income, tagID, date) |
|
incomeSections[10] = initIncomeSection(3000, 5000, 10, income, tagID, date) |
|
incomeSections[11] = initIncomeSection(5000, math.MaxInt32, 11, income, tagID, date) |
|
return incomeSections |
|
} |
|
|
|
func initIncomeSection(min, max, section, income, tagID int64, date xtime.Time) *model.DateStatis { |
|
var tips string |
|
if max == math.MaxInt32 { |
|
tips = fmt.Sprintf("\"%d+\"", min) |
|
} else { |
|
tips = fmt.Sprintf("\"%d~%d\"", min, max) |
|
} |
|
return &model.DateStatis{ |
|
MinIncome: min, |
|
MaxIncome: max, |
|
MoneySection: section, |
|
MoneyTips: tips, |
|
Income: income, |
|
CategoryID: tagID, |
|
CDate: date, |
|
} |
|
} |
|
|
|
func (s *DateStatis) handleDateStatis(c context.Context, archiveCh chan []*model.ArchiveIncome, date time.Time, table string) (incomeSections []*model.DateStatis, err error) { |
|
// delete |
|
if table != "" { |
|
_, err = s.dao.DelIncomeStatisTable(c, table, date.Format(_layout)) |
|
if err != nil { |
|
log.Error("s.dao.DelIncomeStatisTable error(%v)", err) |
|
return |
|
} |
|
} |
|
// add |
|
incomeSections = s.handleArchives(c, archiveCh, date) |
|
return |
|
} |
|
|
|
// handleArchives handle archive_income_daily_statis, archive_income_weekly_statis, archive_income_monthly_statis |
|
func (s *DateStatis) handleArchives(c context.Context, archiveCh chan []*model.ArchiveIncome, date time.Time) (incomeSections []*model.DateStatis) { |
|
archTagMap := make(map[int64]map[int64]int64) // key TagID, value map[int64]int64 -> key aid, value income |
|
tagIncomeMap := make(map[int64]int64) // key TagID, value TagID total income |
|
for archive := range archiveCh { |
|
handleArchive(archive, archTagMap, tagIncomeMap, date) |
|
} |
|
incomeSections = make([]*model.DateStatis, 0) |
|
for tagID, avMap := range archTagMap { |
|
incomeSection := countIncomeDailyStatis(avMap, tagIncomeMap[tagID], tagID, date) |
|
incomeSections = append(incomeSections, incomeSection...) |
|
} |
|
return |
|
} |
|
|
|
func handleArchive(archives []*model.ArchiveIncome, archTagMap map[int64]map[int64]int64, tagIncomeMap map[int64]int64, startDate time.Time) { |
|
if archives == nil { |
|
return |
|
} |
|
if archTagMap == nil { |
|
archTagMap = make(map[int64]map[int64]int64) |
|
} |
|
if tagIncomeMap == nil { |
|
tagIncomeMap = make(map[int64]int64) |
|
} |
|
|
|
for _, archive := range archives { |
|
if !startDate.After(archive.Date.Time()) { |
|
tagIncomeMap[archive.TagID] += archive.Income |
|
if _, ok := archTagMap[archive.TagID]; !ok { |
|
archTagMap[archive.TagID] = make(map[int64]int64) |
|
} |
|
archTagMap[archive.TagID][archive.AID] += archive.Income |
|
} |
|
} |
|
} |
|
|
|
func (s *DateStatis) handleDateUp(c context.Context, upStatisCh chan []*model.UpIncome, date time.Time) (upSections, upAvSections, upCmSections, upBgmSections []*model.DateStatis, err error) { |
|
_, err = s.dao.DelIncomeStatisTable(c, "up_income_daily_statis", date.Format(_layout)) |
|
if err != nil { |
|
log.Error("s.dao.DelIncomeStatisTable error(%v)", err) |
|
return |
|
} |
|
|
|
_, err = s.dao.DelIncomeStatisTable(c, "up_av_daily_statis", date.Format(_layout)) |
|
if err != nil { |
|
log.Error("s.dao.DelIncomeStatisTable error(%v)", err) |
|
return |
|
} |
|
|
|
_, err = s.dao.DelIncomeStatisTable(c, "up_column_daily_statis", date.Format(_layout)) |
|
if err != nil { |
|
log.Error("s.dao.DelIncomeStatisTable error(%v)", err) |
|
return |
|
} |
|
|
|
_, err = s.dao.DelIncomeStatisTable(c, "up_bgm_daily_statis", date.Format(_layout)) |
|
if err != nil { |
|
log.Error("s.dao.DelIncomeStatisTable error(%v)", err) |
|
return |
|
} |
|
|
|
upMap := make(map[int64]int64) |
|
upAvMap := make(map[int64]int64) |
|
upCmMap := make(map[int64]int64) |
|
upBgmMap := make(map[int64]int64) |
|
var upTotal, avTotal, cmTotal, bgmTotal int64 |
|
for up := range upStatisCh { |
|
up, av, cm, bgm := handleUp(up, upMap, upAvMap, upCmMap, upBgmMap, date) |
|
upTotal += up |
|
avTotal += av |
|
cmTotal += cm |
|
bgmTotal += bgm |
|
} |
|
upSections = countIncomeDailyStatis(upMap, upTotal, 0, date) |
|
upAvSections = countIncomeDailyStatis(upAvMap, avTotal, 0, date) |
|
upCmSections = countIncomeDailyStatis(upCmMap, cmTotal, 0, date) |
|
upBgmSections = countIncomeDailyStatis(upBgmMap, bgmTotal, 0, date) |
|
return |
|
} |
|
|
|
func handleUp(upIncomes []*model.UpIncome, upMap, upAvMap, upCmMap, upBgmMap map[int64]int64, startDate time.Time) (income, avIncome, cmIncome, bgmIncome int64) { |
|
if len(upIncomes) == 0 { |
|
return |
|
} |
|
for _, upIncome := range upIncomes { |
|
if startDate.Equal(upIncome.Date.Time()) { |
|
income += upIncome.Income |
|
avIncome += upIncome.AvIncome |
|
cmIncome += upIncome.ColumnIncome |
|
bgmIncome += upIncome.BgmIncome |
|
upMap[upIncome.MID] += upIncome.Income |
|
if upIncome.AvIncome > 0 { |
|
upAvMap[upIncome.MID] += upIncome.AvIncome |
|
} |
|
if upIncome.ColumnIncome > 0 { |
|
upCmMap[upIncome.MID] += upIncome.ColumnIncome |
|
} |
|
if upIncome.BgmIncome > 0 { |
|
upBgmMap[upIncome.MID] += upIncome.BgmIncome |
|
} |
|
} |
|
} |
|
return |
|
} |
|
|
|
func (s *DateStatis) incomeDateStatisInsert(c context.Context, incomeSection []*model.DateStatis, table string) (rows int64, err error) { |
|
var buf bytes.Buffer |
|
for _, row := range incomeSection { |
|
buf.WriteString("(") |
|
buf.WriteString(strconv.FormatInt(row.Count, 10)) |
|
buf.WriteByte(',') |
|
buf.WriteString(strconv.FormatInt(row.MoneySection, 10)) |
|
buf.WriteByte(',') |
|
buf.WriteString(row.MoneyTips) |
|
buf.WriteByte(',') |
|
buf.WriteString(strconv.FormatInt(row.Income, 10)) |
|
buf.WriteByte(',') |
|
buf.WriteString(strconv.FormatInt(row.CategoryID, 10)) |
|
buf.WriteByte(',') |
|
buf.WriteString("'" + row.CDate.Time().Format(_layout) + "'") |
|
buf.WriteString(")") |
|
buf.WriteByte(',') |
|
} |
|
|
|
if buf.Len() > 0 { |
|
buf.Truncate(buf.Len() - 1) |
|
} |
|
vals := buf.String() |
|
buf.Reset() |
|
rows, err = s.dao.InsertIncomeStatisTable(c, table, vals) |
|
return |
|
} |
|
|
|
func countIncomeDailyStatis(incomes map[int64]int64, totalIncome, tagID int64, date time.Time) (incomeSections []*model.DateStatis) { |
|
if len(incomes) == 0 { |
|
return |
|
} |
|
incomeSections = initIncomeSections(totalIncome, tagID, xtime.Time(date.Unix())) |
|
for _, income := range incomes { |
|
for _, section := range incomeSections { |
|
min, max := section.MinIncome*100, section.MaxIncome*100 |
|
if income >= min && income < max { |
|
section.Count++ |
|
} |
|
} |
|
} |
|
return |
|
} |
|
|
|
func (s *DateStatis) upIncomeDailyStatisInsert(c context.Context, upIncomeSection []*model.DateStatis, table string) (rows int64, err error) { |
|
var buf bytes.Buffer |
|
for _, row := range upIncomeSection { |
|
buf.WriteString("(") |
|
buf.WriteString(strconv.FormatInt(row.Count, 10)) |
|
buf.WriteByte(',') |
|
buf.WriteString(strconv.FormatInt(row.MoneySection, 10)) |
|
buf.WriteByte(',') |
|
buf.WriteString(row.MoneyTips) |
|
buf.WriteByte(',') |
|
buf.WriteString(strconv.FormatInt(row.Income, 10)) |
|
buf.WriteByte(',') |
|
buf.WriteString("'" + row.CDate.Time().Format(_layout) + "'") |
|
buf.WriteString(")") |
|
buf.WriteByte(',') |
|
} |
|
|
|
if buf.Len() > 0 { |
|
buf.Truncate(buf.Len() - 1) |
|
} |
|
vals := buf.String() |
|
buf.Reset() |
|
rows, err = s.dao.InsertUpIncomeDailyStatis(c, table, vals) |
|
return |
|
}
|
|
|