package services import ( "app/commons/constant" "app/commons/model/entity" "fmt" "github.com/samber/lo" "github.com/shopspring/decimal" "gorm.io/gorm" ) // 指定用户ID 获取当前有效币种信息 检查并写入资产信息 // 兼容新增币种 func (s *CommonService) GetAndCheckAssets(userId int64, uid string) ([]*entity.Asset, error) { coins, err := s.AllCoins(s.DB().Where("enable", true)) if err != nil { return nil, err } allAsset, err := s.AllAssets(s.DB().Where("user_id", userId)) if err != nil { return nil, err } if len(allAsset) == len(coins) { return allAsset, nil } haveCoin := make([]string, 0) for _, asset := range allAsset { haveCoin = append(haveCoin, asset.Symbol) } items := make([]*entity.Asset, 0) for _, item := range coins { if lo.Contains(haveCoin, item.Symbol) { continue } items = append(items, &entity.Asset{ UserId: userId, Uid: uid, Symbol: item.Symbol, Balance: decimal.Zero, Frozen: decimal.Zero, TotalAmount: decimal.Zero, Version: 0, }) } err = s.DB().Create(items).Error return items, err } // 获取单币种资产 -- 如果不存在则创建 func (s *CommonService) GetAssetBySymbol(userId interface{}, symbol string) (*entity.Asset, error) { asset, err := GetOne[entity.Asset](s.DB().Where("user_id", userId), "symbol", symbol) if err == nil { return asset, nil } // 检查symbol 是否存在并启用 _, err = s.FirstCoin(s.DB().Where("symbol", symbol).Where("enable", true)) if err != nil { return nil, fmt.Errorf("symbol:%s is not sup", symbol) } user, err := s.GetUserByUserId(userId) if err != nil { return nil, err } asset = &entity.Asset{ Uid: user.Uid, UserId: user.Id, Symbol: symbol, Balance: decimal.Zero, Frozen: decimal.Zero, TotalAmount: decimal.Zero, Version: 0, } err = s.DB().Create(&asset).Error return asset, err } func (s *CommonService) CheckUserAssetByUserIdSymbol(txDb *gorm.DB, userId interface{}, symbol string) (*entity.Asset, error) { asset, err := GetOne[entity.Asset](txDb.Where("user_id", userId), "symbol", symbol) if err == nil { return asset, nil } // 检查symbol 是否存在并启用 _, err = s.FirstCoin(txDb.Where("symbol", symbol).Where("enable", true)) if err != nil { return nil, fmt.Errorf("symbol:%s is not sup", symbol) } user, err := s.GetUserByUserId(userId) if err != nil { return nil, err } asset = &entity.Asset{ Uid: user.Uid, UserId: user.Id, Symbol: symbol, Balance: decimal.Zero, Frozen: decimal.Zero, TotalAmount: decimal.Zero, Version: 0, } err = txDb.Create(&asset).Error return asset, err } // 构建资产流水记录 func (s *CommonService) BuildBill(asset *entity.Asset, balance, frozen, amount decimal.Decimal, bs *constant.BusinessType) *entity.AssetBill { if bs.Desc == "" { bs.Desc = fmt.Sprintf("业务:%s\n变更前余额:%s 变更金额:%s 变更后:%s", bs.BusinessName, asset.TotalAmount.Truncate(8), amount.Truncate(8), asset.TotalAmount.Add(amount).Truncate(8)) } return &entity.AssetBill{ AssetId: asset.Id, UserId: asset.UserId, Uid: asset.Uid, Symbol: asset.Symbol, BeforeAmount: asset.TotalAmount, Balance: balance, Frozen: frozen, Amount: amount, AfterAmount: asset.TotalAmount.Add(amount), BusinessNumber: bs.BusinessNumber, BusinessName: bs.BusinessName, ContextName: bs.ContextName, ContextValue: bs.ContextValue, Describe: bs.Desc, } } // 生成资产流水并修改资产 func (s *CommonService) GenBillAndActionAsset(txDB *gorm.DB, userId int64, symbol string, balance, frozen decimal.Decimal, bs *constant.BusinessType) error { var err error asset, err := s.FirstAsset(txDB.Where("user_id", userId).Where("symbol", symbol)) if err != nil { return err } bill := s.BuildBill(asset, balance, frozen, balance.Add(frozen), bs) err = txDB.Create(&bill).Error if err != nil { return err } err = s.ActionAsset(txDB, asset.UserId, asset.Symbol, balance, frozen) if err != nil { return err } return err } // 修改资产 func (s *CommonService) ActionAsset(txDb *gorm.DB, userId int64, symbol string, amount, frozen decimal.Decimal) error { return txDb.Model(&entity.Asset{}). Where("user_id", userId). Where("symbol", symbol). Updates(map[string]interface{}{ "balance": gorm.Expr("balance + ?", amount.String()), "frozen": gorm.Expr("frozen + ?", frozen.String()), "total_amount": gorm.Expr("total_amount + ?", amount.Add(frozen).String()), "version": gorm.Expr("version + ?", 1), }).Error }