|
|
@@ -0,0 +1,121 @@ |
|
|
|
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" |
|
|
|
"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" |
|
|
|
"time" |
|
|
|
"xorm.io/xorm" |
|
|
|
) |
|
|
|
|
|
|
|
// DealUserWallet 处理给用户金额 |
|
|
|
func DealUserWallet(session *xorm.Session, req md.DealUserWalletReq) (err error) { |
|
|
|
if req.Amount < 0 { |
|
|
|
req.Amount = 0 |
|
|
|
} |
|
|
|
//1、分布式锁阻拦 |
|
|
|
requestIdPrefix := fmt.Sprintf(md.UserWalletRedisKey, req.Uid) |
|
|
|
cb, err := svc.HandleDistributedLockForUserWallet(zhios_order_relate_utils.Int64ToStr(req.Uid), requestIdPrefix) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
if cb != nil { |
|
|
|
defer cb() // 释放锁 |
|
|
|
} |
|
|
|
|
|
|
|
//2、计算&&组装数据 |
|
|
|
now := time.Now() |
|
|
|
userAmount, err := GetUserWalletAmount(session, req.Uid) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
amountValue := decimal.NewFromFloat(req.Amount).RoundFloor(4) |
|
|
|
|
|
|
|
var userWalletFlow model.UserWalletFlow |
|
|
|
userWalletFlow.Uid = req.Uid |
|
|
|
userWalletFlow.Title = req.Title |
|
|
|
userWalletFlow.Kind = req.Kind |
|
|
|
userWalletFlow.BeforeAmount = userAmount |
|
|
|
userWalletFlow.Amount = amountValue.String() |
|
|
|
userWalletFlow.CreateAt = now.Format("2006-01-02 15:04:05") |
|
|
|
|
|
|
|
if req.Direction == "add" { |
|
|
|
userWalletFlow.Direction = 1 |
|
|
|
userWalletFlow.AfterAmount = amountValue.Add(amountValue).RoundFloor(8).String() |
|
|
|
} else if req.Direction == "sub" { |
|
|
|
userWalletFlow.Direction = 2 |
|
|
|
userWalletFlow.AfterAmount = amountValue.Sub(amountValue).RoundFloor(8).String() |
|
|
|
if zhios_order_relate_utils.StrToFloat64(userWalletFlow.AfterAmount) < 0 { |
|
|
|
return errors.New("用户钱包余额不足") |
|
|
|
} |
|
|
|
} else { |
|
|
|
err = errors.New("错误的Direction类型") |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
//3、插入 `user_wallet_flow` 记录 |
|
|
|
userWalletFlowDb := implement.NewUserWalletFlowDb(session.Engine()) |
|
|
|
_, err = userWalletFlowDb.UserWalletFlowInsertBySession(session, &userWalletFlow) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
//4、修改 `user_wallet`的amount值 && 及缓存 |
|
|
|
err = SetUserWalletAmount(session, userWalletFlow.AfterAmount, req.Uid, true) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
// GetUserWalletAmount 获取用户钱包余额 |
|
|
|
func GetUserWalletAmount(session *xorm.Session, uid int64) (amount string, err error) { |
|
|
|
redisKey := fmt.Sprintf(md.UserWalletRedisKey, uid) |
|
|
|
amount, err = cache.GetString(redisKey) |
|
|
|
if err != nil { |
|
|
|
if err.Error() == "redigo: nil returned" { |
|
|
|
userWalletDb := implement.NewUserWalletDb(session.Engine()) |
|
|
|
userVirtualAmount, err := userWalletDb.GetUserVirtualWallet(uid) |
|
|
|
if err != nil { |
|
|
|
return amount, err |
|
|
|
} |
|
|
|
if userVirtualAmount == nil { |
|
|
|
amount = "0" |
|
|
|
} else { |
|
|
|
amount = userVirtualAmount.Amount |
|
|
|
} |
|
|
|
//将获取到的余额值缓存至redis |
|
|
|
_ = SetUserWalletAmount(session, amount, uid, false) |
|
|
|
return amount, nil |
|
|
|
} |
|
|
|
return amount, err |
|
|
|
} |
|
|
|
return amount, nil |
|
|
|
} |
|
|
|
|
|
|
|
// SetUserWalletAmount 设置缓存的用户虚拟币积分余额 |
|
|
|
func SetUserWalletAmount(session *xorm.Session, amount string, uid int64, isUpdateDb bool) error { |
|
|
|
redisKey := fmt.Sprintf(md.UserWalletRedisKey, uid) |
|
|
|
if isUpdateDb { |
|
|
|
_, err := session.Where("uid=?", uid).Update(model.UserWallet{ |
|
|
|
Uid: uid, |
|
|
|
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 |
|
|
|
} |