package daily_profit import ( "app/commons/core" "app/commons/model/entity" "app/commons/services" "app/commons/utils" "errors" "fmt" "gorm.io/gorm" ) type Service struct { //job *entity.SysJob services.CommonService } func NewService() *Service { return &Service{} } // 每日收益任务 // nextDay 是否启动下一日任务 func (s *Service) RunDailyProfitJob(nextDay bool) error { var err error // 预创建每日任务 err = s.PreCreationDailyJob() if err != nil { return err } dailyJob, err := s.getNextRunDailyJob() if err != nil { return err } if dailyJob.JobDate != utils.Today20060102Format() && !nextDay { return fmt.Errorf("当前待发放奖励日期:%s 当日:%s 启动失败", dailyJob.JobDate, utils.Today20060102Format()) } // 记录任务状态 defer func() { state := entity.JobFinish msg := "每日任务完成" if err != nil { state = entity.JobFail msg = err.Error() } if err = s.updateJobStateAndDesc(dailyJob, state, msg); err != nil { core.JobLog.Errorf(err.Error()) } }() if err = s.updateJobStateAndDesc(dailyJob, entity.JobRunning, fmt.Sprintf("天任务开启")); err != nil { return err } // 1 节点收益计算 if err = s.nodeProfitCal(dailyJob.JobDate); err != nil { return err } // 2 团队业绩排行收益计算 if err = s.achievementRankingProfitCal(dailyJob.JobDate); err != nil { return err } // 3 个人质押排行收益计算 if err = s.stakeRankingProfitCal(dailyJob.JobDate); err != nil { return err } return nil } // 更新任务状态 func (s *Service) updateJobStateAndDesc(job *entity.SysJob, state, errMsg string) error { errMsg = fmt.Sprintf("%s:%s", errMsg, utils.NowTimeSecStr()) if job.Desc != "" { errMsg = fmt.Sprintf("%s\n%s", job.Desc, errMsg) } return s.DB().Model(&entity.SysJob{}). Where("id", job.Id). Updates(map[string]interface{}{ "state": state, "desc": errMsg, }).Error } // 获取当前任务 func (s *Service) getNextRunDailyJob() (*entity.SysJob, error) { // 等待状态任务 firstWaiting, err := s.FirstSysJob(s.DB().Where("state = ?", entity.JobWaiting)) if err != nil { return nil, err } // 非等待状态任务 runningOrSuccessOrFailRow, err := s.FirstSysJob(s.DB().Where("state != ?", entity.JobWaiting)) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return firstWaiting, nil } return nil, err } if runningOrSuccessOrFailRow.State == entity.JobFinish { return firstWaiting, nil } if runningOrSuccessOrFailRow.State == entity.JobRunning { return nil, fmt.Errorf("存在运行中天任务:%s", runningOrSuccessOrFailRow.JobDate) } if runningOrSuccessOrFailRow.State == entity.JobFail { return nil, fmt.Errorf("存在运行错误天任务:%s,必须处理错误后才可以正常运行", runningOrSuccessOrFailRow.JobDate) } return nil, fmt.Errorf("天任务:%s,未知状态错误", runningOrSuccessOrFailRow.JobDate) } // 预创建3个 每日任务 func (s *Service) PreCreationDailyJob() error { var err error firstWaitingJob, err := s.FirstSysJob(s.DB().Where("state", entity.JobWaiting)) if err != nil { // 当不存在等待中 创建一条当日任务 if errors.Is(err, gorm.ErrRecordNotFound) { firstWaitingJob, err = s.newDailyJob(utils.Today20060102Format()) if err != nil { return err } } else { return err } } lastJob, err := s.LastSysJob(s.DB().Where("state", entity.JobWaiting)) if err != nil { return err } // 计算两天 日期跨度 n, err := utils.CalculateApartDays(firstWaitingJob.JobDate, lastJob.JobDate) if err != nil { return err } // 保持三天任务 if n < 3 { // 目标期 targetDay, err := utils.ChangeDay(firstWaitingJob.JobDate, 3) if err != nil { return err } nowDate := lastJob.JobDate for { nextDate, err := utils.NextPeriodNo(nowDate) if err != nil { return err } if _, err = s.newDailyJob(nextDate); err != nil { return err } if nextDate >= targetDay { break } nowDate = nextDate } } return err } // 每日任务初始化 func (s *Service) createJob(nextJob bool) (*entity.SysJob, error) { lastJob, err := s.LastSysJob(s.DB()) if err != nil { // 初始化一条记录 当日任务 并返回 return s.newDailyJob(utils.TimeDate()) } if lastJob.State != entity.JobFinish { return nil, fmt.Errorf("%s任务:%s", lastJob.JobDate, entity.JobStateNameById(lastJob.State)) } // 启动下一日任务 -- 用于测试 if nextJob { nextDate, err := utils.AfterOneDay(lastJob.JobDate) if err != nil { return s.newDailyJob(utils.TimeDate()) } return s.newDailyJob(nextDate) } else { if lastJob.JobDate == utils.TimeDate() { return nil, fmt.Errorf("%s任务:%s", lastJob.JobDate, entity.JobStateNameById(lastJob.State)) } // 创建当日任务 } return s.newDailyJob(utils.TimeDate()) } func (s *Service) newDailyJob(date string) (*entity.SysJob, error) { newJob := &entity.SysJob{ JobDate: date, State: entity.JobWaiting, Desc: "", } if err := s.DB().Create(&newJob).Error; err != nil { return nil, err } return newJob, nil }