package data import ( "context" "github.com/go-xorm/xorm" "github.com/shopspring/decimal" "matchmaking-system/internal/biz/structure" "matchmaking-system/internal/data/tradedeal/virtual" "matchmaking-system/internal/pkg/flags" "matchmaking-system/internal/pkg/logging/applogger" "matchmaking-system/internal/pkg/logging/common" "matchmaking-system/internal/pkg/setting" "matchmaking-system/internal/pkg/utils" "strings" orders "matchmaking-system/internal/data/convert" models "matchmaking-system/internal/pkg/model" ) // GetBotDigitalTradeList // // @Description: 现货列表查询 // @receiver uo // @param ctx // @param pageSize // @param pageCount // @param userId // @param status // @return []*models.BotDigitalTrade // @return int64 // @return error func (uo *userOrderRepo) GetBotDigitalTradeList(pageSize, pageCount, userId, status int64) ([]*models.BotDigitalTrade, int64, error) { totalCount, err := uo.data.mysqlDB.Table(flags.BotDigitalTrade). Where("user_id = ?", userId). Where("status = ?", status). Count() if err != nil { return nil, 0, flags.ErrMySqlDB } if totalCount == 0 { return nil, 0, nil } var digitalList []*models.BotDigitalTrade if err = uo.data.mysqlDB.Table(flags.BotDigitalTrade). Where("user_id = ?", userId). Where("status = ?", status). Limit(int(pageSize), int(pageCount)). Desc(GetOrderByStatusSort(status)). Find(&digitalList); err != nil { return nil, 0, flags.ErrMySqlDB } var digitalUpdateList []*models.BotDigitalTrade for _, value := range digitalList { value.KeepDecimal = GetKeepDecimal(flags.SpotsSystemSetUpKey, value.DigitalId) digitalUpdateList = append(digitalUpdateList, value) } return digitalUpdateList, totalCount, nil } // CreateBotDigitalTrade // // @Description: 现货下单 // @receiver uo // @param ctx // @param userId // @param order // @return string // @return error func (uo *userOrderRepo) CreateBotDigitalTrade(ctx context.Context, userId int64, order structure.SpotsOrder) (string, error) { // 1、下单通知订阅 digitalId := strings.ToLower(order.DigitalId) _, ok := spots.SpotsMapSymbol.Load(digitalId) if ok { go func() { spots.SpotsMap <- []byte(digitalId) }() } order.DigitalId = strings.ToUpper(order.DigitalId) // 2、交易币市价 priceNew, err := GetDigitalCurrencyPrice(ctx, flags.Xh, digitalId) if len(priceNew) == 0 || err != nil { applogger.Error("%v CreateBotDigitalTrade.DealSpotsMarketPrice:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrPriceUpdate } // 3、限价下单记录(1>下单判定 2>订单表 3>资产表[其他交易对]) order.DealPrice = priceNew orderId, err := uo.SpotOrdersDealDB(ctx, userId, order) if err != nil || len(orderId) == 0 { applogger.Error("%v CreateBotDigitalTrade.SpotOrdersDealDB:%v", common.ErrSpots, err) return flags.SetNull, err } // 4、写入缓存队列等待计算|平仓 switch order.DealType { case flags.DealTypeLimited: // 限价下单(限价买入挂单|限价卖出挂单) if err = virtual.DealSpotsLimitedPrice(uo.data.redisDB, userId, order, digitalId, orderId); err != nil { applogger.Error("%v CreateBotDigitalTrade.DealSpotsLimitedPrice:%v", common.ErrSpots, err) return flags.SetNull, err } case flags.DealTypeMarket: // 市价下单(市价买入平仓|市价卖出平仓) openPrice := decimal.RequireFromString(priceNew) // 市价下单平仓操作-->更新订单表|更新资产表|计算手续费|录入返佣明细|录入交易明细 orderId, err = SpotOrdersClosingDB(ctx, uo.data.mysqlDB, userId, order, orderId, openPrice.String()) if err != nil { applogger.Error("%v CreateBotDigitalTrade.SpotOrdersClosingDB:%v", common.ErrSpots, err) return flags.SetNull, err } default: return flags.SetNull, flags.ErrSpotMsgOne } return orderId, nil } // SpotOrdersClosingDB // // @Description: 现货平仓 // @param ctx // @param db // @param userId // @param order // @param orderId // @param closingPrice // @return string // @return error func SpotOrdersClosingDB(ctx context.Context, db *xorm.EngineGroup, userId int64, order structure.SpotsOrder, orderId, closingPrice string) (string, error) { session := db.NewSession() defer session.Close() err := session.Begin() if err != nil { applogger.Error("%v SpotOrdersClosingDB.NewSession:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } // 当前用户(买入|卖出)的(可用|冻结)资产 usableOld, frozenOld, _, err := Uo.GetBotUserDigital(session, userId, flags.BasicUnit) if err != nil { applogger.Error("%v SpotOrdersClosingDB.GetBotUserDigital:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } // 当前用户非(买入|卖出)的(可用|冻结)资产 var usableNoOld, frozenNoOld decimal.Decimal if order.DigitalId != flags.BasicUnit { usableNoOld, frozenNoOld, _, err = Uo.GetBotUserDigital(session, userId, order.DigitalId) if err != nil { applogger.Error("%v SpotOrdersClosingDB.GetBotUserDigital:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } } if !flags.CheckSetting { applogger.Debug("可用资产:%v", usableOld) applogger.Debug("冻结资产:%v", frozenOld) applogger.Debug("非可用资产:%v", usableNoOld) applogger.Debug("非冻结资产:%v", frozenNoOld) } // Operational Spot Asset Table orderNumber := decimal.RequireFromString(order.OrderNumber) // 订单数量 orderMoney := orderNumber.Mul(decimal.RequireFromString(order.DealPrice)) // 订单金额 = (订单数量 * 订单价格) serviceCost := decimal.RequireFromString(order.ServiceCost) // 订单手续费 totalMoney := orderMoney.Add(serviceCost) // 订单总金额 = (订单金额 + 手续费) if !flags.CheckSetting { applogger.Debug("平仓开仓价格:%v", order.DealPrice) applogger.Debug("平仓金额:%v", orderMoney) applogger.Debug("平仓数量:%v", order.OrderNumber) applogger.Debug("平仓手续费:%v", serviceCost) applogger.Debug("平仓总金额:%v", totalMoney) } // (开仓|平仓)价格重新计算:订单金额|手续费|订单总金额 closePrice := decimal.RequireFromString(closingPrice) orderNumberNew := orderMoney.Div(closePrice) // 订单数量 = 下单金额 / 平仓价格 // 平仓(手续费处理) cost, err := Uo.CalculateHandlingFees(ctx, session, int(userId), flags.SpotsMarketType, int(order.TradeType), orderId, orderMoney.String(), flags.SetOne) if err != nil { applogger.Error("%v SpotOrdersClosingDB.CalculateHandlingFees:%v", common.ErrSpots, err) return flags.SetNull, err } openOrClosingCost := decimal.RequireFromString(cost) totalMoneyPrice := orderNumberNew.Mul(closePrice).Add(openOrClosingCost) // (开仓|平仓)订单总金额 = (开仓|平仓)订单金额 + (开仓|平仓)订单手续费 if !flags.CheckSetting { applogger.Debug("平仓价格:%v", closingPrice) applogger.Debug("平仓订单数量:%v", orderNumberNew) applogger.Debug("平仓手续费:%v", cost) applogger.Debug("平仓总金额:%v", totalMoneyPrice) } // 判定是买入还是卖出 var usableNew, frozenNew, usableNoNew, frozenNoNew decimal.Decimal switch order.TradeType { case flags.TradeTypeBuy: // 买入 usableNew = usableOld.Add(totalMoney).Sub(totalMoneyPrice) // 用户总资产 frozenNew = frozenOld.Sub(totalMoney) // 用户冻结资产 if order.DigitalId != flags.BasicUnit { usableNoNew = usableNoOld.Add(orderNumberNew) // 非资产 frozenNoNew = frozenNoOld // 非冻结资产 } case flags.TradeTypeSell: // 卖出 usableNew = usableOld.Add(orderMoney).Sub(openOrClosingCost) // 用户可用资产 frozenNew = frozenOld // 用户冻结资产 if order.DigitalId != flags.BasicUnit { if orderNumberNew.Cmp(orderNumber) > 0 { orderNumberNew = orderNumber } usableNoNew = usableNoOld.Sub(orderNumberNew) // 非可用资产 frozenNoNew = frozenNoOld.Sub(orderNumber) // 非冻结资产 } default: } if !flags.CheckSetting { applogger.Debug("可用资产:%v", usableNew) applogger.Debug("冻结资产:%v", frozenNew) applogger.Debug("非可用资产:%v", usableNoNew) applogger.Debug("非冻结资产:%v", frozenNoNew) } // 更新用户资产信息 userDigitalUSDT := orders.UpdateBotUserDigital(ctx, usableNew.String(), frozenNew.String()) checkNum, err := Uo.UpdateBotUserDigital(session, userId, flags.BasicUnit, userDigitalUSDT) if err != nil || checkNum <= 0 { applogger.Error("%v SpotOrdersClosingDB.UpdateBotUserDigital:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } // 更新订单信息 botStockTrade := orders.UpdateBotDigitalStatusByOrderId(ctx, closingPrice, cost, orderMoney.String(), totalMoneyPrice.String(), orderNumberNew.String()) if err = Uo.UpdateBotDigitalTradeByOrderId(session, orderId, botStockTrade); err != nil { applogger.Error("%v SpotOrdersClosingDB.UpdateBotDigitalTradeByOrderId:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } // 更新当前用户非的资产信息 if order.DigitalId != flags.BasicUnit { userDigitalSymbol := orders.UpdateBotUserDigital(ctx, usableNoNew.String(), frozenNoNew.String()) checkNum, err = Uo.UpdateBotUserDigital(session, userId, order.DigitalId, userDigitalSymbol) if err != nil || checkNum <= 0 { applogger.Error("%v SpotOrdersClosingDB.UpdateBotUserDigital:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } } // 返佣记录表|资产表|资金变动表 err = Uo.SpotsRebateCalculation(ctx, session, int(userId), flags.SpotsMarketType, flags.ClosingPosition, flags.CloseMRebate, cost, orderId) if err != nil { applogger.Error("%v SpotOrdersClosingDB.SpotsRebateCalculation:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } // 交易明细表(资产|非资产|手续费) err = Uo.CreatBotUserDigitalLog(ctx, session, userId, order.TradeType, order.DigitalId, orderMoney.String(), orderNumberNew.String(), cost, orderId) if err != nil { applogger.Error("%v SpotOrdersClosingDB.CreatBotUserDigitalLog:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrSpotMsgTow } err = session.Commit() if err != nil { applogger.Error("%v SpotOrdersClosingDB.Commit:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } return orderId, nil } // UpdateBotDigitalCancelByOrderId // // @Description: 现货撤单 // @receiver uo // @param ctx // @param orderId // @return bool // @return error func (uo *userOrderRepo) UpdateBotDigitalCancelByOrderId(ctx context.Context, orderId string) (bool, error) { session := uo.data.mysqlDB.NewSession() defer session.Close() err := session.Begin() if err != nil { applogger.Error("%v UpdateBotDigitalCancelByOrderId.NewSession:%v", common.ErrSpots, err) return false, flags.ErrMySqlDB } // get BotStockTrade var digitalTrade []models.BotDigitalTrade if err = session.Table(flags.BotDigitalTrade). Where("order_id = ?", orderId). Find(&digitalTrade); err != nil || len(digitalTrade) <= 0 { applogger.Error("%v UpdateBotDigitalCancelByOrderId.Find:%v", common.ErrSpots, err) return false, flags.ErrMySqlDB } var userId, tradeType int var orderMoneyT, serviceCostT, orderNumber, digitalId string for _, value := range digitalTrade { userId = value.UserId tradeType = value.TradeType digitalId = value.DigitalId orderNumber = value.OrderNumber orderMoneyT = value.OrderMoney serviceCostT = value.ServiceCost } if !flags.CheckSetting { applogger.Debug("撤单用户ID:%v", userId) applogger.Debug("撤单类型:%v", tradeType) applogger.Debug("撤单下单币种:%v", digitalId) applogger.Debug("撤单下单购买数量:%v", orderNumber) applogger.Debug("撤单下单金额:%v", orderMoneyT) applogger.Debug("撤单下单手续费:%v", serviceCostT) } // get BotUserStock By usableNum, frozenNum, _, err := uo.GetBotUserDigital(session, int64(userId), flags.BasicUnit) if err != nil { applogger.Error("%v UpdateBotDigitalCancelByOrderId.GetBotUserDigital:%v", common.ErrSpots, err) return false, flags.ErrMySqlDB } if !flags.CheckSetting { applogger.Debug("撤单可用资产:%v", usableNum) applogger.Debug("撤单冻结资产:%v", frozenNum) } var usableSymbolOld, frozenSymbolOld decimal.Decimal if digitalId != flags.BasicUnit { usableSymbolOld, frozenSymbolOld, _, err = uo.GetBotUserDigital(session, int64(userId), digitalId) if err != nil { applogger.Error("%v UpdateBotDigitalCancelByOrderId.GetBotUserDigital:%v", common.ErrSpots, err) return false, flags.ErrMySqlDB } } if !flags.CheckSetting { applogger.Debug("撤单下单非可用资产:%v", usableSymbolOld) applogger.Debug("撤单下单非冻结资产:%v", frozenSymbolOld) } // update digitalCancel botStockTrade := orders.UpdateBotDigitalCancelByOrderId(ctx) checkInt, err := session.Table(flags.BotDigitalTrade). Where("order_id = ?", orderId). Update(&botStockTrade) if err != nil || checkInt <= 0 { applogger.Error("%v UpdateBotDigitalCancelByOrderId.UpdateBotDigitalCancelByOrderId:%v", common.ErrSpots, err) return false, flags.ErrMySqlDB } orderMoney := decimal.RequireFromString(orderMoneyT) // 订单金额 serviceCost := decimal.RequireFromString(serviceCostT) // 手续费 totalMoney := orderMoney.Add(serviceCost) // 订单总金额 if !flags.CheckSetting { applogger.Debug("下单金额:%v", orderMoney) applogger.Debug("下单手续费:%v", serviceCost) applogger.Debug("下单总金额:%v", totalMoney) } var usableNew, frozenNew, usableSN, frozenSN decimal.Decimal switch tradeType { case flags.TradeTypeBuy: // 买入 usableNew = usableNum.Add(totalMoney) // 用户总资产 frozenNew = frozenNum.Sub(totalMoney) // 用户冻结资产 usableSN = usableSymbolOld // 用户可用资产 frozenSN = frozenSymbolOld // 用户非冻结资产 case flags.TradeTypeSell: // 卖出 usableNew = usableNum // 用户总资产 frozenNew = frozenNum // 用户冻结资产 if digitalId != flags.BasicUnit { usableSN = usableSymbolOld.Add(decimal.RequireFromString(orderNumber)) // 其它币种可用资产 frozenSN = frozenSymbolOld.Sub(decimal.RequireFromString(orderNumber)) // 其它币种冻结资产 } default: } // 更新用户非资产 if digitalId != flags.BasicUnit { userDigital := orders.UpdateBotUserDigital(ctx, usableSN.String(), frozenSN.String()) checkNum, err := uo.UpdateBotUserDigital(session, int64(userId), digitalId, userDigital) if err != nil || checkNum <= 0 { applogger.Error("%v UpdateBotDigitalCancelByOrderId.UpdateBotUserDigital:%v", common.ErrSpots, err) return false, flags.ErrMySqlDB } } // 更新用户资产 userStockUSDT := orders.UpdateBotUserDigital(ctx, usableNew.String(), frozenNew.String()) checkNum, err := uo.UpdateBotUserDigital(session, int64(userId), flags.BasicUnit, userStockUSDT) if err != nil || checkNum <= 0 { applogger.Error("%v UpdateBotDigitalCancelByOrderId.UpdateBotUserDigital:%v", common.ErrSpots, err) return false, flags.ErrMySqlDB } // 清理现货缓存队列 if err = Reds.HDel(context.Background(), setting.MarketSpotsEntrust, orderId).Err(); err != nil { applogger.Error("%v UpdateBotDigitalCancelByOrderId.HDel:%v", common.ErrSpots, err) return false, flags.ErrCacheDB } // 修改当前用户订阅订单状态 if err = UpdateSpotsSubscribeStatusHashByOrderId(int64(userId), orderId, setting.SpotsSubscribe, flags.Cancel); err != nil { applogger.Error("%v UpdateBotDigitalCancelByOrderId.UpdateSpotsSubscribeStatusByOrderId:%v", common.ErrSpots, err) return false, flags.ErrCacheDB } if err = session.Commit(); err != nil { applogger.Error("%v UpdateBotDigitalCancelByOrderId.Commit:%v", common.ErrSpots, err) return false, flags.ErrMySqlDB } return true, nil } // CreateOneClickRedemption // // @Description: 现货一键兑换 // @receiver uo // @param ctx // @param userId // @param order // @return string // @return error func (uo *userOrderRepo) CreateOneClickRedemption(ctx context.Context, userId int64, order structure.SpotsOrder) (string, error) { // 1、下单通知订阅 digitalId := strings.ToLower(order.DigitalId) spots.SpotsMap <- []byte(digitalId) order.DigitalId = strings.ToUpper(order.DigitalId) // 交易币市价 priceNew, err := GetDigitalCurrencyPrice(ctx, flags.Xh, digitalId) if len(priceNew) == 0 || err != nil { applogger.Error("%v CreateOneClickRedemption.DealSpotsMarketPrice:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrNetWorkMessage } // 2、市价下单记录(1>下单判定 2>订单表 3>资产表[资产|其他交易对]) order.DealPrice = priceNew orderId, err := uo.SpotOrdersDealDB(ctx, userId, order) if err != nil || len(orderId) == 0 { applogger.Error("%v CreateOneClickRedemption.SpotOrdersDealDB:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrSpotsMsgThree } // 3、市价卖出下单 switch order.DealType { case flags.DealTypeMarket: // 市价下单(市价卖出平仓) var openPrice decimal.Decimal switch order.TradeType { case flags.TradeTypeBuy: // 买入 case flags.TradeTypeSell: // 卖出 priceSub := decimal.RequireFromString(priceNew) difference := priceSub.Mul(utils.Difference()) // 设置价差 openPrice = priceSub.Sub(difference) // 开仓价格 default: return flags.SetNull, flags.ErrSpotsMsgFour } // 市价下单平仓操作-->更新订单表|更新资产表|计算手续费|录入返佣明细|录入交易明细 if _, err = SpotOrdersClosingDB(ctx, uo.data.mysqlDB, userId, order, orderId, openPrice.String()); err != nil { applogger.Error("%v CreateOneClickRedemption.SpotOrdersClosingDB:%v", common.ErrSpots, err) // 一键兑换失败,撤单操作 _, err = uo.UpdateBotDigitalCancelByOrderId(ctx, orderId) if err != nil { applogger.Error("%v CreateOneClickRedemption.UpdateBotDigitalCancelByOrderId:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } return flags.SetNull, err } default: return flags.SetNull, flags.ErrSpotMsgOne } return orderId, nil } // GetBotDigitalTradeByOrderId // // @Description: // @receiver uo // @param ctx // @param orderId // @return []models.BotDigitalTrade // @return error func (uo *userOrderRepo) GetBotDigitalTradeByOrderId(orderId string) ([]models.BotDigitalTrade, error) { var botDigitalTrade []models.BotDigitalTrade if err := uo.data.mysqlDB.Table(flags.BotDigitalTrade). Where("order_id = ?", orderId). Find(&botDigitalTrade); err != nil { return nil, err } return botDigitalTrade, nil } // GetBotUserDigital // // @Description: // @receiver uo // @param ctx // @param session // @param userId // @param symbol // @return decimal.Decimal // @return decimal.Decimal // @return int // @return error func (uo *userOrderRepo) GetBotUserDigital(session *xorm.Session, userId int64, symbol string) (decimal.Decimal, decimal.Decimal, int, error) { var digitalUSDT []models.BotUserDigital if err := session.Table(flags.BotUserDigital). Where("user_id = ?", userId). Where("digital_id = ?", strings.ToUpper(symbol)). Find(&digitalUSDT); err != nil { return decimal.Zero, decimal.Zero, 0, err } var usableNum, frozenNum decimal.Decimal for _, value := range digitalUSDT { usableNum = decimal.RequireFromString(value.UsableNum) // 资产可用余额 frozenNum = decimal.RequireFromString(value.FrozenNum) // 资产冻结数量 } return usableNum, frozenNum, len(digitalUSDT), nil } // SpotOrdersDealDB 订单录入 // // @Description: // @receiver uo // @param ctx // @param userId // @param order // @return string // @return error func (uo *userOrderRepo) SpotOrdersDealDB(ctx context.Context, userId int64, order structure.SpotsOrder) (string, error) { session := uo.data.mysqlDB.NewSession() defer session.Close() err := session.Begin() if err != nil { applogger.Error("%v SpotOrdersDealDB:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } // 查询当前用户买入或者卖出的可用总资产和冻结总资产 usableOld, frozenOld, _, err := uo.GetBotUserDigital(session, userId, flags.BasicUnit) if err != nil { applogger.Error("%v SpotOrdersDealDB.GetBotUserDigital:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } if usableOld.IsZero() || frozenOld.IsNegative() { return flags.SetNull, flags.ErrPublicOne } // 查询当前用户买入或者卖出的可用总资产和冻结总非资产 var checkCount int var usableSymbolOld, frozenSymbolOld decimal.Decimal if order.DigitalId != flags.BasicUnit { usableSymbolOld, frozenSymbolOld, checkCount, err = uo.GetBotUserDigital(session, userId, order.DigitalId) if err != nil { applogger.Error("%v SpotOrdersDealDB.GetBotUserDigital:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } } if !flags.CheckSetting { applogger.Debug("可用资产:%v,冻结资产:%v", userId, frozenOld) applogger.Debug("可用非资产:%v,冻结非资产:%v", usableSymbolOld, frozenSymbolOld) } // 开仓录入订单表 checkInt, orderId, err := uo.CreatBotDigitalTrade(ctx, session, userId, order) if err != nil || checkInt <= 0 { applogger.Error("%v SpotOrdersDealDB.CreatBotDigitalTrade:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } orderNumber := decimal.RequireFromString(order.OrderNumber) // 下单数量 orderMoney := decimal.RequireFromString(order.DealPrice).Mul(orderNumber) // 下单金额 = 訂單金額 * 訂單數量 serviceCost := decimal.RequireFromString(order.ServiceCost) // 下单手续费 totalMoney := orderMoney.Add(serviceCost) // 下单总金额 if !flags.CheckSetting { applogger.Debug("现货下单金额:%v", orderMoney) applogger.Debug("现货下单数量:%v", orderNumber) applogger.Debug("现货下单手续费:%v", serviceCost) applogger.Debug("现货下单总金额:%v", totalMoney) } // 通过交易类型处理下单: 1买入(冻结资产), 2卖出(冻结资产) var usableNew, frozenNew, usableNewNo, frozenNewNo decimal.Decimal switch order.TradeType { case flags.TradeTypeBuy: // 买入 voteUsaBledOld := usableOld.Cmp(totalMoney) voteMix := usableOld.Sub(totalMoney).Div(usableOld).Cmp(utils.DecimalsStrInt()) if voteUsaBledOld < 0 || voteMix <= 0 { return flags.SetNull, flags.ErrSpotsMsgSix } usableNew = usableOld.Sub(totalMoney) // 可用资产 frozenNew = frozenOld.Add(totalMoney) // 冻结资产 usableNewNo = usableSymbolOld // 非可用资产 frozenNewNo = frozenSymbolOld // 非冻结资产 case flags.TradeTypeSell: // 卖出 if usableSymbolOld.IsZero() || usableSymbolOld.Cmp(orderNumber) < 0 { return flags.SetNull, flags.ErrPublicOne } usableNew = usableOld // 可用资产 frozenNew = frozenOld // 非可用冻结资产 if order.DigitalId != flags.BasicUnit { usableNewNo = usableSymbolOld // 可用非资产 frozenNewNo = frozenSymbolOld.Add(orderNumber) // 冻结非资产 } default: return flags.SetNull, flags.ErrSpotsMsgSeven } // 更新当前下单用户可用资产表 userDigitalUSDT := orders.UpdateBotUserDigital(ctx, usableNew.String(), frozenNew.String()) checkNum, err := uo.UpdateBotUserDigital(session, userId, flags.BasicUnit, userDigitalUSDT) if err != nil || checkNum <= 0 { applogger.Error("%v SpotOrdersDealDB.UpdateBotUserDigital:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } // 更新非账户资金 if order.DigitalId != flags.BasicUnit { if checkCount == 0 { userDigitalSymbol := orders.BotUserDigital(ctx, userId, usableNewNo.String(), frozenNewNo.String(), order) checkInt, err = uo.CreatBotUserDigital(session, userDigitalSymbol) if err != nil || checkInt <= 0 { applogger.Error("%v SpotOrdersDealDB.CreatBotUserDigital:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } } else { userDigital := orders.UpdateBotUserDigital(ctx, usableNewNo.String(), frozenNewNo.String()) checkNum, err = uo.UpdateBotUserDigital(session, userId, order.DigitalId, userDigital) if err != nil || checkNum <= 0 { applogger.Error("%v SpotOrdersDealDB.UpdateBotUserDigital:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } } } err = session.Commit() if err != nil { applogger.Error("%v SpotOrdersDealDB:%v", common.ErrSpots, err) return flags.SetNull, flags.ErrMySqlDB } return orderId, nil } // CreatBotDigitalTrade // // @Description: // @receiver uo // @param ctx // @param session // @param userId // @param order // @return int64 // @return string // @return error func (uo *userOrderRepo) CreatBotDigitalTrade(ctx context.Context, session *xorm.Session, userId int64, order structure.SpotsOrder) (int64, string, error) { var orderId string for { orderId = orders.CreateRandCodeOrder(10) orderList, err := uo.GetBotDigitalTradeByOrderId(orderId) if err != nil || len(orderList) > 0 { applogger.Error("%v CreatBotDigitalTrade.GetBotDigitalTradeByOrderId:%v", err) continue } break } botStockTrade := orders.BotDigitalTrade(ctx, userId, orderId, order) checkInt, err := session.Table(flags.BotDigitalTrade).Insert(&botStockTrade) if err != nil || checkInt < 0 { return 0, flags.SetNull, err } return checkInt, botStockTrade.OrderId, err } // UpdateBotDigitalTradeByOrderId // // @Description: // @receiver uo // @param ctx // @param session // @param orderId // @param trade // @return error func (uo *userOrderRepo) UpdateBotDigitalTradeByOrderId(session *xorm.Session, orderId string, trade models.BotDigitalTrade) error { _, err := session.Table(flags.BotDigitalTrade). Where("order_id = ?", orderId). Update(&trade) if err != nil { return err } return nil } // UpdateBotUserDigital // // @Description: // @receiver uo // @param ctx // @param session // @param userId // @param symbol // @param userDigitalUSDT // @return int64 // @return error func (uo *userOrderRepo) UpdateBotUserDigital(session *xorm.Session, userId int64, symbol string, userDigitalUSDT models.BotUserDigital) (int64, error) { checkNum, err := session.Table(flags.BotUserDigital). Where("user_id = ?", userId). Where("digital_id = ?", symbol). Update(&userDigitalUSDT) if err != nil { return 0, nil } return checkNum, nil } // CreatBotUserDigital // // @Description: // @receiver uo // @param ctx // @param session // @param digital // @return int64 // @return error func (uo *userOrderRepo) CreatBotUserDigital(session *xorm.Session, digital models.BotUserDigital) (int64, error) { checkInt, err := session.Table(flags.BotUserDigital).Insert(&digital) if err != nil { return 0, err } return checkInt, nil }