|
- package rule
-
- import (
- "code.fnuoos.com/EggPlanet/egg_models.git/src/implement"
- "code.fnuoos.com/EggPlanet/egg_models.git/src/model"
- zhios_order_relate_utils "code.fnuoos.com/EggPlanet/egg_models.git/utils"
- "code.fnuoos.com/EggPlanet/egg_system_rules.git/md"
- md2 "code.fnuoos.com/EggPlanet/egg_system_rules.git/rule/egg_energy/md"
- "code.fnuoos.com/EggPlanet/egg_system_rules.git/svc"
- "code.fnuoos.com/EggPlanet/egg_system_rules.git/utils/cache"
- "errors"
- "fmt"
- "github.com/shopspring/decimal"
- "strconv"
- "time"
- "xorm.io/xorm"
- )
-
- // DealUserVirtualCoin 处理给用户虚拟币积分
- func DealUserVirtualCoin(session *xorm.Session, req md.DealUserVirtualCoinReq) (err error) {
- if req.Amount < 0 {
- req.Amount = 0
- }
- //1、分布式锁阻拦
- requestIdPrefix := fmt.Sprintf(md2.DealUserCoinRequestIdPrefix, req.CoinId, req.Uid)
- cb, err := svc.HandleDistributedLock(zhios_order_relate_utils.Int64ToStr(req.Uid), strconv.Itoa(req.CoinId), requestIdPrefix)
- if err != nil {
- return err
- }
- if cb != nil {
- defer cb() // 释放锁
- }
-
- //2、计算&&组装数据
- now := time.Now()
- coinAmount, err := GetUserCoinAmount(session, req.CoinId, req.Uid)
- if err != nil {
- return err
- }
- coinAmountValue := decimal.NewFromFloat(zhios_order_relate_utils.StrToFloat64(coinAmount))
- amountValue := decimal.NewFromFloat(req.Amount).RoundFloor(4)
-
- var userVirtualCoinFlow model.UserVirtualCoinFlow
- userVirtualCoinFlow.CoinId = req.CoinId
- userVirtualCoinFlow.Title = req.Title
- userVirtualCoinFlow.TransferType = req.TransferType
- userVirtualCoinFlow.Uid = req.Uid
- userVirtualCoinFlow.BeforeAmount = coinAmount
- userVirtualCoinFlow.Amount = amountValue.String()
- userVirtualCoinFlow.CreateAt = now.Format("2006-01-02 15:04:05")
-
- if req.Kind == "add" {
- userVirtualCoinFlow.Direction = 1
- userVirtualCoinFlow.AfterAmount = coinAmountValue.Add(amountValue).RoundFloor(8).String()
- } else if req.Kind == "sub" {
- userVirtualCoinFlow.Direction = 2
- userVirtualCoinFlow.AfterAmount = coinAmountValue.Sub(amountValue).RoundFloor(8).String()
- if zhios_order_relate_utils.StrToFloat64(userVirtualCoinFlow.AfterAmount) < 0 {
- var coin model.VirtualCoin
- _, err = session.Where("id = ?", req.CoinId).Get(&coin)
- if err != nil {
- return err
- }
- zhios_order_relate_utils.FilePutContents("virtual_coin_not", zhios_order_relate_utils.SerializeStr(map[string]interface{}{
- "uid": userVirtualCoinFlow.Uid,
- "amount": userVirtualCoinFlow.Amount,
- "before_amount": userVirtualCoinFlow.BeforeAmount,
- "after_amount": userVirtualCoinFlow.AfterAmount,
- "coin_id": userVirtualCoinFlow.CoinId,
- }))
- return errors.New("用户" + zhios_order_relate_utils.Int64ToStr(userVirtualCoinFlow.Uid) + "的" + coin.Name + "不足")
- }
- } else {
- err = errors.New("错误的kind类型")
- return err
- }
-
- //3、插入 `user_virtual_coin_flow` 记录
- userVirtualCoinFlowDb := implement.NewUserVirtualCoinFlowDb(session.Engine())
- _, err = userVirtualCoinFlowDb.UserVirtualCoinFlowInsertBySession(session, &userVirtualCoinFlow)
- if err != nil {
- return err
- }
-
- //4、修改 `user_virtual_amount`的amount值 && 及缓存
- err = SetCacheUserVirtualAmount(session, userVirtualCoinFlow.AfterAmount, req.CoinId, req.Uid, true)
- if err != nil {
- return err
- }
-
- return nil
- }
-
- // GetUserCoinAmount 获取用户虚拟积分余额
- func GetUserCoinAmount(session *xorm.Session, coinId int, uid int64) (amount string, err error) {
- redisKey := fmt.Sprintf(md.UserVirtualAmountRedisKey, coinId, uid)
- amount, err = cache.GetString(redisKey)
- if err != nil {
- if err.Error() == "redigo: nil returned" {
- userVirtualAmountDb := implement.NewUserVirtualAmountDb(session.Engine())
- userVirtualAmount, err := userVirtualAmountDb.GetUserVirtualWalletBySession(uid, coinId)
- if err != nil {
- return amount, err
- }
- if userVirtualAmount == nil {
- amount = "0"
- } else {
- amount = userVirtualAmount.Amount
- }
- //将获取到的余额值缓存至redis
- _ = SetCacheUserVirtualAmount(session, amount, coinId, uid, false)
- return amount, nil
- }
- return amount, err
- }
- return amount, nil
- }
-
- // SetCacheUserVirtualAmount 设置缓存的用户虚拟币积分余额
- func SetCacheUserVirtualAmount(session *xorm.Session, amount string, coinId int, uid int64, isUpdateDb bool) error {
- redisKey := fmt.Sprintf(md.UserVirtualAmountRedisKey, coinId, uid)
- if isUpdateDb {
- _, err := session.Where("uid=?", uid).And("coin_id=?", coinId).Update(model.UserVirtualAmount{
- Uid: uid,
- CoinId: coinId,
- Amount: amount,
- })
- if err != nil {
- return err
- }
- }
- //TODO::默认缓存1小时 (先调整为 20 min)
- _, err := cache.SetEx(redisKey, zhios_order_relate_utils.StrToFloat64(amount), 60*20)
- if err != nil {
- return err
- }
- return nil
- }
|