package models

import (
	"mtp2_if/db"
	"strconv"
	"time"
)

// Market 市场表
type Market struct {
	Marketid             int32   `json:"marketid"  xorm:"'MARKETID'" binding:"required"`                         // 市场ID正常5位，前三位固定：两位表示交易模式， 一位表示交易属性(1:收益权，2：所有权) 其它特殊市场：0-系统 1-交割服务 2-账户服务3-履约服务 4-仓单服务 5-积分服务 6-银行服务
	Marketname           string  `json:"marketname"  xorm:"'MARKETNAME'"`                                        // 市场名称
	Exchareaid           int32   `json:"exchareaid"  xorm:"'EXCHAREAID'"`                                        // 所属交易所，可以没有
	Markettype           int32   `json:"markettype"  xorm:"'MARKETTYPE'"`                                        // 市场类型- 1:非交易服务 2:交易服务
	Trademode            int32   `json:"trademode"  xorm:"'TRADEMODE'" binding:"required"`                       // 交易模式 - 10:做市 13:竞价 15:通道交易 16:挂牌点选 17:仓单贸易 18:期权 19:竞拍-降价式 20:竞拍-竞价式 21:竞拍-大宗式 22:受托竞价
	Tradeproperty        int32   `json:"tradeproperty"  xorm:"'TRADEPROPERTY'" binding:"required"`               // 交易属性 -  1:收益权(可做空) 2:所有权(不可做空) 3:期权 4:现货 5:参考行情 6:通道交易 7:币交易 8:场外期权
	Openmethod           int32   `json:"openmethod"  xorm:"'OPENMETHOD'" binding:"required"`                     // 开盘模式 - 0 自动 1手动
	Reckonpricealgorithm int32   `json:"reckonpricealgorithm"  xorm:"'RECKONPRICEALGORITHM'" binding:"required"` // 结算价算法: 1:最后多少笔成交价加权平均 2:最后多少秒成交价加权平均 3:全天加权平均 4:最后一口价 5.买一价 6.卖一价 7.买一卖一均价 8.外部结算价
	Reckonpriceparam     int32   `json:"reckonpriceparam"  xorm:"'RECKONPRICEPARAM'"`                            // 结算价参数
	Marketstatus         int32   `json:"marketstatus"  xorm:"'MARKETSTATUS'" binding:"required"`                 // 生效状态(ValidStatus枚举): 1:待生效 2:正常 3:注销
	Marketserviceid      int32   `json:"marketserviceid"  xorm:"'MARKETSERVICEID'"`                              // 市场服务ID
	Marginformula        int32   `json:"marginformula"  xorm:"'MARGINFORMULA'"`                                  // 持仓保证金公式 - 1:双边收 2:净头寸收 3:大小边差异收 4:大边收 5:卖持仓收(仅期权)
	Performancetempid    int64   `json:"performancetempid"  xorm:"'PERFORMANCETEMPID'"`                          // 履约计划模板ID - 作废
	Clearinterval        int32   `json:"clearinterval"  xorm:"'CLEARINTERVAL'"`                                  // 待开市间隔(交易市场开盘前多久发市场待开市信号(单位分钟))
	Matchermode          int32   `json:"matchermode"  xorm:"'MATCHERMODE'"`                                      // 指定对手模式[仓单贸易模式专用] - 1:任意对手
	Reckonorder          int32   `json:"reckonorder"  xorm:"'RECKONORDER'"`                                      // 结算顺序
	Canpreexercise       int32   `json:"canpreexercise"  xorm:"'CANPREEXERCISE'"`                                //  [期权]是否可预申报- 0:否 1:是
	Cangoodsexercise     int32   `json:"cangoodsexercise"  xorm:"'CANGOODSEXERCISE'"`                            //  [期权]是否可现货行权- 0:否 1:是
	Goodstype            int32   `json:"goodstype"  xorm:"'GOODSTYPE'"`                                          // 商品类型 - 1:交易商品 2:仓单商品
	Roleprioritytype     int32   `json:"roleprioritytype"  xorm:"'ROLEPRIORITYTYPE'"`                            // 角色优先类型 - 1:无 2:报价商优先 3:非报价商优先 [16:挂牌点选]
	Isrecordsource       int32   `json:"isrecordsource"  xorm:"'ISRECORDSOURCE'"`                                // 是否记录成交源 - 0:不记录 1:记录 [所有权]
	Marginformula2       int32   `json:"marginformula2"  xorm:"'MARGINFORMULA2'"`                                // 持仓保证金公式(仅受托竞价) - 1:双边收 2:净头寸收 3:大小边差异收 4:大边收 5:卖持仓收(仅期权)
	Haswr                int32   `json:"haswr"  xorm:"'HASWR'"`                                                  // [竞拍]是否需要仓单 -  0:不需要  1:需要-作废
	Premiumquotemode     int32   `json:"premiumquotemode"  xorm:"'PREMIUMQUOTEMODE'"`                            // 权利金报价方式 - 1:自动 2:手动
	Cangoodsexercisetype int32   `json:"cangoodsexercisetype"  xorm:"'CANGOODSEXERCISETYPE'"`                    // 可现货行权期权类型 - 1:认购 2认沽 3:认购认沽 [CanGoodsExercise = 1时可设置]
	Canacceptquote       int32   `json:"canacceptquote"  xorm:"'CANACCEPTQUOTE'"`                                // 确认行权是否接收行情 - 0:不接受 1:接受 [可确认权的挂牌期权市场可配置]
	Canmutistage         int32   `json:"canmutistage"  xorm:"'CANMUTISTAGE'"`                                    // 是否可多段运行 – 0:不可 1:可 [挂牌期权]
	Isdeductmargin       int32   `json:"isdeductmargin"  xorm:"'ISDEDUCTMARGIN'"`                                // 竞拍违约是否扣除保证金[竞拍-降价式] - 0:不扣 1:扣除
	Canmanualquotestrike int32   `json:"canmanualquotestrike"  xorm:"'CANMANUALQUOTESTRIKE'"`                    // 是否可手动报行权价- 0:否 1:是 [期权]
	Tradetype            int32   `json:"tradetype"  xorm:"'TRADETYPE'"`                                          // 下单方式[通道交易] - 1:直接转单 2:净头寸下单
	Pendingflag          int32   `json:"pendingflag"  xorm:"'PENDINGFLAG'"`                                      // 待开市时间标识[通道交易-对冲] -  0:当日 1:上日
	Pendingtime          string  `json:"pendingtime"  xorm:"'PENDINGTIME'"`                                      // 待开市时间[通道交易-对冲](HH:mm)
	Reckontime           string  `json:"reckontime"  xorm:"'RECKONTIME'"`                                        // 结算时间[通道交易-对冲](HH:mm)
	Hastradecredit       int32   `json:"hastradecredit"  xorm:"'HASTRADECREDIT'"`                                // 是否交易授信[做市收益权] - 0:不授信 1:授信
	Contracttmp          string  `json:"contracttmp"  xorm:"'CONTRACTTMP'"`                                      // 合同模板[荷兰式][竞价式][仓单贸易]
	Hasrebate            int32   `json:"hasrebate"  xorm:"'HASREBATE'"`                                          // 是否返利[竞价式]  0:不返，1:返利 -- 根据系统参数088显示或隐藏
	Rebateratio          float64 `json:"rebateratio"  xorm:"'REBATERATIO'"`                                      // 返利比率[竞价式]
	Otcuserid            int64   `json:"otcuserid"  xorm:"'OTCUSERID'"`                                          // 场外期权做市商[场外期权]
	Outersynctime        string  `json:"outersynctime"  xorm:"'OUTERSYNCTIME'"`                                  // 外部同步时间点(h24:mi:ss)[场外期权]
	Auctionwrtype        int32   `json:"auctionwrtype"  xorm:"'AUCTIONWRTYPE'"`                                  // 竞拍仓单类型 - 1:无仓单 2:有仓单 3;有无仓单均可
	Isreleasemargin      int32   `json:"isreleasemargin"  xorm:"'ISRELEASEMARGIN'"`                              // 成交参与保证金是否释放[竞价式] - 0:不释放 1释放
	Selllistingauditflag int32   `json:"selllistingauditflag"  xorm:"'SELLLISTINGAUDITFLAG'"`                    // 卖挂牌是否需要审核(仓单贸易) - 0:不需要 1:需要
	Trademarkettype      int32   `json:"trademarkettype"  xorm:"'TRADEMARKETTYPE'"`                              // 交易市场类型 - 1:合约市场 2:外部市场 3:仓单市场
}

// TableName is MARKET
func (Market) TableName() string {
	return "MARKET"
}

// Goodsgroup 商品组表 - 品种(通道交易\场外期权)
type Goodsgroup struct {
	Goodsgroupid           int64     `json:"goodsgroupid"  xorm:"'GOODSGROUPID'" binding:"required"`         // 商品组ID(自增ID)
	Goodsgroupname         string    `json:"goodsgroupname"  xorm:"'GOODSGROUPNAME'" binding:"required"`     // 商品组名称
	Goodsgroupstatus       int64     `json:"goodsgroupstatus"  xorm:"'GOODSGROUPSTATUS'" binding:"required"` // 商品组状态 - 1:正常 2:注销
	Marketid               int64     `json:"marketid"  xorm:"'MARKETID'" binding:"required"`                 // 所属市场ID
	Createtime             time.Time `json:"createtime"  xorm:"'CREATETIME'"`                                // 创建时间
	Creatorid              int64     `json:"creatorid"  xorm:"'CREATORID'"`                                  // 创建人
	Modifytime             time.Time `json:"modifytime"  xorm:"'MODIFYTIME'"`                                // 修改时间
	Modifierid             int64     `json:"modifierid"  xorm:"'MODIFIERID'"`                                // 修改人
	Quotesourcegroupid     int64     `json:"quotesourcegroupid"  xorm:"'QUOTESOURCEGROUPID'"`                // 所属行情源分组ID[参考行情市场用\通道交易]
	Outergroupcode         string    `json:"outergroupcode"  xorm:"'OUTERGROUPCODE'"`                        // 外部商品组代码[通道交易]
	Canshort               int64     `json:"canshort"  xorm:"'CANSHORT'"`                                    // 是否允许做空[通道交易] - 0:不能做空 1:可以做空
	Exexchangeid           int64     `json:"exexchangeid"  xorm:"'EXEXCHANGEID'"`                            // 外部交易所ID[通道交易]
	Currencyid             int64     `json:"currencyid"  xorm:"'CURRENCYID'"`                                // 报价货币ID
	Goodunitid             int64     `json:"goodunitid"  xorm:"'GOODUNITID'"`                                // 报价单位ID
	Agreeunit              float64   `json:"agreeunit"  xorm:"'AGREEUNIT'"`                                  // 合约单位
	Decimalplace           int64     `json:"decimalplace"  xorm:"'DECIMALPLACE'"`                            // 报价小数位
	Quoteminunit           int64     `json:"quoteminunit"  xorm:"'QUOTEMINUNIT'"`                            // 行情最小变动单位 [整数，报价小数位一起使用]
	Innerdealmode          int64     `json:"innerdealmode"  xorm:"'INNERDEALMODE'"`                          // 内部成交方式[通道交易] - 1:净头寸 2:开平 3:平今
	Outerdealmode          int64     `json:"outerdealmode"  xorm:"'OUTERDEALMODE'"`                          // 外部成交方式[通道交易]- 1:净头寸 2:开平 3:平今
	Syncgoodsqty           int64     `json:"syncgoodsqty"  xorm:"'SYNCGOODSQTY'"`                            // 同步合约数[通道交易-投资管理用] - 0表示不限
	Closepricemode         int64     `json:"closepricemode"  xorm:"'CLOSEPRICEMODE'"`                        // 强平价格方式 - 1:市价 2:最新价 3:涨跌停（未实现）
	Closepriceparam        float64   `json:"closepriceparam"  xorm:"'CLOSEPRICEPARAM'"`                      // 强平最新价浮动比例 - 方式为2时使用
	Qtydecimalplace        int64     `json:"qtydecimalplace"  xorm:"'QTYDECIMALPLACE'"`                      // 成交量小数位
	Exercisetype           int64     `json:"exercisetype"  xorm:"'EXERCISETYPE'"`                            // 行权类型[场外期权]-1:欧式期权 2:美式期权
	Premiumdecimalplace    int64     `json:"premiumdecimalplace"  xorm:"'PREMIUMDECIMALPLACE'"`              // 权利金小数位[场外期权]
	Premiumspreadalgorithm int64     `json:"premiumspreadalgorithm"  xorm:"'PREMIUMSPREADALGORITHM'"`        // 权利金点差方式[场外期权]  1:比率  2:固定
	Premiumspreadvalue     float64   `json:"premiumspreadvalue"  xorm:"'PREMIUMSPREADVALUE'"`                // 权利金点差值[场外期权]
	Isbuylimited           int64     `json:"isbuylimited"  xorm:"'ISBUYLIMITED'"`                            // 是否限制建仓量 - 0:不限制 1:限制
	Quotegear              int64     `json:"quotegear"  xorm:"'QUOTEGEAR'"`                                  // 行情档位(1-10)
	Quoterid               int64     `json:"quoterid"  xorm:"'QUOTERID'"`                                    // 报价商ID[场外期权]
}

// TableName is GOODSGROUP
func (Goodsgroup) TableName() string {
	return "GOODSGROUP"
}

// Externalexchange 外部交易所表
type Externalexchange struct {
	Autoid           uint64    `json:"autoid"  xorm:"'AUTOID'" binding:"required"`  // AutoID - SEQ_EXTERNALEXCHANGE
	Exexchangecode   string    `json:"exexchangecode"  xorm:"'EXEXCHANGECODE'"`     // 外部交易所代码
	Exexchangename   string    `json:"exexchangename"  xorm:"'EXEXCHANGENAME'"`     // 外部交易所名称(简称)
	Updatetime       time.Time `json:"updatetime"  xorm:"'UPDATETIME'"`             // 更新时间
	Quotegear        uint32    `json:"quotegear"  xorm:"'QUOTEGEAR'"`               // 行情档位(1-10)
	Showbrokerflag   uint32    `json:"showbrokerflag"  xorm:"'SHOWBROKERFLAG'"`     // 是否显示买卖经纪盘 - 0:不显示 1:显示
	Exchangefullname string    `json:"exchangefullname"  xorm:"'EXCHANGEFULLNAME'"` // 外部交易所全称
	Ismarketprice    uint32    `json:"ismarketprice"  xorm:"'ISMARKETPRICE'"`       // 是否支持市价 - 0:不支持 1:支持
}

// TableName is EXTERNALEXCHANGE
func (Externalexchange) TableName() string {
	return "EXTERNALEXCHANGE"
}

// Marketrun 系统/市场运行参数表
type Marketrun struct {
	Marketid           int32     `json:"marketid"  xorm:"'MARKETID'" binding:"required"`           // 市场ID
	Tradedate          string    `json:"tradedate"  xorm:"'TRADEDATE'" binding:"required"`         // 当前交易日(服务) 资金结算完成即变更，供交易服务使用
	Tradedate2         string    `json:"tradedate2"  xorm:"'TRADEDATE2'" binding:"required"`       // 当前交易日(行情) 在第一个市场待开市时变更为TradeDate，供行情及终端系统使用
	Nexttradedate      string    `json:"nexttradedate"  xorm:"'NEXTTRADEDATE'" binding:"required"` // 下一交易日
	Runstatus          int32     `json:"runstatus"  xorm:"'RUNSTATUS'" binding:"required"`         // 运行状态 - 0:初始化 1:待开市 2:开市 3:休市 4:手工休市 5:闭市 6:确认行权开始 7:确认行权结束 10:日终处理开始 11:日终处理成功 12:日终处理失败 13基础服务结算开始 14基础服务结算成功 23.资金结算开始 24.资金结算成功 25.资金结算失败 26.系统结算成功 27.系统结算失败 28.盘中处理开始 29.盘中处理成功 30.盘中处理失败 31.资金结算开始(内) 32.资金结算成功(内) 33.资金结算失败(内) 40.签到开始 41.签到成功 42.签到部份成功 43.签到失败 44.签退开始 45.签退成功 46.签退部份成功 47.签退失败 48.对账开始 49.对账成功 50.对账失败 51.清算开始 52.清算成功 53.清算失败 54.清算部分成功 55. 系统结算开始 62.今日免清算
	Reckonflag         int32     `json:"reckonflag"  xorm:"'RECKONFLAG'" binding:"required"`       // 结算标识 - 0: 停止结算 1: 正常(管理端控制此字段，交易服务根据此字段判断是否做结算)
	Manualflag         int32     `json:"manualflag"  xorm:"'MANUALFLAG'"`                          // 手动开市标志- 0:否 1:是  (市场为手动时，是否触发了手动开市标志)
	Clearquoteflag     int32     `json:"clearquoteflag"  xorm:"'CLEARQUOTEFLAG'"`                  // 行情清盘标志- 1:未发送 2:已发送 3:已回复
	Updatetime         time.Time `json:"updatetime"  xorm:"'UPDATETIME'"`                          // 更新时间
	Pretradedate       string    `json:"pretradedate"  xorm:"'PRETRADEDATE'"`                      // 上一交易日
	Sectionid          int32     `json:"sectionid"  xorm:"'SECTIONID'"`                            // 时间段号[多时段时用]
	Afternexttradedate string    `json:"afternexttradedate"  xorm:"'AFTERNEXTTRADEDATE'"`          // 下下交易日
	Machinedate        string    `json:"machinedate"  xorm:"'MACHINEDATE'"`                        // 机器时间
	Lastreckondate     string    `json:"lastreckondate"  xorm:"'LASTRECKONDATE'"`                  // 最新交易日(结算成功)
}

// TableName is MARKETRUN
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 市场信息
// 返回值 error 错误
func GetMarket(marketID int) (*Market, error) {
	engine := db.GetEngine()

	var market Market
	has, err := engine.Where("MARKETID = ?", marketID).Get(&market)
	if err != nil {
		return nil, err
	}
	if has {
		return &market, nil
	}

	return nil, nil
}

// GetMarketByGoodsCode 通过商品代码获取市场信息
// 参数 goodsCode string 商品代码
// 返回值 *Market 市场信息
// 返回值 error 错误
func GetMarketByGoodsCode(goodsCode string) (*Market, error) {
	engine := db.GetEngine()

	var market Market
	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
}

// GetMarketByGoodsID 通过商品ID获取市场信息
func GetMarketByGoodsID(goodsID int) (*Market, error) {
	engine := db.GetEngine()

	var market Market
	has, err := engine.Join("LEFT", "GOODS", "GOODS.MARKETID = MARKET.MARKETID").
		Where("GOODS.GOODSID = ?", goodsID).Get(&market)
	if err != nil {
		return nil, err
	}
	if has {
		return &market, nil
	}

	return nil, nil
}

// GetMarketsByTradeMode 通用交易模式获取市场信息
func GetMarketsByTradeMode(tradeMode int) ([]Market, error) {
	markets := make([]Market, 0)

	if err := db.GetEngine().Where("TRADEMODE = ?", tradeMode).Find(&markets); err != nil {
		return nil, err
	}

	return markets, nil
}

// GetMarkets 获取所有市场信息
// 返回值 []Market 市场信息
// 返回值 error 错误
func GetMarkets() ([]Market, error) {
	engine := db.GetEngine()

	markets := make([]Market, 0)
	if err := engine.Find(&markets); err != nil {
		return nil, err
	}

	return markets, 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
}

// GetMarketRuns 获取目标市场运行参数信息
func GetMarketRuns(marketID int) ([]Marketrun, error) {
	engine := db.GetEngine()

	marketRuns := make([]Marketrun, 0)
	session := engine.Table("MARKETRUN")
	if marketID > 0 {
		session = session.Where("MARKETID = ?", marketID)
	}
	if err := session.Find(&marketRuns); err != nil {
		return nil, err
	}

	return marketRuns, nil
}

// GetMarketRuns 通用TradeMode获取目标市场运行参数信息
func GetMarketRunsByTradeMode(tradeMode int) ([]Marketrun, error) {
	engine := db.GetEngine()

	marketRuns := make([]Marketrun, 0)
	if err := engine.Table("MARKETRUN R").Join("INNER", "MARKET M", "M.MARKETID = R.MARKETID").Where("M.TRADEMODE = ?", tradeMode).Find(&marketRuns); err != nil {
		return nil, err
	}

	return marketRuns, nil
}

// FindQuoteSourceGroupRunSteps 获取行情源分组开休市计划明细信息
func FindQuoteSourceGroupRunSteps(goods Goods) ([]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
	// }
	// 这里要注意了：以后写SQL应该要先预估一下结果的数量，从而尽量优化
	if err := engine.Table("QUOTESOURCEGROUPRUNSTEP T").
		Join("INNER", "GOODSGROUP GG", "GG.QUOTESOURCEGROUPID = T.GROUPID").
		Where("GG.GOODSGROUPID = ?", goods.Goodsgroupid).
		And("T.SECTIONID <> 0").
		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 runSteps, nil
}

// GetMarketsByLoginID 获取登录账号有权限的市场列表
func GetMarketsByLoginID(loginID int) ([]Market, error) {
	engine := db.GetEngine()

	// 账户下有权限的市场ID列表
	var marketIDs []int
	markets := make([]Market, 0)

	// 获取账户类型 - 1:交易所 2:机构 3:会员子机构 4:经纪人 5:投资者 6:客户  (目前可能登录交易端的账号类型为 2 5)
	userAccount := new(Useraccount)
	has, err := engine.Join("INNER", "LOGINACCOUNT", "USERACCOUNT.UserID = LOGINACCOUNT.UserID").
		Where("LOGINACCOUNT.LoginID = ?", loginID).
		Get(userAccount)
	if err != nil || !has {
		return nil, err
	}
	if userAccount.Usertype == 5 {
		// 如果账户类型为5（投资者），则需要通过其所属经济会员来获取市场权限（表：AreaRoleMarket, 条件：对应市场状态为正常；角色类型：经济会员）
		if err := engine.Table("AREAROLEMARKET A").
			Cols("v.MARKETID").
			Join("INNER", "MARKET M", "M.MARKETID = A.MARKETID").
			Where("M.MARKETSTATUS = 2 and A.ROLETYPE = 7 and A.AREAUSERID = ?", userAccount.Memberuserid).Find(&marketIDs); err != nil {
			return nil, err
		}
	} else {
		// 非投资者账号直接通过资金账号获取市场权限（表：TAAccountMarket）
		var taAccounts []string // 账户下所有资金账户

		// 先要获取当前登录账户对应的资金账户；如果为外部子资金账号（TaAccount.TaAccountType = 1），则使用TaAccount.FromAccountID来获取市场权限
		type taAccount struct {
			AccountID     int `xorm:"ACCOUNTID"`
			TaAccountType int `xorm:"TAACCOUNTTYPE"`
			FromAccountID int `xorm:"FROMACCOUNTID"`
		}
		datas := make([]taAccount, 0)
		if err := engine.Table("LOGINTAACCOUNT").
			Join("INNER", "TAACCOUNT", "LOGINTAACCOUNT.ACCOUNTID = TAACCOUNT.ACCOUNTID").
			Cols("TAACCOUNT.ACCOUNTID", "TAACCOUNT.TAACCOUNTTYPE", "TAACCOUNT.FROMACCOUNTID").
			Where("LOGINTAACCOUNT.LOGINID = ?", loginID).Find(&datas); err != nil {
			return nil, err
		}
		// 如果一条记录都没有(未配置自营会员资金账户)则直接通过资金账户表获取
		if len(datas) == 0 {
			// 这里要注意，TaAccount表与LoginAccount表关联时，要使用TaAccount.RelatedUserID
			if err := engine.Table("TAACCOUNT").
				Join("INNER", "LOGINACCOUNT", "TAACCOUNT.RELATEDUSERID = LOGINACCOUNT.USERID").
				Cols("TAACCOUNT.ACCOUNTID", "TAACCOUNT.TAACCOUNTTYPE", "TAACCOUNT.FROMACCOUNTID").
				Where("LOGINACCOUNT.LOGINID = ?", loginID).Find(&datas); err != nil {
				return nil, err
			}
		}
		for _, v := range datas {
			if v.TaAccountType == 1 {
				// 外部资金账户使用TaAccount.FromAccountID来获取市场权限
				taAccounts = append(taAccounts, strconv.Itoa(v.FromAccountID))
			} else {
				taAccounts = append(taAccounts, strconv.Itoa(v.AccountID))
			}
		}

		// 获取资金账户对应的市场权限（有权限的市场ID）
		if len(taAccounts) > 0 {
			// taAccountStr := strings.Join(taAccounts, ",")
			if err := engine.Table("TAACCOUNTMARKET").
				Join("INNER", "MARKET", "MARKET.MARKETID = TAACCOUNTMARKET.MARKETID").
				Cols("TAACCOUNTMARKET.MARKETID").
				In("TAACCOUNTMARKET.ACCOUNTID", taAccounts).
				And("MARKET.MARKETSTATUS = 2").Find(&marketIDs); err != nil {
				return nil, err
			}
		}
	}

	// 获取市场信息
	if len(marketIDs) > 0 {
		if err := engine.Table("MARKET M").In("M.MARKETID", marketIDs).Find(&markets); err != nil {
			return nil, err
		}
	}

	return markets, nil
}

// GetExternalexchangeByGoodsGroupID 通过商品组ID获取对应交易所信息
func GetExternalexchangeByGoodsGroupID(goodsGroupID int) (*Externalexchange, error) {
	rst := make([]Externalexchange, 0)
	if err := db.GetEngine().Table("EXTERNALEXCHANGE EX").
		Join("INNER", "GOODSGROUP GG", "GG.EXEXCHANGEID = EX.AUTOID").
		Where("GG.GOODSGROUPID = ?", goodsGroupID).
		Find(&rst); err != nil {
		return nil, err
	}
	if len(rst) == 0 {
		return nil, nil
	}

	return &rst[0], nil
}

// GetGoodsgroupInMarketIDs 通过市场ID列表获取对应的商品组信息
func GetGoodsgroupInMarketIDs(marketIDs []int) ([]Goodsgroup, error) {
	goodsgroups := make([]Goodsgroup, 0)
	if err := db.GetEngine().In("MARKETID", marketIDs).Find(&goodsgroups); err != nil {
		return nil, err
	}

	return goodsgroups, nil
}

// GetExExchangeByIDs 通过ID列表获取对应的外部交易所信息
func GetExExchangeByIDs(exchangeIDs []int) ([]Externalexchange, error) {
	exExchanges := make([]Externalexchange, 0)
	if err := db.GetEngine().In("AUTOID", exchangeIDs).Find(&exExchanges); err != nil {
		return nil, err
	}

	return exExchanges, nil
}
