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
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
|
|
}
|
|
|