You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

reward_operate_record.go 13 kB

3 years ago
2 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
2 years ago
3 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. package models
  2. import (
  3. "code.gitea.io/gitea/modules/log"
  4. "code.gitea.io/gitea/modules/timeutil"
  5. "fmt"
  6. "strconv"
  7. "strings"
  8. "xorm.io/builder"
  9. )
  10. type SourceType string
  11. const (
  12. SourceTypeAccomplishTask SourceType = "ACCOMPLISH_TASK"
  13. SourceTypeAdminOperate SourceType = "ADMIN_OPERATE"
  14. SourceTypeRunCloudbrainTask SourceType = "RUN_CLOUDBRAIN_TASK"
  15. )
  16. func (r SourceType) Name() string {
  17. switch r {
  18. case SourceTypeAccomplishTask:
  19. return "ACCOMPLISH_TASK"
  20. case SourceTypeAdminOperate:
  21. return "ADMIN_OPERATE"
  22. case SourceTypeRunCloudbrainTask:
  23. return "RUN_CLOUDBRAIN_TASK"
  24. default:
  25. return ""
  26. }
  27. }
  28. type RewardType string
  29. const (
  30. RewardTypePoint RewardType = "POINT"
  31. )
  32. func (r RewardType) Name() string {
  33. switch r {
  34. case RewardTypePoint:
  35. return "POINT"
  36. default:
  37. return ""
  38. }
  39. }
  40. func (r RewardType) Show() string {
  41. switch r {
  42. case RewardTypePoint:
  43. return "积分"
  44. default:
  45. return ""
  46. }
  47. }
  48. func GetRewardTypeInstance(s string) RewardType {
  49. switch s {
  50. case RewardTypePoint.Name():
  51. return RewardTypePoint
  52. default:
  53. return ""
  54. }
  55. }
  56. type RewardOperateType string
  57. func (r RewardOperateType) Name() string {
  58. switch r {
  59. case OperateTypeIncrease:
  60. return "INCREASE"
  61. case OperateTypeDecrease:
  62. return "DECREASE"
  63. default:
  64. return ""
  65. }
  66. }
  67. func (r RewardOperateType) Show() string {
  68. switch r {
  69. case OperateTypeIncrease:
  70. return "奖励"
  71. case OperateTypeDecrease:
  72. return "扣减"
  73. default:
  74. return ""
  75. }
  76. }
  77. func GetRewardOperateTypeInstance(s string) RewardOperateType {
  78. switch s {
  79. case OperateTypeIncrease.Name():
  80. return OperateTypeIncrease
  81. case OperateTypeDecrease.Name():
  82. return OperateTypeDecrease
  83. default:
  84. return ""
  85. }
  86. }
  87. const (
  88. OperateTypeIncrease RewardOperateType = "INCREASE"
  89. OperateTypeDecrease RewardOperateType = "DECREASE"
  90. OperateTypeNull RewardOperateType = "NIL"
  91. )
  92. const (
  93. OperateStatusOperating = "OPERATING"
  94. OperateStatusSucceeded = "SUCCEEDED"
  95. OperateStatusFailed = "FAILED"
  96. )
  97. const Semicolon = ";"
  98. type RewardOperateOrderBy string
  99. const (
  100. RewardOrderByIDDesc RewardOperateOrderBy = "reward_operate_record.id desc"
  101. )
  102. type RewardRecordList []*RewardOperateRecord
  103. type RewardRecordShowList []*RewardOperateRecordShow
  104. func (l RewardRecordShowList) loadAttribute(isAdmin bool) {
  105. l.loadAction()
  106. l.loadCloudbrain()
  107. if isAdmin {
  108. l.loadAdminLog()
  109. }
  110. }
  111. func (l RewardRecordShowList) loadAction() error {
  112. if len(l) == 0 {
  113. return nil
  114. }
  115. actionIds := make([]int64, 0)
  116. for _, r := range l {
  117. if r.SourceType != SourceTypeAccomplishTask.Name() {
  118. continue
  119. }
  120. i, _ := strconv.ParseInt(r.SourceId, 10, 64)
  121. actionIds = append(actionIds, i)
  122. }
  123. actions, err := GetActionByIds(actionIds)
  124. if err != nil {
  125. return err
  126. }
  127. actionIdMap := make(map[string]*Action, 0)
  128. for _, v := range actions {
  129. actionIdMap[fmt.Sprint(v.ID)] = v
  130. }
  131. for i, r := range l {
  132. act := actionIdMap[r.SourceId]
  133. if act != nil {
  134. l[i].Action = act.ToShow()
  135. }
  136. }
  137. return nil
  138. }
  139. func (l RewardRecordShowList) loadCloudbrain() error {
  140. if len(l) == 0 {
  141. return nil
  142. }
  143. cloudbrainIds := make([]int64, 0)
  144. cloudbrainMap := make(map[int64]*RewardOperateRecordShow, 0)
  145. for _, r := range l {
  146. if r.SourceType != SourceTypeRunCloudbrainTask.Name() {
  147. continue
  148. }
  149. i, _ := strconv.ParseInt(r.SourceId, 10, 64)
  150. cloudbrainIds = append(cloudbrainIds, i)
  151. cloudbrainMap[i] = r
  152. }
  153. cloudbrains, err := GetCloudbrainByIds(cloudbrainIds)
  154. if err != nil {
  155. return err
  156. }
  157. var repoIds []int64
  158. var taskIds []int64
  159. for _, task := range cloudbrains {
  160. repoIds = append(repoIds, task.RepoID)
  161. taskIds = append(taskIds, task.ID)
  162. }
  163. repositoryMap, err := GetRepositoriesMapByIDs(repoIds)
  164. specMap, err := GetResourceSpecMapByCloudbrainIDs(taskIds)
  165. if err != nil {
  166. return err
  167. }
  168. for _, v := range cloudbrains {
  169. v.Repo = repositoryMap[v.RepoID]
  170. v.Spec = specMap[v.ID]
  171. cloudbrainMap[v.ID].Cloudbrain = v.ToShow()
  172. }
  173. return nil
  174. }
  175. func (l RewardRecordShowList) loadAdminLog() error {
  176. if len(l) == 0 {
  177. return nil
  178. }
  179. logIds := make([]string, 0)
  180. logMap := make(map[string]*RewardOperateRecordShow, 0)
  181. for _, r := range l {
  182. if r.SourceType != SourceTypeAdminOperate.Name() {
  183. continue
  184. }
  185. logIds = append(logIds, r.SourceId)
  186. logMap[r.SourceId] = r
  187. }
  188. adminLogs, err := GetRewardAdminLogByLogIds(logIds)
  189. if err != nil {
  190. return err
  191. }
  192. for _, v := range adminLogs {
  193. logMap[v.LogId].AdminLog = v.ToShow()
  194. }
  195. return nil
  196. }
  197. type RewardOperateRecord struct {
  198. ID int64 `xorm:"pk autoincr"`
  199. SerialNo string `xorm:"INDEX NOT NULL"`
  200. UserId int64 `xorm:"INDEX NOT NULL"`
  201. Amount int64 `xorm:"NOT NULL"`
  202. LossAmount int64
  203. Title string
  204. RewardType string `xorm:"NOT NULL"`
  205. SourceType string `xorm:"NOT NULL"`
  206. SourceId string `xorm:"INDEX NOT NULL"`
  207. SourceTemplateId string
  208. RequestId string `xorm:"INDEX NOT NULL"`
  209. OperateType string `xorm:"NOT NULL"`
  210. Status string `xorm:"NOT NULL"`
  211. Remark string
  212. CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
  213. UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
  214. LastOperateUnix timeutil.TimeStamp `xorm:"INDEX"`
  215. }
  216. type AdminRewardOperateReq struct {
  217. TargetUserId int64 `binding:"Required"`
  218. OperateType RewardOperateType `binding:"Required"`
  219. Amount int64 `binding:"Required;Range(1,100000)"`
  220. Remark string
  221. RewardType RewardType
  222. }
  223. type RewardOperateRecordShow struct {
  224. SerialNo string
  225. Status string
  226. OperateType string
  227. SourceId string
  228. Amount int64
  229. LossAmount int64
  230. BalanceAfter int64
  231. Remark string
  232. SourceType string
  233. UserName string
  234. LastOperateDate timeutil.TimeStamp
  235. UnitPrice int64
  236. SuccessCount int
  237. Action *ActionShow
  238. Cloudbrain *CloudbrainShow
  239. AdminLog *RewardAdminLogShow
  240. }
  241. func getPointOperateRecord(tl *RewardOperateRecord) (*RewardOperateRecord, error) {
  242. has, err := x.Get(tl)
  243. if err != nil {
  244. return nil, err
  245. } else if !has {
  246. return nil, ErrRecordNotExist{}
  247. }
  248. return tl, nil
  249. }
  250. func GetPointOperateRecordBySourceTypeAndRequestId(sourceType, requestId, operateType string) (*RewardOperateRecord, error) {
  251. t := &RewardOperateRecord{
  252. SourceType: sourceType,
  253. RequestId: requestId,
  254. OperateType: operateType,
  255. }
  256. return getPointOperateRecord(t)
  257. }
  258. func GetPointOperateRecordBySerialNo(serialNo string) (*RewardOperateRecord, error) {
  259. t := &RewardOperateRecord{
  260. SerialNo: serialNo,
  261. }
  262. return getPointOperateRecord(t)
  263. }
  264. func InsertRewardOperateRecord(tl *RewardOperateRecord) (int64, error) {
  265. return x.Insert(tl)
  266. }
  267. func UpdateRewardRecordToFinalStatus(sourceType, requestId, newStatus string) (int64, error) {
  268. r := &RewardOperateRecord{
  269. Status: newStatus,
  270. LastOperateUnix: timeutil.TimeStampNow(),
  271. }
  272. return x.Cols("status", "last_operate_unix").Where("source_type=? and request_id=? and status=?", sourceType, requestId, OperateStatusOperating).Update(r)
  273. }
  274. func SumRewardAmountInTaskPeriod(rewardType string, sourceType string, userId int64, period *PeriodResult) (int64, error) {
  275. var cond = builder.NewCond()
  276. if period != nil {
  277. cond = cond.And(builder.Gte{"created_unix": period.StartTime.Unix()})
  278. cond = cond.And(builder.Lt{"created_unix": period.EndTime.Unix()})
  279. }
  280. if sourceType != "" {
  281. cond = cond.And(builder.Eq{"source_type": sourceType})
  282. }
  283. cond = cond.And(builder.Eq{"reward_type": rewardType})
  284. cond = cond.And(builder.Eq{"user_id": userId})
  285. return x.Where(cond).SumInt(&RewardOperateRecord{}, "amount")
  286. }
  287. type RewardOperateContext struct {
  288. SourceType SourceType
  289. SourceId string
  290. SourceTemplateId string
  291. Title string
  292. Remark string
  293. Reward Reward
  294. TargetUserId int64
  295. RequestId string
  296. OperateType RewardOperateType
  297. RejectPolicy LimiterRejectPolicy
  298. PermittedNegative bool
  299. LossAmount int64
  300. }
  301. type Reward struct {
  302. Amount int64
  303. Type RewardType
  304. }
  305. type UserRewardOperationRedis struct {
  306. UserId int64
  307. Amount int64
  308. RewardType RewardType
  309. OperateType RewardOperateType
  310. }
  311. type UserRewardOperation struct {
  312. UserId int64
  313. Msg string
  314. }
  315. func AppendRemark(remark, appendStr string) string {
  316. return strings.TrimPrefix(remark+Semicolon+appendStr, Semicolon)
  317. }
  318. type RewardRecordListOpts struct {
  319. ListOptions
  320. UserId int64
  321. UserName string
  322. OperateType RewardOperateType
  323. RewardType RewardType
  324. SourceType string
  325. TaskType string
  326. SerialNo string
  327. OrderBy RewardOperateOrderBy
  328. IsAdmin bool
  329. Status string
  330. }
  331. func (opts *RewardRecordListOpts) toCond() builder.Cond {
  332. if opts.Page <= 0 {
  333. opts.Page = 1
  334. }
  335. if len(opts.OrderBy) == 0 {
  336. opts.OrderBy = RewardOrderByIDDesc
  337. }
  338. cond := builder.NewCond()
  339. if opts.UserId > 0 {
  340. cond = cond.And(builder.Eq{"reward_operate_record.user_id": opts.UserId})
  341. }
  342. if opts.OperateType != OperateTypeNull {
  343. cond = cond.And(builder.Eq{"reward_operate_record.operate_type": opts.OperateType.Name()})
  344. }
  345. if opts.SourceType != "" {
  346. cond = cond.And(builder.Eq{"reward_operate_record.source_type": opts.SourceType})
  347. }
  348. if opts.TaskType != "" {
  349. cond = cond.And(builder.Eq{"reward_operate_record.source_template_id": opts.TaskType})
  350. }
  351. if opts.SerialNo != "" {
  352. cond = cond.And(builder.Like{"reward_operate_record.serial_no", opts.SerialNo})
  353. }
  354. if opts.Status != "" {
  355. cond = cond.And(builder.Like{"reward_operate_record.status", opts.Status})
  356. }
  357. cond = cond.And(builder.Eq{"reward_operate_record.reward_type": opts.RewardType.Name()})
  358. cond = cond.And(builder.Gt{"reward_operate_record.amount": 0})
  359. return cond
  360. }
  361. type TestTT struct {
  362. SerialNo string
  363. UserId int64
  364. Amount int64
  365. UserName string
  366. }
  367. func GetRewardRecordShowList(opts *RewardRecordListOpts) (RewardRecordShowList, int64, error) {
  368. cond := opts.toCond()
  369. count, err := x.Where(cond).Count(&RewardOperateRecord{})
  370. if err != nil {
  371. return nil, 0, err
  372. }
  373. r := make([]*RewardOperateRecordShow, 0)
  374. err = x.Table("reward_operate_record").Cols("reward_operate_record.source_id", "reward_operate_record.serial_no",
  375. "reward_operate_record.status", "reward_operate_record.operate_type", "reward_operate_record.amount",
  376. "reward_operate_record.loss_amount", "reward_operate_record.remark", "reward_operate_record.source_type",
  377. "reward_operate_record.last_operate_unix as last_operate_date").
  378. Where(cond).Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).OrderBy(string(opts.OrderBy)).Find(&r)
  379. if err != nil {
  380. return nil, 0, err
  381. }
  382. RewardRecordShowList(r).loadAttribute(false)
  383. return r, count, nil
  384. }
  385. func GetAdminRewardRecordShowList(opts *RewardRecordListOpts) (RewardRecordShowList, int64, error) {
  386. cond := opts.toCond()
  387. count, err := x.Where(cond).Count(&RewardOperateRecord{})
  388. if err != nil {
  389. return nil, 0, err
  390. }
  391. r := make([]*RewardOperateRecordShow, 0)
  392. switch opts.OperateType {
  393. case OperateTypeIncrease:
  394. err = x.Table("reward_operate_record").Cols("reward_operate_record.source_id", "reward_operate_record.serial_no",
  395. "reward_operate_record.status", "reward_operate_record.operate_type", "reward_operate_record.amount",
  396. "reward_operate_record.loss_amount", "reward_operate_record.remark", "reward_operate_record.source_type",
  397. "reward_operate_record.last_operate_unix as last_operate_date", "public.user.name as user_name",
  398. "point_account_log.balance_after").
  399. Join("LEFT", "public.user", "reward_operate_record.user_id = public.user.id").
  400. Join("LEFT", "point_account_log", " reward_operate_record.serial_no = point_account_log.source_id").
  401. Where(cond).Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).OrderBy(string(opts.OrderBy)).Find(&r)
  402. case OperateTypeDecrease:
  403. err = x.Table("reward_operate_record").Cols("reward_operate_record.source_id", "reward_operate_record.serial_no",
  404. "reward_operate_record.status", "reward_operate_record.operate_type", "reward_operate_record.amount",
  405. "reward_operate_record.loss_amount", "reward_operate_record.remark", "reward_operate_record.source_type",
  406. "reward_operate_record.last_operate_unix as last_operate_date", "public.user.name as user_name",
  407. "reward_periodic_task.amount as unit_price", "reward_periodic_task.success_count").
  408. Join("LEFT", "public.user", "reward_operate_record.user_id = public.user.id").
  409. Join("LEFT", "reward_periodic_task", "reward_operate_record.serial_no = reward_periodic_task.operate_serial_no").
  410. Where(cond).Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).OrderBy(string(opts.OrderBy)).Find(&r)
  411. }
  412. if err != nil {
  413. return nil, 0, err
  414. }
  415. RewardRecordShowList(r).loadAttribute(true)
  416. return r, count, nil
  417. }
  418. func IsWechatOpenIdRewarded(wechatOpenId string) bool {
  419. actions := make([]Action, 0)
  420. err := x.Where(" op_type = ? and content = ?", ActionBindWechat, wechatOpenId).Find(&actions)
  421. if err != nil {
  422. log.Error("IsWechatOpenIdRewarded find actions err.%v", err)
  423. return true
  424. }
  425. if len(actions) == 0 {
  426. return false
  427. }
  428. actionIds := make([]int64, len(actions))
  429. for i, v := range actions {
  430. actionIds[i] = v.ID
  431. }
  432. n, _ := x.Where(builder.Eq{"source_type": SourceTypeAccomplishTask}.And(builder.In("source_id", actionIds))).Count(&RewardOperateRecord{})
  433. return n > 0
  434. }