income.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834
  1. package service
  2. import (
  3. "context"
  4. "crypto/md5"
  5. "encoding/json"
  6. "fmt"
  7. "io/ioutil"
  8. "net/http"
  9. "sort"
  10. "strconv"
  11. "time"
  12. "go-common/app/interface/main/growup/model"
  13. "go-common/library/log"
  14. xtime "go-common/library/time"
  15. "go-common/library/xstr"
  16. )
  17. const (
  18. _video = iota
  19. _audio
  20. _column
  21. _bgm
  22. _up
  23. )
  24. var (
  25. _layout = "2006-01-02"
  26. )
  27. // GetUpCharge get up daily sum(charge) last 30 days
  28. func (s *Service) GetUpCharge(c context.Context, mid int64, t time.Time) (total int, err error) {
  29. begin := t.AddDate(0, 0, -30).Format(_layout)
  30. incs, err := s.dao.GetUpDailyCharge(c, mid, begin)
  31. if err != nil {
  32. return
  33. }
  34. for _, inc := range incs {
  35. total += inc
  36. }
  37. total = int(float64(total) * float64(0.6))
  38. return
  39. }
  40. // ArchiveIncome get archive income by mid
  41. func (s *Service) ArchiveIncome(c context.Context, mid int64, typ, page, size, all int) (data map[string]interface{}, err error) {
  42. redisKey := fmt.Sprintf("growup-archive-income:%d+%d+%d+%d+%d", typ, mid, all, page, size)
  43. data, err = s.dao.GetIncomeCache(c, redisKey)
  44. if err != nil {
  45. log.Error("s.dao.GetIncomeCache error(%v)", err)
  46. return
  47. }
  48. if data != nil {
  49. return
  50. }
  51. data, err = s.archiveIncome(c, mid, typ, page, size, all)
  52. if err != nil {
  53. log.Error("s.archiveIncome error(%v)", err)
  54. return
  55. }
  56. err = s.dao.SetIncomeCache(c, redisKey, data)
  57. if err != nil {
  58. log.Error("s.dao.SetIncomeCache error(%v)", err)
  59. }
  60. return
  61. }
  62. // archiveIncome get archive income by mid
  63. func (s *Service) archiveIncome(c context.Context, mid int64, typ, page, size, all int) (data map[string]interface{}, err error) {
  64. data = make(map[string]interface{})
  65. if page == 0 {
  66. page = 1
  67. }
  68. start, end := (page-1)*size, page*size
  69. date := time.Now().AddDate(0, 0, -2)
  70. startMonth := time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, time.Local).Format(_layout)
  71. if all == 1 {
  72. startMonth = "2017-12-01"
  73. }
  74. var (
  75. archives []*model.ArchiveIncome
  76. total int
  77. )
  78. switch typ {
  79. case _video:
  80. archives, total, err = s.listAvIncome(c, mid, startMonth, date.Format(_layout), start, end)
  81. case _audio:
  82. case _column:
  83. archives, total, err = s.listColumnIncome(c, mid, startMonth, date.Format(_layout), start, end)
  84. case _bgm:
  85. archives, total, err = s.listBgmIncome(c, mid, startMonth, date.Format(_layout), start, end)
  86. }
  87. if err != nil {
  88. log.Error("s.archiveIncome error(%v)", err)
  89. return nil, err
  90. }
  91. data["data"] = archives
  92. data["total_count"] = total
  93. data["page"] = page
  94. return
  95. }
  96. func (s *Service) listAvIncome(c context.Context, mid int64, startTime, endTime string, start, end int) (archiveList []*model.ArchiveIncome, total int, err error) {
  97. avs, err := s.dao.ListAvIncome(c, mid, startTime, endTime)
  98. if err != nil {
  99. log.Error("s.dao.ListAvIncome error(%v)", err)
  100. return
  101. }
  102. return s.handleArchiveIncome(c, avs, start, end, _video)
  103. }
  104. func (s *Service) listColumnIncome(c context.Context, mid int64, startTime, endTime string, start, end int) (archiveList []*model.ArchiveIncome, total int, err error) {
  105. columns, err := s.dao.ListColumnIncome(c, mid, startTime, endTime)
  106. if err != nil {
  107. log.Error("s.dao.ListColumnIncome error(%v)", err)
  108. return
  109. }
  110. return s.handleArchiveIncome(c, columns, start, end, _column)
  111. }
  112. func (s *Service) listBgmIncome(c context.Context, mid int64, startTime, endTime string, start, end int) (archiveList []*model.ArchiveIncome, total int, err error) {
  113. bgms, err := s.dao.ListBgmIncome(c, mid, startTime, endTime)
  114. if err != nil {
  115. log.Error("s.dao.ListBgmIncome error(%v)", err)
  116. return
  117. }
  118. return s.handleArchiveIncome(c, bgms, start, end, _bgm)
  119. }
  120. func calArchiveIncome(archives []*model.ArchiveIncome, avBMap map[int64]struct{}) (archiveMap map[int64]*model.ArchiveIncome) {
  121. endTime := time.Now().AddDate(0, 0, -2)
  122. archiveMap = make(map[int64]*model.ArchiveIncome)
  123. archMonthIncome := make(map[int64]int64)
  124. for _, arch := range archives {
  125. if _, ok := avBMap[arch.ArchiveID]; ok {
  126. continue
  127. }
  128. archiveDate := arch.Date.Time()
  129. // cal month income
  130. if archiveDate.Month() == endTime.Month() {
  131. archMonthIncome[arch.ArchiveID] += arch.Income
  132. }
  133. if archiveDate.Format(_layout) != endTime.Format(_layout) {
  134. arch.Income = 0
  135. }
  136. if old, ok := archiveMap[arch.ArchiveID]; !ok {
  137. archiveMap[arch.ArchiveID] = arch
  138. } else {
  139. if old.Date < arch.Date {
  140. archiveMap[arch.ArchiveID] = arch
  141. }
  142. }
  143. archiveMap[arch.ArchiveID].MonthIncome = archMonthIncome[arch.ArchiveID]
  144. }
  145. return
  146. }
  147. func (s *Service) handleArchiveIncome(c context.Context, archives []*model.ArchiveIncome, start, end, typ int) (archiveList []*model.ArchiveIncome, total int, err error) {
  148. archiveList = make([]*model.ArchiveIncome, 0)
  149. if len(archives) == 0 {
  150. return
  151. }
  152. aIDMap := make(map[int64]struct{})
  153. aIDList := []int64{}
  154. for _, arch := range archives {
  155. if _, ok := aIDMap[arch.ArchiveID]; !ok {
  156. aIDMap[arch.ArchiveID] = struct{}{}
  157. aIDList = append(aIDList, arch.ArchiveID)
  158. }
  159. }
  160. avBMap, err := s.dao.ListAvBlackList(c, aIDList, typ)
  161. if err != nil {
  162. log.Error("s.dao.ListAvBlackList error(%v)", err)
  163. return
  164. }
  165. avsMap := calArchiveIncome(archives, avBMap)
  166. for _, av := range avsMap {
  167. archiveList = append(archiveList, av)
  168. }
  169. sort.Slice(archiveList, func(i, j int) bool {
  170. if archiveList[i].Income == archiveList[j].Income {
  171. if archiveList[i].MonthIncome == archiveList[j].MonthIncome {
  172. return archiveList[i].TotalIncome > archiveList[j].TotalIncome
  173. }
  174. return archiveList[i].MonthIncome > archiveList[j].MonthIncome
  175. }
  176. return archiveList[i].Income > archiveList[j].Income
  177. })
  178. total = len(archiveList)
  179. if end > total {
  180. end = total
  181. }
  182. if start >= total || start > end {
  183. return
  184. }
  185. archiveList = archiveList[start:end]
  186. avIDs := []int64{}
  187. for _, av := range archiveList {
  188. avIDs = append(avIDs, av.ArchiveID)
  189. }
  190. titles := make(map[int64]string)
  191. switch typ {
  192. case _video:
  193. titles, err = s.getAvTitle(c, avIDs)
  194. if err != nil {
  195. log.Error("s.getAvTitle error(%v)", err)
  196. return
  197. }
  198. case _column:
  199. titles, err = s.getColumnTitle(c, avIDs)
  200. if err != nil {
  201. log.Error("s.getColumnTitle error(%v)", err)
  202. return
  203. }
  204. case _bgm:
  205. titles, err = s.getBgmTitle(c, avIDs)
  206. if err != nil {
  207. log.Error("s.getBgmTitle error(%v)", err)
  208. return
  209. }
  210. }
  211. icons, err := s.getAvIcon(c, avIDs)
  212. if err != nil {
  213. log.Error("s.getAvIcon error(%v)", err)
  214. return
  215. }
  216. breachs, err := s.getAvBreach(c, avIDs, typ)
  217. if err != nil {
  218. log.Error("s.getAvBreach error(%v)", err)
  219. return
  220. }
  221. for _, av := range archiveList {
  222. av.Title = titles[av.ArchiveID]
  223. av.Icon = icons[av.ArchiveID]
  224. av.Breach = breachs[av.ArchiveID]
  225. }
  226. return
  227. }
  228. func (s *Service) getColumnTitle(c context.Context, avs []int64) (titles map[int64]string, err error) {
  229. return s.dao.GetColumnTitle(c, avs)
  230. }
  231. func (s *Service) getBgmTitle(c context.Context, avs []int64) (titles map[int64]string, err error) {
  232. return s.dao.GetBgmTitle(c, avs)
  233. }
  234. func (s *Service) getAvTitle(c context.Context, avs []int64) (titles map[int64]string, err error) {
  235. req, err := http.NewRequest("GET", s.conf.Host.ArchiveURI, nil)
  236. if err != nil {
  237. log.Error("http.NewRequest error(%v)", err)
  238. return
  239. }
  240. q := req.URL.Query()
  241. q.Add("aids", xstr.JoinInts(avs))
  242. q.Add("appkey", s.conf.AppConf.Key)
  243. now := time.Now().Unix()
  244. q.Add("ts", strconv.FormatInt(now, 10))
  245. sign := q.Encode() + s.conf.AppConf.Secret
  246. q.Add("sign", fmt.Sprintf("%x", md5.Sum([]byte(sign))))
  247. req.URL.RawQuery = q.Encode()
  248. resp, err := http.DefaultClient.Do(req)
  249. if err != nil {
  250. log.Error("http.DefaultClient.Do error(%v)", err)
  251. return
  252. }
  253. defer resp.Body.Close()
  254. body, err := ioutil.ReadAll(resp.Body)
  255. if err != nil {
  256. log.Error("ioutil.ReadAll error(%v)", err)
  257. return
  258. }
  259. res := model.ArchiveRes{}
  260. err = json.Unmarshal(body, &res)
  261. if err != nil {
  262. log.Error("json.Unmarshal body %s error(%v)", string(body), err)
  263. return
  264. }
  265. titles = make(map[int64]string)
  266. for _, archive := range res.Data {
  267. titles[archive.AID] = archive.Title
  268. }
  269. return
  270. }
  271. func (s *Service) getAvIcon(c context.Context, avs []int64) (acM map[int64]string, err error) {
  272. if len(avs) == 0 {
  273. return
  274. }
  275. activeM, err := s.dao.ListActiveInfo(c, avs)
  276. if err != nil {
  277. log.Error("s.dao.ListActiveInfo error(%v)", err)
  278. return
  279. }
  280. tagIDM := make(map[int64]struct{})
  281. for _, tagID := range activeM {
  282. tagIDM[tagID] = struct{}{}
  283. }
  284. tagIDList := make([]int64, 0)
  285. for tagID := range tagIDM {
  286. tagIDList = append(tagIDList, tagID)
  287. }
  288. if len(tagIDList) == 0 {
  289. return
  290. }
  291. tagIconM, err := s.dao.ListTagInfo(c, tagIDList)
  292. if err != nil {
  293. log.Error("s.dao.ListTagInfo error(%v)", err)
  294. return
  295. }
  296. acM = make(map[int64]string)
  297. for avID, tagID := range activeM {
  298. if _, ok := tagIconM[tagID]; ok {
  299. acM[avID] = tagIconM[tagID].Icon
  300. }
  301. }
  302. return
  303. }
  304. func (s *Service) getAvBreach(c context.Context, avs []int64, typ int) (breachs map[int64]*model.AvBreach, err error) {
  305. if len(avs) == 0 {
  306. return
  307. }
  308. return s.dao.GetAvBreachs(c, avs, typ)
  309. }
  310. // UpSummary summary up income
  311. func (s *Service) UpSummary(c context.Context, mid int64) (data interface{}, err error) {
  312. redisKey := fmt.Sprintf("growup-up-summary:%d", mid)
  313. res, err := s.dao.GetIncomeCache(c, redisKey)
  314. if err != nil {
  315. log.Error("s.dao.GetIncomeCache error(%v)", err)
  316. return
  317. }
  318. if res != nil {
  319. data = res["data"]
  320. return
  321. }
  322. data, err = s.upSummary(c, mid)
  323. if err != nil {
  324. log.Error("s.upSummary error(%v)", err)
  325. return
  326. }
  327. err = s.dao.SetIncomeCache(c, redisKey, map[string]interface{}{"data": data})
  328. if err != nil {
  329. log.Error("s.dao.SetIncomeCache error(%v)", err)
  330. }
  331. return
  332. }
  333. func (s *Service) upSummary(c context.Context, mid int64) (data interface{}, err error) {
  334. summary := new(struct {
  335. DayIncome string `json:"day_income"`
  336. Date string `json:"date"`
  337. Income string `json:"income"`
  338. TotalIncome string `json:"total_income"`
  339. WaitWithdraw string `json:"wait_withdraw"`
  340. BreachMoney string `json:"breach_money"`
  341. UnwithdrawDate string `json:"unwithdraw_date"`
  342. })
  343. summary.DayIncome, summary.Income, summary.TotalIncome, summary.WaitWithdraw, summary.BreachMoney = "0", "0", "0", "0", "0"
  344. now := time.Now().AddDate(0, 0, -2)
  345. nowMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.Local)
  346. count, err := s.dao.GetUpIncomeCount(c, now.Format(_layout))
  347. if err != nil {
  348. log.Error("s.dao.GetUpIncomeCount error(%v)", err)
  349. return
  350. }
  351. if count <= 0 {
  352. summary.DayIncome, summary.Income, summary.TotalIncome, summary.WaitWithdraw, summary.BreachMoney = "-1", "-1", "-1", "-1", "-1"
  353. data = summary
  354. return
  355. }
  356. upIncomes, err := s.dao.ListUpIncome(c, mid, "up_income", nowMonth.Format(_layout), now.AddDate(0, 0, 1).Format(_layout))
  357. if err != nil {
  358. log.Error("s.dao.ListUpIncome error(%v)", err)
  359. return
  360. }
  361. var monthIncome, lastDayIncome, dayIncome int64
  362. for _, up := range upIncomes {
  363. if up.Date.Time().Format(_layout) == now.Format(_layout) {
  364. dayIncome = up.Income
  365. }
  366. if up.Date.Time().Format(_layout) == now.AddDate(0, 0, 1).Format(_layout) {
  367. lastDayIncome = up.Income
  368. }
  369. monthIncome += up.Income
  370. }
  371. upAccount, err := s.dao.ListUpAccount(c, mid)
  372. if err != nil {
  373. log.Error("s.dao.ListUpAccount error(%v)", err)
  374. return
  375. }
  376. if upAccount == nil {
  377. data = summary
  378. return
  379. }
  380. breachs, err := s.dao.ListAvBreach(c, mid, nowMonth.Format(_layout), time.Now().Format(_layout))
  381. if err != nil {
  382. log.Error("s.dao.ListAvBreach error(%v)", err)
  383. return
  384. }
  385. var breachMoney int64
  386. for _, b := range breachs {
  387. breachMoney += b.Money
  388. }
  389. summary.DayIncome = fmt.Sprintf("%.2f", fromYuanToFen(dayIncome))
  390. summary.BreachMoney = fmt.Sprintf("%.2f", fromYuanToFen(breachMoney))
  391. summary.TotalIncome = fmt.Sprintf("%.2f", fromYuanToFen(upAccount.TotalIncome-lastDayIncome))
  392. summary.Date = now.Format(_layout)
  393. wdv, err := time.Parse("2006-01", upAccount.WithdrawDateVersion)
  394. if err != nil {
  395. log.Error("time.Parse error(%v)", err)
  396. return
  397. }
  398. summary.UnwithdrawDate = time.Date(wdv.Year(), wdv.Month()+1, 1, 0, 0, 0, 0, time.Local).Format("2006-01")
  399. // 如果T-1的month不等于T-2的month 当月新增不需要减去那一天的收入:lastDayIncome = 0
  400. if now.AddDate(0, 0, 1).Month() == now.Month() {
  401. monthIncome -= lastDayIncome
  402. }
  403. summary.Income = fmt.Sprintf("%.2f", fromYuanToFen(monthIncome))
  404. // 当月未提现,待结算不能减去昨天收入,当月已提现,需要减去昨日收入
  405. preMonth := time.Date(nowMonth.Year(), nowMonth.Month()-1, 1, 0, 0, 0, 0, time.Local).Format("2006-01")
  406. if preMonth != upAccount.WithdrawDateVersion || now.AddDate(0, 0, 1).Month() != now.Month() {
  407. lastDayIncome = 0
  408. }
  409. summary.WaitWithdraw = fmt.Sprintf("%.2f", fromYuanToFen(upAccount.TotalUnwithdrawIncome-lastDayIncome))
  410. data = summary
  411. return
  412. }
  413. func fromYuanToFen(income int64) float64 {
  414. return float64(income) / float64(100)
  415. }
  416. // ArchiveSummary get archive summary
  417. func (s *Service) ArchiveSummary(c context.Context, typ int, mid int64) (data interface{}, err error) {
  418. redisKey := fmt.Sprintf("growup-archive-summary:%d+%d", typ, mid)
  419. res, err := s.dao.GetIncomeCache(c, redisKey)
  420. if err != nil {
  421. log.Error("s.dao.GetIncomeCache error(%v)", err)
  422. return
  423. }
  424. if res != nil {
  425. data = res["data"]
  426. return
  427. }
  428. data, err = s.archiveSummary(c, typ, mid)
  429. if err != nil {
  430. log.Error("s.archiveSummary error(%v)", err)
  431. return
  432. }
  433. err = s.dao.SetIncomeCache(c, redisKey, map[string]interface{}{"data": data})
  434. if err != nil {
  435. log.Error("s.dao.SetIncomeCache error(%v)", err)
  436. }
  437. return
  438. }
  439. func (s *Service) archiveSummary(c context.Context, typ int, mid int64) (data interface{}, err error) {
  440. date := time.Now().AddDate(0, 0, -2)
  441. startMonth := xtime.Time(time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, time.Local).Unix())
  442. upIncomes, err := s.dao.ListUpIncome(c, mid, "up_income", "2017-12-01", date.Format(_layout))
  443. if err != nil {
  444. log.Error("s.dao.ListUpIncome error(%v)", err)
  445. return
  446. }
  447. summary := new(struct {
  448. DayIncome int64 `json:"day_income"`
  449. Date string `json:"date"`
  450. MonthIncome int64 `json:"income"`
  451. TotalIncome int64 `json:"total_income"`
  452. Breach int64 `json:"breach_money"`
  453. })
  454. if len(upIncomes) == 0 {
  455. data = summary
  456. return
  457. }
  458. sort.Slice(upIncomes, func(i, j int) bool {
  459. return upIncomes[i].Date > upIncomes[j].Date
  460. })
  461. summary.Date = date.Format(_layout)
  462. if upIncomes[0].Date.Time().Format(_layout) == summary.Date {
  463. switch typ {
  464. case _video:
  465. summary.DayIncome = upIncomes[0].AvIncome
  466. case _column:
  467. summary.DayIncome = upIncomes[0].ColumnIncome
  468. case _bgm:
  469. summary.DayIncome = upIncomes[0].BgmIncome
  470. }
  471. }
  472. var breachType []int64
  473. for _, up := range upIncomes {
  474. if up.Date >= startMonth {
  475. switch typ {
  476. case _video:
  477. summary.MonthIncome += up.AvIncome
  478. case _column:
  479. summary.MonthIncome += up.ColumnIncome
  480. case _bgm:
  481. summary.MonthIncome += up.BgmIncome
  482. }
  483. }
  484. switch typ {
  485. case _video:
  486. breachType = []int64{0}
  487. summary.TotalIncome += up.AvIncome
  488. case _column:
  489. breachType = []int64{2}
  490. summary.TotalIncome += up.ColumnIncome
  491. case _bgm:
  492. breachType = []int64{3}
  493. summary.TotalIncome += up.BgmIncome
  494. }
  495. }
  496. breach, err := s.dao.GetAvBreachByType(c, mid, "2017-12-01", time.Now().Format(_layout), breachType)
  497. if err != nil {
  498. log.Error("s.dao.GetAvBreachByType error(%v)", err)
  499. return
  500. }
  501. for d, money := range breach {
  502. if d >= startMonth {
  503. summary.Breach += money
  504. }
  505. summary.TotalIncome -= money
  506. }
  507. if summary.TotalIncome < 0 {
  508. summary.TotalIncome = 0
  509. }
  510. data = summary
  511. return
  512. }
  513. // ArchiveDetail cal archive detail
  514. func (s *Service) ArchiveDetail(c context.Context, typ int, archiveID int64) (data interface{}, err error) {
  515. redisKey := fmt.Sprintf("growup-archive-detail:%d+%d", typ, archiveID)
  516. res, err := s.dao.GetIncomeCache(c, redisKey)
  517. if err != nil {
  518. log.Error("s.dao.GetIncomeCache error(%v)", err)
  519. return
  520. }
  521. if res != nil {
  522. data = res["data"]
  523. return
  524. }
  525. data, err = s.archiveDetail(c, typ, archiveID)
  526. if err != nil {
  527. log.Error("s.archiveDetail error(%v)", err)
  528. return
  529. }
  530. err = s.dao.SetIncomeCache(c, redisKey, map[string]interface{}{"data": data})
  531. if err != nil {
  532. log.Error("s.dao.SetIncomeCache error(%v)", err)
  533. }
  534. return
  535. }
  536. func (s *Service) archiveDetail(c context.Context, typ int, archiveID int64) (archives []*model.ArchiveIncome, err error) {
  537. archives = make([]*model.ArchiveIncome, 0)
  538. endTime := time.Now().AddDate(0, 0, -2).Format(_layout)
  539. switch typ {
  540. case _video:
  541. archives, err = s.dao.ListAvIncomeByID(c, archiveID, endTime)
  542. if err != nil {
  543. log.Error("s.dao.ListAvIncomeByID error(%v)", err)
  544. return
  545. }
  546. case _audio:
  547. case _column:
  548. archives, err = s.dao.ListColumnIncomeByID(c, archiveID, endTime)
  549. if err != nil {
  550. log.Error("s.dao.ListColumnIncomeByID error(%v)", err)
  551. return
  552. }
  553. case _bgm:
  554. archives, err = s.listBgmIncomeByID(c, archiveID, endTime)
  555. if err != nil {
  556. return
  557. }
  558. }
  559. sort.Slice(archives, func(i, j int) bool {
  560. return archives[i].Date > archives[j].Date
  561. })
  562. return
  563. }
  564. func (s *Service) listBgmIncomeByID(c context.Context, archiveID int64, endTime string) (archives []*model.ArchiveIncome, err error) {
  565. as, err := s.dao.ListBgmIncomeByID(c, archiveID, endTime)
  566. if err != nil {
  567. log.Error("s.dao.ListBgmIncomeByID error(%v)", err)
  568. return
  569. }
  570. am := make(map[xtime.Time][]*model.ArchiveIncome)
  571. for _, a := range as {
  572. if _, ok := am[a.Date]; ok {
  573. am[a.Date] = append(am[a.Date], a)
  574. } else {
  575. am[a.Date] = []*model.ArchiveIncome{a}
  576. }
  577. }
  578. archives = make([]*model.ArchiveIncome, 0)
  579. for date, ars := range am {
  580. a := &model.ArchiveIncome{}
  581. a.Date = date
  582. for _, ar := range ars {
  583. a.Income += ar.Income
  584. a.Avs = append(a.Avs, ar.ArchiveID)
  585. }
  586. archives = append(archives, a)
  587. }
  588. return
  589. }
  590. // ArchiveBreach get av_breach_record
  591. func (s *Service) ArchiveBreach(c context.Context, mid int64, typ, page, size, all int) (data interface{}, err error) {
  592. if page == 0 {
  593. page = 1
  594. }
  595. start, end := (page-1)*size, page*size
  596. date := time.Now().AddDate(0, 0, -2)
  597. startMonth := time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, time.Local).Format(_layout)
  598. if all == 1 {
  599. startMonth = "2017-12-01"
  600. }
  601. archives, err := s.dao.ListAvBreach(c, mid, startMonth, date.Format(_layout))
  602. if err != nil {
  603. log.Error("s.dao.ListAvBreach error(%v)", err)
  604. return
  605. }
  606. typBreach := make([]*model.AvBreach, 0)
  607. for _, arch := range archives {
  608. if arch.CType == typ {
  609. typBreach = append(typBreach, arch)
  610. }
  611. }
  612. if len(typBreach) == 0 {
  613. return
  614. }
  615. breachs, err := s.breachInBlacklist(c, typBreach, typ)
  616. if err != nil {
  617. log.Error("s.breachInBlacklist error(%v)", err)
  618. return
  619. }
  620. sort.Slice(breachs, func(i, j int) bool {
  621. return breachs[i].CDate > breachs[j].CDate
  622. })
  623. if end > len(breachs) {
  624. end = len(breachs)
  625. }
  626. list := breachs[start:end]
  627. aIDs := make([]int64, 0)
  628. for _, b := range list {
  629. aIDs = append(aIDs, b.AvID)
  630. }
  631. var titles map[int64]string
  632. switch typ {
  633. case _video:
  634. titles, err = s.getAvTitle(c, aIDs)
  635. if err != nil {
  636. log.Error("s.getAvTitle error(%v)", err)
  637. return
  638. }
  639. case _column:
  640. titles, err = s.getColumnTitle(c, aIDs)
  641. if err != nil {
  642. log.Error("s.getColumnTitle error(%v)", err)
  643. return
  644. }
  645. case _bgm:
  646. titles, err = s.getBgmTitle(c, aIDs)
  647. if err != nil {
  648. log.Error("s.getBgmTitle error(%v)", err)
  649. return
  650. }
  651. }
  652. for _, b := range list {
  653. b.Title = titles[b.AvID]
  654. }
  655. data = map[string]interface{}{
  656. "data": list,
  657. "total_count": len(breachs),
  658. "page": page,
  659. }
  660. return
  661. }
  662. func (s *Service) breachInBlacklist(c context.Context, avs []*model.AvBreach, typ int) (breachs []*model.AvBreach, err error) {
  663. aIDList := make([]int64, 0)
  664. for _, a := range avs {
  665. aIDList = append(aIDList, a.AvID)
  666. }
  667. avBMap, err := s.dao.ListAvBlackList(c, aIDList, typ)
  668. if err != nil {
  669. return
  670. }
  671. breachs = make([]*model.AvBreach, 0)
  672. for _, av := range avs {
  673. if _, ok := avBMap[av.AvID]; ok {
  674. breachs = append(breachs, av)
  675. }
  676. }
  677. return
  678. }
  679. // UpIncomeStat get up income stat by month
  680. func (s *Service) UpIncomeStat(c context.Context, typ int, mid int64, date time.Time) (data interface{}, err error) {
  681. redisKey := fmt.Sprintf("growup-income-stat:%d+%d", typ, mid)
  682. res, err := s.dao.GetIncomeCache(c, redisKey)
  683. if err != nil {
  684. log.Error("s.dao.GetIncomeCache error(%v)", err)
  685. return
  686. }
  687. if res != nil {
  688. data = res["data"]
  689. return
  690. }
  691. data, err = s.upIncomeStat(c, typ, mid, date)
  692. if err != nil {
  693. return
  694. }
  695. err = s.dao.SetIncomeCache(c, redisKey, map[string]interface{}{"data": data})
  696. if err != nil {
  697. log.Error("s.dao.SetIncomeCache error(%v)", err)
  698. }
  699. return
  700. }
  701. func (s *Service) upIncomeStat(c context.Context, typ int, mid int64, date time.Time) (stats []*model.UpIncomeStat, err error) {
  702. et := date.AddDate(0, 0, -2)
  703. end := et.Format(_layout)
  704. // last 30 days
  705. begin := et.AddDate(0, 0, -30).Format(_layout)
  706. upIncomes, err := s.dao.ListUpIncome(c, mid, "up_income", begin, end)
  707. if err != nil {
  708. log.Error("s.dao.ListUpIncome error(%v)", err)
  709. return
  710. }
  711. stats = make([]*model.UpIncomeStat, 0)
  712. if len(upIncomes) == 0 {
  713. return
  714. }
  715. var breachType []int64
  716. for _, up := range upIncomes {
  717. var income, baseIncome int64
  718. switch typ {
  719. case _video:
  720. income, baseIncome = up.AvIncome, up.AvBaseIncome
  721. breachType = []int64{0}
  722. case _column:
  723. income, baseIncome = up.ColumnIncome, up.ColumnBaseIncome
  724. breachType = []int64{2}
  725. case _bgm:
  726. income, baseIncome = up.BgmIncome, up.BgmBaseIncome
  727. breachType = []int64{3}
  728. case _up:
  729. income, baseIncome = up.Income, up.BaseIncome
  730. breachType = []int64{0, 1, 2, 3}
  731. }
  732. extra := income - baseIncome
  733. if extra < 0 {
  734. extra = 0
  735. }
  736. stats = append(stats, &model.UpIncomeStat{
  737. MID: up.MID,
  738. Income: income,
  739. BaseIncome: baseIncome,
  740. ExtraIncome: extra,
  741. Date: up.Date,
  742. })
  743. }
  744. rs, err := s.dao.GetAvBreachByType(c, mid, begin, end, breachType)
  745. if err != nil {
  746. log.Error("s.dao.GetAvBreachByType error(%v)", err)
  747. return
  748. }
  749. for _, stat := range stats {
  750. if _, ok := rs[stat.Date]; ok {
  751. stat.Breach = rs[stat.Date]
  752. delete(rs, stat.Date)
  753. }
  754. }
  755. for date, breach := range rs {
  756. stats = append(stats, &model.UpIncomeStat{
  757. MID: mid,
  758. Date: date,
  759. Breach: breach,
  760. })
  761. }
  762. sort.Slice(stats, func(i, j int) bool {
  763. return stats[i].Date < stats[j].Date
  764. })
  765. return
  766. }