Bläddra i källkod

增加接口:查询敞口现货头寸明细

zou.yingbin 4 år sedan
förälder
incheckning
528ed43167
5 ändrade filer med 286 tillägg och 13 borttagningar
  1. 76 11
      controllers/ermcp/qryExposure.go
  2. 60 0
      global/app/ginUtils.go
  3. 1 0
      go.sum
  4. 147 2
      models/ermcpExposure.go
  5. 2 0
      routers/router.go

+ 76 - 11
controllers/ermcp/qryExposure.go

@@ -56,13 +56,13 @@ func QueryRealtimeExposure(c *gin.Context) {
 //敞口现货明细请求
 type ExposureDetailReq struct {
 	AreaUserId    uint32 `form:"areaUserId" json:"areaUserId"`       // 所属机构ID
-	MiddleGoodsId int32 `form:"middleGoodsId" json:"middlegoodsid"` // 套保商品
+	MiddleGoodsId int32  `form:"middleGoodsId" json:"middlegoodsid"` // 套保商品
 }
 
 //敞口现货明细响应
 type ExposureDetailRsp models.ErmcpExposureDetailModel
 
-// QueryUserInfo 查询敞口现货明细
+// 查询敞口现货明细
 // @Summary 查询敞口现货明细
 // @Produce json
 // @Security ApiKeyAuth
@@ -75,15 +75,15 @@ type ExposureDetailRsp models.ErmcpExposureDetailModel
 func QueryExposureDetail(c *gin.Context) {
 	appG := app.Gin{C: c}
 	var req ExposureDetailReq
-	if err := c.ShouldBind(&req); err != nil{
+	if err := c.ShouldBind(&req); err != nil {
 		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
 		return
 	}
 
 	var m = models.ErmcpExposureDetailModel{Areauserid: req.AreaUserId, MiddlegoodsId: req.MiddleGoodsId}
-	if d, err := m.GetData(); err == nil{
+	if d, err := m.GetData(); err == nil {
 		appG.Response(http.StatusOK, e.SUCCESS, d)
-	}else {
+	} else {
 		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
 	}
 }
@@ -98,7 +98,7 @@ type ExposureSpotReq struct {
 // 敞口/现货头寸应答
 type ExposureSpotRsp models.AreaSpotModel
 
-// QueryUserInfo 查询敞口现货头寸
+// QueryExposureSpot 查询敞口现货头寸
 // @Summary 查询敞口现货头寸(敞口/现货头寸)
 // @Produce json
 // @Security ApiKeyAuth
@@ -107,17 +107,82 @@ type ExposureSpotRsp models.AreaSpotModel
 // @Failure 500 {object} app.Response
 // @Router /Ermcp/QueryExposureSpot [get]
 // @Tags 企业风险管理(app)
-func QueryExposureSpot(c *gin.Context)  {
+func QueryExposureSpot(c *gin.Context) {
 	appG := app.Gin{C: c}
 	var req ExposureSpotReq
-	if err := c.ShouldBind(&req); err != nil{
+	if err := c.ShouldBind(&req); err != nil {
 		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
 		return
 	}
 	var m = models.AreaSpotModel{AREAUSERID: req.AreaUserID}
-	if d, err := m.GetData(); err == nil{
+	if d, err := m.GetData(); err == nil {
+		appG.Response(http.StatusOK, e.SUCCESS, d)
+	} else {
+		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
+	}
+}
+
+////////////////////////////////////////////
+
+// 敞口/现货头寸/现货明细请求
+type ExposureSpotDetailReq struct {
+	AreaUserID   int `form:"areaUserId" binding:"required"`   //所属机构ID
+	WrstandardId int32 `form:"wrstandardId" binding:"required"` // 现货商品ID
+}
+
+// 敞口/现货头寸/现货明细应答
+type ExposureSpotDetailRsp models.ErmcpAreaSpotDetailModel
+
+// @Summary 查询敞口现货头寸明细(敞口/现货头寸/现货明细)
+// @Produce json
+// @Security ApiKeyAuth
+// @Param areaUserId query int true "所属机构ID"
+// @Param wrstandardId query int true "现货品种ID"
+// @Success 200 {array} ExposureSpotDetailRsp
+// @Failure 500 {object} app.Response
+// @Router /Ermcp/QueryExposureSpotDetail [get]
+// @Tags 企业风险管理(app)
+func QueryExposureSpotDetail(c *gin.Context) {
+	appG := app.GinUtils{Gin:app.Gin{C: c}}
+	var req ExposureSpotDetailReq
+	appG.DoBindReq(&req)
+	m := models.ErmcpAreaSpotDetailModel{UserId: req.AreaUserID, WrstandardId: req.WrstandardId}
+	// m必须传指针类型,否则无法进行类型转换
+	appG.DoGetData(&m)
+}
+
+///////////////////////////////////////////
+
+// 敞口/历史敞口请求
+type HisExposureReq struct {
+	AreaUserID int32 `form:"areaUserId" binding:"required"` //所属机构ID
+	LastNum    int32 `form:"lastNum" binding:"required"`    //查询最近多少条记录
+}
+
+// 敞口/历史敞口应答
+type HisExposureRsp models.ErmcpHisExposure
+
+// QueryUserInfo 查询历史敞口
+// @Summary 查询历史敞口(菜单:敞口/历史敞口)
+// @Produce json
+// @Security ApiKeyAuth
+// @Param areaUserId query int true "所属机构ID"
+// @Param lastNum query int true "最近多少条记录, -1:为查全部"
+// @Success 200 {array} HisExposureRsp
+// @Failure 500 {object} app.Response
+// @Router /Ermcp/QueryHisExposure [get]
+// @Tags 企业风险管理(app)
+func QueryHisExposure(c *gin.Context) {
+	appG := app.Gin{C: c}
+	var req HisExposureReq
+	if err := c.ShouldBind(&req); err != nil {
+		appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
+		return
+	}
+	var m = models.ErmcpHisExposure{AREAUSERID: req.AreaUserID, LastNum: req.LastNum}
+	if d, err := m.GetData(); err == nil {
 		appG.Response(http.StatusOK, e.SUCCESS, d)
-	}else{
+	} else {
 		appG.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
 	}
-}
+}

+ 60 - 0
global/app/ginUtils.go

@@ -0,0 +1,60 @@
+/**
+* @Author: zou.yingbin
+* @Create  : 2021/1/25 9:42
+* @Modify  : 2021/1/25 9:42
+ */
+
+package app
+
+import (
+	"mtp2_if/global/e"
+	"mtp2_if/logger"
+	"net/http"
+)
+
+// 获取数据接口
+type IGetData interface {
+	GetData()([]interface{}, error)
+}
+
+// 数据处理接口
+type ICalc interface {
+	Calc()
+}
+
+// 封装绑定和数据获取处理
+type GinUtils struct {
+	Gin
+	err error
+}
+
+// 处理参数绑定
+func (r *GinUtils) DoBindReq(req interface{}) {
+	if r.err = r.C.ShouldBind(req); r.err != nil{
+		r.Gin.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
+	}
+}
+
+// 处理数据获取, 参数obj为models结构体
+func (r *GinUtils) DoGetData(obj interface{}) {
+	// 如果在参数绑定阶段有错误, 则不执行数据获取
+	if r.err != nil{
+		return
+	}
+	if v, ok := obj.(IGetData); ok{
+		if d, err := v.GetData(); err == nil{
+			// 执行数据处理
+			for i := range d {
+				if val, ok := d[i].(ICalc); ok{
+					val.Calc()
+				}else{
+					break
+				}
+			}
+			r.Gin.Response(http.StatusOK, e.SUCCESS, d)
+		}else{
+			logger.GetLogger().Errorf("query fail, %v", err)
+			r.Gin.Response(http.StatusBadRequest, e.ERROR_QUERY_FAIL, nil)
+		}
+	}
+}

+ 1 - 0
go.sum

@@ -310,6 +310,7 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd h1:GGJVjV8waZKRHrgwvtH66z9ZGVurTD1MT0n1Bb+q4aM=
 golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/image v0.0.0-20180628062038-cc896f830ced/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=

+ 147 - 2
models/ermcpExposure.go

@@ -227,7 +227,7 @@ func (r *AreaSpotModel) buildSql() string {
 		"       t.SELLPLANQTY," +
 		"       t.SELLPRICEDQTY," +
 		"       t.TOTALSPOTQTY," +
-		"       to_char(t.UPDATETIME,'yyyy-mm-dd hh24:mi:ss') UPDATETIME"+
+		"       to_char(t.UPDATETIME,'yyyy-mm-dd hh24:mi:ss') UPDATETIME" +
 		"  from ermcp_areaspot t" +
 		"  left join wrstandard w" +
 		"    on t.wrstandardid = w.wrstandardid" +
@@ -239,7 +239,7 @@ func (r *AreaSpotModel) buildSql() string {
 func (r *AreaSpotModel) GetData() ([]AreaSpotModel, error) {
 	e := db.GetEngine()
 	sData := make([]AreaSpotModel, 0)
-	if err := e.SQL(r.buildSql()).Find(&sData); err != nil{
+	if err := e.SQL(r.buildSql()).Find(&sData); err != nil {
 		return nil, err
 	}
 	for i := range sData {
@@ -247,3 +247,148 @@ func (r *AreaSpotModel) GetData() ([]AreaSpotModel, error) {
 	}
 	return sData, nil
 }
+
+// 现货头寸-现货明细
+type ErmcpAreaSpotDetailModel 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-销售
+	Wrstandardname string  `json:"wrstandardname"  xorm:"'wrstandardname'"` // 现货商品名称
+	Wrstandardcode string  `json:"wrstandardcode"  xorm:"'wrstandardcode'"` // 现货商品代码
+	Qty            float64 `json:"qty"  xorm:"'qty'"`                       // 数量
+	Strtime        string  `json:"strtime"  xorm:"'strtime'"`               // 时间
+	Enumdicname    string  `json:"enumdicname"`                             // 现货商品单位名称
+	Recordname     string  `json:"recordname"`                              // 类型名称
+	Unitid         int32   `json:"-"  xorm:"'UNITID'"`                      // 单位ID
+	UserId         int     `json:"-"`                                       // 所属用户ID
+	WrstandardId   int32   `json:"-"`                                       // 现货商品ID
+}
+
+// 组建查询SQL
+func (r *ErmcpAreaSpotDetailModel) buildSql() string {
+	str := "select to_char(t.hedgeplanid) relatedid," +
+		"       t.hedgeplanno relatedno," +
+		"       1 as logType," +
+		"       t.contracttype," +
+		"       w.wrstandardname," +
+		"       w.wrstandardcode," +
+		"       t.planqty qty," +
+		"        w.unitid," +
+		"       to_char(t.createtime, 'yyyy-mm-dd hh:mi:ss') strtime" +
+		"  from ermcp_hedgeplan t" +
+		"  left join wrstandard w" +
+		"    on t.wrstandardid = w.wrstandardid" +
+		" where t.hedgeplanstatus in (2, 3, 5)" +
+		"   and t.areauserid = %v and t.wrstandardid = %v" +
+		" union all " +
+		"select to_char(t.spotcontractid)," +
+		"       t.contractno," +
+		"       1 as logType," +
+		"       t.contracttype," +
+		"       w.wrstandardname," +
+		"       w.wrstandardcode," +
+		"       t.qty," +
+		"       w.unitid," +
+		"       to_char(t.createtime, 'yyyy-mm-dd hh:mi:ss') strtime" +
+		"  from ermcp_spotcontract t" +
+		"  left join wrstandard w" +
+		"    on t.wrstandardid = w.wrstandardid" +
+		" where t.contractstatus in (2, 3, 5)" +
+		"   and t.userid = %v and t.wrstandardid = %v"
+
+	return fmt.Sprintf(str, r.UserId, r.WrstandardId, r.UserId, r.WrstandardId)
+}
+
+// 现货头寸-明细:数据加工处理
+func (r *ErmcpAreaSpotDetailModel) Calc() {
+	var logTypeName, contractTypeName string
+	if r.LogType == 1 {
+		logTypeName = "计划"
+	} else {
+		logTypeName = "合同"
+	}
+
+	if r.Contracttype == 1 {
+		contractTypeName = "采购"
+	} else {
+		contractTypeName = "销售"
+	}
+
+	r.Recordname = contractTypeName + logTypeName
+	r.Enumdicname = mtpcache.GetEnumDicitemName(r.Unitid)
+}
+
+// 现货头寸-明细:从数据库中查询敞口现货头寸明细数据
+func (r *ErmcpAreaSpotDetailModel) GetData() ([]interface{}, error) {
+	sData := make([]ErmcpAreaSpotDetailModel, 0)
+	err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
+	iDatas := make([]interface{}, 0)
+	for i := range sData {
+		// 注意要传指针类型(&sData[i]),因为要接口转换
+		iDatas = append(iDatas, &sData[i])
+	}
+	return iDatas, err
+}
+
+///////////////////////////
+
+/*历史/历史敞口*/
+type ErmcpHisExposure struct {
+	RECKONDATE         string  `json:"reckondate"  xorm:"'RECKONDATE'"`                 // 日照时期(yyyyMMdd)
+	MIDDLEGOODSID      int32   `json:"middlegoodsid"  xorm:"'MIDDLEGOODSID'"`           // 套保品种ID
+	AREAUSERID         int32   `json:"areauserid"  xorm:"'AREAUSERID'"`                 // 所属机构
+	TOTALSPOTQTY       float64 `json:"totalspotqty"  xorm:"'TOTALSPOTQTY'"`             // 现货头寸总量
+	TOTALFUTUREQTY     float64 `json:"totalfutureqty"  xorm:"'TOTALFUTUREQTY'"`         // 期货头寸总量
+	TOTALEXPOSURE      float64 `json:"totalexposure"  xorm:"'TOTALEXPOSURE'"`           // 总敞口
+	TOTALHEDGERATIO    float64 `json:"totalhedgeratio"  xorm:"'TOTALHEDGERATIO'"`       // 敞口比例
+	TOTALNEEDHEDGEQTY  float64 `json:"totalneedhedgeqty"  xorm:"'TOTALNEEDHEDGEQTY'"`   // 应套保总量
+	NEEDHEDGEEXPOSOURE float64 `json:"needhedgeexposourE"  xorm:"'NEEDHEDGEEXPOSOURE'"` // 应套保敞口
+	NEEDHEDGERATIO     float64 `json:"needhedgeratio"  xorm:"'NEEDHEDGERATIO'"`         // 应套保敞口比例
+	MIDDLEGOODSNAME    string  `json:"middlegoodsname"  xorm:"'MIDDLEGOODSNAME'"`       // 套保品种名称
+	MIDDLEGOODSCODE    string  `json:"middlegoodscode"  xorm:"'MIDDLEGOODSCODE'"`       // 套保品种代码
+	LastNum            int32   `json:"-"`                                               // 查询条数
+}
+
+// 历史分品种嵌套结构
+type ErmcpHisExposureS struct {
+	MIDDLEGOODSID   int32              `json:"middlegoodsid"`   // 套保品种ID
+	MIDDLEGOODSNAME string             `json:"middlegoodsname"` // 套保品种名称
+	Data            []ErmcpHisExposure `json:"data"`            // 历史敞口
+}
+
+func (r *ErmcpHisExposure) buildSql() string {
+	str := "select *" +
+		"  from (select t.RECKONDATE," +
+		"               t.MIDDLEGOODSID," +
+		"               t.AREAUSERID," +
+		"               t.TOTALSPOTQTY," +
+		"               t.TOTALFUTUREQTY," +
+		"               t.TOTALEXPOSURE," +
+		"               t.TOTALHEDGERATIO," +
+		"               t.TOTALNEEDHEDGEQTY," +
+		"               t.NEEDHEDGEEXPOSOURE," +
+		"               t.NEEDHEDGERATIO," +
+		"               g.MIDDLEGOODSNAME," +
+		"               g.MIDDLEGOODSCODE" +
+		"          from Reckon_ERMCP_AreaExposure t" +
+		"          left join erms_middlegoods g" +
+		"            on t.middlegoodsid = g.middlegoodsid" +
+		"         where t.areauserid = %v" +
+		"         order by t.middlegoodsid, t.reckondate desc) a" +
+		" where rownum <= %v"
+	if r.LastNum <= 0 {
+		r.LastNum = 100000 //限制最多查10W条
+	}
+	return fmt.Sprintf(str, r.AREAUSERID, r.LastNum)
+}
+
+// 获取历史敞口
+func (r *ErmcpHisExposure) GetData() ([]ErmcpHisExposure, error) {
+	e := db.GetEngine()
+	sData := make([]ErmcpHisExposure, 0)
+	if err := e.SQL(r.buildSql()).Find(&sData); err != nil {
+		return nil, err
+	}
+	return sData, nil
+}

+ 2 - 0
routers/router.go

@@ -321,6 +321,8 @@ func InitRouter() *gin.Engine {
 		ermcpR.GET("/QueryRealtimeExposure", ermcp.QueryRealtimeExposure)
 		ermcpR.GET("/QueryExposureDetail", ermcp.QueryExposureDetail)
 		ermcpR.GET("/QueryExposureSpot", ermcp.QueryExposureSpot)
+		ermcpR.GET("/QueryExposureSpotDetail", ermcp.QueryExposureSpotDetail)
+		ermcpR.GET("/QueryHisExposure", ermcp.QueryHisExposure)
 	}
 
 	return r