|
- package svc
-
- import (
- "applet/app/md"
- "applet/app/utils/cache"
- db "code.fnuoos.com/zhimeng/model.git/src"
- "code.fnuoos.com/zhimeng/model.git/src/super/implement"
- "code.fnuoos.com/zhimeng/model.git/src/super/model"
- zhios_order_relate_utils "code.fnuoos.com/zhimeng/model.git/utils"
- zhios_order_relate_logx "code.fnuoos.com/zhimeng/model.git/utils/logx"
- "errors"
- "fmt"
- "github.com/shopspring/decimal"
- "strconv"
- "time"
- "xorm.io/xorm"
- )
-
- // DealMediumAmount 处理给媒体余额
- func DealMediumAmount(session *xorm.Session, req md.DealMediumAmount) (err error) {
- if req.Amount < 0 {
- req.Amount = 0
- }
- //1、分布式锁阻拦
- requestIdPrefix := fmt.Sprintf(md.DealMediumAmountRequestIdPrefix, req.Mid, req.MediumId)
- cb, err := HandleBalanceDistributedLockForMedium(req.Mid, strconv.Itoa(req.MediumId), requestIdPrefix)
- if err != nil {
- return err
- }
- if cb != nil {
- defer cb() // 释放锁
- }
-
- //2、计算&&组装数据
- now := time.Now()
- userAmount, err := GetMediumAmount(session, req.Mid, req.MediumId, true)
- if err != nil {
- return err
- }
- userAmountValue := decimal.NewFromFloat(zhios_order_relate_utils.StrToFloat64(userAmount))
- amountValue := decimal.NewFromFloat(req.Amount).RoundFloor(4)
-
- var finUserFlow = model.FinMediumFlow{
- MediumId: req.MediumId,
- Type: req.Type,
- Amount: amountValue.String(),
- BeforeAmount: userAmount,
- OrdId: req.OrdId,
- Kind: req.Kind,
- Memo: req.Memo,
- CreateAt: now.Format("2006-01-02 15:04:05"),
- UpdateAt: now.Format("2006-01-02 15:04:05"),
- }
- if req.Type == md.FinMediumFlowDirectionIncome {
- finUserFlow.AfterAmount = userAmountValue.Add(amountValue).RoundFloor(4).String()
- } else if req.Type == md.FinMediumFlowDirectionExpenditure {
- finUserFlow.AfterAmount = userAmountValue.Sub(amountValue).RoundFloor(4).String()
- } else {
- err = errors.New("错误的kind类型")
- return err
- }
- if zhios_order_relate_utils.StrToFloat64(finUserFlow.AfterAmount) < 0 {
- zhios_order_relate_utils.FilePutContents("medium_amount_not", zhios_order_relate_utils.SerializeStr(map[string]interface{}{
- "medium_id": finUserFlow.MediumId,
- "amount": finUserFlow.Amount,
- "before_amount": finUserFlow.BeforeAmount,
- "memo": finUserFlow.Memo,
- "mid": req.Mid,
- }))
- return errors.New("媒体余额不足")
- }
-
- //3、插入 `fin_user_flow` 记录
- affected, err := session.Insert(&finUserFlow)
- if affected == 0 || err != nil {
- _ = zhios_order_relate_logx.Warn(err)
- return err
- }
-
- //4、修改 `user_profile`的fin_valid值 && 及缓存
- err = SetCacheMediumAmount(session, req.Mid, finUserFlow.AfterAmount, req.MediumId, true)
- if err != nil {
- return err
- }
-
- return nil
- }
-
- // GetMediumAmount 获取媒体余额
- func GetMediumAmount(session *xorm.Session, masterId string, mediumId int, isForceUpdate bool) (amount string, err error) {
- if isForceUpdate {
- mediumListDb := implement.NewMediumListDb(db.Db)
- medium, err1 := mediumListDb.GetMediumListBySession(session, mediumId)
- if err1 != nil {
- return amount, err1
- }
- if medium == nil {
- amount = "0"
- } else {
- amount = medium.Amount
- }
- //将获取到的余额值缓存至redis
- _ = SetCacheMediumAmount(session, masterId, amount, mediumId, false)
- } else {
- redisKey := fmt.Sprintf(md.MediumAmountRedisKey, masterId, mediumId)
- amount, err = cache.GetString(redisKey)
- if err != nil && err.Error() != "redigo: nil returned" {
- return
- }
- mediumListDb := implement.NewMediumListDb(db.Db)
- medium, err1 := mediumListDb.GetMediumListBySession(session, mediumId)
- if err1 != nil {
- return amount, err1
- }
- if medium == nil {
- amount = "0"
- } else {
- amount = medium.Amount
- }
- //将获取到的余额值缓存至redis
- _ = SetCacheMediumAmount(session, masterId, amount, mediumId, false)
- }
- return amount, nil
- }
-
- // SetCacheMediumAmount 设置缓存的用户余额
- func SetCacheMediumAmount(session *xorm.Session, masterId, amount string, mediumId int, isUpdateDb bool) error {
- redisKey := fmt.Sprintf(md.MediumAmountRedisKey, masterId, mediumId)
- if isUpdateDb {
- _, err := session.Where("medium_id=?", mediumId).Update(model.MediumList{
- MediumId: mediumId,
- Amount: amount,
- })
- if err != nil {
- return err
- }
- }
- //TODO::默认缓存1小时 (先调整为 2 min)
- _, err := cache.SetEx(redisKey, zhios_order_relate_utils.StrToFloat64(amount), 60*0.5)
- if err != nil {
- return err
- }
- return nil
- }
|