广告平台(站长使用)
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.
 
 
 
 
 

145 lines
4.3 KiB

  1. package svc
  2. import (
  3. "applet/app/md"
  4. "applet/app/utils/cache"
  5. db "code.fnuoos.com/zhimeng/model.git/src"
  6. "code.fnuoos.com/zhimeng/model.git/src/super/implement"
  7. "code.fnuoos.com/zhimeng/model.git/src/super/model"
  8. zhios_order_relate_utils "code.fnuoos.com/zhimeng/model.git/utils"
  9. zhios_order_relate_logx "code.fnuoos.com/zhimeng/model.git/utils/logx"
  10. "errors"
  11. "fmt"
  12. "github.com/shopspring/decimal"
  13. "strconv"
  14. "time"
  15. "xorm.io/xorm"
  16. )
  17. // DealAgentAmount 处理给代理余额
  18. func DealAgentAmount(session *xorm.Session, req md.DealAgentAmount) (err error) {
  19. if req.Amount < 0 {
  20. req.Amount = 0
  21. }
  22. //1、分布式锁阻拦
  23. requestIdPrefix := fmt.Sprintf(md.DealAgentAmountRequestIdPrefix, req.Mid, req.AgentId)
  24. cb, err := HandleBalanceDistributedLockForAgent(req.Mid, strconv.Itoa(req.AgentId), requestIdPrefix)
  25. if err != nil {
  26. return err
  27. }
  28. if cb != nil {
  29. defer cb() // 释放锁
  30. }
  31. //2、计算&&组装数据
  32. now := time.Now()
  33. userAmount, err := GetAgentAmount(session, req.Mid, req.AgentId, true)
  34. if err != nil {
  35. return err
  36. }
  37. userAmountValue := decimal.NewFromFloat(zhios_order_relate_utils.StrToFloat64(userAmount))
  38. amountValue := decimal.NewFromFloat(req.Amount).RoundFloor(4)
  39. var finUserFlow = model.FinAgentFlow{
  40. AgentId: req.AgentId,
  41. Type: req.Type,
  42. Amount: amountValue.String(),
  43. BeforeAmount: userAmount,
  44. OrdId: req.OrdId,
  45. Kind: req.Kind,
  46. Memo: req.Memo,
  47. CreateAt: now.Format("2006-01-02 15:04:05"),
  48. UpdateAt: now.Format("2006-01-02 15:04:05"),
  49. }
  50. if req.Type == md.FinAgentFlowDirectionIncome {
  51. finUserFlow.AfterAmount = userAmountValue.Add(amountValue).RoundFloor(4).String()
  52. } else if req.Type == md.FinAgentFlowDirectionExpenditure {
  53. finUserFlow.AfterAmount = userAmountValue.Sub(amountValue).RoundFloor(4).String()
  54. } else {
  55. err = errors.New("错误的kind类型")
  56. return err
  57. }
  58. if zhios_order_relate_utils.StrToFloat64(finUserFlow.AfterAmount) < 0 {
  59. zhios_order_relate_utils.FilePutContents("agent_amount_not", zhios_order_relate_utils.SerializeStr(map[string]interface{}{
  60. "agent_id": finUserFlow.AgentId,
  61. "amount": finUserFlow.Amount,
  62. "before_amount": finUserFlow.BeforeAmount,
  63. "memo": finUserFlow.Memo,
  64. "mid": req.Mid,
  65. }))
  66. return errors.New("代理余额不足")
  67. }
  68. //3、插入 `fin_user_flow` 记录
  69. affected, err := session.Insert(&finUserFlow)
  70. if affected == 0 || err != nil {
  71. _ = zhios_order_relate_logx.Warn(err)
  72. return err
  73. }
  74. //4、修改 `user_profile`的fin_valid值 && 及缓存
  75. err = SetCacheAgentAmount(session, req.Mid, finUserFlow.AfterAmount, req.AgentId, true)
  76. if err != nil {
  77. return err
  78. }
  79. return nil
  80. }
  81. // GetAgentAmount 获取代理余额
  82. func GetAgentAmount(session *xorm.Session, masterId string, agentId int, isForceUpdate bool) (amount string, err error) {
  83. if isForceUpdate {
  84. agentListDb := implement.NewAgentListDb(db.Db)
  85. agent, err1 := agentListDb.GetAgentListBySession(session, agentId)
  86. if err1 != nil {
  87. return amount, err1
  88. }
  89. if agent == nil {
  90. amount = "0"
  91. } else {
  92. amount = agent.Amount
  93. }
  94. //将获取到的余额值缓存至redis
  95. _ = SetCacheAgentAmount(session, masterId, amount, agentId, false)
  96. } else {
  97. redisKey := fmt.Sprintf(md.AgentAmountRedisKey, masterId, agentId)
  98. amount, err = cache.GetString(redisKey)
  99. if err != nil && err.Error() != "redigo: nil returned" {
  100. return
  101. }
  102. agentListDb := implement.NewAgentListDb(db.Db)
  103. agent, err1 := agentListDb.GetAgentListBySession(session, agentId)
  104. if err1 != nil {
  105. return amount, err1
  106. }
  107. if agent == nil {
  108. amount = "0"
  109. } else {
  110. amount = agent.Amount
  111. }
  112. //将获取到的余额值缓存至redis
  113. _ = SetCacheAgentAmount(session, masterId, amount, agentId, false)
  114. }
  115. return amount, nil
  116. }
  117. // SetCacheAgentAmount 设置缓存的用户余额
  118. func SetCacheAgentAmount(session *xorm.Session, masterId, amount string, agentId int, isUpdateDb bool) error {
  119. redisKey := fmt.Sprintf(md.AgentAmountRedisKey, masterId, agentId)
  120. if isUpdateDb {
  121. _, err := session.Where("agent_id=?", agentId).Update(model.AgentList{
  122. AgentId: agentId,
  123. Amount: amount,
  124. })
  125. if err != nil {
  126. return err
  127. }
  128. }
  129. //TODO::默认缓存1小时 (先调整为 2 min)
  130. _, err := cache.SetEx(redisKey, zhios_order_relate_utils.StrToFloat64(amount), 60*0.5)
  131. if err != nil {
  132. return err
  133. }
  134. return nil
  135. }