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 = "id desc" ) type RewardRecordList []*RewardOperateRecord type RewardRecordShowList []*RewardOperateRecordShow func (l *RewardRecordList) ToShow() (RewardRecordShowList, error) { actionMap, err := l.GetRewardRecordAction() adminLogMap, err := l.GetRewardRecordAdminLog() CloudbrainMap, err := l.GetRewardRecordCloudbrainTask() if err != nil { return nil, err } result := make([]*RewardOperateRecordShow, 0) for _, v := range *l { temp := v.ToShow() switch v.SourceType { case SourceTypeAccomplishTask.Name(): temp.Action = actionMap[v.SourceId] case SourceTypeAdminOperate.Name(): temp.AdminLog = adminLogMap[v.SourceId] case SourceTypeRunCloudbrainTask.Name(): temp.Cloudbrain = CloudbrainMap[v.SourceId] } result = append(result, &temp) } return result, nil } func (l *RewardRecordList) GetRewardRecordAction() (map[string]Action, error) { if len(*l) == 0 { return nil, nil } actionIds := make([]int64, 0) for _, r := range *l { if r.SourceType != SourceTypeAccomplishTask.Name() { continue } i, _ := strconv.ParseInt(r.SourceId, 10, 64) actionIds = append(actionIds, i) } actions, err := GetActionByIds(actionIds) if err != nil { return nil, err } result := make(map[string]Action, 0) for _, v := range actions { result[fmt.Sprint(v.ID)] = *v } return result, nil } func (l *RewardRecordList) GetRewardRecordAdminLog() (map[string]RewardAdminLog, error) { if len(*l) == 0 { return nil, nil } logIds := make([]string, 0) for _, r := range *l { if r.SourceType != SourceTypeAdminOperate.Name() { continue } logIds = append(logIds, r.SourceId) } logs, err := GetRewardAdminLogByLogIds(logIds) if err != nil { return nil, err } result := make(map[string]RewardAdminLog, 0) for _, v := range logs { result[fmt.Sprint(v.LogId)] = v } return result, nil } func (l *RewardRecordList) GetRewardRecordCloudbrainTask() (map[string]Cloudbrain, error) { if len(*l) == 0 { return nil, nil } cloudbrainIds := make([]int64, 0) for _, r := range *l { if r.SourceType != SourceTypeRunCloudbrainTask.Name() { continue } i, _ := strconv.ParseInt(r.SourceId, 10, 64) cloudbrainIds = append(cloudbrainIds, i) } cloudbrains, err := GetCloudbrainByIds(cloudbrainIds) if err != nil { return nil, err } result := make(map[string]Cloudbrain, 0) for _, v := range cloudbrains { result[fmt.Sprint(v.ID)] = v } return result, 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"` 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 } func (r RewardOperateRecord) ToShow() RewardOperateRecordShow { return RewardOperateRecordShow{ SerialNo: r.SerialNo, CreateDate: r.CreatedUnix, OperateType: r.OperateType, Amount: r.Amount, Remark: r.Remark, Status: r.Status, SourceType: r.SourceType, LastOperateDate: r.LastOperateUnix, LossAmount: r.LossAmount, } } type RewardOperateRecordShow struct { SerialNo string CreateDate timeutil.TimeStamp Status string OperateType string Amount int64 LossAmount int64 Remark string SourceType string LastOperateDate timeutil.TimeStamp Action Action Cloudbrain Cloudbrain AdminLog RewardAdminLog } 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 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 OperateType RewardOperateType RewardType RewardType OrderBy RewardOperateOrderBy } func GetRewardRecordList(opts RewardRecordListOpts) (RewardRecordList, int64, error) { if opts.Page <= 0 { opts.Page = 1 } if len(opts.OrderBy) == 0 { opts.OrderBy = RewardOrderByIDDesc } r := make([]*RewardOperateRecord, 0) cond := builder.NewCond() if opts.UserId > 0 { cond = cond.And(builder.Eq{"user_id": opts.UserId}) } if opts.OperateType != OperateTypeNull { cond = cond.And(builder.Eq{"operate_type": opts.OperateType.Name()}) } cond = cond.And(builder.Eq{"reward_type": opts.RewardType.Name()}) cond = cond.And(builder.Gt{"amount": 0}) count, err := x.Where(cond).Count(&RewardOperateRecord{}) if err != nil { return nil, 0, err } err = x.Where(cond).Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).OrderBy(string(opts.OrderBy)).Find(&r) if err != nil { return nil, 0, err } return r, count, nil }