// Package cptrade 产能预售
package cptrade

import (
	"fmt"
	"mtp2_if/db"
	"mtp2_if/global/app"
	"mtp2_if/global/e"
	"mtp2_if/logger"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
)

// QueryPresaleApplyReq 产能预售申请表请求参数
type QueryPresaleApplyReq struct {
	UserID    int `form:"userid" binding:"required"`
	ApplyID   int `form:"applyid"`
	AccountID int `form:"accountid"`
}

// Cptradepresaleapply CPTRADE_PRESALEAPPLY 产能预售申请表
type Cptradepresaleapply struct {
	Applyid        int64     `json:"applyid"  xorm:"'APPLYID'" binding:"required"` // 申请ID(181+Unix秒时间戳(10位)+xxxxxx)
	Userid         int64     `json:"userid"  xorm:"'USERID'"`                      // 申请人ID
	Accountid      int64     `json:"accountid"  xorm:"'ACCOUNTID'"`                // 申请人账户ID
	Goodscode      string    `json:"goodscode"  xorm:"'GOODSCODE'"`                // 商品代码
	Goodsname      string    `json:"goodsname"  xorm:"'GOODSNAME'"`                // 商品名称
	Relatedgoodsid int64     `json:"relatedgoodsid"  xorm:"'RELATEDGOODSID'"`      // 关联交易合约ID
	Presaleqty     int64     `json:"presaleqty"  xorm:"'PRESALEQTY'"`              // 预售数量
	Starttime      time.Time `json:"starttime"  xorm:"'STARTTIME'"`                // 预售开始时间
	Endtime        time.Time `json:"endtime"  xorm:"'ENDTIME'"`                    // 预售结束时间
	Attachmenturl  string    `json:"attachmenturl"  xorm:"'ATTACHMENTURL'"`        // 附件地址
	Applystatus    int64     `json:"applystatus"  xorm:"'APPLYSTATUS'"`            // 申请状态 - 1:已提交 2:初审通过 3:初审拒绝 4:初审失败 5复审通过 6:复审拒绝 7:复审失败 8:已撤销
	Handlestatus   int64     `json:"handlestatus"  xorm:"'HANDLESTATUS'"`          // 处理状态
	Applytime      time.Time `json:"applytime"  xorm:"'APPLYTIME'"`                // 申请时间
	Marketid       int64     `json:"marketid"  xorm:"'MARKETID'"`                  // 预售市场ID
	Tradedate      string    `json:"tradedate"  xorm:"'TRADEDATE'"`                // 交易日(yyyyMMdd)
	Applyremark    string    `json:"applyremark"  xorm:"'APPLYREMARK'"`            // 申请备注

	Relatedgoodscode string `json:"relatedgoodscode" xorm:"'RELATEDGOODSCODE'"` // 关联交易合约代码
	Relatedgoodsname string `json:"relatedgoodsname" xorm:"'RELATEDGOODSNAME'"` // 关联交易合约名称
	Marketname       string `json:"marketname" xorm:"'MARKETNAME'"`             // 预售市场名称
	Trademode        int64  `json:"trademode" xorm:"'TRADEMODE'"`               // 交易模式 - 16:挂牌点选 21:大宗竞拍
	Goodunit         string `json:"goodunit" xorm:"'GOODUNIT'"`                 // 报价单位
	Goodsid          int64  `json:"goodsid" xorm:"'GOODSID'"`                   // 商品ID
}

// QueryPreasleApply 查询产能预售申请信息
// @Summary 查询产能预售申请信息
// @Produce json
// @Security ApiKeyAuth
// @Param userid query int true "账户ID"
// @Param applyid query int false "申请ID"
// @Param accountid query int false "资金账户ID"
// @Success 200 {object} Cptradepresaleapply
// @Failure 500 {object} app.Response
// @Router /CPTrade/QueryPreasleApply [get]
// @Tags 产能预售
func QueryPreasleApply(c *gin.Context) {
	appG := app.Gin{C: c}

	// 获取请求参数
	var req QueryPresaleApplyReq
	if err := appG.C.ShouldBindQuery(&req); err != nil {
		logger.GetLogger().Errorf("QueryPreasleApply failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	// 查询数据
	engine := db.GetEngine()
	datas := make([]Cptradepresaleapply, 0)
	// s := engine.Where("userid=?", req.UserID)
	// if req.AccountID > 0 {
	// 	s = s.And("accountid=?", req.AccountID)
	// }
	// if req.ApplyID > 0 {
	// 	s = s.And("applyid=?", req.ApplyID)
	// }
	sql := fmt.Sprintf(`select
							t.ApplyID,
							t.UserID,
							t.AccountID,
							t.GoodsCode,
							t.GoodsName,
							t.RelatedGoodsID,
							t.PresaleQty,
							t.StartTime,
							t.EndTime,
							t.AttachmentUrl,
							t.ApplyStatus,
							t.HandleStatus,
							t.ApplyTime,
							t.CreatorID,
							t.CreateTime,
							t.MarketID,
							t.TradeDate,
							t.APPLYREMARK,
							g.goodscode RelatedGoodsCode,
							g.goodsname RelatedGoodsName,
							m.MarketName,
							m.TradeMode,
							e.enumdicname GoodUnit,
							g.GoodsID
						from CPTrade_PresaleApply t
						left join goods g on t.RelatedGoodsID = g.goodsid
						left join market m on t.MarketID = m.marketid
						left join enumdicitem e on g.goodunitid = e.enumitemname and e.enumdiccode = 'goodsunit' 
						where t.UserID = %d`, req.UserID)
	if req.AccountID > 0 {
		sql += fmt.Sprintf(` and t.AccountID = %d`, req.AccountID)
	}
	if req.ApplyID > 0 {
		sql += fmt.Sprintf(` and t.ApplyID = %d`, req.ApplyID)
	}
	if err := engine.SQL(sql).Find(&datas); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryPreasleApply failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	// 查询成功
	logger.GetLogger().Debugln("QueryPreasleApply successed: %v", datas)
	appG.Response(http.StatusOK, e.SUCCESS, datas)
}

// QueryCPTradeUserGoodsDataReq 远期订单查询请求参数
type QueryCPTradeUserGoodsDataReq struct {
	AccountID int `form:"accountid" binding:"required"`
}

// Cptradeusergoodsdata 用户合约数据表 - 导历史 (远期订单数据)
type Cptradeusergoodsdata struct {
	Accountid      int64   `json:"accountid"  xorm:"'ACCOUNTID'" binding:"required"` // 账户ID
	Goodsid        int64   `json:"goodsid"  xorm:"'GOODSID'" binding:"required"`     // 商品ID
	Wrstandardid   int64   `json:"wrstandardid"  xorm:"'WRSTANDARDID'"`              // 仓单标准ID
	Userid         int64   `json:"userid"  xorm:"'USERID'"`                          // 用户ID
	Inqty          int64   `json:"inqty"  xorm:"'INQTY'"`                            // 转入量（总数量）
	Cancelqty      int64   `json:"cancelqty"  xorm:"'CANCELQTY'"`                    // 注销量
	Deliveryqty    int64   `json:"deliveryqty"  xorm:"'DELIVERYQTY'"`                // 交割量
	Curpresaleqty  int64   `json:"curpresaleqty"  xorm:"'CURPRESALEQTY'"`            // 当前预售量
	Presaledqty    int64   `json:"presaledqty"  xorm:"'PRESALEDQTY'"`                // 已预售量
	Presaledamount int64   `json:"presaledamount"  xorm:"'PRESALEDAMOUNT'"`          // 已预售总金额
	Marketid       int64   `json:"marketid"  xorm:"'MARKETID'"`                      // 市场ID
	Freezeamount   float64 `json:"freezeamount"  xorm:"'FREEZEAMOUNT'"`              // 冻结金额
	Hasspotfreeze  int64   `json:"hasspotfreeze"  xorm:"'HASSPOTFREEZE'"`            // 是否有现货冻结 - 0:否 1:有

	Goodscode      string `json:"GoodsCode"  xorm:"'GOODSCODE'"`          // 订单商品代码
	Goodsname      string `json:"GoodsName"  xorm:"'GOODSNAME'"`          // 订单商品名称
	Wrstandardcode string `json:"WRStandardCode" xorm:"'WRSTANDARDCODE'"` // 仓单标准代码
	Wrstandardname string `json:"WRStandardName" xorm:"'WRSTANDARDNAME'"` // 仓单标准名称
	Enabledqty     int64  `json:"EnabledQty" xorm:"'ENABLEDQTY'"`         // 可用量
	Goodunit       string `json:"goodunit" xorm:"'GOODUNIT'"`             // 报价单位
}

// TableName is CPTRADE_USERGOODSDATA
// func (Cptradeusergoodsdata) TableName() string {
// 	return "CPTRADE_USERGOODSDATA"
// }

// QueryUserGoodsData 查询远期订单信息
// @Summary 查询远期订单信息
// @Produce json
// @Security ApiKeyAuth
// @Param accountid query int true "资金账户ID"
// @Success 200 {object} Cptradeusergoodsdata
// @Failure 500 {object} app.Response
// @Router /CPTrade/QueryUserGoodsData [get]
// @Tags 产能预售
func QueryUserGoodsData(c *gin.Context) {
	appG := app.Gin{C: c}

	// 获取请求参数
	var req QueryCPTradeUserGoodsDataReq
	if err := appG.C.ShouldBindQuery(&req); err != nil {
		logger.GetLogger().Errorf("QueryUserGoodsData failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	// 查询数据
	engine := db.GetEngine()
	datas := make([]Cptradeusergoodsdata, 0)
	if err := engine.SQL(`select 
							t.AccountID,
							t.GoodsID,
							t.WRStandardID,
							t.UserID,
							t.InQty,
							t.CancelQty,
							t.DeliveryQty,
							t.CurPresaleQty,
							t.PresaledQty,
							t.PresaledAmount,
							t.FreezeAmount,
							t.MarketID,
							t.HasSpotFreeze,
							g.GoodsCode,
							g.GoodsName,
							ws.WRStandardCode,
							ws.WRStandardName,
							(t.InQty - t.CancelQty - t.DeliveryQty - t.CurPresaleQty) EnabledQty,
							e.enumdicname GoodUnit
						from CPTrade_UserGoodsData t
						left join goods g on t.goodsid = g.goodsid
						left join WRStandard ws on t.wrstandardid = ws.wrstandardid 
						left join enumdicitem e on g.goodunitid = e.enumitemname and e.enumdiccode = 'goodsunit' 
						where t.accountid = ?`, req.AccountID).Find(&datas); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryUserGoodsData failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	// 查询成功
	logger.GetLogger().Debugln("QueryUserGoodsData successed: %v", datas)
	appG.Response(http.StatusOK, e.SUCCESS, datas)
}

// QueryPositionCancelReq 查询远期订单注销申请请求参数
type QueryPositionCancelReq struct {
	UserID    int `form:"userid" binding:"required"`
	AccountID int `form:"accountid"`
	CancelID  int `form:"cancelid"`
}

// Cptradepositioncancel 远期订单注销申请表
type Cptradepositioncancel struct {
	Cancelid     int64     `json:"cancelid"  xorm:"'CANCELID'" binding:"required"` // 注销ID(SEQ_CPTRADE_POSITIONCANCEL)
	Userid       int64     `json:"userid"  xorm:"'USERID'"`                        // 申请人ID
	Accountid    int64     `json:"accountid"  xorm:"'ACCOUNTID'"`                  // 申请人账户ID
	Goodsid      int64     `json:"goodsid"  xorm:"'GOODSID'"`                      // 商品ID
	Cancelqty    int64     `json:"cancelqty"  xorm:"'CANCELQTY'"`                  // 注销数量
	Applystatus  int64     `json:"applystatus"  xorm:"'APPLYSTATUS'"`              // 申请状态 - 1:已提交 2:初审通过 3:初审拒绝 4:初审失败 5复审通过 6:复审拒绝 7:复审失败  8:已撤销
	Handlestatus int64     `json:"handlestatus"  xorm:"'HANDLESTATUS'"`            // 处理状态
	Applytime    time.Time `json:"applytime"  xorm:"'APPLYTIME'"`                  // 申请时间
	Creatorid    int64     `json:"creatorid"  xorm:"'CREATORID'"`                  // 创建人ID
	Createtime   time.Time `json:"createtime"  xorm:"'CREATETIME'"`                // 创建时间
	Tradedate    string    `json:"tradedate"  xorm:"'TRADEDATE'"`                  // 交易日(yyyyMMdd)
	Marketid     int64     `json:"marketid"  xorm:"'MARKETID'"`                    // 市场ID

	Goodscode   string `json:"goodscode"  xorm:"'GOODSCODE'"`  // 订单商品代码
	Goodsname   string `json:"goodsname"  xorm:"'GOODSNAME'"`  // 订单商品名称
	Marketname  string `json:"marketname"  xorm:"'GOODSNAME'"` // 市场名称
	Goodunit    string `json:"goodunit" xorm:"'GOODUNIT'"`     // 报价单位
	Creatorname string `json:"creatorname" xorm:"CREATORNAME"` // 创建人
}

// QueryPositionCancel 查询远期订单注销申请信息
// @Summary 查询远期订单注销申请信息
// @Produce json
// @Security ApiKeyAuth
// @Param userid query int true "账户ID"
// @Param cancelid query int false "注销ID"
// @Param accountid query int false "资金账户ID"
// @Success 200 {object} Cptradepositioncancel
// @Failure 500 {object} app.Response
// @Router /CPTrade/QueryPositionCancel [get]
// @Tags 产能预售
func QueryPositionCancel(c *gin.Context) {
	appG := app.Gin{C: c}

	// 获取请求参数
	var req QueryPositionCancelReq
	if err := appG.C.ShouldBindQuery(&req); err != nil {
		logger.GetLogger().Errorf("QueryPositionCancel failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	// 查询数据
	sql := fmt.Sprintf(`select 
							t.CancelID,
							t.UserID,
							t.AccountID,
							t.GoodsID,
							t.CancelQty,
							t.ApplyStatus,
							t.HandleStatus,
							t.ApplyTime,
							t.CreatorID,
							t.CreateTime,
							t.TradeDate,
							t.MarketID,
							g.GoodsCode,
							g.GoodsName,
							m.MarketName,
							e.enumdicname GoodUnit,
							u.username CreatorName
						from CPTrade_PositionCancel t
						left join goods g on t.goodsid = g.goodsid
						left join market m on t.marketid = m.marketid 
						left join enumdicitem e on g.goodunitid = e.enumitemname and e.enumdiccode = 'goodsunit' 
						left join systemmanager u on t.creatorid = u.autoid 
						where t.userid = %d`, req.UserID)
	if req.AccountID > 0 {
		sql += fmt.Sprintf(` and t.AccountID= %d`, req.AccountID)
	}
	if req.CancelID > 0 {
		sql += fmt.Sprintf(` and t.CancelID= %d`, req.CancelID)
	}
	engine := db.GetEngine()
	datas := make([]Cptradepositioncancel, 0)
	if err := engine.SQL(sql).Find(&datas); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryPositionCancel failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	// 查询成功
	logger.GetLogger().Debugln("QueryPositionCancel successed: %v", datas)
	appG.Response(http.StatusOK, e.SUCCESS, datas)
}

// QueryPresaleGoodsExReq 查询产能预售商品扩展请求参数
type QueryPresaleGoodsExReq struct {
	GoodsID     int    `form:"goodsid"`
	MarketID    int    `form:"marketid"`
	PresaleMode int    `form:"presalemode"`
	GoodsIDs    string `form:"goodsids"`
	GoodsCode   string `form:"goodscode"`
}

// QueryPresaleGoodsExRsp 产能预售商品扩展表
type QueryPresaleGoodsExRsp struct {
	Goodsid         int64     `json:"goodsid"  xorm:"'GOODSID'" binding:"required"` // 商品ID（预售）
	Relatedgoodsid  int64     `json:"relatedgoodsid"  xorm:"'RELATEDGOODSID'"`      // 关联交易合约ID
	Presaleqty      int64     `json:"presaleqty"  xorm:"'PRESALEQTY'"`              // 预售数量
	Starttime       time.Time `json:"starttime"  xorm:"'STARTTIME'"`                // 预售开始时间
	Endtime         time.Time `json:"endtime"  xorm:"'ENDTIME'"`                    // 预售结束时间
	Attachmenturl   string    `json:"attachmenturl"  xorm:"'ATTACHMENTURL'"`        // 附件地址
	Presalemode     int64     `json:"presalemode"  xorm:"'PRESALEMODE'"`            // 预售模式 - 1:一口价 2:大宗式竞拍
	Marketid        int64     `json:"marketid"  xorm:"'MARKETID'"`                  // 预售市场ID - 根据预售模式选择市场
	Refprice        float64   `json:"refprice"  xorm:"'REFPRICE'"`                  // 参考价格[一口价]
	Startprice      float64   `json:"startprice"  xorm:"'STARTPRICE'"`              // 起拍价[大宗式竞拍]
	Floorprice      float64   `json:"floorprice"  xorm:"'FLOORPRICE'"`              // 底价[大宗式竞拍]
	Createtime      time.Time `json:"createtime"  xorm:"'CREATETIME'"`              // 创建时间
	Tradedate       string    `json:"tradedate"  xorm:"'TRADEDATE'"`                // 交易日(yyyyMMdd)
	Relatedmarketid int64     `json:"relatedmarketid"  xorm:"'RELATEDMARKETID'"`    // 关联交易合约市场ID
	Presaledqty     int64     `json:"presaledqty"  xorm:"'PRESALEDQTY'"`            // 已预售量(预售结束时更新)
	Sellstatus      int64     `json:"sellstatus"  xorm:"'SELLSTATUS'"`              // 卖方处理状态 - 1:卖方头寸未处理 2:卖方头寸已处理
	Presaledamount  float64   `json:"presaledamount"  xorm:"'PRESALEDAMOUNT'"`      // 已预售总金额(预售结束时更新)
	Goodsdetail     string    `json:"goodsdetail"  xorm:"'GOODSDETAIL'"`            // 详情[大宗]
	Tradeprice      float64   `json:"tradeprice"  xorm:"'TRADEPRICE'"`              // 成交价[大宗]

	Goodunit string `json:"goodunit" xorm:"'GOODUNIT'"` // 报价单位
}

// QueryPresaleGoodsEx 查询产能预售商品扩展信息
// @Summary 查询产能预售商品扩展信息
// @Produce json
// @Security ApiKeyAuth
// @Param goodsid query int false "预售商品ID"
// @Param marketid query int false "预售市场ID"
// @Param presalemode query int false "预售模式 - 1:一口价 2:大宗式竞拍"
// @Param goodsids query string false "预售商品ID列表 - 格式：1,2,3"
// @Param goodscode query string false "预售商品代码"
// @Success 200 {object} QueryPresaleGoodsExRsp
// @Failure 500 {object} app.Response
// @Router /CPTrade/QueryPresaleGoodsEx [get]
// @Tags 产能预售
func QueryPresaleGoodsEx(c *gin.Context) {
	appG := app.Gin{C: c}

	// FIXME: 由于数据中包括[]int类型，会造成校验报错，故暂时不使用
	// 获取请求参数
	var req QueryPresaleGoodsExReq
	if err := appG.C.ShouldBindQuery(&req); err != nil {
		logger.GetLogger().Errorf("QueryPresaleGoodsEx failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	// 查询数据
	engine := db.GetEngine()
	datas := make([]QueryPresaleGoodsExRsp, 0)
	sql := `select
				t.GoodsID,
				t.ApplyID,
				t.UserID,
				t.AccountID,
				t.RelatedGoodsID,
				t.PresaleQty,
				t.StartTime,
				t.EndTime,
				t.AttachmentUrl,
				t.PresaleMode,
				t.MarketID,
				t.RefPrice,
				t.StartPrice,
				t.FloorPrice,
				t.CreateTime,
				t.TradeDate,
				t.RelatedMarketID,
				t.PresaledQty,
				t.PresaledAmount,
				t.SellStatus,
				t.GoodsDetail,
				t.TradePrice,
				e.enumdicname GoodUnit
			from CPTrade_PresaleGoodsEx t
			left join goods g on t.GoodsID = g.goodsid
			left join enumdicitem e on g.goodunitid = e.enumitemname and e.enumdiccode = 'goodsunit'
			where 1=1 `
	if req.GoodsID > 0 {
		sql += fmt.Sprintf(" and t.GoodsID = %d", req.GoodsID)
	}
	if req.MarketID > 0 {
		sql += fmt.Sprintf(" and t.MarketID = %d", req.MarketID)
	}
	if req.PresaleMode > 0 {
		sql += fmt.Sprintf(" and t.PresaleMode = %d", req.PresaleMode)
	}
	if len(req.GoodsIDs) > 0 {
		// s = s.And("GoodsID in (?)", req.GoodsIDs)
		sql += fmt.Sprintf(" and t.GoodsID in (%s)", req.GoodsIDs)
	}
	if len(req.GoodsCode) > 0 {
		sql += fmt.Sprintf(" and g.GoodsCode = '%s'", req.GoodsCode)
	}
	if err := engine.SQL(sql).Find(&datas); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryPresaleGoodsEx failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	// 查询成功
	logger.GetLogger().Debugln("QueryPresaleGoodsEx successed: %v", datas)
	appG.Response(http.StatusOK, e.SUCCESS, datas)
}

// QueryCPTradeMyBidReq 我的出价信息查询请求参数
type QueryCPTradeMyBidReq struct {
	AccountID int `form:"accountid" binding:"required"`
	GoodsID   int `form:"goodsid"`
	MarketID  int `form:"marketid"`
}

// QueryCPTradeMyBidRsp 我的出价信息查询
type QueryCPTradeMyBidRsp struct {
	Orderid    int64     `json:"orderid"  xorm:"'ORDERID'" binding:"required"`     // 委托单号(100+Unix秒时间戳(10位)+2位(MarketServiceID)+xxxx)
	Marketid   int64     `json:"marketid"  xorm:"'MARKETID'" binding:"required"`   // 市场ID
	Goodsid    int64     `json:"goodsid"  xorm:"'GOODSID'" binding:"required"`     // 商品ID
	Accountid  int64     `json:"accountid"  xorm:"'ACCOUNTID'" binding:"required"` // 账户ID[报价币种]
	Orderprice float64   `json:"orderprice"  xorm:"'ORDERPRICE'"`                  // 委托价格
	Orderqty   int64     `json:"orderqty"  xorm:"'ORDERQTY'" binding:"required"`   // 委托数量
	Ordertime  time.Time `json:"ordertime"  xorm:"'ORDERTIME'" binding:"required"` // 委托时间

	Tradeprice float64 `json:"tradeprice"  xorm:"'TRADEPRICE'" binding:"required"` // 成交价格
	Tradeqty   int64   `json:"tradeqty"  xorm:"'TRADEQTY'" binding:"required"`     // 成交数量

	Goodunit string `json:"goodunit" xorm:"'GOODUNIT'"` // 报价单位

	OrderTotalPrice  float64 `json:"ordertotalprice"  xorm:"'ORDERTOTALPRICE'"`   // 货款金额（委托总价格=委托价格*委托数量*合约单位）
	OrderTotalWeight int64   `json:"ordertotalweight"  xorm:"'ORDERTOTALWEIGHT'"` // 竞拍总重量（委托总重量=委托数量*合约单位）
	TotalTotalPrice  float64 `json:"totaltotalprice"  xorm:"'TOTALTOTALPRICE'"`   // 成交货款金额（成交总价格=成交价格*成交数量*合约单位）
}

// QueryCPTradeMyBidInfos 查询产能预售我的出价信息
// @Summary 查询产能预售我的出价信息
// @Produce json
// @Security ApiKeyAuth
// @Param accountid query int true "资金账户"
// @Param marketid query int false "预售市场ID"
// @Param goodsid query int false "预售商品ID"
// @Success 200 {object} QueryCPTradeMyBidRsp
// @Failure 500 {object} app.Response
// @Router /CPTrade/QueryCPTradeMyBidInfos [get]
// @Tags 产能预售
func QueryCPTradeMyBidInfos(c *gin.Context) {
	appG := app.Gin{C: c}

	// 获取请求参数
	var req QueryCPTradeMyBidReq
	if err := appG.C.ShouldBindQuery(&req); err != nil {
		logger.GetLogger().Errorf("QueryCPTradeMyBidInfos failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	// 查询数据
	engine := db.GetEngine()
	datas := make([]QueryCPTradeMyBidRsp, 0)
	// 我的出价 -> 限价买建仓委托单
	sql := fmt.Sprintf(`select 
							t.OrderID,
							t.MarketID,
							t.GoodsID,
							t.AccountID,
							t.OrderPrice,
							t.OrderQty,
							t.OrderTime,
							td.TradePrice,
							td.TradeQty,
							e.enumdicname GoodUnit,
							(t.orderprice * t.orderqty * g.agreeunit) OrderTotalPrice,
							(t.orderqty * g.agreeunit) OrderTotalWeight,
							(td.tradeprice * td.tradeqty * g.agreeunit) TotalTotalPrice
						from Trade_OrderDetail t
						left join Trade_TradeDetail td on t.orderid = td.OrderID
						left join goods g on t.goodsid = g.goodsid
						left join enumdicitem e on g.goodunitid = e.enumitemname and e.enumdiccode = 'goodsunit' 
						where t.BuyOrSell = 0 and t.BuildType = 1 and t.PriceMode = 2 and t.AccountID = %d`, req.AccountID)
	if req.GoodsID > 0 {
		sql += fmt.Sprintf(" and t.GoodsID = %d", req.GoodsID)
	}
	if req.MarketID > 0 {
		sql += fmt.Sprintf(" and t.MarketID = %d", req.MarketID)
	} else {
		// 如果没有传市场ID，则肯定查询预售一口价挂牌（40）和预售大宗竞拍（41）两个市场的数据
		// FIXME: 目前暂时直接写死市场ID
		sql += fmt.Sprintf(" and t.MarketID in (%s)", "40201,41201")
	}
	if err := engine.SQL(sql).Find(&datas); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryCPTradeMyBidInfos failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	// 查询成功
	logger.GetLogger().Debugln("QueryCPTradeMyBidInfos successed: %v", datas)
	appG.Response(http.StatusOK, e.SUCCESS, datas)
}

// QueryMyCPTradeGoodsReq 查询我的预售信息请求参数
type QueryMyCPTradeGoodsReq struct {
	AccountID int `form:"accountid" binding:"required"`
}

// QueryMyCPTradeGoodsRsp 我的预售信息
type QueryMyCPTradeGoodsRsp struct {
	Goodsid      int64   `json:"goodsid"  xorm:"'GOODSID'" binding:"required"`     // 商品ID(自增ID SEQ_GOODS)
	Goodscode    string  `json:"goodscode"  xorm:"'GOODSCODE'" binding:"required"` // 商品代码(预售)
	Goodsname    string  `json:"goodsname"  xorm:"'GOODSNAME'" binding:"required"` // 商品名称(预售)
	Marketid     int64   `json:"marketid"  xorm:"'MARKETID'" binding:"required"`   // 所属市场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'"`              // 报价小数位

	Marketname string `json:"marketname" xorm:"'MARKETNAME'"` // 预售市场名称

	Goodunit string `json:"goodunit" xorm:"'GOODUNIT'"` // 报价单位

	Applyid         int64     `json:"applyid"  xorm:"'APPLYID'"`                 // 关联申请ID
	Userid          int64     `json:"userid"  xorm:"'USERID'"`                   // 卖方用户ID
	Accountid       int64     `json:"accountid"  xorm:"'ACCOUNTID'"`             // 卖方账户ID
	Relatedgoodsid  int64     `json:"relatedgoodsid"  xorm:"'RELATEDGOODSID'"`   // 关联交易合约ID
	Presaleqty      int64     `json:"presaleqty"  xorm:"'PRESALEQTY'"`           // 预售数量
	Starttime       time.Time `json:"starttime"  xorm:"'STARTTIME'"`             // 预售开始时间
	Endtime         time.Time `json:"endtime"  xorm:"'ENDTIME'"`                 // 预售结束时间
	Attachmenturl   string    `json:"attachmenturl"  xorm:"'ATTACHMENTURL'"`     // 附件地址
	Presalemode     int64     `json:"presalemode"  xorm:"'PRESALEMODE'"`         // 预售模式 - 1:一口价 2:大宗式竞拍
	Refprice        float64   `json:"refprice"  xorm:"'REFPRICE'"`               // 参考价格[一口价]
	Startprice      float64   `json:"startprice"  xorm:"'STARTPRICE'"`           // 起拍价[大宗式竞拍]
	Floorprice      float64   `json:"floorprice"  xorm:"'FLOORPRICE'"`           // 底价[大宗式竞拍]
	Createtime      time.Time `json:"createtime"  xorm:"'CREATETIME'"`           // 创建时间
	Tradedate       string    `json:"tradedate"  xorm:"'TRADEDATE'"`             // 交易日(yyyyMMdd)
	Relatedmarketid int64     `json:"relatedmarketid"  xorm:"'RELATEDMARKETID'"` // 关联交易合约市场ID
	Presaledqty     int64     `json:"presaledqty"  xorm:"'PRESALEDQTY'"`         // 已预售量(预售结束时更新)
	Sellstatus      int64     `json:"sellstatus"  xorm:"'SELLSTATUS'"`           // 卖方处理状态 - 1:卖方头寸未处理 2:卖方头寸已处理
	Presaledamount  float64   `json:"presaledamount"  xorm:"'PRESALEDAMOUNT'"`   // 已预售总金额(预售结束时更新)
	Goodsdetail     string    `json:"goodsdetail"  xorm:"'GOODSDETAIL'"`         // 详情[大宗]
	Tradeprice      float64   `json:"tradeprice"  xorm:"'TRADEPRICE'"`           // 成交价[大宗]

	Relatedgoodscode string `json:"relatedgoodscode"  xorm:"'RELATEDGOODSCODE'" binding:"required"` // 商品代码(订单)
	Relatedgoodsname string `json:"relatedgoodsname"  xorm:"'RELATEDGOODSNAME'" binding:"required"` // 商品名称(订单)
}

// QueryMyCPTradeGoods 查询我的预售信息
// @Summary 查询我的预售信息
// @Produce json
// @Security ApiKeyAuth
// @Param accountid query int true "资金账户"
// @Success 200 {object} QueryMyCPTradeGoodsRsp
// @Failure 500 {object} app.Response
// @Router /CPTrade/QueryMyCPTradeGoods [get]
// @Tags 产能预售
func QueryMyCPTradeGoods(c *gin.Context) {
	appG := app.Gin{C: c}

	// 获取请求参数
	var req QueryMyCPTradeGoodsReq
	if err := appG.C.ShouldBindQuery(&req); err != nil {
		logger.GetLogger().Errorf("QueryMyCPTradeGoods failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	// 查询数据
	engine := db.GetEngine()
	datas := make([]QueryMyCPTradeGoodsRsp, 0)
	sql := fmt.Sprintf(`select
							t.Goodsid,
							t.Goodscode,
							t.Goodsname,
							t.Marketid,
							t.Currencyid,
							t.Goodunitid,
							t.Agreeunit,
							t.Decimalplace,
							m.Marketname,
							e.enumdicname GoodUnit,
							c.Applyid,
							c.Userid,
							c.Accountid,
							c.Relatedgoodsid,
							c.Presaleqty,
							c.Starttime,
							c.Endtime,
							c.Attachmenturl,
							c.Presalemode,
							c.Refprice,
							c.Startprice,
							c.Floorprice,
							c.Createtime,
							c.Tradedate,
							c.Relatedmarketid,
							c.Presaledqty,
							c.Sellstatus,
							c.Presaledamount,
							c.Goodsdetail,
							c.Tradeprice,
							g1.Goodscode RelatedGoodsCode,
							g1.GoodsName RelatedGoodsName
						from goods t
						left join market m on t.marketid = m.marketid
						left join enumdicitem e on t.goodunitid = e.enumitemname and e.enumdiccode = 'goodsunit'
						left join CPTRADE_PRESALEGOODSEX c on t.goodsid = c.goodsid
						left join goods g1 on c.Relatedgoodsid = g1.goodsid
						where m.trademode in (40,41) and c.Accountid = %d`, req.AccountID)
	if err := engine.SQL(sql).Find(&datas); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryMyCPTradeGoods failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	// 查询成功
	logger.GetLogger().Debugln("QueryMyCPTradeGoods successed: %v", datas)
	appG.Response(http.StatusOK, e.SUCCESS, datas)
}

// QueryCPTradeOrderDetailReq 查询产能预售委托单信息请求参数
type QueryCPTradeOrderDetailReq struct {
	GoodsID  int    `form:"goodsid"`
	GoodsIDs string `form:"goodsids"`
	MarketID int    `form:"marketid"`
}

// QueryCPTradeOrderDetailRsq 产能预售委托单信息
type QueryCPTradeOrderDetailRsq struct {
	Strorderid              string    `json:"strorderid"  xorm:"'STRORDERID'" binding:"required"`        // 委托单号
	Tradedate               string    `json:"tradedate"  xorm:"'TRADEDATE'" binding:"required"`          // 交易日(yyyyMMdd)
	Buildtype               int64     `json:"buildtype"  xorm:"'BUILDTYPE'" binding:"required"`          // 委托单据类型 - 1:建仓 2:平仓 3:先平后建
	Preorderid              int64     `json:"preorderid"  xorm:"'PREORDERID'"`                           // 关联预埋单号(止盈止损单时填写)
	Cancelorderid           int64     `json:"cancelorderid"  xorm:"'CANCELORDERID'"`                     // 撤单单号(撤单时填写)
	Relatedid               int64     `json:"relatedid"  xorm:"'RELATEDID'"`                             // 关联单号(交割单)
	Marketid                int64     `json:"marketid"  xorm:"'MARKETID'" binding:"required"`            // 市场ID
	Goodsid                 int64     `json:"goodsid"  xorm:"'GOODSID'" binding:"required"`              // 商品ID
	Accountid               int64     `json:"accountid"  xorm:"'ACCOUNTID'" binding:"required"`          // 账户ID[报价币种]
	Memberuserid            int64     `json:"memberuserid"  xorm:"'MEMBERUSERID'" binding:"required"`    // 所属会员UserID
	Buyorsell               int64     `json:"buyorsell"  xorm:"'BUYORSELL'" binding:"required"`          // 买卖 - 0:买 1:卖
	Pricemode               int64     `json:"pricemode"  xorm:"'PRICEMODE'" binding:"required"`          // 取价方式 - 1:市价 2: 限价
	Orderprice              float64   `json:"orderprice"  xorm:"'ORDERPRICE'"`                           // 委托价格
	Marketmaxsub            float64   `json:"marketmaxsub"  xorm:"'MARKETMAXSUB'"`                       // 市价最大偏移范围
	Orderqty                int64     `json:"orderqty"  xorm:"'ORDERQTY'" binding:"required"`            // 委托数量
	Tradeqty                int64     `json:"tradeqty"  xorm:"'TRADEQTY'"`                               // 成交数量
	Cancelqty               int64     `json:"cancelqty"  xorm:"'CANCELQTY'"`                             // 撤单数量
	Openqty                 int64     `json:"openqty"  xorm:"'OPENQTY'"`                                 // 开仓数量(先建后平操作,需要记录)
	Closeqty                int64     `json:"closeqty"  xorm:"'CLOSEQTY'"`                               // 平仓数量(先建后平操作 需要记录)
	Opentradeqty            int64     `json:"opentradeqty"  xorm:"'OPENTRADEQTY'"`                       // 开仓成交数量(先建后平操作,需要记录)
	Closetradeqty           int64     `json:"closetradeqty"  xorm:"'CLOSETRADEQTY'"`                     // 平仓成交数量(先建后平操作,需要记录)
	Freezemargin            float64   `json:"freezemargin"  xorm:"'FREEZEMARGIN'"`                       // 冻结保证金(冻结交易金额)
	Unfreezemargin          float64   `json:"unfreezemargin"  xorm:"'UNFREEZEMARGIN'"`                   // 解冻保证金
	Freezecharge            float64   `json:"freezecharge"  xorm:"'FREEZECHARGE'"`                       // 冻结手续费
	Unfreezecharge          float64   `json:"unfreezecharge"  xorm:"'UNFREEZECHARGE'"`                   // 解冻手续费
	Openfreezecharge        float64   `json:"openfreezecharge"  xorm:"'OPENFREEZECHARGE'"`               // 开仓冻结手续费(先建后平操作,需要记录)
	Closefreezecharge       float64   `json:"closefreezecharge"  xorm:"'CLOSEFREEZECHARGE'"`             // 平仓冻结手续费(先建后平操作,需要记录)
	Openunfreezecharge      float64   `json:"openunfreezecharge"  xorm:"'OPENUNFREEZECHARGE'"`           // 开仓解冻手续费(先建后平操作,需要记录)
	Closeunfreezecharge     float64   `json:"closeunfreezecharge"  xorm:"'CLOSEUNFREEZECHARGE'"`         // 平仓解冻手续费(先建后平操作,需要记录)
	Validtype               int64     `json:"validtype"  xorm:"'VALIDTYPE'" binding:"required"`          // 有效类型 - 1当日有效 2本周有效 3指定日期有效 4一直有效 5指定时间有效
	Validtime               time.Time `json:"validtime"  xorm:"'VALIDTIME'"`                             // 有效期限
	Volumetype              int64     `json:"volumetype"  xorm:"'VOLUMETYPE'"`                           // 当时间有效类型为 “立即执行否则取消 IOC” 时，需要此项 - 0:任意量  1:最小量（暂时不支持） 2:全部量
	Operatetype             int64     `json:"operatetype"  xorm:"'OPERATETYPE'" binding:"required"`      // 操作类型 - 1:正常下单 2:斩仓 3:转单 4:结算撤单 5:系统卖出(适用于先平后建的卖出) 6:行情源报价 7:（结算)到期强平 8:（结算)协议转让 9:系统对冲单 10:（结算)到期无效 11:交割协议转让 12:交割协议平仓 13:交割成交(所有权) 14:管理端强行平仓 15:管理端协议转让
	Ordertime               time.Time `json:"ordertime"  xorm:"'ORDERTIME'" binding:"required"`          // 委托时间
	Ordersrc                int64     `json:"ordersrc"  xorm:"'ORDERSRC'"`                               // 委托来源 -  1:客户端 2:管理端 3:风控服务 4:交割服务 5:交易服务 6:交易日结 7:商品强平 8:管理端商品退市强平 9:交易接口 10:交割服务商被动(受托竞价) 11:预埋触发
	Orderstatus             int64     `json:"orderstatus"  xorm:"'ORDERSTATUS'"`                         // 委托状态 - 1： 委托请求 2：待冻结 3：委托成功 4： 委托失败 5：配对成功 6： 已撤销 7：部分成交 8：已成交 9：部成部撤 10：成交失败 11：已拒绝 12:经过摘牌(先摘后挂专用-先摘后挂已摘过) 13:冻结成功(通道交易专用) 14:通道已撤 15:通道部成部撤 16:成交失败违约(荷兰式竞拍专用)
	Operatorid              int64     `json:"operatorid"  xorm:"'OPERATORID'"`                           // 登录账号(LoginID)
	Updatetime              time.Time `json:"updatetime"  xorm:"'UPDATETIME'"`                           // 更新时间
	Clientordertime         time.Time `json:"clientordertime"  xorm:"'CLIENTORDERTIME'"`                 // 客户端委托时间
	Clientticket            string    `json:"clientticket"  xorm:"'CLIENTTICKET'"`                       // 客户端流水号
	UUID                    string    `json:"uuid"  xorm:"'UUID'"`                                       // 发起端唯一id
	Clienttype              int64     `json:"clienttype"  xorm:"'CLIENTTYPE'"`                           // 客户端类型 - 0:保留为未填终端类型 1:PC管理端 2:PC交易端 3:手机客户端_安卓 4:网页客户端 5:微信客户端 6:手机客户端_苹果 7:网上开户客户端 8:无效终端编号 9:报价终端(中江)
	Retcode                 int64     `json:"retcode"  xorm:"'RETCODE'"`                                 // 错误代码
	Tradeproperty           int64     `json:"tradeproperty"  xorm:"'TRADEPROPERTY'"`                     // 交易属性
	Listingselecttype       int64     `json:"listingselecttype"  xorm:"'LISTINGSELECTTYPE'"`             // 挂牌点选类型 - 1:挂牌 2:摘牌 3:先摘后挂
	Delistingtype           int64     `json:"delistingtype"  xorm:"'DELISTINGTYPE'"`                     // 摘牌类型 - 1:价格最优 2:点选成交
	Marginalgorithm         int64     `json:"marginalgorithm"  xorm:"'MARGINALGORITHM'"`                 // 保证金收取方式  1：比率  2：固定
	Marginvalue             float64   `json:"marginvalue"  xorm:"'MARGINVALUE'"`                         // 即市保证金设置值
	Openfeealgorithm        int64     `json:"openfeealgorithm"  xorm:"'OPENFEEALGORITHM'"`               // 建仓手续费收取方式  1：比率  2：固定
	Openmemberchargevalue   float64   `json:"openmemberchargevalue"  xorm:"'OPENMEMBERCHARGEVALUE'"`     // 建仓会员手续费设置值
	Openexchagechargevalue  float64   `json:"openexchagechargevalue"  xorm:"'OPENEXCHAGECHARGEVALUE'"`   // 建仓交易所手续费设置值
	Closefeealgorithm       int64     `json:"closefeealgorithm"  xorm:"'CLOSEFEEALGORITHM'"`             // 平仓手续费收取方式 1：比率  2：固定
	Closememberchargevalue  float64   `json:"closememberchargevalue"  xorm:"'CLOSEMEMBERCHARGEVALUE'"`   // 平仓会员手续费设置值
	Closeexchagechargevalue float64   `json:"closeexchagechargevalue"  xorm:"'CLOSEEXCHAGECHARGEVALUE'"` // 平仓交易所手续费设置值
	Optiontype              int64     `json:"optiontype"  xorm:"'OPTIONTYPE'"`                           // 期权类型 - 1:认购(看涨) 2:认沽(看跌)
	Premium                 float64   `json:"premium"  xorm:"'PREMIUM'"`                                 // 权利金
	Ispreexercise           int64     `json:"ispreexercise"  xorm:"'ISPREEXERCISE'"`                     // 是否预申报- 0:否 1:是
	Preexerciseprice        float64   `json:"preexerciseprice"  xorm:"'PREEXERCISEPRICE'"`               // 预申报价格
	Isconfirmexercise       int64     `json:"isconfirmexercise"  xorm:"'ISCONFIRMEXERCISE'"`             // 是否确认行权- 0:否 1:是
	Quoteid                 int64     `json:"quoteid"  xorm:"'QUOTEID'"`                                 // 报价单ID
	Gcaccountid             int64     `json:"gcaccountid"  xorm:"'GCACCOUNTID'"`                         // 账户ID[合约币种]
	Sessionid               int64     `json:"sessionid"  xorm:"'SESSIONID'"`                             // 会话ID
}

// QueryCPTradeOrderDetail 查询产能预售委托单信息
// @Summary 查询产能预售委托单信息
// @Produce json
// @Security ApiKeyAuth
// @Param goodsid query int false "预售商品ID"
// @Param marketid query int false "预售市场ID"
// @Param goodsids query string false "预售商品ID列表 - 格式：1,2,3"
// @Success 200 {object} QueryCPTradeOrderDetailRsq
// @Failure 500 {object} app.Response
// @Router /CPTrade/QueryCPTradeOrderDetail [get]
// @Tags 产能预售
func QueryCPTradeOrderDetail(c *gin.Context) {
	appG := app.Gin{C: c}

	// FIXME: 由于数据中包括[]int类型，会造成校验报错，故暂时不使用
	// 获取请求参数
	var req QueryCPTradeOrderDetailReq
	if err := appG.C.ShouldBindQuery(&req); err != nil {
		logger.GetLogger().Errorf("QueryCPTradeOrderDetail failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
		return
	}

	// 查询数据
	engine := db.GetEngine()
	datas := make([]QueryCPTradeOrderDetailRsq, 0)
	sql := `select
				to_char(t.orderid) strOrderID, 
				t.*
			from Trade_OrderDetail t
			where t.BuyOrSell = 1 and t.BuildType = 2 and t.MarketID in (40201,41201)`
	if req.GoodsID > 0 {
		sql += fmt.Sprintf(" and t.GoodsID = %d", req.GoodsID)
	}
	if req.MarketID > 0 {
		sql += fmt.Sprintf(" and t.MarketID = %d", req.MarketID)
	}
	if len(req.GoodsIDs) > 0 {
		// s = s.And("GoodsID in (?)", req.GoodsIDs)
		sql += fmt.Sprintf(" and t.GoodsID in (%s)", req.GoodsIDs)
	}
	if err := engine.SQL(sql).Find(&datas); err != nil {
		// 查询失败
		logger.GetLogger().Errorf("QueryCPTradeOrderDetail failed: %s", err.Error())
		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
		return
	}

	// 查询成功
	logger.GetLogger().Debugln("QueryCPTradeOrderDetail successed: %v", datas)
	appG.Response(http.StatusOK, e.SUCCESS, datas)
}
