archive_income.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. package income
  2. import (
  3. "context"
  4. "fmt"
  5. "sort"
  6. "strconv"
  7. "time"
  8. model "go-common/app/admin/main/growup/model/income"
  9. "go-common/library/log"
  10. "go-common/library/xstr"
  11. )
  12. // ArchiveStatis archive income statis
  13. func (s *Service) ArchiveStatis(c context.Context, categoryID []int64, typ, groupType int, fromTime, toTime int64) (data interface{}, err error) {
  14. table := setArchiveTableByGroup(typ, groupType)
  15. from := getDateByGroup(groupType, time.Unix(fromTime, 0))
  16. to := getDateByGroup(groupType, time.Unix(toTime, 0))
  17. query := formatArchiveQuery(categoryID, from, to)
  18. if typ == _lottery {
  19. data, err = s.lotteryStatis(c, categoryID, from, addDayByGroup(groupType, to).AddDate(0, 0, -1), groupType)
  20. if err != nil {
  21. log.Error("s.lotteryStatis error(%v)", err)
  22. }
  23. return
  24. }
  25. avs, err := s.GetArchiveStatis(c, table, query)
  26. if err != nil {
  27. log.Error("s.GetArchiveStatis error(%v)", err)
  28. return
  29. }
  30. data = archiveStatis(avs, from, to, groupType)
  31. return
  32. }
  33. func archiveStatis(avs []*model.ArchiveStatis, from, to time.Time, groupType int) interface{} {
  34. avsMap := make(map[string]*model.ArchiveStatis)
  35. ctgyMap := make(map[string]bool)
  36. for _, av := range avs {
  37. date := formatDateByGroup(av.CDate.Time(), groupType)
  38. ctgykey := date + strconv.FormatInt(av.CategroyID, 10)
  39. if val, ok := avsMap[date]; ok {
  40. val.Avs += av.Avs
  41. if !ctgyMap[ctgykey] {
  42. val.Income += av.Income
  43. ctgyMap[ctgykey] = true
  44. }
  45. } else {
  46. avsMap[date] = &model.ArchiveStatis{
  47. Avs: av.Avs,
  48. Income: av.Income,
  49. }
  50. ctgyMap[ctgykey] = true
  51. }
  52. }
  53. return parseArchiveStatis(avsMap, from, to, groupType)
  54. }
  55. func parseArchiveStatis(avsMap map[string]*model.ArchiveStatis, from, to time.Time, groupType int) interface{} {
  56. income, counts, xAxis := []string{}, []int64{}, []string{}
  57. // get result by date
  58. to = to.AddDate(0, 0, 1)
  59. for from.Before(to) {
  60. dateStr := formatDateByGroup(from, groupType)
  61. xAxis = append(xAxis, dateStr)
  62. if val, ok := avsMap[dateStr]; ok {
  63. income = append(income, fmt.Sprintf("%.2f", float64(val.Income)/float64(100)))
  64. counts = append(counts, val.Avs)
  65. } else {
  66. income = append(income, "0")
  67. counts = append(counts, int64(0))
  68. }
  69. from = addDayByGroup(groupType, from)
  70. }
  71. return map[string]interface{}{
  72. "counts": counts,
  73. "incomes": income,
  74. "xaxis": xAxis,
  75. }
  76. }
  77. // ArchiveSection get av/column income section
  78. func (s *Service) ArchiveSection(c context.Context, categoryID []int64, typ, groupType int, fromTime, toTime int64) (data interface{}, err error) {
  79. table := setArchiveTableByGroup(typ, groupType)
  80. from := getDateByGroup(groupType, time.Unix(fromTime, 0))
  81. to := getDateByGroup(groupType, time.Unix(toTime, 0))
  82. query := formatArchiveQuery(categoryID, from, to)
  83. avs, err := s.GetArchiveStatis(c, table, query)
  84. if err != nil {
  85. log.Error("s.GetArchiveStatis error(%v)", err)
  86. return
  87. }
  88. data = archiveSection(avs, from, to, groupType)
  89. return
  90. }
  91. func archiveSection(avs []*model.ArchiveStatis, from, to time.Time, groupType int) interface{} {
  92. ret := make([]map[string]interface{}, 0)
  93. avsMap := make(map[string][]int64)
  94. for _, av := range avs {
  95. date := formatDateByGroup(av.CDate.Time(), groupType)
  96. if val, ok := avsMap[date]; ok {
  97. val[av.MoneySection] += av.Avs
  98. } else {
  99. avsMap[date] = make([]int64, 12)
  100. avsMap[date][av.MoneySection] = av.Avs
  101. ret = append(ret, map[string]interface{}{
  102. "date_format": date,
  103. "sections": avsMap[date],
  104. })
  105. }
  106. }
  107. return ret
  108. }
  109. // ArchiveDetail archive detail (av column)
  110. func (s *Service) ArchiveDetail(c context.Context, mid int64, typ, groupType int, fromTime, toTime int64) (archives []*model.ArchiveIncome, err error) {
  111. archives = make([]*model.ArchiveIncome, 0)
  112. from := getDateByGroup(groupType, time.Unix(fromTime, 0))
  113. to := getDateByGroup(groupType, time.Unix(toTime, 0))
  114. to = addDayByGroup(groupType, to).AddDate(0, 0, -1)
  115. if typ == _video || typ == _up {
  116. var avs []*model.ArchiveIncome
  117. avs, err = s.archiveDetail(c, _video, groupType, mid, from, to)
  118. if err != nil {
  119. log.Error("s.archiveDetail error(%v)", err)
  120. return
  121. }
  122. archives = append(archives, avs...)
  123. }
  124. if typ == _column || typ == _up {
  125. var columns []*model.ArchiveIncome
  126. columns, err = s.archiveDetail(c, _column, groupType, mid, from, to)
  127. if err != nil {
  128. log.Error("s.archiveDetail error(%v)", err)
  129. return
  130. }
  131. archives = append(archives, columns...)
  132. }
  133. if typ == _bgm || typ == _up {
  134. var bgms []*model.ArchiveIncome
  135. bgms, err = s.archiveDetail(c, _bgm, groupType, mid, from, to)
  136. if err != nil {
  137. log.Error("s.archiveDetail error(%v)", err)
  138. return
  139. }
  140. archives = append(archives, bgms...)
  141. }
  142. return
  143. }
  144. func (s *Service) archiveDetail(c context.Context, typ, groupType int, mid int64, from, to time.Time) (archives []*model.ArchiveIncome, err error) {
  145. archives = make([]*model.ArchiveIncome, 0)
  146. query := fmt.Sprintf("mid = %d", mid)
  147. origins, err := s.GetArchiveIncome(c, typ, query, from.Format(_layout), to.Format(_layout))
  148. if err != nil {
  149. log.Error("s.GetArchiveIncome error(%v)", err)
  150. return
  151. }
  152. var black map[int64]struct{}
  153. black, err = s.dao.GetAvBlackListByMID(c, mid, typ)
  154. if err != nil {
  155. log.Error("s.dao.GetAvBlackListByMID error(%v)", err)
  156. return
  157. }
  158. archives = calArchiveDetail(origins, black, groupType)
  159. return
  160. }
  161. func calArchiveDetail(archives []*model.ArchiveIncome, blackMap map[int64]struct{}, groupType int) []*model.ArchiveIncome {
  162. avsMap := make(map[string]*model.ArchiveIncome)
  163. for _, av := range archives {
  164. if _, ok := blackMap[av.AvID]; ok {
  165. continue
  166. }
  167. date := formatDateByGroup(av.Date.Time(), groupType)
  168. key := date + strconv.FormatInt(av.AvID, 10)
  169. if val, ok := avsMap[key]; ok {
  170. val.Income += av.Income
  171. } else {
  172. av.DateFormat = date
  173. avsMap[key] = av
  174. }
  175. }
  176. list := make([]*model.ArchiveIncome, 0)
  177. for _, av := range avsMap {
  178. list = append(list, av)
  179. }
  180. sort.Slice(list, func(i, j int) bool {
  181. if list[i].DateFormat == list[j].DateFormat {
  182. return list[i].Income > list[j].Income
  183. }
  184. return list[i].DateFormat > list[j].DateFormat
  185. })
  186. return list
  187. }
  188. // ArchiveTop archive_income top
  189. 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) {
  190. query := ""
  191. if len(aIDs) != 0 {
  192. switch typ {
  193. case _video, _lottery:
  194. query = fmt.Sprintf("av_id IN (%s)", xstr.JoinInts(aIDs))
  195. case _column:
  196. query = fmt.Sprintf("aid IN (%s)", xstr.JoinInts(aIDs))
  197. case _bgm:
  198. query = fmt.Sprintf("sid IN (%s)", xstr.JoinInts(aIDs))
  199. }
  200. }
  201. if query == "" && typ != _lottery {
  202. query = fmt.Sprintf("income >= %d", _leastAvIncome)
  203. }
  204. avs, err := s.GetArchiveIncome(c, typ, query, time.Unix(fromTime, 0).Format(_layout), time.Unix(toTime, 0).Format(_layout))
  205. if err != nil {
  206. log.Error("s.GetArchiveIncome error(%v)", err)
  207. return
  208. }
  209. if typ == _lottery {
  210. typ = _video
  211. }
  212. avBMap, err := s.GetAvBlackListByAvIds(c, avs, typ)
  213. if err != nil {
  214. log.Error("s.GetAvBlackListByAvIds error(%v)", err)
  215. return
  216. }
  217. data, total = archiveTop(avs, avBMap, from, limit)
  218. upInfo, err := s.GetUpInfoByAIDs(c, data)
  219. if err != nil {
  220. log.Error("s.GetUpInfoByAIDs error(%v)", err)
  221. return
  222. }
  223. for i := 0; i < len(data); i++ {
  224. data[i].Nickname = upInfo[data[i].MID]
  225. }
  226. return
  227. }
  228. func archiveTop(avs []*model.ArchiveIncome, avBlack map[int64]struct{}, from, limit int) ([]*model.ArchiveIncome, int) {
  229. nAvs := make([]*model.ArchiveIncome, 0)
  230. for _, av := range avs {
  231. if _, ok := avBlack[av.AvID]; ok {
  232. continue
  233. }
  234. av.DateFormat = av.Date.Time().Format(_layout)
  235. nAvs = append(nAvs, av)
  236. }
  237. sort.Slice(nAvs, func(i, j int) bool {
  238. if nAvs[i].Date == nAvs[j].Date {
  239. return nAvs[i].Income > nAvs[j].Income
  240. }
  241. return nAvs[i].Date > nAvs[j].Date
  242. })
  243. if limit+from > len(nAvs) {
  244. limit = len(nAvs)
  245. }
  246. total := len(nAvs)
  247. return nAvs[from:limit], total
  248. }
  249. // BgmDetail bgm detail
  250. func (s *Service) BgmDetail(c context.Context, sid int64, fromTime, toTime int64, from, limit int) (avs []*model.ArchiveIncome, total int, err error) {
  251. avs = make([]*model.ArchiveIncome, 0)
  252. fromDate := time.Unix(fromTime, 0).Format(_layout)
  253. toDate := time.Unix(toTime, 0).Format(_layout)
  254. avMap, err := s.dao.GetAvByBgm(c, sid, fromDate, toDate)
  255. if err != nil {
  256. log.Error("s.dao.GetAvByBgm error(%v)", err)
  257. return
  258. }
  259. if len(avMap) == 0 {
  260. return
  261. }
  262. avIDs := make([]int64, 0, len(avMap))
  263. for avID := range avMap {
  264. avIDs = append(avIDs, avID)
  265. }
  266. avs, err = s.GetArchiveIncome(c, _video, fmt.Sprintf("av_id in (%s)", xstr.JoinInts(avIDs)), fromDate, toDate)
  267. if err != nil {
  268. log.Error("s.GetArchiveIncome error(%v)", err)
  269. return
  270. }
  271. if limit > len(avs) {
  272. limit = len(avs)
  273. }
  274. total = len(avs)
  275. avs = avs[from:limit]
  276. return
  277. }
  278. // GetArchiveStatis get up income
  279. func (s *Service) GetArchiveStatis(c context.Context, table, query string) (avs []*model.ArchiveStatis, err error) {
  280. offset, size := 0, 2000
  281. for {
  282. av, err := s.dao.GetArchiveStatis(c, table, query, offset, size)
  283. if err != nil {
  284. return nil, err
  285. }
  286. avs = append(avs, av...)
  287. if len(av) < size {
  288. break
  289. }
  290. offset += len(av)
  291. }
  292. return
  293. }
  294. // GetArchiveIncome get archive income
  295. func (s *Service) GetArchiveIncome(c context.Context, typ int, query string, from, to string) (archs []*model.ArchiveIncome, err error) {
  296. var id int64
  297. limit := 2000
  298. for {
  299. var arch []*model.ArchiveIncome
  300. arch, err = s.dao.GetArchiveIncome(c, id, query, from, to, limit, typ)
  301. if err != nil {
  302. return
  303. }
  304. archs = append(archs, arch...)
  305. if len(arch) < limit {
  306. break
  307. }
  308. id = arch[len(arch)-1].ID
  309. }
  310. if typ == _bgm {
  311. bgms := make(map[string]*model.ArchiveIncome)
  312. for _, bgm := range archs {
  313. key := bgm.Date.Time().Format(_layout) + strconv.FormatInt(bgm.AvID, 10)
  314. if b, ok := bgms[key]; !ok {
  315. bgms[key] = bgm
  316. } else {
  317. b.Income += bgm.Income
  318. b.TotalIncome += bgm.TotalIncome
  319. b.TaxMoney += bgm.TaxMoney
  320. }
  321. bgms[key].Avs++
  322. }
  323. archs = make([]*model.ArchiveIncome, 0, len(bgms))
  324. for _, b := range bgms {
  325. archs = append(archs, b)
  326. }
  327. }
  328. return
  329. }
  330. func formatDateByGroup(date time.Time, groupType int) string {
  331. str := ""
  332. if groupType == _groupWeek {
  333. date = getStartWeekDate(date)
  334. str = date.Format(_layout) + "~" + date.AddDate(0, 0, 6).Format(_layout)
  335. } else if groupType == _groupMonth {
  336. date = getStartMonthDate(date)
  337. str = date.Format(_layoutMonth)
  338. } else {
  339. str = date.Format(_layout)
  340. }
  341. return str
  342. }
  343. func formatArchiveQuery(categoryID []int64, from, to time.Time) string {
  344. query := "cdate >= '" + from.Format(_layout) + "'"
  345. query += " AND "
  346. query += "cdate <= '" + to.Format(_layout) + "'"
  347. if len(categoryID) != 0 {
  348. query += " AND "
  349. query += "category_id in (" + xstr.JoinInts(categoryID) + ")"
  350. }
  351. return query
  352. }