蛋蛋星球-制度模式
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

user_virtual_coin.go 4.7 KiB

1 month ago
1 month ago
1 month ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package rule
  2. import (
  3. "code.fnuoos.com/EggPlanet/egg_models.git/src/implement"
  4. "code.fnuoos.com/EggPlanet/egg_models.git/src/model"
  5. zhios_order_relate_utils "code.fnuoos.com/EggPlanet/egg_models.git/utils"
  6. "code.fnuoos.com/EggPlanet/egg_system_rules.git/md"
  7. md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md"
  8. "code.fnuoos.com/EggPlanet/egg_system_rules.git/svc"
  9. "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache"
  10. "errors"
  11. "fmt"
  12. "github.com/shopspring/decimal"
  13. "strconv"
  14. "time"
  15. "xorm.io/xorm"
  16. )
  17. // DealUserVirtualCoin 处理给用户虚拟币积分
  18. func DealUserVirtualCoin(session *xorm.Session, req md.DealUserVirtualCoinReq) (err error) {
  19. if req.Amount < 0 {
  20. req.Amount = 0
  21. }
  22. //1、分布式锁阻拦
  23. requestIdPrefix := fmt.Sprintf(md2.DealUserCoinRequestIdPrefix, req.CoinId, req.Uid)
  24. cb, err := svc.HandleDistributedLock(zhios_order_relate_utils.Int64ToStr(req.Uid), strconv.Itoa(req.CoinId), requestIdPrefix)
  25. if err != nil {
  26. return err
  27. }
  28. if cb != nil {
  29. defer cb() // 释放锁
  30. }
  31. //2、计算&&组装数据
  32. now := time.Now()
  33. coinAmount, err := GetUserCoinAmount(session, req.CoinId, req.Uid)
  34. if err != nil {
  35. return err
  36. }
  37. coinAmountValue := decimal.NewFromFloat(zhios_order_relate_utils.StrToFloat64(coinAmount))
  38. amountValue := decimal.NewFromFloat(req.Amount).RoundFloor(4)
  39. var userVirtualCoinFlow model.UserVirtualCoinFlow
  40. userVirtualCoinFlow.CoinId = req.CoinId
  41. userVirtualCoinFlow.Title = req.Title
  42. userVirtualCoinFlow.TransferType = req.TransferType
  43. userVirtualCoinFlow.Uid = req.Uid
  44. userVirtualCoinFlow.BeforeAmount = coinAmount
  45. userVirtualCoinFlow.Amount = amountValue.String()
  46. userVirtualCoinFlow.CreateAt = now.Format("2006-01-02 15:04:05")
  47. if req.Kind == "add" {
  48. userVirtualCoinFlow.Direction = 1
  49. userVirtualCoinFlow.AfterAmount = coinAmountValue.Add(amountValue).RoundFloor(8).String()
  50. } else if req.Kind == "sub" {
  51. userVirtualCoinFlow.Direction = 2
  52. userVirtualCoinFlow.AfterAmount = coinAmountValue.Sub(amountValue).RoundFloor(8).String()
  53. if zhios_order_relate_utils.StrToFloat64(userVirtualCoinFlow.AfterAmount) < 0 {
  54. var coin model.VirtualCoin
  55. _, err = session.Where("id = ?", req.CoinId).Get(&coin)
  56. if err != nil {
  57. return err
  58. }
  59. zhios_order_relate_utils.FilePutContents("virtual_coin_not", zhios_order_relate_utils.SerializeStr(map[string]interface{}{
  60. "uid": userVirtualCoinFlow.Uid,
  61. "amount": userVirtualCoinFlow.Amount,
  62. "before_amount": userVirtualCoinFlow.BeforeAmount,
  63. "after_amount": userVirtualCoinFlow.AfterAmount,
  64. "coin_id": userVirtualCoinFlow.CoinId,
  65. }))
  66. return errors.New("用户" + zhios_order_relate_utils.Int64ToStr(userVirtualCoinFlow.Uid) + "的" + coin.Name + "不足")
  67. }
  68. } else {
  69. err = errors.New("错误的kind类型")
  70. return err
  71. }
  72. //3、插入 `user_virtual_coin_flow` 记录
  73. userVirtualCoinFlowDb := implement.NewUserVirtualCoinFlowDb(session.Engine())
  74. _, err = userVirtualCoinFlowDb.UserVirtualCoinFlowInsertBySession(session, &userVirtualCoinFlow)
  75. if err != nil {
  76. return err
  77. }
  78. //4、修改 `user_virtual_amount`的amount值 && 及缓存
  79. err = SetCacheUserVirtualAmount(session, userVirtualCoinFlow.AfterAmount, req.CoinId, req.Uid, true)
  80. if err != nil {
  81. return err
  82. }
  83. return nil
  84. }
  85. // GetUserCoinAmount 获取用户虚拟积分余额
  86. func GetUserCoinAmount(session *xorm.Session, coinId int, uid int64) (amount string, err error) {
  87. redisKey := fmt.Sprintf(md.UserVirtualAmountRedisKey, coinId, uid)
  88. amount, err = cache.GetString(redisKey)
  89. if err != nil {
  90. if err.Error() == "redigo: nil returned" {
  91. userVirtualAmountDb := implement.NewUserVirtualAmountDb(session.Engine())
  92. userVirtualAmount, err := userVirtualAmountDb.GetUserVirtualWalletBySession(uid, coinId)
  93. if err != nil {
  94. return amount, err
  95. }
  96. if userVirtualAmount == nil {
  97. amount = "0"
  98. } else {
  99. amount = userVirtualAmount.Amount
  100. }
  101. //将获取到的余额值缓存至redis
  102. _ = SetCacheUserVirtualAmount(session, amount, coinId, uid, false)
  103. return amount, nil
  104. }
  105. return amount, err
  106. }
  107. return amount, nil
  108. }
  109. // SetCacheUserVirtualAmount 设置缓存的用户虚拟币积分余额
  110. func SetCacheUserVirtualAmount(session *xorm.Session, amount string, coinId int, uid int64, isUpdateDb bool) error {
  111. redisKey := fmt.Sprintf(md.UserVirtualAmountRedisKey, coinId, uid)
  112. if isUpdateDb {
  113. _, err := session.Where("uid=?", uid).And("coin_id=?", coinId).Update(model.UserVirtualAmount{
  114. Uid: uid,
  115. CoinId: coinId,
  116. Amount: amount,
  117. })
  118. if err != nil {
  119. return err
  120. }
  121. }
  122. //TODO::默认缓存1小时 (先调整为 20 min)
  123. _, err := cache.SetEx(redisKey, zhios_order_relate_utils.StrToFloat64(amount), 60*20)
  124. if err != nil {
  125. return err
  126. }
  127. return nil
  128. }