enter.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. package daily_profit
  2. import (
  3. "app/commons/core"
  4. "app/commons/model/entity"
  5. "app/commons/services"
  6. "app/commons/utils"
  7. "errors"
  8. "fmt"
  9. "gorm.io/gorm"
  10. )
  11. type Service struct {
  12. //job *entity.SysJob
  13. services.CommonService
  14. }
  15. func NewService() *Service {
  16. return &Service{}
  17. }
  18. // 每日收益任务
  19. // nextDay 是否启动下一日任务
  20. func (s *Service) RunDailyProfitJob(nextDay bool) error {
  21. var err error
  22. // 预创建每日任务
  23. err = s.PreCreationDailyJob()
  24. if err != nil {
  25. return err
  26. }
  27. dailyJob, err := s.getNextRunDailyJob()
  28. if err != nil {
  29. return err
  30. }
  31. if dailyJob.JobDate != utils.Today20060102Format() && !nextDay {
  32. return fmt.Errorf("当前待发放奖励日期:%s 当日:%s 启动失败", dailyJob.JobDate, utils.Today20060102Format())
  33. }
  34. // 记录任务状态
  35. defer func() {
  36. state := entity.JobFinish
  37. msg := "每日任务完成"
  38. if err != nil {
  39. state = entity.JobFail
  40. msg = err.Error()
  41. }
  42. if err = s.updateJobStateAndDesc(dailyJob, state, msg); err != nil {
  43. core.JobLog.Errorf(err.Error())
  44. }
  45. }()
  46. if err = s.updateJobStateAndDesc(dailyJob, entity.JobRunning, fmt.Sprintf("天任务开启")); err != nil {
  47. return err
  48. }
  49. // 1 节点收益计算
  50. if err = s.nodeProfitCal(dailyJob.JobDate); err != nil {
  51. return err
  52. }
  53. // 2 团队业绩排行收益计算
  54. if err = s.achievementRankingProfitCal(dailyJob.JobDate); err != nil {
  55. return err
  56. }
  57. // 3 个人质押排行收益计算
  58. if err = s.stakeRankingProfitCal(dailyJob.JobDate); err != nil {
  59. return err
  60. }
  61. return nil
  62. }
  63. // 更新任务状态
  64. func (s *Service) updateJobStateAndDesc(job *entity.SysJob, state, errMsg string) error {
  65. errMsg = fmt.Sprintf("%s:%s", errMsg, utils.NowTimeSecStr())
  66. if job.Desc != "" {
  67. errMsg = fmt.Sprintf("%s\n%s", job.Desc, errMsg)
  68. }
  69. return s.DB().Model(&entity.SysJob{}).
  70. Where("id", job.Id).
  71. Updates(map[string]interface{}{
  72. "state": state,
  73. "desc": errMsg,
  74. }).Error
  75. }
  76. // 获取当前任务
  77. func (s *Service) getNextRunDailyJob() (*entity.SysJob, error) {
  78. // 等待状态任务
  79. firstWaiting, err := s.FirstSysJob(s.DB().Where("state = ?", entity.JobWaiting))
  80. if err != nil {
  81. return nil, err
  82. }
  83. // 非等待状态任务
  84. runningOrSuccessOrFailRow, err := s.FirstSysJob(s.DB().Where("state != ?", entity.JobWaiting))
  85. if err != nil {
  86. if errors.Is(err, gorm.ErrRecordNotFound) {
  87. return firstWaiting, nil
  88. }
  89. return nil, err
  90. }
  91. if runningOrSuccessOrFailRow.State == entity.JobFinish {
  92. return firstWaiting, nil
  93. }
  94. if runningOrSuccessOrFailRow.State == entity.JobRunning {
  95. return nil, fmt.Errorf("存在运行中天任务:%s", runningOrSuccessOrFailRow.JobDate)
  96. }
  97. if runningOrSuccessOrFailRow.State == entity.JobFail {
  98. return nil, fmt.Errorf("存在运行错误天任务:%s,必须处理错误后才可以正常运行", runningOrSuccessOrFailRow.JobDate)
  99. }
  100. return nil, fmt.Errorf("天任务:%s,未知状态错误", runningOrSuccessOrFailRow.JobDate)
  101. }
  102. // 预创建3个 每日任务
  103. func (s *Service) PreCreationDailyJob() error {
  104. var err error
  105. firstWaitingJob, err := s.FirstSysJob(s.DB().Where("state", entity.JobWaiting))
  106. if err != nil {
  107. // 当不存在等待中 创建一条当日任务
  108. if errors.Is(err, gorm.ErrRecordNotFound) {
  109. firstWaitingJob, err = s.newDailyJob(utils.Today20060102Format())
  110. if err != nil {
  111. return err
  112. }
  113. } else {
  114. return err
  115. }
  116. }
  117. lastJob, err := s.LastSysJob(s.DB().Where("state", entity.JobWaiting))
  118. if err != nil {
  119. return err
  120. }
  121. // 计算两天 日期跨度
  122. n, err := utils.CalculateApartDays(firstWaitingJob.JobDate, lastJob.JobDate)
  123. if err != nil {
  124. return err
  125. }
  126. // 保持三天任务
  127. if n < 3 {
  128. // 目标期
  129. targetDay, err := utils.ChangeDay(firstWaitingJob.JobDate, 3)
  130. if err != nil {
  131. return err
  132. }
  133. nowDate := lastJob.JobDate
  134. for {
  135. nextDate, err := utils.NextPeriodNo(nowDate)
  136. if err != nil {
  137. return err
  138. }
  139. if _, err = s.newDailyJob(nextDate); err != nil {
  140. return err
  141. }
  142. if nextDate >= targetDay {
  143. break
  144. }
  145. nowDate = nextDate
  146. }
  147. }
  148. return err
  149. }
  150. // 每日任务初始化
  151. func (s *Service) createJob(nextJob bool) (*entity.SysJob, error) {
  152. lastJob, err := s.LastSysJob(s.DB())
  153. if err != nil {
  154. // 初始化一条记录 当日任务 并返回
  155. return s.newDailyJob(utils.TimeDate())
  156. }
  157. if lastJob.State != entity.JobFinish {
  158. return nil, fmt.Errorf("%s任务:%s", lastJob.JobDate, entity.JobStateNameById(lastJob.State))
  159. }
  160. // 启动下一日任务 -- 用于测试
  161. if nextJob {
  162. nextDate, err := utils.AfterOneDay(lastJob.JobDate)
  163. if err != nil {
  164. return s.newDailyJob(utils.TimeDate())
  165. }
  166. return s.newDailyJob(nextDate)
  167. } else {
  168. if lastJob.JobDate == utils.TimeDate() {
  169. return nil, fmt.Errorf("%s任务:%s", lastJob.JobDate, entity.JobStateNameById(lastJob.State))
  170. }
  171. // 创建当日任务
  172. }
  173. return s.newDailyJob(utils.TimeDate())
  174. }
  175. func (s *Service) newDailyJob(date string) (*entity.SysJob, error) {
  176. newJob := &entity.SysJob{
  177. JobDate: date,
  178. State: entity.JobWaiting,
  179. Desc: "",
  180. }
  181. if err := s.DB().Create(&newJob).Error; err != nil {
  182. return nil, err
  183. }
  184. return newJob, nil
  185. }