소스 검색

完成部分分时数据功能

Zhou.xiaoning 5 년 전
부모
커밋
758b36e26d
4개의 변경된 파일190개의 추가작업 그리고 9개의 파일을 삭제
  1. 79 4
      controllers/quote/history.go
  2. 2 0
      global/e/code.go
  3. 2 0
      global/e/msg.go
  4. 107 5
      models/market.go

+ 79 - 4
controllers/quote/history.go

@@ -1,11 +1,13 @@
 package quote
 
 import (
+	"encoding/json"
 	"mtp2_if/global/app"
 	"mtp2_if/global/e"
 	"mtp2_if/logger"
 	"mtp2_if/models"
 	"net/http"
+	"sort"
 	"time"
 
 	"github.com/gin-gonic/gin"
@@ -61,9 +63,7 @@ func QueryTSData(c *gin.Context) {
 
 	var queryTSDataRsp QueryTSDataRsp
 
-	// 获取目标品种交易日
-
-	// FIXME: - 一些不常变化的数据(如市场信息、商品信息等)应缓存到Redis中
+	// FIXME: - 一些不常变化的数据(如市场信息、商品信息等)应缓存到Redis中, 或缓存到服务内存
 	market, err := models.GetMarketByGoodsCode(req.GoodsCode)
 	if err != nil {
 		logger.GetLogger().Errorf("QueryTSData failed: %s", err.Error())
@@ -75,12 +75,87 @@ func QueryTSData(c *gin.Context) {
 		appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKET_FAILED, nil)
 		return
 	}
-
+	// 获取目标品种交易日
 	// FIXME: - 由于mtp2.0目前未同步外部交易所品种的当前交易日,
 	//          故通道交易的品种目前只能在交易系统的外部市场中获
 	//          取统一的交易日,后期应要求服务端同步外部数据
+	marketRun, err := models.GetMarketRun(int(market.Marketid))
+	if marketRun == nil {
+		logger.GetLogger().Errorf("QueryTSData failed: %s", err.Error())
+		appG.Response(http.StatusBadRequest, e.ERROR_GET_MARKETRUN_FAILED, nil)
+		return
+	}
 
 	// 获取目标品种的开休市计划
+	var runSteps []map[string]interface{}
+	// 通道交易外部市场开休市计划表 - QuoteSourceGroupRunStep; 其它市场的 - MarketRunStepDetail
+	if market.Trademode == 15 {
+		// 外部市场
+		sourceRunSteps, err := models.FindQuoteSourceGroupRunStepsByMarket(*market)
+		if err != nil {
+			logger.GetLogger().Errorf("QueryTSData failed: %s", err.Error())
+			appG.Response(http.StatusBadRequest, e.ERROR_GET_RUNSTEP_FAILED, nil)
+			return
+		}
+		for v := range sourceRunSteps {
+			// struct -> json
+			if jsonBytes, err := json.Marshal(v); err == nil {
+				// json -> struct
+				var runStepMap map[string]interface{}
+				json.Unmarshal(jsonBytes, &runStepMap)
+
+				runSteps = append(runSteps, runStepMap)
+			}
+		}
+	}
+	// 非外部市场或外部市场没有配置QuoteSourceGroupRunStep表数据的情况下,都从MarketRunStepDetail中获取数据
+	if len(runSteps) == 0 {
+		sourceRunSteps, err := models.FindMarketRunStepDetails(int(market.Marketid))
+		if err != nil {
+			logger.GetLogger().Errorf("QueryTSData failed: %s", err.Error())
+			appG.Response(http.StatusBadRequest, e.ERROR_GET_RUNSTEP_FAILED, nil)
+			return
+		}
+		for _, v := range sourceRunSteps {
+			// struct -> json
+			if jsonBytes, err := json.Marshal(v); err == nil {
+				// json -> struct
+				var runStepMap map[string]interface{}
+				json.Unmarshal(jsonBytes, &runStepMap)
+
+				runSteps = append(runSteps, runStepMap)
+			}
+		}
+	}
+	// 构建分时图可直接使用的开休市数据
+	// 这里有一个知识点:TRADEWEEKDAY 与 STARTWEEKDAY,以及 TRADEWEEKDAY 与 ENDWEEKDAY 之间相差最多一天(管理端限制),
+	//                所以目前并不支持正真的周五夜盘模式。我们在实现时不用做得太复杂。
+	// 当前交易日(周几)对应的开休市计划
+	tradeDate, err := time.ParseInLocation("2006-01-02", marketRun.Tradedate, time.Local)
+	if err != nil {
+		logger.GetLogger().Errorf("QueryTSData failed: %s", err.Error())
+		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
+		return
+	}
+	curWeekRunSteps := make([]map[string]interface{}, 0)
+	for _, v := range runSteps {
+		tradeWeekDay := v["tradeweekday"].(int)
+		if tradeWeekDay == int(tradeDate.Weekday()) {
+			curWeekRunSteps = append(curWeekRunSteps, v)
+		}
+	}
+	// 获取不到可用的开休市计划
+	if len(curWeekRunSteps) == 0 {
+		logger.GetLogger().Errorf("QueryTSData failed: %s", err.Error())
+		appG.Response(http.StatusBadRequest, e.ERROR_GET_RUNSTEP_FAILED, nil)
+		return
+	}
+	// 按 SECTIONID 顺序排序(管理端会按时间顺序添加开休市计划)
+	sort.Slice(curWeekRunSteps, func(i int, j int) bool {
+		return curWeekRunSteps[i]["sectionid"].(int) < curWeekRunSteps[j]["sectionid"].(int)
+	})
+	// 把各开休市时间段转化为真实的时间
+	//
 
 	// 查询成功
 	logger.GetLogger().Debugln("QueryTSData successed: %v", queryTSDataRsp)

+ 2 - 0
global/e/code.go

@@ -14,6 +14,8 @@ const (
 	ERROR_OPERATION_FAILED         = 30010
 	ERROR_GET_GOODS_FAILED         = 30011
 	ERROR_GET_MARKET_FAILED        = 30012
+	ERROR_GET_MARKETRUN_FAILED     = 30013
+	ERROR_GET_RUNSTEP_FAILED       = 30014
 
 	ERROR_UPLOAD_SAVE_IMAGE_FAIL    = 40001
 	ERROR_UPLOAD_CHECK_IMAGE_FAIL   = 40002

+ 2 - 0
global/e/msg.go

@@ -14,6 +14,8 @@ var MsgFlags = map[int]string{
 	ERROR_OPERATION_FAILED:         "执行失败",
 	ERROR_GET_GOODS_FAILED:         "获取商品信息失败",
 	ERROR_GET_MARKET_FAILED:        "获取市场信息失败",
+	ERROR_GET_MARKETRUN_FAILED:     "获取市场运行参数失败",
+	ERROR_GET_RUNSTEP_FAILED:       "获取市场开休市计划失败",
 
 	ERROR_UPLOAD_SAVE_IMAGE_FAIL:    "保存图片失败",
 	ERROR_UPLOAD_CHECK_IMAGE_FAIL:   "检查图片失败",

+ 107 - 5
models/market.go

@@ -1,6 +1,7 @@
 package models
 
 import (
+	"errors"
 	"mtp2_if/db"
 	"time"
 )
@@ -136,6 +137,45 @@ func (Marketrun) TableName() string {
 	return "MARKETRUN"
 }
 
+// Marketrunstepdetail 市场运行时间段明细
+type Marketrunstepdetail struct {
+	Autoid       int64  `json:"autoid"  xorm:"'AUTOID'" binding:"required"`             // 自增ID
+	Marketid     int32  `json:"marketid"  xorm:"'MARKETID'" binding:"required"`         // 市场ID --  其它特殊如下 0-系统 1-交割服务 2-账户服务3-履约服务 4-仓单服务 5-积分服务 6-银行服务
+	Tradeweekday int32  `json:"tradeweekday"  xorm:"'TRADEWEEKDAY'" binding:"required"` // 交易日归属 - 0:星期天、1:星期一、2:星期二、3:星期三、4:星期四、5:星期五、6:星期六
+	Sectionid    int32  `json:"sectionid"  xorm:"'SECTIONID'" binding:"required"`       // 从 1 开始 往下编
+	Runstep      int32  `json:"runstep"  xorm:"'RUNSTEP'" binding:"required"`           // 运行阶段 - 1:集合竞价、  2:连续竞价(交割)  3:-- 4:确认行权\交收时段\(补充交收
+	Startweekday int32  `json:"startweekday"  xorm:"'STARTWEEKDAY'" binding:"required"` // 开市时间
+	Starttime    string `json:"starttime"  xorm:"'STARTTIME'" binding:"required"`       // 起始时间(HH:mm)
+	Endweekday   int32  `json:"endweekday"  xorm:"'ENDWEEKDAY'" binding:"required"`     // 休市时间
+	Endtime      string `json:"endtime"  xorm:"'ENDTIME'" binding:"required"`           // 结束时间(HH:mm)
+	Startflag    int32  `json:"startflag"  xorm:"'STARTFLAG'"`                          // 开始日标识 - (-1:上日 0:当日 1:次日 )
+	Endflag      int32  `json:"endflag"  xorm:"'ENDFLAG'"`                              // 结束日标识 - (-1:上日 0:当日 1:次日 )
+}
+
+// TableName is MARKETRUNSTEPDETAIL
+func (Marketrunstepdetail) TableName() string {
+	return "MARKETRUNSTEPDETAIL"
+}
+
+// Quotesourcegrouprunstep 行情源分组开休市计划明细
+type Quotesourcegrouprunstep struct {
+	Groupid      int32  `json:"groupid"  xorm:"'GROUPID'" binding:"required"`           // 分组ID
+	Tradeweekday int32  `json:"tradeweekday"  xorm:"'TRADEWEEKDAY'" binding:"required"` // 交易日归属 - 0:星期天、1:星期一、2:星期二、3:星期三、4:星期四、5:星期五、6:星期六
+	Sectionid    int32  `json:"sectionid"  xorm:"'SECTIONID'" binding:"required"`       // 从 1 开始 往下编 [0为系统清盘、结算时间] SectionId = 0时,开始时间=清盘时间  开始周几= 清盘周几, 结束时间=结算时间 结束周几=结算周几
+	Runstep      int32  `json:"runstep"  xorm:"'RUNSTEP'"`                              // 运行阶段 - 2:连续交易
+	Startweekday int32  `json:"startweekday"  xorm:"'STARTWEEKDAY'"`                    // 起始周几
+	Starttime    string `json:"starttime"  xorm:"'STARTTIME'"`                          // 起始时间(HH:mm)
+	Endweekday   int32  `json:"endweekday"  xorm:"'ENDWEEKDAY'"`                        // 结束周几
+	Endtime      string `json:"endtime"  xorm:"'ENDTIME'"`                              // 结束时间(HH:mm)
+	Startflag    int32  `json:"startflag"  xorm:"'STARTFLAG'"`                          // 开始日标识 - (-1:上日 0:当日 1:次日 )
+	Endflag      int32  `json:"endflag"  xorm:"'ENDFLAG'"`                              // 结束日标识 - (-1:上日 0:当日 1:次日 )
+}
+
+// TableName is QUOTESOURCEGROUPRUNSTEP
+func (Quotesourcegrouprunstep) TableName() string {
+	return "QUOTESOURCEGROUPRUNSTEP"
+}
+
 // GetMarket 获取市场信息
 // 参数 marketID int 市场ID
 // 返回值 *Market 市场信息
@@ -144,11 +184,15 @@ func GetMarket(marketID int) (*Market, error) {
 	engine := db.GetEngine()
 
 	var market Market
-	if _, err := engine.Where("MARKETID = ?", marketID).Get(&market); err != nil {
+	has, err := engine.Where("MARKETID = ?", marketID).Get(&market)
+	if err != nil {
 		return nil, err
 	}
+	if has {
+		return &market, nil
+	}
 
-	return &market, nil
+	return nil, nil
 }
 
 // GetMarketByGoodsCode 通过商品代码获取市场信息
@@ -159,10 +203,68 @@ func GetMarketByGoodsCode(goodsCode string) (*Market, error) {
 	engine := db.GetEngine()
 
 	var market Market
-	if _, err := engine.Join("LEFT", "GOODS", "GOODS.MARKETID = MARKET.MARKETID").
-		Where("GOODS.GOODSCODE = ?", goodsCode).Get(&market); err != nil {
+	has, err := engine.Join("LEFT", "GOODS", "GOODS.MARKETID = MARKET.MARKETID").
+		Where("GOODS.GOODSCODE = ?", goodsCode).Get(&market)
+	if err != nil {
+		return nil, err
+	}
+	if has {
+		return &market, nil
+	}
+
+	return nil, nil
+}
+
+// GetMarketRun 获取目标市场运行参数信息
+// 参数 marketID int 市场ID
+// 返回值 *Marketrun 市场运行参数信息
+// 返回值 error 错误
+func GetMarketRun(marketID int) (*Marketrun, error) {
+	engine := db.GetEngine()
+
+	var marketRun Marketrun
+	has, err := engine.Where("MARKETID = ?", marketID).Get(&marketRun)
+	if err != nil {
+		return nil, err
+	}
+	if has {
+		return &marketRun, nil
+	}
+
+	return nil, nil
+}
+
+// FindQuoteSourceGroupRunStepsByMarket 通过市场获取对应的行情源分组开休市计划明细信息
+// 参数 market Market 市场信息
+// 返回值 []Quotesourcegrouprunstep 行情源分组开休市计划明细信息
+// 返回值 error 错误
+func FindQuoteSourceGroupRunStepsByMarket(market Market) ([]Quotesourcegrouprunstep, error) {
+	if market.Trademode != 15 {
+		return nil, errors.New("目标市场非外部市场")
+	}
+
+	engine := db.GetEngine()
+	runSteps := make([]Quotesourcegrouprunstep, 0)
+	if err := engine.Join("INNER", "GOODSGROUP", "GOODSGROUP.GOODSGROUPID = QUOTESOURCEGROUPRUNSTEP.GROUPID").
+		Join("INNER", "MARKET", "MARKET.MARKETID = GOODSGROUP.MARKETID").
+		Where("QUOTESOURCEGROUPRUNSTEP.SECTIONID <> 0 and MARKET.MARKETID = ?", market.Marketid).Find(&runSteps); err != nil {
+		return nil, err
+	}
+
+	return runSteps, nil
+}
+
+// FindMarketRunStepDetails 获取市场运行时间段明细
+// 参数 marketID int 市场ID
+// 返回值 Marketrunstepdetail 市场运行时间段明细
+// 返回值 error 错误
+func FindMarketRunStepDetails(marketID int) ([]Marketrunstepdetail, error) {
+	engine := db.GetEngine()
+
+	runSteps := make([]Marketrunstepdetail, 0)
+	if err := engine.Where("MARKETID = ?", marketID).Find(&runSteps); err != nil {
 		return nil, err
 	}
 
-	return &market, nil
+	return runSteps, nil
 }