package data import ( "context" "encoding/json" "fmt" "github.com/shopspring/decimal" "matchmaking-system/internal/biz/structure" orders "matchmaking-system/internal/data/convert" "matchmaking-system/internal/data/tradedeal/share" "matchmaking-system/internal/data/tradedeal/virtual" "matchmaking-system/internal/pkg/flags" "matchmaking-system/internal/pkg/logging/applogger" "matchmaking-system/internal/pkg/logging/common" models "matchmaking-system/internal/pkg/model" "matchmaking-system/internal/pkg/setting" "strings" "time" ) // GetBotUserSgdPreStockOrder // // @Description: 新加坡股新股申购列表查詢 // @receiver uo // @param ctx // @param id // @return []models.BotUserSgdPreStockOrder // @return error func (uo *userOrderRepo) GetBotUserSgdPreStockOrder(ctx context.Context, id string) ([]models.BotUserSgdPreStockOrder, error) { var botSgd []models.BotUserSgdPreStockOrder if err := uo.data.mysqlDB.Table(flags.BotUserSgdPreStockOrder). Where("pre_stock_id = ?", id). Where("status = 3"). Find(&botSgd); err != nil { applogger.Error("%v GetBotUserSgdPreStockOrder Find:%v", common.ErrSharePre, err) return nil, err } return botSgd, nil } // GetBotUserSgdPreStockOrderByOrderNo // // @Description: 新加坡股新股申购列表查詢orderNo // @receiver uo // @param ctx // @param code // @return []models.BotUserSgdPreStockOrder // @return error func (uo *userOrderRepo) GetBotUserSgdPreStockOrderByOrderNo(ctx context.Context, code []string) ([]models.BotUserSgdPreStockOrder, error) { var botSgd []models.BotUserSgdPreStockOrder if err := uo.data.mysqlDB.Table(flags.BotUserSgdPreStockOrder). In("order_no", code). Where("trade_status = 0"). Where("status = 3"). Find(&botSgd); err != nil { applogger.Error("%v GetBotUserSgdPreStockOrder Find:%v", common.ErrSharePre, err) return nil, err } return botSgd, nil } // GetBotUserSgdGiveStockOrders // // @Description: 新加坡赠股 // @receiver uo // @param ctx // @param id // @return []models.BotUserSgdGiveStockOrder // @return error func (uo *userOrderRepo) GetBotUserSgdGiveStockOrders(ctx context.Context, id string) ([]models.BotUserSgdGiveStockOrder, error) { var botSgd []models.BotUserSgdGiveStockOrder if err := uo.data.mysqlDB.Table(flags.BotUserSgdGiveStockOrder). Where("order_no = ?", id). Find(&botSgd); err != nil { applogger.Error("%v GetBotUserSgdGiveStockOrders Find:%v", common.ErrSharePre, err) return nil, err } return botSgd, nil } // GetBotStockSgdList // // @Description: 新加坡股股票代码列表 // @receiver uo // @param ctx // @return []models.BotStockInList // @return error func (uo *userOrderRepo) GetBotStockSgdList(ctx context.Context) ([]models.BotStockSgdList, error) { var data []models.BotStockSgdList if err := uo.data.mysqlDB.Table(flags.BotStockSgdList).Find(&data); err != nil { applogger.Error("%v GetBotStockSgdList Find:%v", common.ErrSharePre, err) return nil, err } // 清理股票缓存列表 for _, value := range data { strArray := strings.Split(value.StockCode, ":") if len(strArray) >= 2 { codeOld := strArray[1] Reds.HDel(context.Background(), setting.MarketShareSgd, codeOld) Reds.HDel(context.Background(), setting.MarketShareBlkSgd, codeOld) } } return data, nil } // CreateBotUserSgdPreStockOrder // // @Description: 新加坡股新股申购:开仓--持仓 // @receiver uo // @param ctx // @param code // @param order // @return error func (uo *userOrderRepo) CreateBotUserSgdPreStockOrder(ctx context.Context, code string, order []structure.ShareOrder) error { // 同步写入股票列表缓存 SubscribeSgdHSetCodeList(code, false) // 处理新股申购数据订单 session := uo.data.mysqlDB.NewSession() defer session.Close() err := session.Begin() if err != nil { applogger.Error("%v CreatBotUserSgdPreStockOrder.Begin:%v", common.ErrSharePre, err) return flags.ErrMySqlDB } // 强平阈值 flatRatio := GetCacheForcedClosure(flags.StockSGDSystemSetUpKey, code) system := &structure.ShareSystem{ StrongFlatRatio: flatRatio.String(), } // 获取开盘时间 closingTime := SystemTimeGenerate(flags.StockMarketList, flags.SgdMarket, time.Now()) // 初始化订单缓存map orderMap := make(map[string]share.ShareSgdTallyCache) for _, value := range order { value.System = system // 生成订单ID var orderId string orderId, err = uo.VerifyBotStockSgdTradeOrderId(session) if err != nil { applogger.Error("%v CreatBotUserSgdPreStockOrder.VerifyBotStockSgdTradeOrderId:%v", common.ErrSharePre, err) continue } // 查询账户是否存在,再存更新不存在新增 var check bool check, err = uo.CheckStockSgdAmount(ctx, int64(value.UserId), value.StockId, value.OrderNumber, decimal.Zero.String()) if err != nil || !check { applogger.Error("%v CreatBotUserSgdPreStockOrder.CheckStockSgdAmount:%v", common.ErrSharePre, err) continue } // 写入订单数据表 trade := orders.BotStockSgdTradePre(ctx, int64(value.UserId), orderId, value) if err = uo.CreateBotStockSgdTrade(session, trade); err != nil { applogger.Error("%v CreatBotUserSgdPreStockOrder.CreateBotStockSgdTrade:%v", common.ErrSharePre, err) continue } // 写入持仓缓存 resultMsg := share.ShareSgdTallyCache{ UserId: int64(value.UserId), // 用户Id OrderId: orderId, // 订单ID Symbol: value.StockId, // 下单交易对 OpenPrice: value.LimitPrice, // 开仓价格 Status: flags.Position, // 订单状态 Order: value, // 下单信息 ClosingTime: closingTime, // 平仓时间 } orderMap[orderId] = resultMsg } if err = session.Commit(); err != nil { applogger.Error("%v CreatBotUserSgdPreStockOrder.Commit:%v", common.ErrSharePre, err) return flags.ErrMySqlDB } // 写入持仓缓存、用户订单订阅缓存、管理员订单订阅缓存 for _, resultMsg := range orderMap { var byteStr []byte byteStr, err = json.Marshal(resultMsg) if err != nil { applogger.Error("%v CreatBotUserSgdPreStockOrder.Marshal:%v", common.ErrSharePre, err) continue } // 写入持仓缓存 if err = Reds.HSet(context.Background(), setting.MarketShareSgdPosition, resultMsg.OrderId, string(byteStr)).Err(); err != nil { continue } // 写入用户订单订阅缓存 orderIdKey := virtual.OrderIdListKey(setting.ShareSgdSubscribe, resultMsg.UserId) if err = share.ShareSgdHashUserOrder(Reds, orderIdKey, &resultMsg); err != nil { applogger.Error("%v CreatBotUserSgdPreStockOrder.ShareSgdHashUserOrder:%v", common.ErrSharePre, err) return flags.ErrCacheDB } // 写入管理员订单订阅缓存 if err = share.ShareSgdHashUserOrder(Reds, setting.AdminShareSgdSubscribe, &resultMsg); err != nil { applogger.Error("%v CreatBotUserSgdPreStockOrder.AdminShareSgdSubscribe:%v", common.ErrSharePre, err) return flags.ErrCacheDB } // TODO: 获取IPO未支付订单缓存,并更新缓存中的持仓订单ID keyCache := fmt.Sprintf("%v%v", flags.StockIpoList, resultMsg.Order.OrderNo) checkInt, err := Reds.Exists(ctx, keyCache).Result() if err != nil { continue } if checkInt > 0 { if err = Reds.Set(ctx, keyCache, resultMsg.OrderId, 0).Err(); err != nil { applogger.Error("CreatBotUserSgdPreStockOrder.Set err:%v", err) } } } return nil } // CheckStockSgdAmount // // @Description: 新加坡股新股申购【创建|更新】用戶资产 // @receiver uo // @param ctx // @param userId // @param stockId // @param usableNum // @param frozenNum // @return bool // @return error func (uo *userOrderRepo) CheckStockSgdAmount(ctx context.Context, userId int64, stockId, usableNum, frozenNum string) (bool, error) { var botUserStockSgd []models.BotUserStockSgd if err := uo.data.mysqlDB.Table(flags.BotUserStockSgd). Where("user_id = ?", userId). Where("stock_id = ?", stockId). Find(&botUserStockSgd); err != nil { applogger.Error("%v CheckStockSgdAmount Find:%v", common.ErrSharePre, err) return false, err } var usableNumOld, frozenNumOld decimal.Decimal for _, value := range botUserStockSgd { usableNumOld = decimal.RequireFromString(value.UsableNum) frozenNumOld = decimal.RequireFromString(value.FrozenNum) } if len(botUserStockSgd) == 0 { // 创建账户 userStock := orders.CreatBotUserStockSgdPre(ctx, userId, stockId, usableNum, frozenNum) _, err := uo.data.mysqlDB.Table(flags.BotUserStockSgd).Insert(&userStock) if err != nil { applogger.Error("%v CheckStockSgdAmount Insert:%v", common.ErrSharePre, err) return false, err } } else { // 更新账户 usableNumNew := usableNumOld.Add(decimal.RequireFromString(usableNum)) frozenNumNew := frozenNumOld.Add(decimal.RequireFromString(frozenNum)) userStock := orders.UpdateBotUserStockSgdPre(ctx, usableNumNew.String(), frozenNumNew.String()) _, err := uo.data.mysqlDB.Table(flags.BotUserStockSgd). Where("user_id = ?", userId). Where("stock_id = ?", stockId). Update(&userStock) if err != nil { applogger.Error("%v CheckStockSgdAmount Update:%v", common.ErrSharePre, err) return false, err } } return true, nil } // UpdateShareSgdTradeStockId // // @Description: 更新-新加坡股新股申购股票stockId // @receiver uo // @param ctx // @param code // @param codeOld // @param stock // @return error func (uo *userOrderRepo) UpdateShareSgdTradeStockId(ctx context.Context, code, codeOld string) error { // 同步写入股票列表缓存 SubscribeSgdHSetCodeList(code, false) // 新增到新加坡股缓存列表 if err := Reds.HSet(context.Background(), setting.MarketShareSgd, code, code).Err(); err != nil { applogger.Error("%v UpdateShareSgdTradeStockId.HSet.MarketShareSgd:%v", common.ErrSharePre, err) return flags.ErrCacheDB } session := uo.data.mysqlDB.NewSession() defer session.Close() err := session.Begin() if err != nil { applogger.Error("%v UpdateShareSgdTradeStockId.Begin:%v", common.ErrSharePre, err) return flags.ErrMySqlDB } // 1、更新订单股票代码 var userStockTrade []models.BotStockSgdTrade if err = session.Table(flags.BotStockSgdTrade).Where("stock_id =?", codeOld).Find(&userStockTrade); err != nil { return flags.ErrMySqlDB } for _, value := range userStockTrade { value.StockId = code // 1、更新订单信息 inCheck, err := session.Table(flags.BotStockSgdTrade).Where("trade_id =?", value.TradeId).Update(&value) if err != nil || inCheck <= 0 { applogger.Error("%v UpdateShareSgdTradeStockId BotStockSgdTrade err:%v", common.ErrSharePre, err) continue } // 2、处理缓存订单 orderMap, err := Reds.HGet(context.Background(), setting.AdminShareSgdSubscribe, value.OrderId).Result() if err != nil { continue } var entrustJson share.ShareSgdTallyCache if err = json.Unmarshal([]byte(orderMap), &entrustJson); err != nil { continue } var entrust *share.ShareSgdTallyCache entrust = &entrustJson if entrust == nil { continue } entrust.Symbol = code entrust.Order.StockId = code // 3、处理挂单|持仓|用户订阅|管理员订阅缓存数据 switch value.Status { case 0: // 挂单 if err = share.ShareSgdHashUserOrder(Reds, setting.MarketShareSgdEntrust, entrust); err != nil { continue } case 1: // 持仓 if err = share.ShareSgdHashUserOrder(Reds, setting.MarketShareSgdPosition, entrust); err != nil { continue } default: continue } // 更新用户订阅缓存 cacheKey := fmt.Sprintf("%v-%v", setting.ShareSgdSubscribe, entrust.UserId) if err = share.ShareSgdHashUserOrder(Reds, cacheKey, entrust); err != nil { continue } // 更新管理员订阅缓存 if err = share.ShareSgdHashUserOrder(Reds, setting.AdminShareSgdSubscribe, entrust); err != nil { continue } } // 2、更新资产表股票代码 var userStock []models.BotUserStockSgd if err = session.Table(flags.BotUserStockSgd).Where("stock_id =?", codeOld).Find(&userStock); err != nil { return flags.ErrMySqlDB } for _, value := range userStock { value.StockId = code inCheck, err := session.Table(flags.BotUserStockSgd).Where("id =?", value.Id).Update(&value) if err != nil || inCheck <= 0 { applogger.Error("%v UpdateShareSgdTradeStockId BotUserStockSgd err:%v", common.ErrSharePre, err) continue } } // 3、更新资产表日志股票代码 var userStockLog []models.BotUserStockSgdLog if err = session.Table(flags.BotUserStockSgdLog).Where("stock_id =?", codeOld).Find(&userStockLog); err != nil { return flags.ErrMySqlDB } for _, value := range userStockLog { value.StockId = code inCheck, err := session.Table(flags.BotUserStockSgdLog).Where("id =?", value.Id).Update(&value) if err != nil || inCheck <= 0 { applogger.Error("%v UpdateShareSgdTradeStockId BotUserStockSgdLog err:%v", common.ErrSharePre, err) continue } } if err = session.Commit(); err != nil { applogger.Error("%v UpdateShareSgdTradeStockId.Commit:%v", common.ErrSharePre, err) return flags.ErrMySqlDB } return nil }