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
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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  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. SourceTemplateId string
  234. UserName string
  235. LastOperateDate timeutil.TimeStamp
  236. UnitPrice int64
  237. SuccessCount int
  238. Action *ActionShow
  239. Cloudbrain *CloudbrainShow
  240. AdminLog *RewardAdminLogShow
  241. }
  242. func getPointOperateRecord(tl *RewardOperateRecord) (*RewardOperateRecord, error) {
  243. has, err := x.Get(tl)
  244. if err != nil {
  245. return nil, err
  246. } else if !has {
  247. return nil, ErrRecordNotExist{}
  248. }
  249. return tl, nil
  250. }
  251. func GetPointOperateRecordBySourceTypeAndRequestId(sourceType, requestId, operateType string) (*RewardOperateRecord, error) {
  252. t := &RewardOperateRecord{
  253. SourceType: sourceType,
  254. RequestId: requestId,
  255. OperateType: operateType,
  256. }
  257. return getPointOperateRecord(t)
  258. }
  259. func GetPointOperateRecordBySerialNo(serialNo string) (*RewardOperateRecord, error) {
  260. t := &RewardOperateRecord{
  261. SerialNo: serialNo,
  262. }
  263. return getPointOperateRecord(t)
  264. }
  265. func InsertRewardOperateRecord(tl *RewardOperateRecord) (int64, error) {
  266. return x.Insert(tl)
  267. }
  268. func UpdateRewardRecordToFinalStatus(sourceType, requestId, newStatus string) (int64, error) {
  269. r := &RewardOperateRecord{
  270. Status: newStatus,
  271. LastOperateUnix: timeutil.TimeStampNow(),
  272. }
  273. return x.Cols("status", "last_operate_unix").Where("source_type=? and request_id=? and status=?", sourceType, requestId, OperateStatusOperating).Update(r)
  274. }
  275. func SumRewardAmountInTaskPeriod(rewardType string, sourceType string, userId int64, period *PeriodResult) (int64, error) {
  276. var cond = builder.NewCond()
  277. if period != nil {
  278. cond = cond.And(builder.Gte{"created_unix": period.StartTime.Unix()})
  279. cond = cond.And(builder.Lt{"created_unix": period.EndTime.Unix()})
  280. }
  281. if sourceType != "" {
  282. cond = cond.And(builder.Eq{"source_type": sourceType})
  283. }
  284. cond = cond.And(builder.Eq{"reward_type": rewardType})
  285. cond = cond.And(builder.Eq{"user_id": userId})
  286. return x.Where(cond).SumInt(&RewardOperateRecord{}, "amount")
  287. }
  288. type RewardOperateContext struct {
  289. SourceType SourceType
  290. SourceId string
  291. SourceTemplateId string
  292. Title string
  293. Remark string
  294. Reward Reward
  295. TargetUserId int64
  296. RequestId string
  297. OperateType RewardOperateType
  298. RejectPolicy LimiterRejectPolicy
  299. PermittedNegative bool
  300. LossAmount int64
  301. }
  302. type Reward struct {
  303. Amount int64
  304. Type RewardType
  305. }
  306. type UserRewardOperationRedis struct {
  307. UserId int64
  308. Amount int64
  309. RewardType RewardType
  310. OperateType RewardOperateType
  311. }
  312. type UserRewardOperation struct {
  313. UserId int64
  314. Msg string
  315. }
  316. func AppendRemark(remark, appendStr string) string {
  317. return strings.TrimPrefix(remark+Semicolon+appendStr, Semicolon)
  318. }
  319. type RewardRecordListOpts struct {
  320. ListOptions
  321. UserId int64
  322. UserName string
  323. OperateType RewardOperateType
  324. RewardType RewardType
  325. SourceType string
  326. TaskType string
  327. SerialNo string
  328. OrderBy RewardOperateOrderBy
  329. IsAdmin bool
  330. Status string
  331. }
  332. func (opts *RewardRecordListOpts) toCond() builder.Cond {
  333. if opts.Page <= 0 {
  334. opts.Page = 1
  335. }
  336. if len(opts.OrderBy) == 0 {
  337. opts.OrderBy = RewardOrderByIDDesc
  338. }
  339. cond := builder.NewCond()
  340. if opts.UserId > 0 {
  341. cond = cond.And(builder.Eq{"reward_operate_record.user_id": opts.UserId})
  342. }
  343. if opts.OperateType != OperateTypeNull {
  344. cond = cond.And(builder.Eq{"reward_operate_record.operate_type": opts.OperateType.Name()})
  345. }
  346. if opts.SourceType != "" {
  347. cond = cond.And(builder.Eq{"reward_operate_record.source_type": opts.SourceType})
  348. }
  349. if opts.TaskType != "" {
  350. cond = cond.And(builder.Eq{"reward_operate_record.source_template_id": opts.TaskType})
  351. }
  352. if opts.SerialNo != "" {
  353. cond = cond.And(builder.Like{"reward_operate_record.serial_no", opts.SerialNo})
  354. }
  355. if opts.Status != "" {
  356. cond = cond.And(builder.Like{"reward_operate_record.status", opts.Status})
  357. }
  358. cond = cond.And(builder.Eq{"reward_operate_record.reward_type": opts.RewardType.Name()})
  359. cond = cond.And(builder.Gt{"reward_operate_record.amount": 0})
  360. return cond
  361. }
  362. type TestTT struct {
  363. SerialNo string
  364. UserId int64
  365. Amount int64
  366. UserName string
  367. }
  368. func GetRewardRecordShowList(opts *RewardRecordListOpts) (RewardRecordShowList, int64, error) {
  369. cond := opts.toCond()
  370. count, err := x.Where(cond).Count(&RewardOperateRecord{})
  371. if err != nil {
  372. return nil, 0, err
  373. }
  374. r := make([]*RewardOperateRecordShow, 0)
  375. err = x.Table("reward_operate_record").Cols("reward_operate_record.source_id", "reward_operate_record.serial_no",
  376. "reward_operate_record.status", "reward_operate_record.operate_type", "reward_operate_record.amount",
  377. "reward_operate_record.loss_amount", "reward_operate_record.remark", "reward_operate_record.source_type", "reward_operate_record.source_template_id",
  378. "reward_operate_record.last_operate_unix as last_operate_date").
  379. Where(cond).Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).OrderBy(string(opts.OrderBy)).Find(&r)
  380. if err != nil {
  381. return nil, 0, err
  382. }
  383. RewardRecordShowList(r).loadAttribute(false)
  384. return r, count, nil
  385. }
  386. func GetAdminRewardRecordShowList(opts *RewardRecordListOpts) (RewardRecordShowList, int64, error) {
  387. cond := opts.toCond()
  388. count, err := x.Where(cond).Count(&RewardOperateRecord{})
  389. if err != nil {
  390. return nil, 0, err
  391. }
  392. r := make([]*RewardOperateRecordShow, 0)
  393. switch opts.OperateType {
  394. case OperateTypeIncrease:
  395. err = x.Table("reward_operate_record").Cols("reward_operate_record.source_id", "reward_operate_record.serial_no",
  396. "reward_operate_record.status", "reward_operate_record.operate_type", "reward_operate_record.amount",
  397. "reward_operate_record.loss_amount", "reward_operate_record.remark", "reward_operate_record.source_type", "reward_operate_record.source_template_id",
  398. "reward_operate_record.last_operate_unix as last_operate_date", "public.user.name as user_name",
  399. "point_account_log.balance_after").
  400. Join("LEFT", "public.user", "reward_operate_record.user_id = public.user.id").
  401. Join("LEFT", "point_account_log", " reward_operate_record.serial_no = point_account_log.source_id").
  402. Where(cond).Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).OrderBy(string(opts.OrderBy)).Find(&r)
  403. case OperateTypeDecrease:
  404. err = x.Table("reward_operate_record").Cols("reward_operate_record.source_id", "reward_operate_record.serial_no",
  405. "reward_operate_record.status", "reward_operate_record.operate_type", "reward_operate_record.amount",
  406. "reward_operate_record.loss_amount", "reward_operate_record.remark", "reward_operate_record.source_type", "reward_operate_record.source_template_id",
  407. "reward_operate_record.last_operate_unix as last_operate_date", "public.user.name as user_name",
  408. "reward_periodic_task.amount as unit_price", "reward_periodic_task.success_count").
  409. Join("LEFT", "public.user", "reward_operate_record.user_id = public.user.id").
  410. Join("LEFT", "reward_periodic_task", "reward_operate_record.serial_no = reward_periodic_task.operate_serial_no").
  411. Where(cond).Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).OrderBy(string(opts.OrderBy)).Find(&r)
  412. }
  413. if err != nil {
  414. return nil, 0, err
  415. }
  416. RewardRecordShowList(r).loadAttribute(true)
  417. return r, count, nil
  418. }
  419. func IsWechatOpenIdRewarded(wechatOpenId string) bool {
  420. actions := make([]Action, 0)
  421. err := x.Where(" op_type = ? and content = ?", ActionBindWechat, wechatOpenId).Find(&actions)
  422. if err != nil {
  423. log.Error("IsWechatOpenIdRewarded find actions err.%v", err)
  424. return true
  425. }
  426. if len(actions) == 0 {
  427. return false
  428. }
  429. actionIds := make([]int64, len(actions))
  430. for i, v := range actions {
  431. actionIds[i] = v.ID
  432. }
  433. n, _ := x.Where(builder.Eq{"source_type": SourceTypeAccomplishTask}.And(builder.In("source_id", actionIds))).Count(&RewardOperateRecord{})
  434. return n > 0
  435. }