package models import ( "code.gitea.io/gitea/modules/timeutil" "fmt" "strconv" "strings" "xorm.io/builder" ) type SourceType string const ( SourceTypeAccomplishTask SourceType = "ACCOMPLISH_TASK" SourceTypeAdminOperate SourceType = "ADMIN_OPERATE" SourceTypeRunCloudbrainTask SourceType = "RUN_CLOUDBRAIN_TASK" ) func (r SourceType) Name() string { switch r { case SourceTypeAccomplishTask: return "ACCOMPLISH_TASK" case SourceTypeAdminOperate: return "ADMIN_OPERATE" case SourceTypeRunCloudbrainTask: return "RUN_CLOUDBRAIN_TASK" default: return "" } } type RewardType string const ( RewardTypePoint RewardType = "POINT" ) func (r RewardType) Name() string { switch r { case RewardTypePoint: return "POINT" default: return "" } } func (r RewardType) Show() string { switch r { case RewardTypePoint: return "积分" default: return "" } } func GetRewardTypeInstance(s string) RewardType { switch s { case RewardTypePoint.Name(): return RewardTypePoint default: return "" } } type RewardOperateType string func (r RewardOperateType) Name() string { switch r { case OperateTypeIncrease: return "INCREASE" case OperateTypeDecrease: return "DECREASE" default: return "" } } func (r RewardOperateType) Show() string { switch r { case OperateTypeIncrease: return "奖励" case OperateTypeDecrease: return "扣减" default: return "" } } func GetRewardOperateTypeInstance(s string) RewardOperateType { switch s { case OperateTypeIncrease.Name(): return OperateTypeIncrease case OperateTypeDecrease.Name(): return OperateTypeDecrease default: return "" } } const ( OperateTypeIncrease RewardOperateType = "INCREASE" OperateTypeDecrease RewardOperateType = "DECREASE" OperateTypeNull RewardOperateType = "NIL" ) const ( OperateStatusOperating = "OPERATING" OperateStatusSucceeded = "SUCCEEDED" OperateStatusFailed = "FAILED" ) const Semicolon = ";" type RewardOperateOrderBy string const ( RewardOrderByIDDesc RewardOperateOrderBy = "reward_operate_record.id desc" ) type RewardRecordList []*RewardOperateRecord type RewardRecordShowList []*RewardOperateRecordShow func (l RewardRecordShowList) loadAttribute(isAdmin bool) { l.loadAction() l.loadCloudbrain() if isAdmin { l.loadAdminLog() } } func (l RewardRecordShowList) loadAction() error { if len(l) == 0 { return nil } actionIds := make([]int64, 0) actionIdMap := make(map[int64]*RewardOperateRecordShow, 0) for _, r := range l { if r.SourceType != SourceTypeAccomplishTask.Name() { continue } i, _ := strconv.ParseInt(r.SourceId, 10, 64) actionIds = append(actionIds, i) actionIdMap[i] = r } actions, err := GetActionByIds(actionIds) if err != nil { return err } for _, v := range actions { actionIdMap[v.ID].Action = v.ToShow() } return nil } func (l RewardRecordShowList) loadCloudbrain() error { if len(l) == 0 { return nil } cloudbrainIds := make([]int64, 0) cloudbrainMap := make(map[int64]*RewardOperateRecordShow, 0) for _, r := range l { if r.SourceType != SourceTypeRunCloudbrainTask.Name() { continue } i, _ := strconv.ParseInt(r.SourceId, 10, 64) cloudbrainIds = append(cloudbrainIds, i) cloudbrainMap[i] = r } cloudbrains, err := GetCloudbrainByIds(cloudbrainIds) if err != nil { return err } var ids []int64 for _, task := range cloudbrains { ids = append(ids, task.RepoID) } repositoryMap, err := GetRepositoriesMapByIDs(ids) if err != nil { return err } for _, v := range cloudbrains { v.Repo = repositoryMap[v.RepoID] cloudbrainMap[v.ID].Cloudbrain = v.ToShow() } return nil } func (l RewardRecordShowList) loadAdminLog() error { if len(l) == 0 { return nil } logIds := make([]string, 0) logMap := make(map[string]*RewardOperateRecordShow, 0) for _, r := range l { if r.SourceType != SourceTypeAdminOperate.Name() { continue } logIds = append(logIds, r.SourceId) logMap[r.SourceId] = r } adminLogs, err := GetRewardAdminLogByLogIds(logIds) if err != nil { return err } for _, v := range adminLogs { logMap[v.LogId].AdminLog = v.ToShow() } return nil } type RewardOperateRecord struct { ID int64 `xorm:"pk autoincr"` SerialNo string `xorm:"INDEX NOT NULL"` UserId int64 `xorm:"INDEX NOT NULL"` Amount int64 `xorm:"NOT NULL"` LossAmount int64 Tittle string RewardType string `xorm:"NOT NULL"` SourceType string `xorm:"NOT NULL"` SourceId string `xorm:"INDEX NOT NULL"` SourceTemplateId string RequestId string `xorm:"INDEX NOT NULL"` OperateType string `xorm:"NOT NULL"` Status string `xorm:"NOT NULL"` Remark string CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` LastOperateUnix timeutil.TimeStamp `xorm:"INDEX"` } type AdminRewardOperateReq struct { TargetUserId int64 `binding:"Required"` OperateType RewardOperateType `binding:"Required"` Amount int64 `binding:"Required;Range(1,100000)"` Remark string RewardType RewardType } type RewardOperateRecordShow struct { SerialNo string Status string OperateType string SourceId string Amount int64 LossAmount int64 BalanceAfter int64 Remark string SourceType string UserName string LastOperateDate timeutil.TimeStamp UnitPrice int64 SuccessCount int Action *ActionShow Cloudbrain *CloudbrainShow AdminLog *RewardAdminLogShow } func getPointOperateRecord(tl *RewardOperateRecord) (*RewardOperateRecord, error) { has, err := x.Get(tl) if err != nil { return nil, err } else if !has { return nil, ErrRecordNotExist{} } return tl, nil } func GetPointOperateRecordBySourceTypeAndRequestId(sourceType, requestId, operateType string) (*RewardOperateRecord, error) { t := &RewardOperateRecord{ SourceType: sourceType, RequestId: requestId, OperateType: operateType, } return getPointOperateRecord(t) } func GetPointOperateRecordBySerialNo(serialNo string) (*RewardOperateRecord, error) { t := &RewardOperateRecord{ SerialNo: serialNo, } return getPointOperateRecord(t) } func InsertRewardOperateRecord(tl *RewardOperateRecord) (int64, error) { return x.Insert(tl) } func UpdateRewardRecordToFinalStatus(sourceType, requestId, newStatus string) (int64, error) { r := &RewardOperateRecord{ Status: newStatus, LastOperateUnix: timeutil.TimeStampNow(), } return x.Cols("status", "last_operate_unix").Where("source_type=? and request_id=? and status=?", sourceType, requestId, OperateStatusOperating).Update(r) } func SumRewardAmountInTaskPeriod(rewardType string, sourceType string, userId int64, period *PeriodResult) (int64, error) { var cond = builder.NewCond() if period != nil { cond = cond.And(builder.Gte{"created_unix": period.StartTime.Unix()}) cond = cond.And(builder.Lt{"created_unix": period.EndTime.Unix()}) } if sourceType != "" { cond = cond.And(builder.Eq{"source_type": sourceType}) } cond = cond.And(builder.Eq{"reward_type": rewardType}) cond = cond.And(builder.Eq{"user_id": userId}) return x.Where(cond).SumInt(&RewardOperateRecord{}, "amount") } type RewardOperateContext struct { SourceType SourceType SourceId string SourceTemplateId string Tittle string Remark string Reward Reward TargetUserId int64 RequestId string OperateType RewardOperateType RejectPolicy LimiterRejectPolicy PermittedNegative bool LossAmount int64 } type Reward struct { Amount int64 Type RewardType } type UserRewardOperationRedis struct { UserId int64 Amount int64 RewardType RewardType OperateType RewardOperateType } type UserRewardOperation struct { UserId int64 Msg string } func AppendRemark(remark, appendStr string) string { return strings.TrimPrefix(remark+Semicolon+appendStr, Semicolon) } type RewardRecordListOpts struct { ListOptions UserId int64 UserName string OperateType RewardOperateType RewardType RewardType SourceType string ActionType int SerialNo string OrderBy RewardOperateOrderBy IsAdmin bool Status string } func (opts *RewardRecordListOpts) toCond() builder.Cond { if opts.Page <= 0 { opts.Page = 1 } if len(opts.OrderBy) == 0 { opts.OrderBy = RewardOrderByIDDesc } cond := builder.NewCond() if opts.UserId > 0 { cond = cond.And(builder.Eq{"reward_operate_record.user_id": opts.UserId}) } if opts.OperateType != OperateTypeNull { cond = cond.And(builder.Eq{"reward_operate_record.operate_type": opts.OperateType.Name()}) } if opts.SourceType != "" { cond = cond.And(builder.Eq{"reward_operate_record.source_type": opts.SourceType}) } if opts.SourceType == SourceTypeAccomplishTask.Name() { if opts.ActionType > 0 { cond = cond.And(builder.Eq{"reward_operate_record.source_template_id": fmt.Sprint(opts.ActionType)}) } } if opts.SerialNo != "" { cond = cond.And(builder.Like{"reward_operate_record.serial_no", opts.SerialNo}) } if opts.Status != "" { cond = cond.And(builder.Like{"reward_operate_record.status", opts.Status}) } cond = cond.And(builder.Eq{"reward_operate_record.reward_type": opts.RewardType.Name()}) cond = cond.And(builder.Gt{"reward_operate_record.amount": 0}) return cond } type TestTT struct { SerialNo string UserId int64 Amount int64 UserName string } func GetRewardRecordShowList(opts *RewardRecordListOpts) (RewardRecordShowList, int64, error) { cond := opts.toCond() count, err := x.Where(cond).Count(&RewardOperateRecord{}) if err != nil { return nil, 0, err } r := make([]*RewardOperateRecordShow, 0) err = x.Table("reward_operate_record").Cols("reward_operate_record.source_id", "reward_operate_record.serial_no", "reward_operate_record.status", "reward_operate_record.operate_type", "reward_operate_record.amount", "reward_operate_record.loss_amount", "reward_operate_record.remark", "reward_operate_record.source_type", "reward_operate_record.last_operate_unix as last_operate_date"). Where(cond).Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).OrderBy(string(opts.OrderBy)).Find(&r) if err != nil { return nil, 0, err } RewardRecordShowList(r).loadAttribute(false) return r, count, nil } func GetAdminRewardRecordShowList(opts *RewardRecordListOpts) (RewardRecordShowList, int64, error) { cond := opts.toCond() count, err := x.Where(cond).Count(&RewardOperateRecord{}) if err != nil { return nil, 0, err } r := make([]*RewardOperateRecordShow, 0) switch opts.OperateType { case OperateTypeIncrease: err = x.Table("reward_operate_record").Cols("reward_operate_record.source_id", "reward_operate_record.serial_no", "reward_operate_record.status", "reward_operate_record.operate_type", "reward_operate_record.amount", "reward_operate_record.loss_amount", "reward_operate_record.remark", "reward_operate_record.source_type", "reward_operate_record.last_operate_unix as last_operate_date", "public.user.name as user_name", "point_account_log.balance_after"). Join("LEFT", "public.user", "reward_operate_record.user_id = public.user.id"). Join("LEFT", "point_account_log", " reward_operate_record.serial_no = point_account_log.source_id"). Where(cond).Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).OrderBy(string(opts.OrderBy)).Find(&r) case OperateTypeDecrease: err = x.Table("reward_operate_record").Cols("reward_operate_record.source_id", "reward_operate_record.serial_no", "reward_operate_record.status", "reward_operate_record.operate_type", "reward_operate_record.amount", "reward_operate_record.loss_amount", "reward_operate_record.remark", "reward_operate_record.source_type", "reward_operate_record.last_operate_unix as last_operate_date", "public.user.name as user_name", "reward_periodic_task.amount as unit_price", "reward_periodic_task.success_count"). Join("LEFT", "public.user", "reward_operate_record.user_id = public.user.id"). Join("LEFT", "reward_periodic_task", "reward_operate_record.serial_no = reward_periodic_task.operate_serial_no"). Where(cond).Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).OrderBy(string(opts.OrderBy)).Find(&r) } if err != nil { return nil, 0, err } RewardRecordShowList(r).loadAttribute(true) return r, count, nil }