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.

747 lines
26 KiB

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
}