/**
* @Author: zou.yingbin
* @Create  : 2021/4/14 11:11
* @Modify  : 2021/4/14 11:11
 */

package models

import (
	"encoding/json"
	"fmt"
	"mtp2_if/db"
	"mtp2_if/logger"
	"mtp2_if/mtpcache"
	"mtp2_if/utils"
	"strings"
)

// ErmcpDeliveryGoods 现货品种(交割品种)
type ErmcpDeliveryGoods struct {
	DELIVERYGOODSID   int32  `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"`     // 现货品种ID(SEQ_DELIVERYGOODS)
	DELIVERYGOODSCODE string `json:"deliverygoodscode"  xorm:"'DELIVERYGOODSCODE'"` // 现货品种代码
	DELIVERYGOODSNAME string `json:"deliverygoodsname"  xorm:"'DELIVERYGOODSNAME'"` // 现货品种名称
	GOODSUNITID       int32  `json:"goodsunitid"  xorm:"'GOODSUNITID'"`             // 现货品种单位ID
	DELIVERYGOODSTYPE int32  `json:"deliverygoodstype"  xorm:"'DELIVERYGOODSTYPE'"` // 现货品种类型: 1-整装不拆分 2-散装记录明细 3:整装拆分 4:散装不记录明细
	STANDARDQTY       int32  `json:"standardqty"  xorm:"'STANDARDQTY'"`             // 标准数量(库位数量) [标准品特有]
	STANDARDQTYRANGE  int32  `json:"standardqtyrange"  xorm:"'STANDARDQTYRANGE'"`   // 标准数量偏差范围 [标准品特有]
	AUDITFLAG         int32  `json:"auditflag"  xorm:"'AUDITFLAG'"`                 // 交割是否需要审核 - 0:不需要 1:需要审核   默认为0
	ISVALID           int32  `json:"isvalid"  xorm:"'ISVALID'"`                     // 是否有效 - 0:无效 1:有效
	AGREEUNIT         int32  `json:"agreeunit"  xorm:"'AGREEUNIT'"`                 // 合约单位[散货时默认为1， 整装时默认为标准数量]
	QTYDECIMALPLACE   int32  `json:"qtydecimalplace"  xorm:"'QTYDECIMALPLACE'"`     // 成交量小数位
	CATEGORYID        int32  `json:"categoryid"  xorm:"'CATEGORYID'"`               // 类别ID(SEQ_WRCATEGORY)
	DGSTATUS          int32  `json:"dgstatus"  xorm:"'DGSTATUS'"`                   // 品种状态 - 作废 - 0:未激活 1:正常
	AREAUSERID        int64  `json:"areauserid"  xorm:"'AREAUSERID'"`               // 所属机构
	REMARK            string `json:"remark"  xorm:"'REMARK'"`                       // 备注

	EnumdicName string `json:"enumdicname"` // 现货品种单位名称
	ExcludeCfg  int32  `json:"-"`           // 排除已配置的业务类型商品 1-套保 2-套利
}

func (r *ErmcpDeliveryGoods) calc() {
	r.EnumdicName = mtpcache.GetEnumDicitemName(r.GOODSUNITID)
}

func (r *ErmcpDeliveryGoods) buildSql() string {
	var sqlId utils.SQLVal = "SELECT t.DELIVERYGOODSID," +
		"       t.DELIVERYGOODSCODE," +
		"       t.DELIVERYGOODSNAME," +
		"       t.GOODSUNITID," +
		"       t.DELIVERYGOODSTYPE," +
		"       t.STANDARDQTY," +
		"       t.STANDARDQTYRANGE," +
		"       t.AUDITFLAG," +
		"       t.ISVALID," +
		"       t.ISSPLIT," +
		"       t.AGREEUNIT," +
		"       t.QTYDECIMALPLACE," +
		"       t.CATEGORYID," +
		"       t.DGSTATUS," +
		"       t.REMARK," +
		"       t.AREAUSERID" +
		"  FROM DELIVERYGOODS t" +
		" WHERE 1 = 1"
	sqlId.AndEx("t.AREAUSERID", r.AREAUSERID, r.AREAUSERID > 0)
	sqlId.AndEx("t.DELIVERYGOODSID", r.DELIVERYGOODSID, r.DELIVERYGOODSID > 0)
	if r.ExcludeCfg > 0 {
		sqlId.Join(fmt.Sprintf(" and t.deliverygoodsid not in(select distinct deliverygoodsid from ermcp_bizgroupspotgoods where biztype = %v)", r.ExcludeCfg))
	}
	return sqlId.String()
}

// GetDataEx 获取现货商品(交割商品)
func (r *ErmcpDeliveryGoods) GetDataEx() (interface{}, error) {
	return r.GetData()
}

// GetData
func (r *ErmcpDeliveryGoods) GetData() ([]ErmcpDeliveryGoods, error) {
	sData := make([]ErmcpDeliveryGoods, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	for i := range sData {
		sData[i].calc()
	}
	return sData, err
}

// ErmcpDGFactoryItem 品种选择项定义表
type ErmcpDGFactoryItem struct {
	DGFACTORYITEMID     int64  `json:"dgfactoryitemid"  xorm:"'DGFACTORYITEMID'"`         // 选择项ID(SEQ_DGFACTORYITEM)
	DELIVERYGOODSID     int32  `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"`         // 现货品种ID
	DGFACTORYITEMTYPEID int64  `json:"dgfactoryitemtypeid"  xorm:"'DGFACTORYITEMTYPEID'"` // 要素项类型
	DGFACTORYITEMVALUE  string `json:"dgfactoryitemvalue"  xorm:"'DGFACTORYITEMVALUE'"`   // 要素项值(类型为仓库时填写仓库名称)
	WAREHOUSEID         int64  `json:"warehouseid"  xorm:"'WAREHOUSEID'"`                 // 仓库ID(类型为仓库时填写)
	ISVALID             int32  `json:"isvalid"  xorm:"'ISVALID'"`                         // 是否有效 - 0:无效 1:有效
	ORDERINDEX          int32  `json:"orderindex"  xorm:"'ORDERINDEX'"`                   // 顺序
	AREAUSERID          int64  `json:"areauserid"  xorm:"'AREAUSERID'"`                   // 用户id
}

func (r *ErmcpDGFactoryItem) buildSql() string {
	var sqlId utils.SQLVal = "SELECT DGFACTORYITEMID," +
		"       t.DELIVERYGOODSID," +
		"       to_char(t.DGFACTORYITEMTYPEID) DGFACTORYITEMTYPEID," +
		"       t.DGFACTORYITEMVALUE," +
		"       to_char(t.WAREHOUSEID) WAREHOUSEID," +
		"       t.ISVALID," +
		"       t.ORDERINDEX," +
		"       g.areauserid" +
		"  FROM DGFACTORYITEM t" +
		"  left join deliverygoods g" +
		"    on t.deliverygoodsid = g.deliverygoodsid" +
		" WHERE t.ISVALID = 1"
	sqlId.AndEx("g.areauserid", r.AREAUSERID, r.AREAUSERID > 0)
	sqlId.AndEx("t.DGFACTORYITEMID", r.DGFACTORYITEMID, r.DGFACTORYITEMID > 0)
	sqlId.AndEx("t.DELIVERYGOODSID", r.DELIVERYGOODSID, r.DELIVERYGOODSID > 0)
	sqlId.AndEx("t.DGFACTORYITEMTYPEID", r.DGFACTORYITEMTYPEID, r.DGFACTORYITEMTYPEID > 0)
	sqlId.AndEx("t.ORDERINDEX", r.ORDERINDEX, r.ORDERINDEX > 0)

	return sqlId.String()
}

// GetDataEx 获取品种选择项定义
func (r *ErmcpDGFactoryItem) GetDataEx() (interface{}, error) {
	return r.GetData()
}

// GetData
func (r *ErmcpDGFactoryItem) GetData() (interface{}, error) {
	sData := make([]ErmcpDGFactoryItem, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	return sData, err
}

// Ermcp3Brand 品牌(从品种选择项定义表中查)
type Ermcp3Brand struct {
	BRANDID         int64  `json:"brandid"`         // 品牌id
	BRANDNAME       string `json:"brandname"`       // 品牌名称
	DELIVERYGOODSID int32  `json:"deliverygoodsid"` // 品种ID
	AREAUSERID      int64  `json:"areauserid"`      // 用户id
}

// GetDataEx
func (r *Ermcp3Brand) GetDataEx() (interface{}, error) {
	return r.GetData()
}

// GetData 获取品牌数据
func (r *Ermcp3Brand) GetData() ([]Ermcp3Brand, error) {
	m := ErmcpDGFactoryItem{
		DELIVERYGOODSID:     r.DELIVERYGOODSID,
		DGFACTORYITEMTYPEID: 2,
		ORDERINDEX:          1,
	}
	sData := make([]Ermcp3Brand, 0)
	if d, err := m.GetDataEx(); err == nil {
		if dgLst, ok := d.([]ErmcpDGFactoryItem); ok {
			for _, val := range dgLst {
				sData = append(sData, Ermcp3Brand{BRANDID: val.DGFACTORYITEMID, AREAUSERID: val.AREAUSERID,
					BRANDNAME: val.DGFACTORYITEMVALUE, DELIVERYGOODSID: val.DELIVERYGOODSID})
			}
		}
	}
	return sData, nil
}

// ErmcpRelatedGoods 现货品种的关联交易商品
type ErmcpRelatedGoods struct {
	GoodsId         int    `json:"goodsid"  xorm:"'GoodsId'"`                 // 商品id
	GoodsCode       string `json:"goodscode"  xorm:"'GoodsCode'"`             // 商品代码
	GoodsName       string `json:"goodsname"  xorm:"'GoodsName'"`             // 商品名称
	DELIVERYGOODSID int32  `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"` // 品种ID

	AREAUSERID int64 `json:"-"` // 所属机构
}

func (r *ErmcpRelatedGoods) buildSql() string {
	var sqlId utils.SQLVal = "select distinct t.deliverygoodsid, g.goodsid, g.goodscode, g.goodsname" +
		"  from deliverygoods t" +
		" inner join ERMS2_WRSConvertDetail w" +
		"    on t.deliverygoodsid = w.deliverygoodsid" +
		" inner join erms_middlegoods m" +
		"    on w.middlegoodsid = m.middlegoodsid" +
		" inner join ERMCP_GGConvertConfig gc" +
		"    on m.goodsgroupid = gc.destgoodsgroupid" +
		" inner join goods g" +
		"    on gc.srcgoodsgroupid = g.goodsgroupid" +
		" where 1 = 1"
	sqlId.AndEx("t.AREAUSERID", r.AREAUSERID, r.AREAUSERID > 0)
	sqlId.AndEx("t.DELIVERYGOODSID", r.DELIVERYGOODSID, r.DELIVERYGOODSID > 0)
	return sqlId.String()
}

// GetDataEx 获取现货关联交易商品
func (r *ErmcpRelatedGoods) GetDataEx() (interface{}, error) {
	return r.GetData()
}

// GetData 获取现货关联交易商品
func (r *ErmcpRelatedGoods) GetData() ([]ErmcpRelatedGoods, error) {
	sData := make([]ErmcpRelatedGoods, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	return sData, err
}

// ErmcpDeliveryGoodsDetail2 现货商品详情(含转换系数)
type ErmcpDeliveryGoodsDetail2 struct {
	ErmcpDeliveryGoodsDetail
	CONVERTRATIO float64 `json:"convertratio"  xorm:"'CONVERTRATIO'"` // 套保系数(折算系数)
}

// ErmcpDeliveryGoodsDetail 现货商品详情
type ErmcpDeliveryGoodsDetail struct {
	Data   ErmcpDeliveryGoods `json:"data"`   // 现货商品基本信息(交割品种)
	GmList []Ermcp3Wrstandard `json:"gmlist"` // 品类列表(仓单标准)
	GbList []Ermcp3Brand      `json:"gblist"` // 品牌列表
}

func (r *ErmcpDeliveryGoodsDetail) addGmList(lst []Ermcp3Wrstandard) {
	for i := range lst {
		if lst[i].DELIVERYGOODSID == r.Data.DELIVERYGOODSID {
			r.GmList = append(r.GmList, lst[i])
		}
	}
}

func (r *ErmcpDeliveryGoodsDetail) addGbList(lst []Ermcp3Brand) {
	for i := range lst {
		if lst[i].DELIVERYGOODSID == r.Data.DELIVERYGOODSID {
			r.GbList = append(r.GbList, lst[i])
		}
	}
}

// GetData
func (r *ErmcpDeliveryGoodsDetail) GetData() ([]ErmcpDeliveryGoodsDetail, error) {
	sData := make([]ErmcpDeliveryGoodsDetail, 0)
	m := ErmcpDeliveryGoods{AREAUSERID: r.Data.AREAUSERID, DELIVERYGOODSID: r.Data.DELIVERYGOODSID}
	data, err := m.GetData()
	if err != nil {
		return sData, err
	}
	if data == nil || len(data) == 0 {
		return sData, nil
	}
	// 基本信息
	for i := range data {
		val := ErmcpDeliveryGoodsDetail{Data: data[i],
			GmList: make([]Ermcp3Wrstandard, 0), GbList: make([]Ermcp3Brand, 0),
		}
		sData = append(sData, val)
	}
	//品类/品牌/套保信息
	gm := Ermcp3Wrstandard{AREAUSERID: r.Data.AREAUSERID, DELIVERYGOODSID: r.Data.DELIVERYGOODSID, ISVALID: 1}
	gb := Ermcp3Brand{DELIVERYGOODSID: r.Data.DELIVERYGOODSID}
	gmLst, _ := gm.GetDataEx()
	gbLst, _ := gb.GetData()

	for i := range sData {
		sData[i].addGmList(gmLst.([]Ermcp3Wrstandard))
		sData[i].addGbList(gbLst)
	}

	return sData, nil
}

// GetDataEx
func (r *ErmcpDeliveryGoodsDetail) GetDataEx() (interface{}, error) {
	return r.GetData()
}

// ErmcpDeliveryGoodsDetailEx 现货商品详情(含套保列表)
type ErmcpDeliveryGoodsDetailEx struct {
	ErmcpDeliveryGoodsDetail
	MgList []Ermcp3MiddleGoodsDetail2 `json:"mgList"` // 套保列表
}

// GetData 获取现货商品详情(含套保信息列表)
func (r *ErmcpDeliveryGoodsDetailEx) GetDataEx() (interface{}, error) {
	sData := make([]ErmcpDeliveryGoodsDetailEx, 0)
	mDg := r.ErmcpDeliveryGoodsDetail
	// 查现货商品列表
	if dgList, err := mDg.GetData(); err == nil {
		for i := range dgList {
			sData = append(sData, ErmcpDeliveryGoodsDetailEx{ErmcpDeliveryGoodsDetail: dgList[i],
				MgList: make([]Ermcp3MiddleGoodsDetail2, 0)})
		}
	}
	if len(sData) == 0 {
		return sData, nil
	}
	// 查转换关系
	mWc := WRSConverTDetail{}
	if wc, err := mWc.GetData(); err == nil {
		// 查套保商品列表
		mMg := Ermcp3MiddleGoodsDetail{}
		mMg.Mg.AREAUSERID = r.Data.AREAUSERID
		if mgLst, err := mMg.GetData(); err == nil {
			for i := range sData {
				sData[i].addMgList(mgLst, wc)
			}
		}
	}

	return sData, nil
}

// addMgList 添加关联的套保信息列表
func (r *ErmcpDeliveryGoodsDetailEx) addMgList(lst []Ermcp3MiddleGoodsDetail, wc []WRSConverTDetail) {
	for i := range wc {
		if r.Data.DELIVERYGOODSID == wc[i].DELIVERYGOODSID {
			for k := range lst {
				if int64(lst[k].Mg.MIDDLEGOODSID) == wc[i].MIDDLEGOODSID {
					val := Ermcp3MiddleGoodsDetail2{Ermcp3MiddleGoodsDetail: lst[k], CONVERTRATIO: wc[i].CONVERTRATIO}
					r.MgList = append(r.MgList, val)
				}
			}
		}
	}
}

// Ermcp3MiddleGoodsDetail2 套保品种详情(含转换系数)
type Ermcp3MiddleGoodsDetail2 struct {
	Ermcp3MiddleGoodsDetail
	CONVERTRATIO float64 `json:"convertratio"  xorm:"'CONVERTRATIO'"` // 套保系数(折算系数)
}

// Ermcp3MiddleGoodsDetail 套保品种详情
type Ermcp3MiddleGoodsDetail struct {
	Mg     ErmcpMiddleGoodsModel `json:"mg"`     // 套保商品信息
	GPList []Ermcp3GoodsGroupEx  `json:"gplist"` // 关联商品组列表
}

// GetData 获取套保品种详情(不含现货列表)
func (r *Ermcp3MiddleGoodsDetail) GetData() ([]Ermcp3MiddleGoodsDetail, error) {
	sData := make([]Ermcp3MiddleGoodsDetail, 0)
	// 查基本信息
	mMg := ErmcpMiddleGoodsModel{AREAUSERID: r.Mg.AREAUSERID, MIDDLEGOODSID: r.Mg.MIDDLEGOODSID, ISVALID: 1}
	if mgLst, err := mMg.GetData2(); err == nil {
		for i := range mgLst {
			sData = append(sData, Ermcp3MiddleGoodsDetail{Mg: mgLst[i], GPList: make([]Ermcp3GoodsGroupEx, 0)})
		}
	}
	if len(sData) == 0 {
		return sData, nil
	}
	bExist := false
	// 查关联期货商品组
	mGp := Ermcp3MiddleGoodsRelateGroup{AREAUSERID: r.Mg.AREAUSERID}
	if gpLst, err := mGp.GetData(); err == nil {
		for i := range sData {
			sData[i].addGoodsGroup(gpLst)
		}
		bExist = len(gpLst) > 0
	}

	if bExist {
		mGoods := Ermcp3GoodsEx{AREAUSERID: r.Mg.AREAUSERID}
		if gLst, err := mGoods.GetData(); err == nil {
			for i := range sData {
				sData[i].addGoods(gLst)
			}
		}
	}

	return sData, nil
}

func (r *Ermcp3MiddleGoodsDetail) addGoodsGroup(gpLst []Ermcp3MiddleGoodsRelateGroup) {
	for i := range gpLst {
		if gpLst[i].MIDDLEGOODSID == r.Mg.MIDDLEGOODSID {
			bExist := false
			for _, v := range r.GPList {
				if v.GOODSGROUPID == gpLst[i].GOODSGROUPID {
					bExist = true
					break
				}
			}
			if !bExist {
				val := Ermcp3GoodsGroupEx{
					GOODSGROUPID:   gpLst[i].GOODSGROUPID,
					MIDDLEGOODSID:  gpLst[i].MIDDLEGOODSID,
					CONVERTRATIO:   gpLst[i].CONVERTRATIO,
					EXEXCHANGECODE: gpLst[i].EXEXCHANGECODE,
					GOODSGROUPNAME: gpLst[i].GOODSGROUPNAME,
					ENUMDICNAME:    gpLst[i].ENUMDICNAME,
					GOODSUNITID:    gpLst[i].GOODSUNITID,
					GList:          make([]Ermcp3Goods, 0),
				}
				r.GPList = append(r.GPList, val)
			}
		}
	}
}

func (r *Ermcp3MiddleGoodsDetail) addGoods(gpLst []Ermcp3GoodsEx) {
	for i := range gpLst {
		if gpLst[i].MIDDLEGOODSID == r.Mg.MIDDLEGOODSID {
			for k := range r.GPList {
				if r.GPList[k].GOODSGROUPID == gpLst[i].GOODSGROUPID {
					r.GPList[k].GList = append(r.GPList[k].GList, Ermcp3Goods{
						GOODSID:        gpLst[i].GOODSID,
						GOODSNAME:      gpLst[i].GOODSNAME,
						GOODSCODE:      gpLst[i].GOODSCODE,
						AGREEUNIT:      gpLst[i].AGREEUNIT,
						EXEXCHANGECODE: gpLst[i].EXEXCHANGECODE,
						ENUMDICNAME:    gpLst[i].ENUMDICNAME,
					})
				}
			}
		}
	}
}

// Ermcp3MiddleGoodsDetailEx 套保品种详情(含现货列表)
type Ermcp3MiddleGoodsDetailEx struct {
	Ermcp3MiddleGoodsDetail
	DgList []ErmcpDeliveryGoodsDetail2 `json:"dglist"` // 关联的现货品种列表
}

func (r *Ermcp3MiddleGoodsDetailEx) addDgList(dglst []ErmcpDeliveryGoodsDetail, wc []WRSConverTDetail) {
	for i := range wc {
		if wc[i].MIDDLEGOODSID == int64(r.Mg.MIDDLEGOODSID) {
			for _, detail := range dglst {
				if wc[i].DELIVERYGOODSID == detail.Data.DELIVERYGOODSID && detail.Data.ISVALID == 1 {
					val := ErmcpDeliveryGoodsDetail2{ErmcpDeliveryGoodsDetail: detail, CONVERTRATIO: wc[i].CONVERTRATIO}
					r.DgList = append(r.DgList, val)
				}
			}
		}
	}
}

// GetDataEx
func (r *Ermcp3MiddleGoodsDetailEx) GetDataEx() (interface{}, error) {
	sData := make([]Ermcp3MiddleGoodsDetailEx, 0)
	// 查套保品种基本信息
	m := r.Ermcp3MiddleGoodsDetail
	if mgLst, err := m.GetData(); err == nil {
		for i := range mgLst {
			sData = append(sData, Ermcp3MiddleGoodsDetailEx{Ermcp3MiddleGoodsDetail: mgLst[i],
				DgList: make([]ErmcpDeliveryGoodsDetail2, 0)})
		}
	}
	// 查转换关系
	mWc := WRSConverTDetail{}
	if wc, err := mWc.GetData(); err == nil {
		// 查现货商品列表
		mDg := ErmcpDeliveryGoodsDetail{}
		mDg.Data.AREAUSERID = r.Mg.AREAUSERID
		if dgLst, err := mDg.GetData(); err == nil {
			for i := range sData {
				sData[i].addDgList(dgLst, wc)
			}
		}
	}
	return sData, nil
}

// Ermcp3MiddleGoodsRelateGroup 套保商品关联的期货商品组
type Ermcp3MiddleGoodsRelateGroup struct {
	MIDDLEGOODSID  uint32  `json:"middlegoodsid"  xorm:"'middlegoodsid'"`   // 套保商品id
	GOODSGROUPID   int32   `json:"goodsgroupid"  xorm:"'goodsgroupid'"`     // 商品组id
	CONVERTRATIO   float64 `json:"convertratio"  xorm:"'convertratio'"`     // 折算系数(品种系数)
	EXEXCHANGECODE string  `json:"exexchangecode"  xorm:"'exexchangecode'"` // 交易所代码
	GOODSGROUPNAME string  `json:"goodsgroupname"  xorm:"'goodsgroupname'"` // 商品组名称
	GOODSUNITID    int32   `json:"goodsunitid"  xorm:"'GOODUNITID'"`        // 单位id
	ENUMDICNAME    string  `json:"enumdicname"`                             // 单位名称
	AREAUSERID     int64   `json:"-"`                                       // 所属机构id
}

func (r *Ermcp3MiddleGoodsRelateGroup) calc() {
	r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.GOODSUNITID)
}

func (r *Ermcp3MiddleGoodsRelateGroup) buildSql() string {
	var sqlId utils.SQLVal = "select mg.areauserid," +
		"       mg.middlegoodsid," +
		"       gc.convertratio," +
		"       ex.exexchangecode," +
		"       gp.goodsgroupname," +
		"       gp.goodunitid," +
		"       gp.goodsgroupid" +
		"  from erms_middlegoods mg" +
		" inner join ERMCP_GGConvertConfig gc" +
		"    on mg.goodsgroupid = gc.destgoodsgroupid" +
		" inner join goodsgroup gp" +
		"    on gc.srcgoodsgroupid = gp.goodsgroupid" +
		"  left join externalexchange ex" +
		"    on gp.exexchangeid = ex.autoid" +
		" where mg.isvalid = 1" +
		"   and gp.goodsgroupstatus = 1"
	sqlId.AndEx("mg.AREAUSERID", r.AREAUSERID, r.AREAUSERID > 0)
	return sqlId.String()
}

// GetData 套保品关联的期货商品组信息
func (r *Ermcp3MiddleGoodsRelateGroup) GetData() ([]Ermcp3MiddleGoodsRelateGroup, error) {
	sData := make([]Ermcp3MiddleGoodsRelateGroup, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	for i := range sData {
		sData[i].calc()
	}
	return sData, err
}

// GetDataEx 套保品关联的期货商品组信息
func (r *Ermcp3MiddleGoodsRelateGroup) GetDataEx() (interface{}, error) {
	return r.GetData()
}

// Ermcp3GoodsGroupEx 商品组(含商品列表)
type Ermcp3GoodsGroupEx struct {
	MIDDLEGOODSID  uint32        `json:"middlegoodsid"  xorm:"'middlegoodsid'"`   // 套保商品id
	GOODSGROUPID   int32         `json:"goodsgroupid"  xorm:"'goodsgroupid'"`     // 商品组id
	CONVERTRATIO   float64       `json:"convertratio"  xorm:"'convertratio'"`     // 折算系数(品种系数)
	EXEXCHANGECODE string        `json:"exexchangecode"  xorm:"'exexchangecode'"` // 交易所代码
	GOODSGROUPNAME string        `json:"goodsgroupname"  xorm:"'goodsgroupname'"` // 商品组名称
	GOODSUNITID    int32         `json:"goodsunitid"  xorm:"'GOODSUNITID'"`       // 单位id
	ENUMDICNAME    string        `json:"enumdicname"`                             // 单位名称
	GList          []Ermcp3Goods `json:"glist"`                                   // 合约列表
}

// Ermcp3Goods 商品信息
type Ermcp3Goods struct {
	GOODSID        int32   `json:"goodsid"  xorm:"'goodsid'"`               // 期货商品id
	GOODSCODE      string  `json:"goodscode"  xorm:"'goodscode'"`           // 期货商品代码
	GOODSNAME      string  `json:"goodsname"  xorm:"'goodsname'"`           // 期货商品名称
	AGREEUNIT      float32 `json:"agreeunit"  xorm:"'agreeunit'"`           // 合约单位(合约乘数)
	EXEXCHANGECODE string  `json:"exexchangecode"  xorm:"'exexchangecode'"` // 交易所代码
	ENUMDICNAME    string  `json:"enumdicname"`                             // 单位名称
}

// Ermcp3GoodsEx 套保品关联的期货商品(少量字段)
type Ermcp3GoodsEx struct {
	MIDDLEGOODSID  uint32  `json:"middlegoodsid"  xorm:"'middlegoodsid'"`   // 套保商品id
	GOODSID        int32   `json:"goodsid"  xorm:"'goodsid'"`               // 期货商品id
	GOODSCODE      string  `json:"goodscode"  xorm:"'goodscode'"`           // 期货商品代码
	GOODSNAME      string  `json:"goodsname"  xorm:"'goodsname'"`           // 期货商品名称
	GOODUNITID     int32   `json:"goodunitid"  xorm:"'goodunitid'"`         // 期货商品单位id
	CONVERTRATIO   float64 `json:"convertratio"  xorm:"'convertratio'"`     // 折算系数(品种系数)
	GOODSGROUPID   int32   `json:"goodsgroupid"  xorm:"'goodsgroupid'"`     // 商品组id
	EXEXCHANGECODE string  `json:"exexchangecode"  xorm:"'exexchangecode'"` // 交易所代码
	GOODSGROUPNAME string  `json:"goodsgroupname"  xorm:"'goodsgroupname'"` // 商品组名称
	GPUNITID       int32   `json:"gpunitid"  xorm:"'gpunitid'"`             // 商品组单位id
	AGREEUNIT      float32 `json:"agreeunit"  xorm:"'agreeunit'"`           // 合约单位(合约乘数)

	ENUMDICNAME   string `json:"enumdicname"` // 单位名称
	GPENUMDICNAME string `json:"enumdicname"` // 商品组单位名称
	AREAUSERID    int64  `json:"-"`           // 所属机构id
}

func (r *Ermcp3GoodsEx) calc() {
	r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.GOODUNITID)
	r.GPENUMDICNAME = mtpcache.GetEnumDicitemName(r.GPUNITID)
}

func (r *Ermcp3GoodsEx) buildSql() string {
	var sqlId utils.SQLVal = "select mg.areauserid," +
		"       mg.middlegoodsid," +
		"       g.goodsid," +
		"       g.goodscode," +
		"       g.goodsname," +
		"       g.goodunitid," +
		"       g.goodsgroupid," +
		"       g.agreeunit," +
		"       gc.convertratio," +
		"       ex.exexchangecode," +
		"       gp.goodsgroupname," +
		"       gp.goodunitid gpunitid" +
		"  from erms_middlegoods mg" +
		" inner join ERMCP_GGConvertConfig gc" +
		"    on mg.goodsgroupid = gc.destgoodsgroupid" +
		" inner join goodsgroup gp" +
		"    on gc.srcgoodsgroupid = gp.goodsgroupid" +
		" inner join goods g" +
		"    on gp.goodsgroupid = g.goodsgroupid" +
		"  left join externalexchange ex" +
		"    on gp.exexchangeid = ex.autoid" +
		" where g.goodsstatus not in(4,5,6) and mg.isvalid=1 and gp.goodsgroupstatus=1"
	sqlId.AndEx("mg.areauserid", r.AREAUSERID, r.AREAUSERID > 0)
	sqlId.Join(" order by mg.middlegoodsid")
	return sqlId.String()
}

// GetData
func (r *Ermcp3GoodsEx) GetData() ([]Ermcp3GoodsEx, error) {
	sData := make([]Ermcp3GoodsEx, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	for i := range sData {
		sData[i].calc()
	}
	return sData, err
}

// GetDataEx
func (r *Ermcp3GoodsEx) GetDataEx() (interface{}, error) {
	return r.GetData()
}

// Ermcp3Contract 现货合同
type Ermcp3Contract struct {
	SPOTCONTRACTID    string  `json:"spotcontractid"  xorm:"'SPOTCONTRACTID'"`       // 现货合同ID(602+Unix秒时间戳(10位)+xxxxxx)
	CONTRACTNO        string  `json:"contractno"  xorm:"'CONTRACTNO'"`               // 现货合同编号
	CONTRACTTYPE      int32   `json:"contracttype"  xorm:"'CONTRACTTYPE'"`           // 现货合同类型 - 1:采购 -1:销售
	USERID            int64   `json:"userid"  xorm:"'USERID'"`                       // 所属机构ID
	BUYUSERID         int64   `json:"buyuserid"  xorm:"'BUYUSERID'"`                 // 采购方ID
	BUYUSERName       string  `json:"buyusername"  xorm:"'BUYUSERName'"`             // 采购方名称
	SELLUSERID        int64   `json:"selluserid"  xorm:"'SELLUSERID'"`               // 销售方ID
	SELLUSERNAME      string  `json:"sellusername"  xorm:"'SELLUSERNAME'"`           // 销售方名称
	DELIVERYGOODSID   int32   `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"`     // 现货品种ID
	WRSTANDARDID      int32   `json:"wrstandardid"  xorm:"'wrstandardid'"`           // 品类ID
	WRSTANDARDNAME    string  `json:"wrstandardname"  xorm:"'WRSTANDARDNAME'"`       // 品类名称
	WRSTANDARDCODE    string  `json:"wrstandardcode"  xorm:"'WRSTANDARDCODE'"`       // 品类代码
	DELIVERYGOODSCODE string  `json:"deliverygoodscode"  xorm:"'DELIVERYGOODSCODE'"` // 现货品种代码
	DELIVERYGOODSNAME string  `json:"deliverygoodsname"  xorm:"'DELIVERYGOODSNAME'"` // 现货品种名称
	PRODUCTTYPE       int32   `json:"producttype"  xorm:"'PRODUCTTYPE'"`             // 产品类型 - 1:标准仓单 2:等标 3:非标
	CONVERTFACTOR     float64 `json:"convertfactor"  xorm:"'CONVERTFACTOR'"`         // 标仓系数(品类)
	SPOTGOODSDESC     string  `json:"spotgoodsdesc"  xorm:"'SPOTGOODSDESC'"`         // 商品型号
	PRICETYPE         int32   `json:"pricetype"  xorm:"'PRICETYPE'"`                 // 定价类型 - 1:一口价 2:点价 3:暂定价
	QTY               float64 `json:"qty"  xorm:"'QTY'"`                             // 数量
	PRICE             float64 `json:"price"  xorm:"'PRICE'"`                         // 价格\暂定价 [1:一口价、3:暂定价]
	AMOUNT            float64 `json:"amount"  xorm:"'AMOUNT'"`                       // 金额 [1:一口价、3:暂定价]
	DELIVERYSTARTDATE string  `json:"deliverystartdate"  xorm:"'DELIVERYSTARTDATE'"` // 交收期(开始)
	DELIVERYENDDATE   string  `json:"deliveryenddate"  xorm:"'DELIVERYENDDATE'"`     // 交收期(结束)
	GOODSID           int32   `json:"goodsid"  xorm:"'GOODSID'"`                     // 点价合约ID - 0:为现货，其它为期货商品合约ID [2:点价 3:暂定价]
	GOODSCODE         string  `json:"goodscode"  xorm:"'GOODSCODE'"`                 // 点价合约代码
	GOODSNAME         string  `json:"goodsname"  xorm:"'GOODSNAME'"`                 // 点价商品名称
	PRICEMOVE         float64 `json:"pricemove"  xorm:"'PRICEMOVE'"`                 // 升贴水 [2:点价 3:暂定价]
	STARTDATE         string  `json:"startdate"  xorm:"'STARTDATE'"`                 // 点价开始日期 [2:点价 3:暂定价]
	ENDDATE           string  `json:"enddate"  xorm:"'ENDDATE'"`                     // 点价结束日期 [2:点价 3:暂定价]
	MARGIN            float64 `json:"margin"  xorm:"'MARGIN'"`                       // 当前保证金
	CONTRACTMARGIN    float64 `json:"contractmargin"  xorm:"'CONTRACTMARGIN'"`       // 合同保证金
	EnumdicName       string  `json:"enumdicname"  xorm:"'ENUMDICNAME'"`             // 单位名称
	CONTRACCTSTATUS   int32   `json:"contracctstatus"  xorm:"'CONTRACTSTATUS'"`      // 合同状态 - 0:未提交 1:待审核 2:执行中 3:正常完结 4:审核拒绝 5:异常完结 6:已撤回
	Remark            string  `json:"remark"  xorm:"'Remark'"`                       // 备注
	AUDITREMARK       string  `json:"auditremark"  xorm:"'AUDITREMARK'"`             // 审核意见
	AUDITTIME         string  `json:"audittime"  xorm:"'AUDITTIME'"`                 // 审核时间
	CREATETIME        string  `json:"createtime"  xorm:"'CREATETIME'"`               // 创建时间
	UPDATETIME        string  `json:"updatetime"  xorm:"'UPDATETIME'"`               // 更新时间
	SPOTGOODSBRANDID  int32   `json:"spotgoodsbrandid"  xorm:"'SPOTGOODSBRANDID'"`   // 现货品牌ID(DGFactoryItem表的ID)
	BRANDNAME         string  `json:"brandname"  xorm:"'brandname'"`                 // 品牌名称
	ATTACHMENT        string  `json:"attachment"  xorm:"'ATTACHMENT'"`               // 附件
	UNITID            int32   `json:"unitid"  xorm:"'UNITID'"`                       // 单位id(取品类上的单位id)
	TRADEUSERID       int64   `json:"tradeuserid"  xorm:"'TRADEUSERID'"`             // 交易员id
	SALEUSERID        int64   `json:"saleuserid"  xorm:"'SALEUSERID'"`               // 业务员id
	MERUSERID         int64   `json:"meruserid"  xorm:"'MERUSERID'"`                 // 跟单员id
	ACCOUNTID         string  `json:"accountid"  xorm:"'ACCOUNTID'"`                 // 期货账户id
	BIZTYPE           int32   `json:"biztype"  xorm:"'BIZTYPE'"`                     // 业务类型 1-套保 2-套利
	CURRENCYID        int32   `json:"currencyid"  xorm:"'CURRENCYID'"`               // 币种id

	SELLNICKNAME       string `json:"sellnickname"`       // 采购方昵称
	BUYNICKNAME        string `json:"buynickname"`        // 销售方昵称
	TRADEUSERLOGINCODE string `json:"tradeuserlogincode"` // 交易员登录代码
	SALEUSERLOGINCODE  string `json:"saleuserlogincode"`  // 业务员登录代码
	MERUSERLOGINCODE   string `json:"meruserlogincode"`   // 跟单员登录代码
	CURRENCYNAME       string `json:"currencyname"`       // 币种名称
	TRADEUSERNAME      string `json:"tradeusername"`      // 交易员名称

	// 筛选条件
	QryType   int32 `json:"-"` // 查询类型 1-未提交 2-待审核 3-履约中 4-已完成
	UserType  int32 `json:"-"` // 用户类型  2-管理员 7-企业成员
	OwnUserId int64 `json:"-"` // 登录用户id
}

func (r *Ermcp3Contract) getQryTypeStatus() string {
	var status string
	switch r.QryType {
	case 1: // 未提交
		status = "0,4,6"
	case 2: // 待审核
		status = "1"
	case 3: // 履约中
		status = "2"
	case 4: // 已完成
		status = "3,5"
	}
	return status
}

func (r *Ermcp3Contract) calc() {
	r.BUYUSERName, r.BUYNICKNAME = mtpcache.GetUserNameAndNickName(r.BUYUSERID)
	r.SELLUSERNAME, r.SELLNICKNAME = mtpcache.GetUserNameAndNickName(r.SELLUSERID)
	r.EnumdicName = mtpcache.GetEnumDicitemName(r.UNITID)
	r.TRADEUSERLOGINCODE = mtpcache.GetLoginCodeByUserId(r.TRADEUSERID)
	r.SALEUSERLOGINCODE = mtpcache.GetLoginCodeByUserId(r.SALEUSERID)
	r.MERUSERLOGINCODE = mtpcache.GetLoginCodeByUserId(r.MERUSERID)
	r.TRADEUSERNAME = mtpcache.GetUserNameByUserId(r.TRADEUSERID)
	r.CURRENCYNAME = mtpcache.GetCurrencyName(r.CURRENCYID)
}

func (r *Ermcp3Contract) buildSql() string {
	var sqlId utils.SQLVal = "SELECT to_char(t.SPOTCONTRACTID) SPOTCONTRACTID," +
		"       t.CONTRACTNO," +
		"       t.CONTRACTTYPE," +
		"       t.USERID," +
		"       t.BUYUSERID," +
		"       t.SELLUSERID," +
		"       t.DELIVERYGOODSID," +
		"       t.wrstandardid," +
		"       t.PRODUCTTYPE," +
		"       w.CONVERTFACTOR," +
		"       t.SPOTGOODSDESC," +
		"       t.PRICETYPE," +
		"       t.QTY," +
		"       t.PRICE," +
		"       t.AMOUNT," +
		"       to_char(t.DELIVERYSTARTDATE, 'yyyy-mm-dd hh24:mi:ss') DELIVERYSTARTDATE," +
		"       to_char(t.DELIVERYENDDATE, 'yyyy-mm-dd hh24:mi:ss') DELIVERYENDDATE," +
		"       t.GOODSID," +
		"       t.PRICEMOVE," +
		"       to_char(t.STARTDATE, 'yyyy-mm-dd hh24:mi:ss') STARTDATE," +
		"       to_char(t.ENDDATE, 'yyyy-mm-dd hh24:mi:ss') ENDDATE," +
		"       t.MARGIN," +
		"       t.contractmargin," +
		"       t.remark," +
		"       t.auditremark," +
		"       to_char(t.contractattachment) attachment," +
		"       t.contractstatus," +
		"       t.SPOTGOODSBRANDID," +
		"       to_char(t.audittime, 'yyyy-mm-dd hh24:mi:ss') audittime," +
		"       to_char(t.createtime, 'yyyy-mm-dd hh24:mi:ss') createtime," +
		"       to_char(t.updatetime, 'yyyy-mm-dd hh24:mi:ss') updatetime," +
		"       g.deliverygoodscode," +
		"       g.deliverygoodsname," +
		"       g2.goodscode," +
		"       g2.goodsname," +
		"       gb.dgfactoryitemvalue brandname," +
		"       w.wrstandardname," +
		"       w.wrstandardcode," +
		"       w.unitid," +
		"       t.tradeuserid," +
		"       t.saleuserid," +
		"       t.meruserid," +
		"       t.currencyid," +
		"       to_char(t.accountid) accountid," +
		"       t.biztype" +
		"  FROM ERMCP_SPOTCONTRACT t" +
		"  left join deliverygoods g" +
		"    on t.deliverygoodsid = g.deliverygoodsid" +
		"  left join goods g2" +
		"    on t.goodsid = g2.goodsid" +
		"  left join DGFACTORYITEM gb" +
		"    on t.spotgoodsbrandid = gb.dgfactoryitemid" +
		"  left join wrstandard w" +
		"    on t.wrstandardid = w.wrstandardid" +
		"  left join loginaccount l on t.applyid=l.loginid" +
		" where 1 = 1"
	sqlId.AndEx("t.SPOTCONTRACTID", r.SPOTCONTRACTID, len(r.SPOTCONTRACTID) > 0)
	// 用户条件
	sqlId.Join(fmt.Sprintf(" and %v in(t.userid, t.saleuserid, t.tradeuserid, t.meruserid, l.userid)", r.OwnUserId))
	status := r.getQryTypeStatus()
	if len(status) > 0 {
		sqlId.Join(fmt.Sprintf(" and t.contractstatus in (%v)", status))
	}

	return sqlId.String()
}

// GetDataEx
func (r *Ermcp3Contract) GetDataEx() (interface{}, error) {
	sData := make([]Ermcp3Contract, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	for i := range sData {
		sData[i].calc()
	}
	return sData, err
}

// Ermcp3SellBuyContract 采购/销售合同
type Ermcp3SellBuyContract struct {
	UserID             int64   `json:"userid"  xorm:"'UserID'"`                         // 机构ID
	SpotContractId     string  `json:"spotcontractid"  xorm:"'SPOTCONTRACTID'"`         // 合同ID
	AccountName        string  `json:"accountname"  xorm:"'ACCOUNTNAME'"`               // 账户名称
	DeliveryGoodsId    int     `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"`       // 现货商品ID
	DeliveryGoodsCode  string  `json:"deliverygoodscode"  xorm:"'DELIVERYGOODSCODE'"`   // 现货品种代码
	DeliveryGoodsName  string  `json:"deliverygoodsname"  xorm:"'DELIVERYGOODSNAME'"`   // 现货品种名称
	SpotGoodsdesc      string  `json:"spotgoodsdesc"  xorm:"'SPOTGOODSDESC'"`           // 商品型号(商品规格)
	GoodsId            int     `json:"goodsid"  xorm:"'GOODSID'"`                       // 点价商品ID
	GOODSNAME          string  `json:"goodsname"  xorm:"'GOODSNAME'"`                   // 点价商品名称
	Goodscode          string  `json:"goodscode"  xorm:"'GOODSCODE'"`                   // 点价商品代码
	Pricemove          float64 `json:"pricemove"  xorm:"'PRICEMOVE'"`                   // 升贴水
	Qty                float64 `json:"qty"  xorm:"'QTY'"`                               // 合同量
	UnpricedQty        float64 `json:"unpricedqty"  xorm:"'UNPRICEDQTY'"`               // 未定价量
	PricedQty          float64 `json:"pricedqty"  xorm:"'PRICEDQTY'"`                   // 已定价量
	UnsureQty          float64 `json:"unsureqty"  xorm:"'UNSUREQTY'"`                   // 未确定量
	PayAmount          float64 `json:"payamount"  xorm:"'PAYAMOUNT'"`                   // 已收付额(收款或付款)
	UnpayAmount        float64 `json:"unpayamount"`                                     // 应收付款额(应支付或应收款)
	PrePayAmount       float64 `json:"prepayamount"`                                    // 预收付额
	InvoiceAmount      float64 `json:"invoiceamount"  xorm:"'INVOICEAMOUNT'"`           // 已开票额
	DaikaiAmount       float64 `json:"daikaiamount"  xorm:"'DAIKAIAMOUNT'"`             // 应收(开)票额
	PreInvoiceAmount   float64 `json:"preinvoiceamount"`                                // 预收(开)票额
	StartDate          string  `json:"startdate"  xorm:"'STARTDATE'"`                   // 点价开始日
	EndDate            string  `json:"enddate"  xorm:"'ENDDATE'"`                       // 点价结束日
	DeliveryStartDate  string  `json:"deliverystartdate"  xorm:"'DELIVERYSTARTDATE'"`   // 交割开始日
	DeliveryendDate    string  `json:"deliveryenddate"  xorm:"'DELIVERYENDDATE'"`       // 交割结束日
	Convertfactor      float64 `json:"convertfactor"  xorm:"'CONVERTFACTOR'"`           // 标仓系数(品类)
	EnumdicName        string  `json:"enumdicname"  xorm:"'ENUMDICNAME'"`               // 单位名称
	Contracctstatus    uint    `json:"contracctstatus"  xorm:"'CONTRACTSTATUS'"`        // 合同状态- 0:未提交 1:待审核 2:执行中 3:正常完结 4:审核拒绝 5:异常完结 6:已撤回
	PriceType          int     `json:"pricetype"  xorm:"'PRICETYPE'"`                   // 定价类型 - 1:一口价 2:点价 3:暂定价
	ProductType        int     `json:"producttype"  xorm:"'PRODUCTTYPE'"`               // 产品类型 - 1:标准仓单 2:等标 3:非标
	Contracttype       int32   `json:"contracttype"  xorm:"'CONTRACTTYPE'"`             // 合同类型 1-采购, -1-销售
	Pricedamount       float64 `json:"pricedamount"  xorm:"'PRICEDAMOUNT'"`             // 已定价额
	PricedAvg          float64 `json:"pricedavg"  xorm:"'PRICEDAVG'"`                   // 已点均价
	Margin             float64 `json:"margin"  xorm:"'MARGIN'"`                         // 保证金
	CONTRACTMARGIN     float64 `json:"contractmargin"  xorm:"'CONTRACTMARGIN'"`         // 合同保证金
	Remark             string  `json:"remark"  xorm:"'Remark'"`                         // 备注
	ATTACHMENT         string  `json:"attachment"  xorm:"'ATTACHMENT'"`                 // 附件
	ReckonRealQty      float64 `json:"reckonrealqty"  xorm:"'ReckonRealQty'"`           // 已确定量
	ReckonOtherAmount  float64 `json:"reckonotheramount"  xorm:"'ReckonOtherAmount'"`   // 其它费用
	ReckonAdjustAmount float64 `json:"reckonadjustamount"  xorm:"'ReckonAdjustAmount'"` // 调整金额
	Price              float64 `json:"price"  xorm:"'Price'"`                           // 价格
	LoanAmount         float64 `json:"loanamount"  xorm:"'LoanAmount'"`                 // 贷款总额=已定价额+调整金额
	Contractno         string  `json:"contractno"  xorm:"'Contractno'"`                 // 合同编号
	TotalAmount        float64 `json:"totalamount"  xorm:"'-'"`                         // 合计总额
	ReckonedAmount     float64 `json:"reckonedamount"  xorm:"'ReckonedAmount'"`         // 实际已收付额(已确定额,已收付总额-已退款总额)
	BUYUSERID          int64   `json:"-"  xorm:"'BUYUSERID'"`                           // 采购方ID
	SELLUSERID         int64   `json:"-"  xorm:"'SELLUSERID'"`                          // 销售方ID
	AUDITTIME          string  `json:"audittime"  xorm:"'AUDITTIME'"`                   // 审核时间
	CREATETIME         string  `json:"createtime"  xorm:"'CREATETIME'"`                 // 创建时间
	SPOTGOODSBRANDID   int32   `json:"spotgoodsbrandid"  xorm:"'SPOTGOODSBRANDID'"`     // 现货品牌ID(DGFactoryItem表的ID)
	BRANDNAME          string  `json:"brandname"  xorm:"'brandname'"`                   // 品牌名称
	WRSTANDARDID       int64   `json:"wrstandardid"  xorm:"'WRSTANDARDID'"`             // 品类ID
	WRSTANDARDNAME     string  `json:"wrstandardname"  xorm:"'WRSTANDARDNAME'"`         // 品类名称
	WRSTANDARDCODE     string  `json:"wrstandardcode"  xorm:"'WRSTANDARDCODE'"`         // 品类代码
	TRADEUSERID        int64   `json:"tradeuserid"  xorm:"'TRADEUSERID'"`               // 交易员id
	SALEUSERID         int64   `json:"saleuserid"  xorm:"'SALEUSERID'"`                 // 业务员id
	MERUSERID          int64   `json:"meruserid"  xorm:"'MERUSERID'"`                   // 跟单员id
	ACCOUNTID          string  `json:"accountid"  xorm:"'ACCOUNTID'"`                   // 期货账户id
	BIZTYPE            int32   `json:"biztype"  xorm:"'BIZTYPE'"`                       // 业务类型 1-套保 2-套利
	CURRENCYID         int32   `json:"currencyid"  xorm:"'CURRENCYID'"`                 // 币种id

	NICKNAME           string `json:"nickname"`           // 账户昵称
	TRADEUSERLOGINCODE string `json:"tradeuserlogincode"` // 交易员登录代码
	SALEUSERLOGINCODE  string `json:"saleuserlogincode"`  // 业务员登录代码
	MERUSERLOGINCODE   string `json:"meruserlogincode"`   // 跟单员登录代码
	CURRENCYNAME       string `json:"currencyname"`       // 币种名称
	TRADEUSERNAME      string `json:"tradeusername"`      // 交易员名称
	// 筛选条件
	QryType   int32 `json:"-"` // 查询类型 1-未提交 2-待审核 3-履约中 4-已完成
	UserType  int32 `json:"-"` // 用户类型  2-管理员 7-企业成员
	OwnUserId int64 `json:"-"` // 登录用户id
}

func (r *Ermcp3SellBuyContract) calc() {
	r.TotalAmount = r.LoanAmount + r.ReckonOtherAmount
	// #95629 公式变更 modify:2021-06-16 09:54:08
	// 应付款额=货款总额-已付款额+已退款额
	// 应收款额=货款总额-已收款额+已退款额
	r.UnpayAmount = r.LoanAmount - r.ReckonedAmount
	// 预付款额=已付款额-已退款额-货款总额
	// 预收款额=已收款额-已退款额-货款总额
	r.PrePayAmount = r.ReckonedAmount - r.LoanAmount
	// 预收票额=已收票额-货款总额
	// 预开票额=已开票额-货款总额
	r.PreInvoiceAmount = r.InvoiceAmount - r.LoanAmount

	// 应收票额=货款总额-已收票额
	// 应开票额=货款总额-已开票额
	r.DaikaiAmount = r.LoanAmount - r.InvoiceAmount

	if r.Contracttype == 1 {
		//采购合同, 取销售方名称
		r.AccountName, r.NICKNAME = mtpcache.GetUserNameAndNickName(r.SELLUSERID)
	} else {
		//销售合同, 取采购方名称
		r.AccountName, r.NICKNAME = mtpcache.GetUserNameAndNickName(r.BUYUSERID)
	}

	r.TRADEUSERLOGINCODE = mtpcache.GetLoginCodeByUserId(r.TRADEUSERID)
	r.SALEUSERLOGINCODE = mtpcache.GetLoginCodeByUserId(r.SALEUSERID)
	r.MERUSERLOGINCODE = mtpcache.GetLoginCodeByUserId(r.MERUSERID)
	r.TRADEUSERNAME = mtpcache.GetUserNameByUserId(r.TRADEUSERID)
	r.CURRENCYNAME = mtpcache.GetCurrencyName(r.CURRENCYID)
}

func (r *Ermcp3SellBuyContract) buildSql() string {
	var sqlId utils.SQLVal = "select t.contractno," +
		"       to_char(t.SpotContractId) SpotContractId," +
		"       t.deliverygoodsid," +
		"       t.spotgoodsdesc," +
		"       t.goodsid," +
		"       t.pricemove," +
		"       t.userid," +
		"       t.BUYUSERID," +
		"       t.SELLUSERID," +
		"       t.qty," +
		"       t.qty - t.pricedqty unpricedqty," +
		"       t.pricedqty," +
		"       (case" +
		"         when t.pricetype = 3 then" +
		"          t.qty - t.RECKONREALQTY" +
		"         else" +
		"          t.pricedqty - nvl(t.ReckonRealQty,0)" +
		"       end) unsureqty," +
		"       t.reckonedamount PayAmount," +
		"       t.invoiceamount," +
		"       (t.pricedamount + t.RECKONADJUSTAMOUNT -" +
		"       t.invoiceamount) as daikaiAmount," +
		"       to_char(t.startdate, 'yyyy-mm-dd hh24:mi:ss') startdate," +
		"       to_char(t.enddate, 'yyyy-mm-dd hh24:mi:ss') enddate," +
		"       to_char(t.deliverystartdate, 'yyyy-mm-dd hh24:mi:ss') deliverystartdate," +
		"       to_char(t.deliveryenddate, 'yyyy-mm-dd hh24:mi:ss') deliveryenddate," +
		"       wr.convertfactor," +
		"       t.contractstatus," +
		"       t.pricetype," +
		"       t.producttype," +
		"       t.contracttype," +
		"       t.remark," +
		"       to_char(t.contractattachment) attachment," +
		"       t.margin," +
		"       t.contractmargin," +
		"       t.SPOTGOODSBRANDID," +
		"       t.tradeuserid," +
		"       t.saleuserid," +
		"       t.meruserid," +
		"       t.currencyid," +
		"       t.biztype," +
		"       g.deliverygoodscode," +
		"       g.deliverygoodsname," +
		"       wr.wrstandardid," +
		"       wr.wrstandardname," +
		"       wr.wrstandardcode," +
		"       g2.goodscode," +
		"       g2.goodsname," +
		"       e.enumdicname," +
		"       t.contracttype," +
		"       t.pricedamount," +
		"       case" +
		"         when t.pricedqty > 0 then" +
		"          (t.pricedamount) / t.pricedqty" +
		"         else" +
		"          0" +
		"       end pricedAvg," +
		"       t.ReckonRealQty," +
		"       t.ReckonOtherAmount," +
		"       t.ReckonAdjustAmount," +
		"       t.Price," +
		"       t.ReckonedAmount," +
		"       to_char(t.audittime, 'yyyy-mm-dd hh24:mi:ss') audittime," +
		"       to_char(t.createtime, 'yyyy-mm-dd hh24:mi:ss') createtime," +
		"       t.pricedamount + t.ReckonAdjustAmount as LoanAmount," +
		"       gb.dgfactoryitemvalue BRANDNAME" +
		"  from ermcp_spotcontract t" +
		"  left join deliverygoods g" +
		"    on t.deliverygoodsid = g.deliverygoodsid" +
		"  left join goods g2" +
		"    on t.goodsid = g2.goodsid" +
		"  left join wrstandard wr" +
		"    on t.wrstandardid = wr.wrstandardid" +
		"  left join DGFactoryItem gb" +
		"    on t.spotgoodsbrandid = gb.dgfactoryitemid" +
		"  left join enumdicitem e" +
		"    on wr.unitid = e.enumitemname" +
		"   and e.enumdiccode = 'goodsunit'" +
		" where 1 = 1"
	sqlId.AndEx("t.userid", r.UserID, r.UserID > 0)
	sqlId.AndEx("t.contracttype", r.Contracttype, r.Contracttype != 0)
	sqlId.AndEx("t.SpotContractId", r.SpotContractId, len(r.SpotContractId) > 0)
	if r.UserType == 7 {
		// 企业成员
		sqlId.Join(fmt.Sprintf(" and %v in(t.saleuserid, t.tradeuserid, t.meruserid)", r.OwnUserId))
	}

	var status string
	nQueryType := r.QryType
	if 1 == nQueryType {
		// 全部
		status = "2,3"
	} else if 2 == nQueryType {
		// 待点价
		status = "2"
	} else {
		// 履约
		status = "2"
	}

	if len(status) > 0 {
		sqlId.Join(fmt.Sprintf(" and t.contractstatus in (%v)", status))
	}
	sqlId.JoinEx(r.QryType == 2, " and t.qty - t.pricedqty > 0 and t.pricetype !=1")
	return sqlId.String()
}

// GetDataEx
func (r *Ermcp3SellBuyContract) GetDataEx() (interface{}, error) {
	sData := make([]Ermcp3SellBuyContract, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	for i := range sData {
		sData[i].calc()
	}
	return sData, err
}

// Ermcp3ExposureDetail 敞口现货明细
type Ermcp3ExposureDetail struct {
	Createtime        string  `json:"createtime"  xorm:"'createtime'"`               // 时间
	Areauserid        int64   `json:"areauserid"  xorm:"'areauserid'"`               // 机构ID
	Logtype           int32   `json:"logtype"  xorm:"'logtype'"`                     // 类型 - 1:套保计划 2:现货合同
	Contracttype      int32   `json:"contracttype"  xorm:"'contracttype'"`           // 现货合同类型 - 1:采购 -1:销售
	Qty               float64 `json:"qty"  xorm:"'qty'"`                             // 数量
	RelateNo          string  `json:"relateNo"  xorm:"'relateNo'"`                   // 现货合同/套保计划编号
	Middlegoodsname   string  `json:"middlegoodsname"  xorm:"'middlegoodsname'"`     // 套保商品名称
	Middlegoodscode   string  `json:"middlegoodscode"  xorm:"'middlegoodscode'"`     // 套保商品代码
	MiddlegoodsId     int32   `json:"middlegoodsId"  xorm:"'middlegoodsId'"`         // 套保商品id
	Unitid            int32   `json:"-"  xorm:"'unitid'"`                            // 现货商品单位ID
	Enumdicname       string  `json:"enumdicname"  xorm:"'enumdicname'"`             // 现货商品单位名称
	ChangeQty         float64 `json:"changeQty"  xorm:"'changeQty'"`                 // 套保变动量
	Convertfactor     float64 `json:"convertfactor"  xorm:"'convertfactor'"`         // 标仓系数
	Convertratio      float64 `json:"convertratio"  xorm:"'convertratio'"`           // 套保系数
	DELIVERYGOODSID   int32   `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"`     // 现货品种id
	DELIVERYGOODSCODE string  `json:"deliverygoodscode"  xorm:"'DELIVERYGOODSCODE'"` // 现货品种代码
	DELIVERYGOODSNAME string  `json:"deliverygoodsname"  xorm:"'DELIVERYGOODSNAME'"` // 现货品种名称
	MGUNITID          int32   `json:"mgunitid"  xorm:"'MGUNITID'"`                   // 套保品种单位id
	MGUNITIDNAME      string  `json:"mgunitidname"`                                  // 套保品种单位名称
}

func (r *Ermcp3ExposureDetail) calc() {
	// 销售合同转换为负数
	if r.Logtype == 2 && r.Contracttype == -1 {
		r.ChangeQty *= -1
		r.Qty *= -1
	}

	// 采购计划 转换为负数
	if r.Logtype == 1 && r.Contracttype == 1 {
		r.ChangeQty *= -1
		r.Qty *= -1
	}

	if r.Convertratio > 0 && r.Convertfactor > 0 {
		r.Qty = r.Qty / r.Convertfactor / r.Convertratio
	}
	r.MGUNITIDNAME = mtpcache.GetEnumDicitemName(r.MGUNITID)
}

func (r *Ermcp3ExposureDetail) buildSql() string {
	var sqlId utils.SQLVal = "with tmp as" +
		" (select 2                as LogType," +
		"         s.spotcontractid as relatedid," +
		"         s.contractno     as relateNo," +
		"         s.qty" +
		"    from ermcp_spotcontract s" +
		"  union all" +
		"  select 1," +
		"         t.hedgeplanid as relateid," +
		"         t.hedgeplanno as relateNo," +
		"         t.planqty     as qty" +
		"    from ermcp_hedgeplan t)" +
		"select to_char(t.createtime, 'yyyy-mm-dd hh24:mi:ss') createtime," +
		"       t.middlegoodsid," +
		"       t.areauserid," +
		"       t.logtype," +
		"       t.contracttype," +
		"       t.qty," +
		"       t.convertfactor," +
		"       t.convertratio," +
		"       t.qty changeQty," +
		"       tmp.relateNo," +
		"       m.middlegoodsname," +
		"       m.middlegoodscode," +
		"       m.goodsunitid mgunitid," +
		"       g.deliverygoodsid," +
		"       g.deliverygoodscode," +
		"       g.deliverygoodsname," +
		"       g.goodsunitid unitid," +
		"       e.enumdicname" +
		"  from ermcp_spotexposurelog t" +
		"  left join erms_middlegoods m" +
		"    on t.middlegoodsid = m.middlegoodsid" +
		"  left join deliverygoods g" +
		"    on t.deliverygoodsid = g.deliverygoodsid" +
		"  left join enumdicitem e" +
		"    on g.goodsunitid = e.enumitemname" +
		"   and e.enumdiccode = 'goodsunit'" +
		"  left join tmp" +
		"    on t.logtype = tmp.LogType" +
		"   and t.relatedid = tmp.relatedid" +
		" where 1=1 and t.tradedate=to_char(sysdate, 'yyyymmdd')"
	sqlId.And("t.areauserid", r.Areauserid)
	sqlId.And("t.middlegoodsid", r.MiddlegoodsId)
	return sqlId.String()
}

// GetDataEx
func (r *Ermcp3ExposureDetail) GetDataEx() (interface{}, error) {
	e := db.GetEngine()
	s := e.SQL(r.buildSql())
	sData := make([]Ermcp3ExposureDetail, 0)
	if err := s.Find(&sData); err != nil {
		return nil, err
	}
	for i := range sData {
		sData[i].calc()
	}
	return sData, nil
}

// Ermcp3AreaSpot 敞口现货头寸
type Ermcp3AreaSpot struct {
	AREAUSERID        int64   `json:"areauserid"  xorm:"'AREAUSERID'"`               // 所属机构
	ORIBUYPLANQTY     float64 `json:"-"  xorm:"'ORIBUYPLANQTY'"`                     // 期初采购计划数量
	ORIBUYPRICEDQTY   float64 `json:"-"  xorm:"'ORIBUYPRICEDQTY'"`                   // 期初采购合同已定价数量
	ORISELLPLANQTY    float64 `json:"-"  xorm:"'ORISELLPLANQTY'"`                    // 期初销售计划数量
	ORISELLPRICEDQTY  float64 `json:"-"  xorm:"'ORISELLPRICEDQTY'"`                  // 期初销售合同已定价数量
	BUYPLANQTY        float64 `json:"-"  xorm:"'BUYPLANQTY'"`                        // 采购计划数量
	BUYPRICEDQTY      float64 `json:"-"  xorm:"'BUYPRICEDQTY'"`                      // 采购合同已定价数量
	SELLPLANQTY       float64 `json:"-"  xorm:"'SELLPLANQTY'"`                       // 销售计划数量
	SELLPRICEDQTY     float64 `json:"-"  xorm:"'SELLPRICEDQTY'"`                     // 销售合同已定价数量
	TOTALSPOTQTY      float64 `json:"totalspotqty"  xorm:"'TOTALSPOTQTY'"`           // 当前数量(现货头寸总量) =  (销售计划数量 - 销售已定价数量)  - (采购计划数量 - 采购已定价数量)
	OriToalSpotQty    float64 `json:"oritoalspotqty"  xorm:"'OriToalSpotQty'"`       // 昨日数量
	IncreaseQty       float64 `json:"increaseqty"  xorm:"'IncreaseQty'"`             // 增加数量=销售计划数量+采购已定价数量
	DecreaseQty       float64 `json:"decreaseqty"  xorm:"'DecreaseQty'"`             // 减少数量=-(销售已定价数量+采购计划数量)
	UPDATETIME        string  `json:"updatetime"  xorm:"'UPDATETIME'"`               // 更新时间
	DELIVERYGOODSID   int32   `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"`     // 现货品种id
	DELIVERYGOODSCODE string  `json:"deliverygoodscode"  xorm:"'DELIVERYGOODSCODE'"` // 现货品种代码
	DELIVERYGOODSNAME string  `json:"deliverygoodsname"  xorm:"'DELIVERYGOODSNAME'"` // 现货品种名称
	GOODSUNITID       int32   `json:"goodsunitid"  xorm:"'GOODSUNITID'"`             // 现货品种单位id

	ENUMDICNAME string `json:"enumdicname"` // 单位名称
}

func (r *Ermcp3AreaSpot) calc() {
	/*
		增加数量=今日销售计划数量+今日采购已定价数量
		减少数量=-(今日销售已定价数量+今日采购计划数量)

		其中，
		今日销售计划数量=期末销售计划数量-期初销售计划数量
		今日采购已定价数量=期末采购已定价数量-期初采购已定价数量
		今日销售已定价数量=期末销售已定价数量-期初销售已定价数量
		今日采购计划数量=期末采购计划数量-期初采购计划数量
	*/
	r.IncreaseQty = r.SELLPLANQTY - r.ORISELLPLANQTY + r.BUYPRICEDQTY - r.ORIBUYPRICEDQTY
	r.DecreaseQty = (r.SELLPRICEDQTY - r.ORISELLPRICEDQTY + r.BUYPLANQTY - r.ORIBUYPLANQTY) * -1
	r.OriToalSpotQty = (r.ORISELLPLANQTY - r.ORISELLPRICEDQTY) - (r.ORIBUYPLANQTY - r.ORIBUYPRICEDQTY)
	r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.GOODSUNITID)
}

func (r *Ermcp3AreaSpot) buildSql() string {
	var sqlId utils.SQLVal = "select t.AREAUSERID," +
		"       t.ORIBUYPLANQTY," +
		"       t.ORIBUYPRICEDQTY," +
		"       t.ORISELLPLANQTY," +
		"       t.ORISELLPRICEDQTY," +
		"       t.BUYPLANQTY," +
		"       t.BUYPRICEDQTY," +
		"       t.SELLPLANQTY," +
		"       t.SELLPRICEDQTY," +
		"       t.TOTALSPOTQTY," +
		"       g.deliverygoodsid," +
		"       g.deliverygoodscode," +
		"       g.deliverygoodsname," +
		"       g.goodsunitid," +
		"       to_char(t.UPDATETIME, 'yyyy-mm-dd hh24:mi:ss') UPDATETIME" +
		"  from ermcp_areaspot t" +
		"  left join deliverygoods g" +
		"    on t.deliverygoodsid = g.deliverygoodsid" +
		" where 1 = 1"
	sqlId.And("t.areauserid", r.AREAUSERID)
	return sqlId.String()
}

// GetDataEx
func (r *Ermcp3AreaSpot) GetDataEx() (interface{}, error) {
	e := db.GetEngine()
	s := e.SQL(r.buildSql())
	sData := make([]Ermcp3AreaSpot, 0)
	if err := s.Find(&sData); err != nil {
		return nil, err
	}
	for i := range sData {
		sData[i].calc()
	}
	return sData, nil
}

// Ermcp3AreaSpotDetail 敞口现货头寸明细
type Ermcp3AreaSpotDetail struct {
	Relatedid         string  `json:"relatedid"  xorm:"'relatedid'"`                 // 套保计划ID/现货合同ID
	Relatedno         string  `json:"relatedno"  xorm:"'relatedno'"`                 // 编号
	LogType           int32   `json:"logtype"  xorm:"'logType'"`                     // 记录类型 1-套保 2-现货合同
	Contracttype      int32   `json:"contracttype"  xorm:"'contracttype'"`           // 合同类型 1-采购 -1-销售
	Qty               float64 `json:"qty"  xorm:"'qty'"`                             // 数量
	Strtime           string  `json:"strtime"  xorm:"'strtime'"`                     // 时间
	Enumdicname       string  `json:"enumdicname"`                                   // 现货商品单位名称
	Recordname        string  `json:"recordname"`                                    // 类型名称
	CREATETIME        string  `json:"createtime"  xorm:"'CREATETIME'"`               // 创建时间
	Unitid            int32   `json:"-"  xorm:"'UNITID'"`                            // 单位ID
	UserId            int64   `json:"-"`                                             // 所属用户ID
	DELIVERYGOODSID   int32   `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"`     // 现货品种id
	DELIVERYGOODSCODE string  `json:"deliverygoodscode"  xorm:"'DELIVERYGOODSCODE'"` // 现货品种代码
	DELIVERYGOODSNAME string  `json:"deliverygoodsname"  xorm:"'DELIVERYGOODSNAME'"` // 现货品种名称
}

func (r *Ermcp3AreaSpotDetail) calc() {
	var logTypeName, contractTypeName string
	if r.LogType == 1 {
		logTypeName = "计划"
	} else {
		logTypeName = "合同"
	}

	if r.Contracttype == 1 {
		contractTypeName = "采购"
	} else {
		contractTypeName = "销售"
	}

	// 销售合同 数量转为负数
	if r.LogType == 2 && r.Contracttype == -1 {
		if r.Qty > 0 {
			r.Qty = r.Qty * -1
		}
	}

	// 采购计划 数量转为负数
	if r.LogType == 1 && r.Contracttype == 1 {
		if r.Qty > 0 {
			r.Qty = r.Qty * -1
		}
	}

	r.Recordname = contractTypeName + logTypeName
	r.Enumdicname = mtpcache.GetEnumDicitemName(r.Unitid)
}

func (r *Ermcp3AreaSpotDetail) buildSql() string {
	var sqlId utils.SQLVal = "with tmp as" +
		" (select to_char(t.hedgeplanid) relatedid," +
		"         t.hedgeplanno relatedno," +
		"         1 as logType," +
		"         t.contracttype" +
		"    from ermcp_hedgeplan t" +
		"   where  %v in(t.areauserid, t.tradeuserid)" +
		"     and t.deliverygoodsid = %v" +
		"  union all" +
		"  select to_char(t.spotcontractid)," +
		"         t.contractno," +
		"         2 as logType," +
		"         t.contracttype" +
		"    from ermcp_spotcontract t" +
		"   where %v in(t.userid, t.tradeuserid)" +
		"     and t.deliverygoodsid = %v)" +
		"select t.relatedid," +
		"       tmp.relatedno," +
		"       t.LogType," +
		"       tmp.contracttype," +
		"       t.RealQty qty," +
		"       to_char(t.createtime, 'yyyy-mm-dd hh24:mi:ss') createtime," +
		"       g.deliverygoodsid," +
		"       g.deliverygoodsname," +
		"       g.deliverygoodscode," +
		"       g.goodsunitid unitid" +
		"  from ermcp_spotlog t" +
		" inner join tmp" +
		"    on t.LogType = tmp.logType" +
		"   and t.relatedid = tmp.relatedid" +
		"   and t.areauserid = %v" +
		"   and t.deliverygoodsid = %v" +
		"  left join deliverygoods g" +
		"    on t.deliverygoodsid = g.deliverygoodsid" +
		" where t.tradedate = to_char(sysdate, 'yyyymmdd')"
	sqlId.FormatParam(r.UserId, r.DELIVERYGOODSID, r.UserId, r.DELIVERYGOODSID, r.UserId, r.DELIVERYGOODSID)
	return sqlId.String()
}

// GetDataEx
func (r *Ermcp3AreaSpotDetail) GetDataEx() (interface{}, error) {
	e := db.GetEngine()
	s := e.SQL(r.buildSql())
	sData := make([]Ermcp3AreaSpotDetail, 0)
	if err := s.Find(&sData); err != nil {
		return nil, err
	}
	for i := range sData {
		sData[i].calc()
	}
	return sData, nil
}

// Ermcp3Wrstandard 现货品类
type Ermcp3Wrstandard struct {
	WRSTANDARDID    int64   `json:"wrstandardid"  xorm:"'WRSTANDARDID'"`       // 品类ID(SEQ_WRSTANDARD)
	WRSTANDARDCODE  string  `json:"wrstandardcode"  xorm:"'WRSTANDARDCODE'"`   // 品类代码
	DELIVERYGOODSID int32   `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"` // 现货品种ID
	UNITID          int32   `json:"unitid"  xorm:"'UNITID'"`                   // 品类单位ID
	MINIVALUE       int32   `json:"minivalue"  xorm:"'MINIVALUE'"`             // 最小变动值
	MINIVALUEDP     int32   `json:"minivaluedp"  xorm:"'MINIVALUEDP'"`         // 最小变动值小数位
	REALMINIVALUE   int32   `json:"realminivalue"  xorm:"'REALMINIVALUE'"`     // 实际最小变动值
	REALMINIVALUEDP int32   `json:"realminivaluedp"  xorm:"'REALMINIVALUEDP'"` // 实际最小变动值小数位
	CREATORID       int64   `json:"creatorid"  xorm:"'CREATORID'"`             // 创建人
	CREATETIME      string  `json:"createtime"  xorm:"'CREATETIME'"`           // 创建时间
	WRSTANDARDNAME  string  `json:"wrstandardname"  xorm:"'WRSTANDARDNAME'"`   // 品类名称
	AREAUSERID      int64   `json:"areauserid"  xorm:"'AREAUSERID'"`           // 所属机构
	EnumdicName     string  `json:"enumdicname"`                               // 品类单位名称
	ISVALID         int32   `json:"isvalid"  xorm:"'ISVALID'"`                 // 是否有效 0-无效(停用) 1-有效(正常)
	UPDATETIME      string  `json:"updatetime"  xorm:"'UPDATETIME'"`           // 更新时间
	REMARK          string  `json:"remark"  xorm:"'REMARK'"`                   // 备注
	CONVERTFACTOR   float64 `json:"convertfactor"  xorm:"'CONVERTFACTOR'"`     // 标仓系数
}

func (r *Ermcp3Wrstandard) calc() {
	r.EnumdicName = mtpcache.GetEnumDicitemName(r.UNITID)
}

func (r *Ermcp3Wrstandard) buildSql() string {
	str := "select WRSTANDARDID," +
		"       WRSTANDARDCODE," +
		"       DELIVERYGOODSID," +
		"       UNITID," +
		"       MINIVALUE," +
		"       MINIVALUEDP," +
		"       REALMINIVALUE," +
		"       REALMINIVALUEDP," +
		"       CREATORID," +
		"       to_char(CREATETIME, 'yyyy-mm-dd hh24:mi:ss') CREATETIME," +
		"       WRSTANDARDNAME," +
		"       ISVALID," +
		"       to_char(UPDATETIME, 'yyyy-mm-dd hh24:mi:ss') UPDATETIME," +
		"       REMARK," +
		"       CONVERTFACTOR," +
		"       AREAUSERID" +
		"  from wrstandard t" +
		" where t.AREAUSERID=%v"
	sqlId := fmt.Sprintf(str, r.AREAUSERID)
	if r.DELIVERYGOODSID > 0 {
		sqlId = sqlId + fmt.Sprintf(" and DELIVERYGOODSID=%v", r.DELIVERYGOODSID)
	}
	sqlId += " order by createtime desc"
	return sqlId
}

// GetDataEx
func (r *Ermcp3Wrstandard) GetDataEx() (interface{}, error) {
	e := db.GetEngine()
	s := e.SQL(r.buildSql())
	sData := make([]Ermcp3Wrstandard, 0)
	if err := s.Find(&sData); err != nil {
		return nil, err
	}
	for i := range sData {
		sData[i].calc()
	}
	return sData, nil
}

// Ermcp3AreaStockApply 出入库申请
type Ermcp3AreaStockApply struct {
	INOUTAPPLYID      string  `json:"inoutapplyid"  xorm:"'INOUTAPPLYID'"`           // 申请ID(607+Unix秒时间戳(10位)+xxxxxx)
	USERID            int64   `json:"userid"  xorm:"'USERID'"`                       // 机构ID
	INOUTTYPE         int32   `json:"inouttype"  xorm:"'INOUTTYPE'"`                 // 出入库类型 - 5:采购入库 6:销售出库 7:生产入库 8:生产出库
	WRSTANDARDID      int32   `json:"wrstandardid"  xorm:"'WRSTANDARDID'"`           // 品类ID
	SPOTGOODSBRANDID  int32   `json:"spotgoodsbrandid"  xorm:"'SPOTGOODSBRANDID'"`   // 现货品牌ID
	SPOTCONTRACTID    string  `json:"spotcontractid"  xorm:"'SPOTCONTRACTID'"`       // 关联现货合同ID
	WAREHOUSEINFOID   string  `json:"warehouseinfoid"  xorm:"'WAREHOUSEINFOID'"`     // 现货仓库ID
	APPLYSTATUS       int32   `json:"applystatus"  xorm:"'APPLYSTATUS'"`             // 申请状态 - 1:待审核 2:审核通过 3:审核拒绝 4:处理失败 5:已撤回
	APPLYSRC          int32   `json:"applysrc"  xorm:"'APPLYSRC'"`                   // 申请来源 - 1:管理端 2:终端
	APPLYID           int64   `json:"applyid"  xorm:"'APPLYID'"`                     // 申请人
	APPLYREMARK       string  `json:"applyremark"  xorm:"'APPLYREMARK'"`             // 申请备注
	APPLYTIME         string  `json:"applytime"  xorm:"'APPLYTIME'"`                 // 申请时间
	AUDITSRC          int32   `json:"auditsrc"  xorm:"'AUDITSRC'"`                   // 审核来源 - 1:管理端 2:终端
	AUDITID           int64   `json:"auditid"  xorm:"'AUDITID'"`                     // 审核人
	AUDITTIME         string  `json:"audittime"  xorm:"'AUDITTIME'"`                 // 审核时间
	AUDITREMARK       string  `json:"auditremark"  xorm:"'AUDITREMARK'"`             // 审核备注
	AUDITTRADEDATE    string  `json:"audittradedate"  xorm:"'AUDITTRADEDATE'"`       // 审核交易日(yyyyMMdd)
	WRSTANDARDNAME    string  `json:"wrstandardname"  xorm:"'WRSTANDARDNAME'"`       // 品类名称
	WRSTANDARDCODE    string  `json:"wrstandardcode"  xorm:"'WRSTANDARDCODE'"`       // 品类代码
	UNITID            int32   `json:"unitid"  xorm:"'UNITID'"`                       // 单位id
	BRANDNAME         string  `json:"brandname"  xorm:"'BRANDNAME'"`                 // 品牌名称
	WAREHOUSENAME     string  `json:"warehousename"  xorm:"'WAREHOUSENAME'"`         // 仓库名称
	WAREHOUSECODE     string  `json:"warehousecode"  xorm:"'WAREHOUSECODE'"`         // 仓库代码
	WAREHOUSETYPE     int32   `json:"warehousetype"  xorm:"'WAREHOUSETYPE'"`         // 仓库类型 - 1 厂库  2 自有库  3 合作库
	CONTRACTNO        string  `json:"contractno"  xorm:"'CONTRACTNO'"`               // 合同编号
	CONTRACTTYPE      int32   `json:"contracttype"  xorm:"'CONTRACTTYPE'"`           // 现货合同类型 - 1:采购 -1:销售
	BUYUSERID         int64   `json:"buyuserid"  xorm:"'BUYUSERID'"`                 // 采购方userid
	SELLUSERID        int64   `json:"selluserid"  xorm:"'SELLUSERID'"`               // 销售方userid
	PRICETYPE         int32   `json:"pricetype"  xorm:"'PRICETYPE'"`                 // 定价类型 - 1:一口价 2:点价 3:暂定价
	CONTRACTQTY       float64 `json:"contractqty"  xorm:"'CONTRACTQTY'"`             // 合同量
	DETAILJSON        string  `json:"detailjson"  xorm:"'DETAILJSON'"`               // 明细数据
	BUYUSERNAME       string  `json:"buyusername"`                                   // 采购方名称
	SELLUSERNAME      string  `json:"sellusername"`                                  // 销售方名称
	APPLYNAME         string  `json:"applyname"`                                     // 申请人名称
	AUDITNAME         string  `json:"auditname"`                                     // 审核人名称
	ENUMDICNAME       string  `json:"enumdicname"`                                   // 现货商品单位名称
	DELIVERYGOODSID   int32   `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"`     // 现货品种id
	DELIVERYGOODSCODE string  `json:"deliverygoodscode"  xorm:"'DELIVERYGOODSCODE'"` // 现货品种代码
	DELIVERYGOODSNAME string  `json:"deliverygoodsname"  xorm:"'DELIVERYGOODSNAME'"` // 现货品种名称
	BUYNICKNAME       string  `json:"buynickname"`                                   // 采购方昵称
	SELLNICKNAME      string  `json:"sellnickname"`                                  // 销售方昵称
	QTY               float64 `json:"qty"`                                           // 数量

	FilterStatus string `json:"-"` // 查询条件, 申请状态, 逗号隔开
	FilterType   string `json:"-"` // 查询条件, 出入库类型, 逗号隔开
	BeginDate    string `json:"-"` // 开始日期
	EndDate      string `json:"-"` // 结束日期
	UserType     int32  `json:"-"` // 用户类型
}

func (r *Ermcp3AreaStockApply) calc() {
	// 采购方名称
	r.BUYUSERNAME, r.BUYNICKNAME = mtpcache.GetUserNameAndNickName(r.BUYUSERID)
	// 销售方名称
	r.SELLUSERNAME, r.SELLNICKNAME = mtpcache.GetUserNameAndNickName(r.SELLUSERID)
	// 申请人名称
	if r.APPLYSRC == 1 {
		r.APPLYNAME = mtpcache.GetSystemmangerLoginCode(r.APPLYID)
	} else {
		r.APPLYNAME = mtpcache.GetLoginCodeByLoginId(r.APPLYID)
	}
	// 审核人名称
	if r.AUDITSRC == 1 {
		r.AUDITNAME = mtpcache.GetSystemmangerLoginCode(r.AUDITID)
	} else {
		r.AUDITNAME = mtpcache.GetLoginCodeByLoginId(r.AUDITID)
	}
	// 单位名称
	r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.UNITID)

	if len(r.DETAILJSON) > 0 {
		// 解析qty字段
		req := struct {
			QTY float64 `json:"InOutQty"` // 数量
		}{}
		if json.Unmarshal([]byte(r.DETAILJSON), &req) == nil {
			r.QTY = req.QTY
		}
	}
}

func (r *Ermcp3AreaStockApply) buildSql() string {
	var sqlId utils.SQLVal = "SELECT to_char(t.operateapplyid) INOUTAPPLYID," +
		"       t.USERID," +
		"       t.operateapplytype INOUTTYPE," +
		"       t.WRSTANDARDID," +
		"       t.SPOTGOODSBRANDID," +
		"       t.DELIVERYGOODSID," +
		"       to_char(t.relatedid) SPOTCONTRACTID," +
		"       to_char(t.WAREHOUSEINFOID) WAREHOUSEINFOID," +
		"       to_char(t.detailjson) detailjson," +
		"       t.APPLYSTATUS," +
		"       t.APPLYSRC," +
		"       t.APPLYID," +
		"       t.remark APPLYREMARK," +
		"       to_char(t.APPLYTIME, 'yyyy-mm-dd hh24:mi:ss') APPLYTIME," +
		"       t.AUDITSRC," +
		"       t.AUDITID," +
		"       to_char(t.AUDITTIME, 'yyyy-mm-dd hh24:mi:ss') AUDITTIME," +
		"       t.AUDITREMARK," +
		"       t.AUDITTRADEDATE," +
		"       w.wrstandardname," +
		"       w.wrstandardcode," +
		"       g.goodsunitid unitid," +
		"       gb.dgfactoryitemvalue brandname," +
		"       h.warehousename," +
		"       h.warehousecode," +
		"       h.warehousetype," +
		"       s.contractno," +
		"       s.contracttype," +
		"       s.buyuserid," +
		"       s.selluserid," +
		"       s.pricetype," +
		"       s.qty CONTRACTQTY," +
		"       g.deliverygoodscode," +
		"       g.deliverygoodsname" +
		"  FROM ermcp_contractoperateapply t" +
		"  left join wrstandard w" +
		"    on t.wrstandardid = w.wrstandardid" +
		"  left join dgfactoryitem gb" +
		"    on t.spotgoodsbrandid = gb.dgfactoryitemid" +
		"  left join deliverygoods g" +
		"    on t.deliverygoodsid = g.deliverygoodsid" +
		"  left join warehouseinfo h" +
		"    on t.warehouseinfoid = h.autoid" +
		"  left join ermcp_spotcontract s" +
		"    on t.relatedid = s.spotcontractid" +
		" WHERE t.operateapplytype in(5,6,7,8)"

	areaUserId := mtpcache.GetAreaUserId(r.USERID, r.UserType)
	if areaUserId == r.USERID {
		// 机构用户
		sqlId.And("t.USERID", r.USERID)
	} else {
		if r.INOUTTYPE == 7 || r.INOUTTYPE == 8 {
			// 生产出入库, 没有相关合同
			sqlId.And("t.USERID", r.USERID)
		} else {
			sqlId.Join(fmt.Sprintf(" and %v in(s.saleuserid, s.tradeuserid, s.meruserid)", r.USERID))
		}
	}
	// 合同id
	sqlId.AndInterEx("t.RELATEDID", r.SPOTCONTRACTID, len(r.SPOTCONTRACTID) > 0)

	// 现货品种id
	if r.DELIVERYGOODSID > 0 {
		sqlId.And("t.DELIVERYGOODSID", r.DELIVERYGOODSID)
	}
	// 品类id
	if r.WRSTANDARDID > 0 {
		sqlId.And("t.WRSTANDARDID", r.WRSTANDARDID)
	}
	// 品牌id
	if r.SPOTGOODSBRANDID > 0 {
		sqlId.And("t.SPOTGOODSBRANDID", r.SPOTGOODSBRANDID)
	}
	// 仓库id
	sqlId.AndInterEx("t.WAREHOUSEINFOID", r.WAREHOUSEINFOID, len(r.WAREHOUSEINFOID) > 0)
	// 日期范围
	if len(r.BeginDate) > 0 {
		if r.BeginDate == r.EndDate {
			sqlId.And("t.tradedate", r.BeginDate)
		} else if r.EndDate > r.BeginDate {
			sqlId.BiggerOrEq("t.tradedate", r.BeginDate)
			sqlId.LessOrEq("t.tradedate", r.EndDate)
		}
	}
	// 出入库类型
	if len(r.FilterType) > 0 {

		// 原INOUTTYPE 1,2,3,4 转为 新表 5,6,7,8
		r.FilterType = strings.ReplaceAll(r.FilterType, "1", "5")
		r.FilterType = strings.ReplaceAll(r.FilterType, "2", "6")
		r.FilterType = strings.ReplaceAll(r.FilterType, "3", "7")
		r.FilterType = strings.ReplaceAll(r.FilterType, "4", "8")

		if len(r.FilterType) == 1 {
			sqlId.AndInterEx("t.OPERATEAPPLYTYPE", r.FilterType, true)
		} else {
			sqlId.Join(fmt.Sprintf(" and t.OPERATEAPPLYTYPE in(%v)", r.FilterType))
		}
	}
	// 出入库状态
	if len(r.FilterStatus) > 0 {
		sqlId.Join(fmt.Sprintf(" and t.APPLYSTATUS in(%v)", r.FilterStatus))
	}
	// 排序
	sqlId.Join(" order by t.APPLYTIME desc")
	return sqlId.String()
}

// GetDataEx 查询库存申请(记录)
func (r *Ermcp3AreaStockApply) GetDataEx() (interface{}, error) {
	sData := make([]Ermcp3AreaStockApply, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	if err == nil {
		for i := range sData {
			sData[i].calc()
		}
	}
	return sData, err
}

// Ermcp3AreaStockApplySum 合同出入库数量汇总
type Ermcp3AreaStockApplySum struct {
	INOUTTYPE        int32   `json:"inouttype"  xorm:"'INOUTTYPE'"`               // 出入库类型 - 1:采购入库 2:销售出库 3:生产入库 4:生产出库
	WRSTANDARDID     int32   `json:"wrstandardid"  xorm:"'WRSTANDARDID'"`         // 品类id
	SPOTGOODSBRANDID int32   `json:"spotgoodsbrandid"  xorm:"'SPOTGOODSBRANDID'"` // 品牌id
	BRANDNAME        string  `json:"brandname"  xorm:"'BRANDNAME'"`               // 品牌名称
	WRSTANDARDNAME   string  `json:"wrstandardname"  xorm:"'WRSTANDARDNAME'"`     // 品类名称
	TOTALQTY         float64 `json:"totalqty"  xorm:"'TOTALQTY'"`                 // 总数量
	SPOTCONTRACTID   string  `json:"spotcontractid"  xorm:"'SPOTCONTRACTID'"`     // 关联现货合同ID
}

func (r *Ermcp3AreaStockApplySum) buildSql() string {
	sqlId := "select a.*, gb.dgfactoryitemvalue brandname, w.wrstandardname" +
		"  from (SELECT t.INOUTTYPE," +
		"               t.wrstandardid," +
		"               t.SPOTGOODSBRANDID," +
		"               t.SPOTCONTRACTID," +
		"               sum(t.QTY) TOTALQTY" +
		"          FROM ERMCP_AREAINOUTSTOCKAPPLY t" +
		"         WHERE t.applystatus = 2" +
		"           and t.spotcontractid = %v" +
		"         group by t.inouttype," +
		"                  t.spotgoodsbrandid," +
		"                  t.wrstandardid," +
		"                  t.spotcontractid) a" +
		"  left join dgfactoryitem gb" +
		"    on a.spotgoodsbrandid = gb.dgfactoryitemid" +
		"  left join wrstandard w" +
		"    on a.wrstandardid = w.wrstandardid"
	sqlId = fmt.Sprintf(sqlId, r.SPOTCONTRACTID)

	// 不关联合同id
	sqlId2 := "select a.*, gb.dgfactoryitemvalue brandname, w.wrstandardname" +
		"  from (SELECT t.INOUTTYPE," +
		"               t.wrstandardid," +
		"               t.SPOTGOODSBRANDID," +
		"               t.SPOTCONTRACTID," +
		"               sum(t.QTY) TOTALQTY" +
		"          FROM ERMCP_AREAINOUTSTOCKAPPLY t" +
		"         WHERE t.applystatus = 2" +
		"         group by t.inouttype," +
		"                  t.spotgoodsbrandid," +
		"                  t.wrstandardid," +
		"                  t.spotcontractid) a" +
		"  left join dgfactoryitem gb" +
		"    on a.spotgoodsbrandid = gb.dgfactoryitemid" +
		"  left join wrstandard w" +
		"    on a.wrstandardid = w.wrstandardid"
	if len(r.SPOTCONTRACTID) == 0 {
		return sqlId2
	}
	return sqlId
}

// GetDataEx 获取合同出入库汇总信息
func (r *Ermcp3AreaStockApplySum) GetDataEx() (interface{}, error) {
	sData := make([]Ermcp3AreaStockApplySum, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	return sData, err
}

// Ermcp3AreaStock 机构库存表
type Ermcp3AreaStock struct {
	TODAYBUYINQTY      float64 `json:"todaybuyinqty"  xorm:"'TODAYBUYINQTY'"`                    // 今日采购入库量
	TODAYPRODUCEINQTY  float64 `json:"todayproduceinqty"  xorm:"'TODAYPRODUCEINQTY'"`            // 今日生产入库量
	TODAYSELLOUTQTY    float64 `json:"todayselloutqty"  xorm:"'TODAYSELLOUTQTY'"`                // 今日销售出库量
	TODAYPRODUCEOUTQTY float64 `json:"todayproduceoutqty"  xorm:"'TODAYPRODUCEOUTQTY'"`          // 今日生产出库量
	UPDATETIME         string  `json:"updatetime"  xorm:"'UPDATETIME'"`                          // 更新时间
	USERID             int64   `json:"userid"  xorm:"'USERID'" form:"userid" binding:"required"` // 机构ID
	WRSTANDARDID       string  `json:"wrstandardid"  xorm:"'WRSTANDARDID'"`                      // 品类ID
	SPOTGOODSBRANDID   int32   `json:"spotgoodsbrandid"  xorm:"'SPOTGOODSBRANDID'"`              // 现货品牌ID
	WAREHOUSEINFOID    string  `json:"warehouseinfoid"  xorm:"'WAREHOUSEINFOID'"`                // 仓库ID
	ORISTOCK           float64 `json:"oristock"  xorm:"'ORISTOCK'"`                              // 期初库存量(昨日量)
	CURSTOCK           float64 `json:"curstock"  xorm:"'CURSTOCK'"`                              // 期末库存量(今日量)
	WRSTANDARDNAME     string  `json:"wrstandardname"  xorm:"'WRSTANDARDNAME'"`                  // 品类名称
	WRSTANDARDCODE     string  `json:"wrstandardcode"  xorm:"'WRSTANDARDCODE'"`                  // 品类代码
	UNITID             int32   `json:"unitid"  xorm:"'UNITID'"`                                  // 单位id
	BRANDNAME          string  `json:"brandname"  xorm:"'BRANDNAME'"`                            // 品牌名称
	WAREHOUSENAME      string  `json:"warehousename"  xorm:"'WAREHOUSENAME'"`                    // 仓库名称
	WAREHOUSECODE      string  `json:"warehousecode"  xorm:"'WAREHOUSECODE'"`                    // 仓库代码
	WAREHOUSETYPE      int32   `json:"warehousetype"  xorm:"'WAREHOUSETYPE'"`                    // 仓库类型 - 1 厂库  2 自有库  3 合作库
	USERNAME           string  `json:"username"`                                                 // 机构名称
	ENUMDICNAME        string  `json:"enumdicname"`                                              // 单位名称
	DELIVERYGOODSID    int32   `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"`                // 现货品种id
	DELIVERYGOODSCODE  string  `json:"deliverygoodscode"  xorm:"'DELIVERYGOODSCODE'"`            // 现货品种代码
	DELIVERYGOODSNAME  string  `json:"deliverygoodsname"  xorm:"'DELIVERYGOODSNAME'"`            // 现货品种名称
	GOODSUNITID        int32   `json:"goodsunitid"  xorm:"'GOODSUNITID'"`                        // 现货商品单位id
}

func (r *Ermcp3AreaStock) calc() {
	r.USERNAME = mtpcache.GetUserNameByUserId(r.USERID)
	r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.UNITID)
}

func (r *Ermcp3AreaStock) buildSql() string {
	var sqlId utils.SQLVal = "SELECT t.TODAYBUYINQTY," +
		"       t.TODAYPRODUCEINQTY," +
		"       t.TODAYSELLOUTQTY," +
		"       t.TODAYPRODUCEOUTQTY," +
		"       to_char(t.UPDATETIME, 'yyyy-mm-dd hh24:mi:ss') UPDATETIME," +
		"       t.USERID," +
		"       t.WRSTANDARDID," +
		"       t.SPOTGOODSBRANDID," +
		"       t.WAREHOUSEINFOID," +
		"       t.DELIVERYGOODSID," +
		"       t.ORISTOCK," +
		"       t.CURSTOCK," +
		"       w.wrstandardname," +
		"       w.wrstandardcode," +
		"       w.unitid," +
		"       gb.dgfactoryitemvalue brandname," +
		"       h.warehousename," +
		"       h.warehousecode," +
		"       h.warehousetype," +
		"       g.deliverygoodsid," +
		"       g.deliverygoodscode," +
		"       g.deliverygoodsname," +
		"       g.goodsunitid" +
		"  FROM ERMCP_AREASTOCK t" +
		"  LEFT JOIN WRSTANDARD w" +
		"    on t.wrstandardid = w.wrstandardid" +
		"  LEFT JOIN dgfactoryitem gb" +
		"    on t.spotgoodsbrandid = gb.dgfactoryitemid" +
		"  LEFT JOIN deliverygoods g" +
		"    on t.deliverygoodsid = g.deliverygoodsid" +
		"  LEFT JOIN WAREHOUSEINFO h" +
		"    on t.warehouseinfoid = h.autoid" +
		" WHERE 1 = 1"
	sqlId.And("t.USERID", r.USERID)
	sqlId.Join(" order by t.WRSTANDARDID, t.UPDATETIME desc")
	return sqlId.String()
}

// GetDataEx 获取机构库存信息
func (r *Ermcp3AreaStock) GetDataEx() (interface{}, error) {
	sData := make([]Ermcp3AreaStock, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	if err == nil {
		for i := range sData {
			sData[i].calc()
		}
	}
	return sData, err
}

// Ermcp3SpotGoodsPrice 现货市价
type Ermcp3SpotGoodsPrice struct {
	WRSTANDARDID      int64   `json:"wrstandardid"  xorm:"'WRSTANDARDID'"`           // 现货品类ID(通用则为0)
	SPOTGOODSBRANDID  int32   `json:"spotgoodsbrandid"  xorm:"'SPOTGOODSBRANDID'"`   // 现货品牌ID(通用则为0, 不为0则须先有品类ID)
	CURRENCYID        int32   `json:"currencyid"  xorm:"'CURRENCYID'"`               // 报价货币ID
	SPOTGOODSPRICE    float64 `json:"spotgoodsprice"  xorm:"'SPOTGOODSPRICE'"`       // 现货价格
	TRADEDATE         string  `json:"tradedate"  xorm:"'TRADEDATE'"`                 // 交易日(yyyyMMdd)
	OPERATESRC        int32   `json:"operatesrc"  xorm:"'OPERATESRC'"`               // 最后操作来源 - 1:管理端 2:终端
	OPERATEID         int64   `json:"operateid"  xorm:"'OPERATEID'"`                 // 最后操作人
	OPERATETIME       string  `json:"operatetime"  xorm:"'OPERATETIME'"`             // 最后操作时间
	ISVALID           int32   `json:"isvalid"  xorm:"'ISVALID'"`                     // 是否有效 - 0:无效 1:有效
	AREAUSERID        int64   `json:"areauserid"  xorm:"'AREAUSERID'"`               // 所属机构id
	WRSTANDARDCODE    string  `json:"wrstandardcode"  xorm:"'WRSTANDARDCODE'"`       // 品类代码
	WRSTANDARDNAME    string  `json:"wrstandardname"  xorm:"'WRSTANDARDNAME'"`       // 品类名称
	UNITID            int32   `json:"unitid"  xorm:"'UNITID'"`                       // 现货商品单位id
	BRANDNAME         string  `json:"brandname"  xorm:"'BRANDNAME'"`                 // 品牌名称
	GMUNITID          int32   `json:"gmunitid"  xorm:"'GMUNITID'"`                   // 品类单位id
	DELIVERYGOODSID   int32   `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"`     // 现货商品id
	DELIVERYGOODSCODE string  `json:"deliverygoodscode"  xorm:"'DELIVERYGOODSCODE'"` // 现货商品代码
	DELIVERYGOODSNAME string  `json:"deliverygoodsname"  xorm:"'DELIVERYGOODSNAME'"` // 现货商品名称

	OPERATORNAME  string `json:"operatorname"`  // 操作人名称
	ENUMDICNAME   string `json:"enumdicname"`   // 现货商品单位名称
	GBENUMDICNAME string `json:"gbenumdicname"` // 品类单位名称
	CURRENCYNAME  string `json:"currencyname"`  // 币种名称
}

func (r *Ermcp3SpotGoodsPrice) calc() {
	if r.OPERATESRC == 1 {
		r.OPERATORNAME = mtpcache.GetSystemmangerLoginCode(r.OPERATEID)
	} else {
		r.OPERATORNAME = mtpcache.GetLoginCodeByLoginId(r.OPERATEID)
	}
	r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.UNITID)
	r.GBENUMDICNAME = mtpcache.GetEnumDicitemName(r.GMUNITID)
	r.CURRENCYNAME = mtpcache.GetCurrencyName(r.CURRENCYID)
}

func (r *Ermcp3SpotGoodsPrice) buildSql() string {
	var sqlId utils.SQLVal = "SELECT t.WRSTANDARDID," +
		"       t.SPOTGOODSBRANDID," +
		"       t.CURRENCYID," +
		"       t.SPOTGOODSPRICE," +
		"       t.TRADEDATE," +
		"       t.OPERATESRC," +
		"       t.OPERATEID," +
		"       to_char(t.OPERATETIME, 'yyyy-mm-dd hh24:mi:ss') OPERATETIME," +
		"       t.ISVALID," +
		"       w.areauserid," +
		"       w.wrstandardcode," +
		"       w.wrstandardname," +
		"       w.unitid gmunitid," +
		"       gb.dgfactoryitemvalue brandname," +
		"       g.deliverygoodsid," +
		"       g.deliverygoodscode," +
		"       g.deliverygoodsname," +
		"       g.goodsunitid unitid" +
		"  FROM ERMCP_SPOTGOODSPRICE t" +
		"  left join wrstandard w" +
		"    on t.wrstandardid = w.wrstandardid" +
		"  left join dgfactoryitem gb" +
		"    on t.spotgoodsbrandid = gb.dgfactoryitemid" +
		"  left join deliverygoods g" +
		"    on t.deliverygoodsid = g.deliverygoodsid" +
		" WHERE 1 = 1"
	sqlId.And("w.areauserid", r.AREAUSERID)
	return sqlId.String()
}

// GetDataEx 获取现货市价
func (r *Ermcp3SpotGoodsPrice) GetDataEx() (interface{}, error) {
	sData := make([]Ermcp3SpotGoodsPrice, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	if err == nil {
		for i := range sData {
			sData[i].calc()
		}
	}
	return sData, err
}

// Ermcp3SpotGoodsPriceLog 现货市价操作日志
type Ermcp3SpotGoodsPriceLog struct {
	LOGID             int64   `json:"logid"  xorm:"'LOGID'"`                         // 日志id
	WRSTANDARDID      int64   `json:"wrstandardid"  xorm:"'WRSTANDARDID'"`           // 现货品类ID(通用则为0)
	SPOTGOODSBRANDID  int32   `json:"spotgoodsbrandid"  xorm:"'SPOTGOODSBRANDID'"`   // 现货品牌ID(通用则为0, 不为0则须先有品类ID)
	CURRENCYID        int64   `json:"currencyid"  xorm:"'CURRENCYID'"`               // 报价货币ID
	SPOTGOODSPRICE    float64 `json:"spotgoodsprice"  xorm:"'SPOTGOODSPRICE'"`       // 现货价格
	TRADEDATE         string  `json:"tradedate"  xorm:"'TRADEDATE'"`                 // 交易日(yyyyMMdd)
	OPERATESRC        int32   `json:"operatesrc"  xorm:"'OPERATESRC'"`               // 最后操作来源 - 1:管理端 2:终端
	OPERATEID         int64   `json:"operateid"  xorm:"'OPERATEID'"`                 // 最后操作人
	OPERATETIME       string  `json:"operatetime"  xorm:"'OPERATETIME'"`             // 最后操作时间
	AREAUSERID        int64   `json:"areauserid"  xorm:"'AREAUSERID'"`               // 所属机构id
	WRSTANDARDCODE    string  `json:"wrstandardcode"  xorm:"'WRSTANDARDCODE'"`       // 品类代码
	WRSTANDARDNAME    string  `json:"wrstandardname"  xorm:"'WRSTANDARDNAME'"`       // 品类名称
	UNITID            int32   `json:"unitid"  xorm:"'UNITID'"`                       // 现货商品单位id
	BRANDNAME         string  `json:"brandname"  xorm:"'BRANDNAME'"`                 // 品牌名称
	GMUNITID          int32   `json:"gmunitid"  xorm:"'GMUNITID'"`                   // 品类单位id
	DELIVERYGOODSID   int32   `json:"deliverygoodsid"  xorm:"'DELIVERYGOODSID'"`     // 现货商品id
	DELIVERYGOODSCODE string  `json:"deliverygoodscode"  xorm:"'DELIVERYGOODSCODE'"` // 现货商品代码
	DELIVERYGOODSNAME string  `json:"deliverygoodsname"  xorm:"'DELIVERYGOODSNAME'"` // 现货商品名称

	OPERATORNAME  string `json:"operatorname"`  // 操作人名称
	ENUMDICNAME   string `json:"enumdicname"`   // 现货商品单位名称
	GBENUMDICNAME string `json:"gbenumdicname"` // 品类单位名称
}

func (r *Ermcp3SpotGoodsPriceLog) calc() {
	if r.OPERATESRC == 1 {
		r.OPERATORNAME = mtpcache.GetSystemmangerLoginCode(r.OPERATEID)
	} else {
		r.OPERATORNAME = mtpcache.GetLoginCodeByLoginId(r.OPERATEID)
	}
	r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.UNITID)
	r.GBENUMDICNAME = mtpcache.GetEnumDicitemName(r.GMUNITID)
}

func (r *Ermcp3SpotGoodsPriceLog) buildSql() string {
	var sqlId utils.SQLVal = "SELECT t.WRSTANDARDID," +
		"       t.SPOTGOODSBRANDID," +
		"       t.CURRENCYID," +
		"       t.SPOTGOODSPRICE," +
		"       t.TRADEDATE," +
		"       t.OPERATESRC," +
		"       t.OPERATEID," +
		"       to_char(t.OPERATETIME, 'yyyy-mm-dd hh24:mi:ss') OPERATETIME," +
		"       t.LOGID," +
		"       w.areauserid," +
		"       w.wrstandardcode," +
		"       w.wrstandardname," +
		"       w.unitid gmunitid," +
		"       gb.dgfactoryitemvalue brandname," +
		"       g.goodsunitid unitid ," +
		"       g.deliverygoodsid," +
		"       g.deliverygoodscode," +
		"       g.deliverygoodsname" +
		"  FROM ERMCP_SPOTGOODSPRICELOG t" +
		"  left join wrstandard w" +
		"    on t.wrstandardid = w.wrstandardid" +
		"  left join dgfactoryitem gb" +
		"    on t.spotgoodsbrandid = gb.dgfactoryitemid" +
		"  left join deliverygoods g" +
		"    on t.deliverygoodsid = g.deliverygoodsid" +
		" WHERE 1 = 1"
	sqlId.And("w.areauserid", r.AREAUSERID)
	sqlId.And("t.deliverygoodsid", r.DELIVERYGOODSID)
	sqlId.AndEx("t.SPOTGOODSBRANDID", r.SPOTGOODSBRANDID, r.SPOTGOODSBRANDID > 0)
	sqlId.AndEx("t.wrstandardid", r.WRSTANDARDID, r.WRSTANDARDID > 0)
	return sqlId.String()
}

// GetDataEx 获取现货市价信息日志
func (r *Ermcp3SpotGoodsPriceLog) GetDataEx() (interface{}, error) {
	sData := make([]Ermcp3SpotGoodsPriceLog, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	if err == nil {
		for i := range sData {
			sData[i].calc()
		}
	}
	return sData, err
}

// Ermcp3HedgePlan 套保计划表结构
type Ermcp3HedgePlan struct {
	Areauserid        int64   `json:"areauserid"  xorm:"'Areauserid'"`               // 用户ID
	Hedgeplanid       string  `json:"hedgeplanid"  xorm:"'Hedgeplanid'"`             // 套保计划ID(601+Unix秒时间戳(10位)+xxxxxx)
	Hedgeplanno       string  `json:"hedgeplanno"  xorm:"'Hedgeplanno'"`             // 套保计划编号(名称)
	Contracttype      int     `json:"contracttype"  xorm:"'Contracttype'"`           // 计划类型 - 1:采购 -1:销售
	Deliverygoodsid   int     `json:"deliverygoodsid"  xorm:"'Deliverygoodsid'"`     // 现货品种ID
	Deliverygoodsname string  `json:"deliverygoodsname"  xorm:"'Deliverygoodsname'"` // 现货品种名称
	DELIVERYGOODSCODE string  `json:"deliverygoodscode"  xorm:"'DELIVERYGOODSCODE'"` // 现货品种代码
	Producttype       int     `json:"producttype"  xorm:"'Producttype'"`             // 产品类型 - 1:标准仓单 2:等标 3:非标
	Spotgoodsdesc     string  `json:"spotgoodsdesc"  xorm:"'Spotgoodsdesc'"`         // 商品型号
	Planqty           float64 `json:"planqty"  xorm:"'Planqty'"`                     // 计划数量
	Convertfactor     float64 `json:"convertfactor"  xorm:"'Convertfactor'"`         // 标仓系数
	Plantime          string  `json:"plantime"  xorm:"'Plantime'"`                   // 计划时间
	Hedgeplanstatus   int     `json:"hedgeplanstatus"  xorm:"'Hedgeplanstatus'"`     // 套保计划状态 -  0:未提交 1:待审核 2:执行中 3:正常完结 4:审核拒绝 5:异常完结 6:已撤回
	Remark            string  `json:"remark"  xorm:"'Remark'"`                       // 备注
	CREATETIME        string  `json:"createtime"  xorm:"'CREATETIME'"`               // 创建时间
	UPDATETIME        string  `json:"updatetime"  xorm:"'UPDATETIME'"`               // 更新时间
	AUDITTIME         string  `json:"audittime"  xorm:"'AUDITTIME'"`                 // 审核时间
	UNITID            int32   `json:"unitid"  xorm:"'UNITID'"`                       // 单位id(现货商品)
	ENUMDICNAME       string  `json:"enumdicname"`                                   // 单位名称(现货商品)
	WRSTANDARDID      int32   `json:"wrstandardid"  xorm:"'WRSTANDARDID'"`           // 品类id
	WRSTANDARDCODE    string  `json:"wrstandardcode"  xorm:"'WRSTANDARDCODE'"`       // 品类代码
	WRSTANDARDNAME    string  `json:"wrstandardname"  xorm:"'WRSTANDARDNAME'"`       // 品类名称
	ACCOUNTID         int64   `json:"accountid"  xorm:"'ACCOUNTID'"`                 // 资金账号
	TAACCOUNTNAME     string  `json:"taaccountname"  xorm:"'TAACCOUNTNAME'"`         // 资金账号名称
	TRADEUSERID       int64   `json:"tradeuserid"  xorm:"'TRADEUSERID'"`             // 交易用户id
	CURRENCYID        int32   `json:"currencyid"  xorm:"'CURRENCYID'"`               // 币种id
	WRUNITID          int32   `json:"wrunitid"  xorm:"'WRUNITID'"`                   // 品类单位id

	WRUNITIDNAME  string `json:"wrunitidame"`   // 品类单位名称
	TRADEUSERNAME string `json:"tradeusername"` // 交易用户名称
	CURRENCYNAME  string `json:"currencyname"`  // 币种名称

	UserType int32 `json:"-"` // 过滤条件, 用户类型
}

func (r *Ermcp3HedgePlan) calc() {
	r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.UNITID)
	r.TRADEUSERNAME = mtpcache.GetUserNameByUserId(r.TRADEUSERID)
	r.CURRENCYNAME = mtpcache.GetCurrencyName(r.CURRENCYID)
	if r.WRUNITID > 0 {
		r.WRUNITIDNAME = mtpcache.GetEnumDicitemName(r.WRUNITID)
	}
}

func (r *Ermcp3HedgePlan) buildSql(status string) string {
	str := "select to_char(t.Hedgeplanid) Hedgeplanid," +
		"       t.Hedgeplanno," +
		"       t.Contracttype," +
		"       t.Deliverygoodsid," +
		"       g.Deliverygoodsname," +
		"       g.deliverygoodscode," +
		"       g.goodsunitid unitid," +
		"       t.Producttype," +
		"       t.Spotgoodsdesc," +
		"       t.Planqty," +
		"       t.Convertfactor," +
		"       to_char(t.Plantime, 'yyyy-mm-dd hh24:mi:ss') Plantime," +
		"       to_char(t.createtime, 'yyyy-mm-dd hh24:mi:ss') createtime," +
		"       to_char(t.updatetime, 'yyyy-mm-dd hh24:mi:ss') updatetime," +
		"       to_char(t.audittime, 'yyyy-mm-dd hh24:mi:ss') audittime," +
		"       t.Hedgeplanstatus," +
		"       t.Remark," +
		"       t.wrstandardid," +
		"       w.wrstandardcode," +
		"       w.wrstandardname," +
		"       w.unitid wrunitid," +
		"       t.accountid," +
		"       t.tradeuserid," +
		"       t.currencyid," +
		"       ta.accountname taaccountname" +
		"  from ermcp_hedgeplan t" +
		"  left join deliverygoods g" +
		"    on t.deliverygoodsid = g.deliverygoodsid" +
		"  left join wrstandard w on t.wrstandardid=w.wrstandardid" +
		"  left join taaccount ta on t.accountid=ta.accountid" +
		" where t.hedgeplanstatus in (%v)"

	if r.UserType == 0 {
		// 终端没传值, 则自己去找
		userId := mtpcache.GetAreaUserId(r.Areauserid, 0)
		if userId == r.Areauserid {
			r.UserType = 2
		} else {
			r.UserType = 7
		}
	}

	if r.UserType == 2 {
		str += "   and t.areauserid = %v"
	} else if r.UserType == 7 {
		// 企业成员用tradeuserid匹配
		str += "   and t.tradeuserid = %v"
	} else {
		str += "   and t.areauserid = %v"
	}

	if status == "2" {
		// 执行中状态，按审核时间倒序
		str += " order by t.audittime desc"
	} else {
		str += " order by t.updatetime desc"
	}

	return fmt.Sprintf(str, status, r.Areauserid)
}

// GetData 从数据库中查询套保计划数据
func (r *Ermcp3HedgePlan) GetData(status string) ([]Ermcp3HedgePlan, error) {
	e := db.GetEngine()
	sData := make([]Ermcp3HedgePlan, 0)
	if err := e.SQL(r.buildSql(status)).Find(&sData); err != nil {
		logger.GetLogger().Errorf("query hedgeplan:%v", err)
		return sData, err
	}
	for i := range sData {
		sData[i].calc()
	}

	return sData, nil
}

// Ermcp3GoodsGroup 商品组
type Ermcp3GoodsGroup struct {
	GOODSGROUPID       int32   `json:"goodsgroupid"  xorm:"'GOODSGROUPID'"`             // 商品组ID(自增ID)
	GOODSGROUPNAME     string  `json:"goodsgroupname"  xorm:"'GOODSGROUPNAME'"`         // 商品组名称
	GOODSGROUPSTATUS   int32   `json:"goodsgroupstatus"  xorm:"'GOODSGROUPSTATUS'"`     // 商品组状态 - 1:正常 2:注销
	MARKETID           int32   `json:"marketid"  xorm:"'MARKETID'"`                     // 所属市场ID
	CREATETIME         string  `json:"createtime"  xorm:"'CREATETIME'"`                 // 创建时间
	CREATORID          int32   `json:"creatorid"  xorm:"'CREATORID'"`                   // 创建人
	MODIFYTIME         string  `json:"modifytime"  xorm:"'MODIFYTIME'"`                 // 修改时间
	MODIFIERID         int32   `json:"modifierid"  xorm:"'MODIFIERID'"`                 // 修改人
	QUOTESOURCEGROUPID int64   `json:"quotesourcegroupid"  xorm:"'QUOTESOURCEGROUPID'"` // 所属行情源分组ID[参考行情市场用\通道交易]
	OUTERGROUPCODE     string  `json:"outergroupcode"  xorm:"'OUTERGROUPCODE'"`         // 外部商品组代码[通道交易]
	CANSHORT           int32   `json:"canshort"  xorm:"'CANSHORT'"`                     // 是否允许做空[通道交易] - 0:不能做空 1:可以做空
	EXEXCHANGEID       int64   `json:"exexchangeid"  xorm:"'EXEXCHANGEID'"`             // 外部交易所ID[通道交易]
	CURRENCYID         int32   `json:"currencyid"  xorm:"'CURRENCYID'"`                 // 报价货币ID
	GOODUNITID         int32   `json:"goodunitid"  xorm:"'GOODUNITID'"`                 // 报价单位ID
	AGREEUNIT          float32 `json:"agreeunit"  xorm:"'AGREEUNIT'"`                   // 合约单位
	DECIMALPLACE       int32   `json:"decimalplace"  xorm:"'DECIMALPLACE'"`             // 报价小数位
	QUOTEMINUNIT       int32   `json:"quoteminunit"  xorm:"'QUOTEMINUNIT'"`             // 行情最小变动单位 [整数，报价小数位一起使用]
	INNERDEALMODE      int32   `json:"innerdealmode"  xorm:"'INNERDEALMODE'"`           // 内部成交方式[通道交易] - 1:净头寸 2:开平 3:平今
	OUTERDEALMODE      int32   `json:"outerdealmode"  xorm:"'OUTERDEALMODE'"`           // 外部成交方式[通道交易]- 1:净头寸 2:开平 3:平今
	SYNCGOODSQTY       int32   `json:"syncgoodsqty"  xorm:"'SYNCGOODSQTY'"`             // 同步合约数[通道交易-投资管理用] - 0表示不限
	CLOSEPRICEMODE     int32   `json:"closepricemode"  xorm:"'CLOSEPRICEMODE'"`         // 强平价格方式 - 1:市价 2:最新价 3:涨跌停（未实现）
	GROUPCATEGROYID    int32   `json:"groupcategroyid"  xorm:"'GROUPCATEGROYID'"`       // 品种分类ID
	EXEXCHANGECODE     string  `json:"exexchangecode"  xorm:"'EXEXCHANGECODE'"`         // 交易所代码
	EXEXCHANGENAME     string  `json:"exexchangename"  xorm:"'EXEXCHANGENAME'"`         // 交易所名称
	EXCHANGEFULLNAME   string  `json:"exchangefullname"  xorm:"'EXCHANGEFULLNAME'"`     // 交易所全称

	ENUMDICNAME string `json:"enumdicname"`                                     // 单位名称
	AreaUserId  int64  `json:"areauserid" form:"areauserid" binding:"required"` // 所属机构id(套保品是有areauserid的,当要排除已配置商品组时需要areauserid过滤)
	ExcludeCfg  int32  `json:"excludecfg" form:"excludecfg"`                    // 排除套保品已配置期货分类下的商品组(但显示已配置商品组) 1-排除
}

func (r *Ermcp3GoodsGroup) calc() {
	r.ENUMDICNAME = mtpcache.GetEnumDicitemName(r.GOODUNITID)
}

func (r *Ermcp3GoodsGroup) buildSql() string {
	var sqlId utils.SQLVal = "SELECT t.GOODSGROUPID," +
		"       t.GOODSGROUPNAME," +
		"       t.GOODSGROUPSTATUS," +
		"       t.MARKETID," +
		"       to_char(t.CREATETIME, 'yyyy-mm-dd hh24:mi:ss') CREATETIME," +
		"       t.CREATORID," +
		"       to_char(t.MODIFYTIME, 'yyyy-mm-dd hh24:mi:ss') MODIFYTIME," +
		"       t.MODIFIERID," +
		"       t.QUOTESOURCEGROUPID," +
		"       t.OUTERGROUPCODE," +
		"       t.CANSHORT," +
		"       t.EXEXCHANGEID," +
		"       t.CURRENCYID," +
		"       t.GOODUNITID," +
		"       t.AGREEUNIT," +
		"       t.DECIMALPLACE," +
		"       t.QUOTEMINUNIT," +
		"       t.INNERDEALMODE," +
		"       t.OUTERDEALMODE," +
		"       t.SYNCGOODSQTY," +
		"       t.CLOSEPRICEMODE," +
		"       t.GROUPCATEGROYID," +
		"       e.exexchangecode," +
		"       e.exexchangename," +
		"       e.exchangefullname" +
		"  FROM GOODSGROUP t" +
		"  LEFT JOIN market m" +
		"    on t.marketid = m.marketid" +
		"  LEFT JOIN externalexchange e on t.exexchangeid=e.autoid" +
		" WHERE 1 = 1" +
		"   and m.trademode = 15"
	if r.ExcludeCfg == 1 {
		str := "select t.goodsgroupid" +
			"  from ERMS_MiddleGoods t" +
			" where t.isvalid=1 and t.areauserid = %v" +
			" union all " +
			"select goodsgroupid" +
			"  from goodsgroup t" +
			" where t.groupcategroyid not in" +
			"       (select distinct g.groupcategroyid" +
			"          from erms_middlegoods t" +
			"          left join goodsgroup g" +
			"            on t.goodsgroupid = g.goodsgroupid" +
			"         where t.isvalid=1 and t.areauserid = %v)"
		str = fmt.Sprintf(str, r.AreaUserId, r.AreaUserId)
		sqlId.Join(fmt.Sprintf(" and t.goodsgroupid in(%v)", str))
	}
	return sqlId.String()
}

// GetData
func (r *Ermcp3GoodsGroup) GetData() ([]Ermcp3GoodsGroup, error) {
	sData := make([]Ermcp3GoodsGroup, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	for i := range sData {
		sData[i].calc()
	}
	return sData, err
}

// GetDataEx 商品组信息
func (r *Ermcp3GoodsGroup) GetDataEx() (interface{}, error) {
	return r.GetData()
}

// Ermcp3RootUserAccount 顶级用户
type Ermcp3RootUserAccount struct {
	ROOTUSERID       int64  `json:"rootuserid"  xorm:"ROOTUSERID"`             // 根用户ID
	CANRECOMMEND     int32  `json:"canrecommend"  xorm:"CANRECOMMEND"`         // 是否可推荐 - 0:不可 1;可
	USERID           int64  `json:"userid"  xorm:"USERID"`                     // 用户ID
	USERTYPE         int32  `json:"usertype"  xorm:"USERTYPE"`                 // 账户类型 -  1:交易所 2:机构 3:会员子机构 4:经纪人 5:投资者 6:客户 7:企业成员(云平台)
	MODIFYSTATUS     int32  `json:"modifystatus"  xorm:"MODIFYSTATUS"`         // 变更状态 1 未变更 2 变更中 3 变更待审核 4 变更待复核(投资者)
	ACCOUNTNAME      string `json:"accountname"  xorm:"ACCOUNTNAME"`           // 账户名称(机构名称)
	PARENTUSERID     int64  `json:"parentuserid"  xorm:"PARENTUSERID"`         // 所属机构ID
	BROKER           int64  `json:"broker"  xorm:"BROKER"`                     // 所属经纪人ID
	SUBAREALEVELPATH string `json:"subarealevelpath"  xorm:"SUBAREALEVELPATH"` // 子机构层级路径(逗号分隔,首尾加逗号)
	REFEREEUSERID    int64  `json:"refereeuserid"  xorm:"REFEREEUSERID"`       // 推荐人ID
	MEMBERUSERID     int64  `json:"memberuserid"  xorm:"MEMBERUSERID"`         // 所属会员ID
	ACCOUNTSTATUS    int32  `json:"accountstatus"  xorm:"ACCOUNTSTATUS"`       // 账户状态 -  1:待激活 2:待审核 3:待复审 4:正常 5:审核拒绝 6:停用(注销) 7:注销(删除)
	RECKONACCOUNTID  int64  `json:"reckonaccountid"  xorm:"RECKONACCOUNTID"`   // 默认结算资金账号ID(机构分润使用) 作废
	CREATETIME       string `json:"createtime"  xorm:"CREATETIME"`             // 创建时间
	CREATORID        int64  `json:"creatorid"  xorm:"CREATORID"`               // 创建人
	AUDITTIME        string `json:"audittime"  xorm:"AUDITTIME"`               // 审核时间
	AUDITUSERID      int64  `json:"audituserid"  xorm:"AUDITUSERID"`           // 审核人
	AUDITREMARK      string `json:"auditremark"  xorm:"AUDITREMARK"`           // 审核备注
	CANCELTIME       string `json:"canceltime"  xorm:"CANCELTIME"`             // 销户时间
	CANCELUSERID     int64  `json:"canceluserid"  xorm:"CANCELUSERID"`         // 销户人
	MODIFYTIME       string `json:"modifytime"  xorm:"MODIFYTIME"`             // 修改时间
	MODIFIERID       int64  `json:"modifierid"  xorm:"MODIFIERID"`             // 修改人
	MODIFYREMARK     string `json:"modifyremark"  xorm:"MODIFYREMARK"`         // 变更备注
	MAXINVESTORNUM   int64  `json:"maxinvestornum"  xorm:"MAXINVESTORNUM"`     // 最大用户数(经纪会员下投资者个数)
	HASAUTH          int32  `json:"hasauth"  xorm:"HASAUTH"`                   // 是否已实名认证 - 0:未认证 1:已认证 2:已提交(待审核) 3:已拒绝
	REFERCOUNT       int32  `json:"refercount"  xorm:"REFERCOUNT"`             // 推荐总人数
	REFERNUM         string `json:"refernum"  xorm:"REFERNUM"`                 // 推荐码
	ISANONYMOUS      int32  `json:"isanonymous"  xorm:"ISANONYMOUS"`           // 是否匿名下单 - 0:否 1:是
	PARENTTOPUSER    string `json:"parenttopuser"  xorm:"PARENTTOPUSER"`       // 上级顶级机构 [092=0,1时，默认为1， 092=2时若自已为顶级，则填入自己，自己不为顶级，填入ParentUserID的"ParentTopUser"]
	SUBACCOUNTLEVEL  int32  `json:"subaccountlevel"  xorm:"SUBACCOUNTLEVEL"`   // 子账户层数
	APPLYSRC         int32  `json:"applysrc"  xorm:"APPLYSRC"`                 // 申请来源 - 1:管理端 2:终端
	AUDITSRC         int32  `json:"auditsrc"  xorm:"AUDITSRC"`                 // 审核来源 - 1:管理端 2:终端
}

func (r *Ermcp3RootUserAccount) calc() {

}

func (r *Ermcp3RootUserAccount) buildSql() string {
	var sqlId utils.SQLVal = "SELECT t.ROOTUSERID," +
		"       t.CANRECOMMEND," +
		"       t.USERID," +
		"       t.USERTYPE," +
		"       t.MODIFYSTATUS," +
		"       t.ACCOUNTNAME," +
		"       t.PARENTUSERID," +
		"       t.BROKER," +
		"       t.SUBAREALEVELPATH," +
		"       t.REFEREEUSERID," +
		"       t.MEMBERUSERID," +
		"       t.ACCOUNTSTATUS," +
		"       t.RECKONACCOUNTID," +
		"       to_char(t.CREATETIME, 'yyyy-mm-dd hh24:mi:ss') CREATETIME," +
		"       t.CREATORID," +
		"       to_char(t.AUDITTIME, 'yyyy-mm-dd hh24:mi:ss') AUDITTIME," +
		"       t.AUDITUSERID," +
		"       t.AUDITREMARK," +
		"       to_char(t.CANCELTIME, 'yyyy-mm-dd hh24:mi:ss') CANCELTIME," +
		"       t.CANCELUSERID," +
		"       to_char(t.MODIFYTIME, 'yyyy-mm-dd hh24:mi:ss') MODIFYTIME," +
		"       t.MODIFIERID," +
		"       t.MODIFYREMARK," +
		"       t.MAXINVESTORNUM," +
		"       t.HASAUTH," +
		"       t.REFERCOUNT," +
		"       t.REFERNUM," +
		"       t.ISANONYMOUS," +
		"       t.PARENTTOPUSER," +
		"       t.SUBACCOUNTLEVEL," +
		"       t.APPLYSRC," +
		"       t.AUDITSRC" +
		"  FROM USERACCOUNT t" +
		" WHERE 1 = 1 and t.userid in(select rootuserid from useraccount where userid=%v)"
	sqlId.FormatParam(r.USERID)
	return sqlId.String()
}

// GetDataEx 获取顶级用户
func (r *Ermcp3RootUserAccount) GetDataEx() (interface{}, error) {
	sData := make([]Ermcp3RootUserAccount, 0)
	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
	for i := range sData {
		sData[i].calc()
	}
	return sData, err
}
