com_handler_asset.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package services
  2. import (
  3. "app/commons/constant"
  4. "app/commons/model/entity"
  5. "fmt"
  6. "github.com/samber/lo"
  7. "github.com/shopspring/decimal"
  8. "gorm.io/gorm"
  9. )
  10. // 指定用户ID 获取当前有效币种信息 检查并写入资产信息
  11. // 兼容新增币种
  12. func (s *CommonService) GetAndCheckAssets(userId int64, uid string) ([]*entity.Asset, error) {
  13. coins, err := s.AllCoins(s.DB().Where("enable", true))
  14. if err != nil {
  15. return nil, err
  16. }
  17. allAsset, err := s.AllAssets(s.DB().Where("user_id", userId))
  18. if err != nil {
  19. return nil, err
  20. }
  21. if len(allAsset) == len(coins) {
  22. return allAsset, nil
  23. }
  24. haveCoin := make([]string, 0)
  25. for _, asset := range allAsset {
  26. haveCoin = append(haveCoin, asset.Symbol)
  27. }
  28. items := make([]*entity.Asset, 0)
  29. for _, item := range coins {
  30. if lo.Contains(haveCoin, item.Symbol) {
  31. continue
  32. }
  33. items = append(items, &entity.Asset{
  34. UserId: userId,
  35. Uid: uid,
  36. Symbol: item.Symbol,
  37. Balance: decimal.Zero,
  38. Frozen: decimal.Zero,
  39. TotalAmount: decimal.Zero,
  40. Version: 0,
  41. })
  42. }
  43. err = s.DB().Create(items).Error
  44. return items, err
  45. }
  46. // 获取单币种资产 -- 如果不存在则创建
  47. func (s *CommonService) GetAssetBySymbol(userId interface{}, symbol string) (*entity.Asset, error) {
  48. asset, err := GetOne[entity.Asset](s.DB().Where("user_id", userId), "symbol", symbol)
  49. if err == nil {
  50. return asset, nil
  51. }
  52. // 检查symbol 是否存在并启用
  53. _, err = s.FirstCoin(s.DB().Where("symbol", symbol).Where("enable", true))
  54. if err != nil {
  55. return nil, fmt.Errorf("symbol:%s is not sup", symbol)
  56. }
  57. user, err := s.GetUserByUserId(userId)
  58. if err != nil {
  59. return nil, err
  60. }
  61. asset = &entity.Asset{
  62. Uid: user.Uid,
  63. UserId: user.Id,
  64. Symbol: symbol,
  65. Balance: decimal.Zero,
  66. Frozen: decimal.Zero,
  67. TotalAmount: decimal.Zero,
  68. Version: 0,
  69. }
  70. err = s.DB().Create(&asset).Error
  71. return asset, err
  72. }
  73. func (s *CommonService) CheckUserAssetByUserIdSymbol(txDb *gorm.DB, userId interface{}, symbol string) (*entity.Asset, error) {
  74. asset, err := GetOne[entity.Asset](txDb.Where("user_id", userId), "symbol", symbol)
  75. if err == nil {
  76. return asset, nil
  77. }
  78. // 检查symbol 是否存在并启用
  79. _, err = s.FirstCoin(txDb.Where("symbol", symbol).Where("enable", true))
  80. if err != nil {
  81. return nil, fmt.Errorf("symbol:%s is not sup", symbol)
  82. }
  83. user, err := s.GetUserByUserId(userId)
  84. if err != nil {
  85. return nil, err
  86. }
  87. asset = &entity.Asset{
  88. Uid: user.Uid,
  89. UserId: user.Id,
  90. Symbol: symbol,
  91. Balance: decimal.Zero,
  92. Frozen: decimal.Zero,
  93. TotalAmount: decimal.Zero,
  94. Version: 0,
  95. }
  96. err = txDb.Create(&asset).Error
  97. return asset, err
  98. }
  99. // 构建资产流水记录
  100. func (s *CommonService) BuildBill(asset *entity.Asset, balance, frozen, amount decimal.Decimal, bs *constant.BusinessType) *entity.AssetBill {
  101. if bs.Desc == "" {
  102. bs.Desc = fmt.Sprintf("业务:%s\n变更前余额:%s 变更金额:%s 变更后:%s",
  103. bs.BusinessName,
  104. asset.TotalAmount.Truncate(8),
  105. amount.Truncate(8),
  106. asset.TotalAmount.Add(amount).Truncate(8))
  107. }
  108. return &entity.AssetBill{
  109. AssetId: asset.Id,
  110. UserId: asset.UserId,
  111. Uid: asset.Uid,
  112. Symbol: asset.Symbol,
  113. BeforeAmount: asset.TotalAmount,
  114. Balance: balance,
  115. Frozen: frozen,
  116. Amount: amount,
  117. AfterAmount: asset.TotalAmount.Add(amount),
  118. BusinessNumber: bs.BusinessNumber,
  119. BusinessName: bs.BusinessName,
  120. ContextName: bs.ContextName,
  121. ContextValue: bs.ContextValue,
  122. Describe: bs.Desc,
  123. }
  124. }
  125. // 生成资产流水并修改资产
  126. func (s *CommonService) GenBillAndActionAsset(txDB *gorm.DB, userId int64, symbol string, balance, frozen decimal.Decimal, bs *constant.BusinessType) error {
  127. var err error
  128. asset, err := s.FirstAsset(txDB.Where("user_id", userId).Where("symbol", symbol))
  129. if err != nil {
  130. return err
  131. }
  132. bill := s.BuildBill(asset, balance, frozen, balance.Add(frozen), bs)
  133. err = txDB.Create(&bill).Error
  134. if err != nil {
  135. return err
  136. }
  137. err = s.ActionAsset(txDB, asset.UserId, asset.Symbol, balance, frozen)
  138. if err != nil {
  139. return err
  140. }
  141. return err
  142. }
  143. // 修改资产
  144. func (s *CommonService) ActionAsset(txDb *gorm.DB, userId int64, symbol string, amount, frozen decimal.Decimal) error {
  145. return txDb.Model(&entity.Asset{}).
  146. Where("user_id", userId).
  147. Where("symbol", symbol).
  148. Updates(map[string]interface{}{
  149. "balance": gorm.Expr("balance + ?", amount.String()),
  150. "frozen": gorm.Expr("frozen + ?", frozen.String()),
  151. "total_amount": gorm.Expr("total_amount + ?", amount.Add(frozen).String()),
  152. "version": gorm.Expr("version + ?", 1),
  153. }).Error
  154. }