ermcpExposure.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. /**
  2. * @Author: zou.yingbin
  3. * @Create : 2021/1/18 9:26
  4. * @Modify : 2021/1/18 9:26
  5. */
  6. package models
  7. import (
  8. "fmt"
  9. "github.com/golang/protobuf/proto"
  10. "mtp2_if/db"
  11. "mtp2_if/mtpcache"
  12. "mtp2_if/pb"
  13. "mtp2_if/rediscli"
  14. )
  15. //实时敞口
  16. type ErmcpRealExposureModel struct {
  17. MiddleGoodsID uint32 // 套保品种
  18. AreaUserID uint32 // 所属机构
  19. OriBuyPlanQty float64 // 期初采购计划数量
  20. OriBuyPricedQty float64 // 期初采购合同已定价数量
  21. OriSellPlanQty float64 // 期初销售计划数量
  22. OriSellPricedQty float64 // 期初销售合同已定价数量
  23. OriBuyFutureQty uint64 // 期初买入期货数量
  24. OriSellFutureQty uint64 // 期初卖出期货数量
  25. BuyPlanQty float64 // 采购计划数量
  26. BuyPricedQty float64 // 采购合同已定价数量
  27. SellPlanQty float64 // 销售计划数量
  28. SellPricedQty float64 // 销售合同已定价数量
  29. BuyFutureQty float64 // 买入期货数量
  30. SellFutureQty float64 // 卖出期货数量
  31. TotalSpotQty float64 // 现货数量
  32. TotalFutureQty float64 // 期货数量
  33. TotalExposure float64 // 总敞口
  34. TotalHedgeRatio float64 // 敞口比例
  35. TotalNeedHedgeQty float64 // 期货应套保量
  36. NeedHedgeExposoure float64 // 应套保敞口
  37. NeedHedgeRatio float64 // 应套保敞口比例
  38. //************以下需计算或非redis数据************//
  39. MiddleGoodsName string // 套保品种名称
  40. MiddleGoodsCode string // 套保品种代码
  41. MiddleGoodsHedgeRatio float64 // 应套保比例
  42. OriTotalSpotQty float64 // 期初现货数量=(期初销售计划数量-期初销售合同已定价数量)-(期初采购计划数量-期初采购合同已定价数量)
  43. OriTotalFutuQty uint64 // 期初期货数量=期初买入期货数量-期初卖出期货数量
  44. }
  45. // 计算相关字段
  46. func (r *ErmcpRealExposureModel) calc() {
  47. r.OriTotalSpotQty = (r.OriSellPlanQty - r.OriSellPricedQty) - (r.OriBuyPlanQty - r.OriBuyPricedQty)
  48. r.OriTotalFutuQty = r.OriBuyFutureQty - r.OriSellFutureQty
  49. }
  50. func (r *ErmcpRealExposureModel) ParseFromProto(v *pb.ErmcpAreaExposure) {
  51. r.MiddleGoodsID = *v.MiddleGoodsID
  52. r.AreaUserID = *v.AreaUserID
  53. r.OriBuyPlanQty = *v.OriBuyPlanQty
  54. r.OriBuyPricedQty = *v.OriBuyPricedQty
  55. r.OriSellPlanQty = *v.OriSellPlanQty
  56. r.OriSellPricedQty = *v.OriSellPricedQty
  57. r.OriBuyFutureQty = *v.OriBuyFutureQty
  58. r.OriSellFutureQty = *v.OriSellFutureQty
  59. r.BuyPlanQty = *v.BuyPlanQty
  60. r.BuyPricedQty = *v.BuyPricedQty
  61. r.SellPlanQty = *v.SellPlanQty
  62. r.SellPricedQty = *v.SellPricedQty
  63. r.BuyFutureQty = *v.BuyFutureQty
  64. r.SellFutureQty = *v.SellFutureQty
  65. r.TotalSpotQty = *v.TotalSpotQty
  66. r.TotalFutureQty = *v.TotalFutureQty
  67. r.TotalExposure = *v.TotalExposure
  68. r.TotalHedgeRatio = *v.TotalHedgeRatio
  69. r.TotalNeedHedgeQty = *v.TotalNeedHedgeQty
  70. r.NeedHedgeExposoure = *v.NeedHedgeExposoure
  71. r.NeedHedgeRatio = *v.NeedHedgeRatio
  72. // 执行相关计算
  73. r.calc()
  74. }
  75. // 实时敞口数据: Redis数据 + 套保品种信息表
  76. func (r *ErmcpRealExposureModel) GetData() ([]ErmcpRealExposureModel, error) {
  77. // 获取关联的套路商品
  78. if sGoods, err := mtpcache.GetMiddleGoodsByUserID(r.AreaUserID); err == nil {
  79. sData := make([]ErmcpRealExposureModel, 0)
  80. // 从Redis获取数据
  81. for i := range sGoods {
  82. key := fmt.Sprintf("ErmcpAreaExposure:%d_%d", sGoods[i].AREAUSERID, sGoods[i].MIDDLEGOODSID)
  83. if ret, err := rediscli.GetRedisClient().Get(key).Result(); err == nil {
  84. if len(ret) > 0 {
  85. var data pb.ErmcpAreaExposure
  86. if err := proto.Unmarshal([]byte(ret), &data); err == nil {
  87. var m ErmcpRealExposureModel
  88. m.ParseFromProto(&data)
  89. sData = append(sData, m)
  90. }
  91. }
  92. }
  93. }
  94. return sData, nil
  95. }
  96. return nil, nil
  97. }
  98. /*************敞口明细**************/
  99. //敞口明细结构
  100. type ErmcpExposureDetailModel struct {
  101. Createtime string `json:"createtime" xorm:"'createtime'"` // 时间
  102. Areauserid uint32 `json:"areauserid" xorm:"'areauserid'"` // 机构ID
  103. Logtype int32 `json:"logtype" xorm:"'logtype'"` // 类型 - 1:套保计划 2:现货合同
  104. Contracttype int32 `json:"contracttype" xorm:"'contracttype'"` // 现货合同类型 - 1:采购 -1:销售
  105. Wrstandardid int32 `json:"wrstandardid" xorm:"'wrstandardid'"` // 现货商品ID
  106. Qty float64 `json:"qty" xorm:"'qty'"` // 数量
  107. RelateNo string `json:"relateNo" xorm:"'relateNo'"` // 现货合同/套保计划编号
  108. Middlegoodsname string `json:"middlegoodsname" xorm:"'middlegoodsname'"` // 套保商品名称
  109. Middlegoodscode string `json:"middlegoodscode" xorm:"'middlegoodscode'"` // 套保商品代码
  110. MiddlegoodsId int32 `json:"middlegoodsId" xorm:"'middlegoodsId'"` // 套保商品id
  111. Unitid int32 `json:"-" xorm:"'unitid'"` // 现货商品单位ID
  112. Wrstandardname string `json:"wrstandardname" xorm:"'wrstandardname'"` // 现货商品名称
  113. Wrstandardcode string `json:"wrstandardcode" xorm:"'wrstandardcode'"` // 现货商品代码
  114. Enumdicname string `json:"enumdicname" xorm:"'enumdicname'"` // 现货商品单位名称
  115. ChangeQty float64 `json:"changeQty" xorm:"'changeQty'"` // 套保变动量
  116. Convertfactor float64 `json:"convertfactor" xorm:"'convertfactor'"` // 标仓系数
  117. Convertratio float64 `json:"convertratio" xorm:"'convertratio'"` // 套保系数
  118. }
  119. func (r *ErmcpExposureDetailModel) buildSql() string {
  120. str := "with tmp as" +
  121. " (select 2 as LogType," +
  122. " s.spotcontractid as relatedid," +
  123. " s.contractno as relateNo" +
  124. " from ermcp_spotcontract s" +
  125. " union all" +
  126. " select 1, t.hedgeplanid as relateid, t.hedgeplanno as relateNo" +
  127. " from ermcp_hedgeplan t)" +
  128. "select to_char(t.createtime, 'yyyy-mm-dd hh24:mi:ss') createtime," +
  129. " t.middlegoodsid," +
  130. " t.areauserid," +
  131. " t.logtype," +
  132. " t.contracttype," +
  133. " wc.wrstandardid," +
  134. " t.qty," +
  135. " t.convertfactor," +
  136. " t.convertratio," +
  137. " t.qty * t.convertfactor * t.convertratio as changeQty," +
  138. " tmp.relateNo," +
  139. " m.middlegoodsname," +
  140. " m.middlegoodscode," +
  141. " w.unitid," +
  142. " w.wrstandardname," +
  143. " w.wrstandardcode," +
  144. " e.enumdicname" +
  145. " from ermcp_spotexposurelog t" +
  146. " left join erms2_wrsconvertdetail wc" +
  147. " on t.wrstandardid = wc.wrstandardid" +
  148. " and t.middlegoodsid = wc.middlegoodsid" +
  149. " left join erms_middlegoods m" +
  150. " on t.middlegoodsid = m.middlegoodsid" +
  151. " left join wrstandard w" +
  152. " on t.wrstandardid = w.wrstandardid" +
  153. " left join enumdicitem e" +
  154. " on w.unitid = e.enumitemname" +
  155. " and e.enumdiccode = 'goodsunit'" +
  156. " left join tmp" +
  157. " on t.logtype = tmp.LogType" +
  158. " and t.relatedid = tmp.relatedid" +
  159. " where t.middlegoodsid=%v and t.areauserid=%v"
  160. return fmt.Sprintf(str, r.MiddlegoodsId, r.Areauserid)
  161. }
  162. // 查询敞口现货明细
  163. func (r *ErmcpExposureDetailModel) GetData() ([]ErmcpExposureDetailModel, error) {
  164. e := db.GetEngine()
  165. s := e.SQL(r.buildSql())
  166. sData := make([]ErmcpExposureDetailModel, 0)
  167. if err := s.Find(&sData); err != nil {
  168. return nil, err
  169. }
  170. return sData, nil
  171. }
  172. /// 现货头寸
  173. // 现货头寸数据
  174. type AreaSpotModel struct {
  175. WRSTANDARDID int32 `json:"wrstandardid" xorm:"'WRSTANDARDID'"` // 现货商品ID
  176. WRSTANDARDNAME string `json:"wrstandardname" xorm:"'WRSTANDARDNAME'"` // 现货品种
  177. WRSTANDARDCODE string `json:"wrstandardcode" xorm:"'WRSTANDARDCODE'"` // 现货品种代码
  178. AREAUSERID int32 `json:"areauserid" xorm:"'AREAUSERID'"` // 所属机构
  179. ORIBUYPLANQTY float64 `json:"-" xorm:"'ORIBUYPLANQTY'"` // 期初采购计划数量
  180. ORIBUYPRICEDQTY float64 `json:"-" xorm:"'ORIBUYPRICEDQTY'"` // 期初采购合同已定价数量
  181. ORISELLPLANQTY float64 `json:"-" xorm:"'ORISELLPLANQTY'"` // 期初销售计划数量
  182. ORISELLPRICEDQTY float64 `json:"-" xorm:"'ORISELLPRICEDQTY'"` // 期初销售合同已定价数量
  183. BUYPLANQTY float64 `json:"-" xorm:"'BUYPLANQTY'"` // 采购计划数量
  184. BUYPRICEDQTY float64 `json:"-" xorm:"'BUYPRICEDQTY'"` // 采购合同已定价数量
  185. SELLPLANQTY float64 `json:"-" xorm:"'SELLPLANQTY'"` // 销售计划数量
  186. SELLPRICEDQTY float64 `json:"-" xorm:"'SELLPRICEDQTY'"` // 销售合同已定价数量
  187. TOTALSPOTQTY float64 `json:"totalspotqty" xorm:"'TOTALSPOTQTY'"` // 当前数量(现货头寸总量) = (销售计划数量 - 销售已定价数量) - (采购计划数量 - 采购已定价数量)
  188. OriToalSpotQty float64 `json:"oritoalspotqty" xorm:"'OriToalSpotQty'"` // 昨日数量
  189. IncreaseQty float64 `json:"increaseqty" xorm:"'IncreaseQty'"` // 增加数量=销售计划数量+采购已定价数量
  190. DecreaseQty float64 `json:"decreaseqty" xorm:"'DecreaseQty'"` // 减少数量=-(销售已定价数量+采购计划数量)
  191. UPDATETIME string `json:"updatetime" xorm:"'UPDATETIME'"` // 更新时间
  192. }
  193. // 进行相关字段的值计算
  194. func (r *AreaSpotModel) calc() {
  195. r.IncreaseQty = r.SELLPLANQTY + r.BUYPRICEDQTY
  196. r.DecreaseQty = (r.SELLPRICEDQTY + r.BUYPLANQTY) * -1
  197. r.OriToalSpotQty = (r.ORISELLPLANQTY - r.ORISELLPRICEDQTY) - (r.ORIBUYPLANQTY - r.ORIBUYPRICEDQTY)
  198. }
  199. func (r *AreaSpotModel) buildSql() string {
  200. str := "select t.WRSTANDARDID," +
  201. " w.WRSTANDARDNAME," +
  202. " w.WRSTANDARDCODE," +
  203. " t.AREAUSERID," +
  204. " t.ORIBUYPLANQTY," +
  205. " t.ORIBUYPRICEDQTY," +
  206. " t.ORISELLPLANQTY," +
  207. " t.ORISELLPRICEDQTY," +
  208. " t.BUYPLANQTY," +
  209. " t.BUYPRICEDQTY," +
  210. " t.SELLPLANQTY," +
  211. " t.SELLPRICEDQTY," +
  212. " t.TOTALSPOTQTY," +
  213. " to_char(t.UPDATETIME,'yyyy-mm-dd hh24:mi:ss') UPDATETIME" +
  214. " from ermcp_areaspot t" +
  215. " left join wrstandard w" +
  216. " on t.wrstandardid = w.wrstandardid" +
  217. " where t.areauserid=%v"
  218. return fmt.Sprintf(str, r.AREAUSERID)
  219. }
  220. // 从数据库中查询现货头寸
  221. func (r *AreaSpotModel) GetData() ([]AreaSpotModel, error) {
  222. e := db.GetEngine()
  223. sData := make([]AreaSpotModel, 0)
  224. if err := e.SQL(r.buildSql()).Find(&sData); err != nil {
  225. return nil, err
  226. }
  227. for i := range sData {
  228. sData[i].calc()
  229. }
  230. return sData, nil
  231. }
  232. // 现货头寸-现货明细
  233. type ErmcpAreaSpotDetailModel struct {
  234. Relatedid string `json:"relatedid" xorm:"'relatedid'"` // 套保计划ID/现货合同ID
  235. Relatedno string `json:"relatedno" xorm:"'relatedno'"` // 编号
  236. LogType int32 `json:"logtype" xorm:"'logType'"` // 记录类型 1-套保 2-现货合同
  237. Contracttype int32 `json:"contracttype" xorm:"'contracttype'"` // 合同类型 1-采购 -1-销售
  238. Wrstandardname string `json:"wrstandardname" xorm:"'wrstandardname'"` // 现货商品名称
  239. Wrstandardcode string `json:"wrstandardcode" xorm:"'wrstandardcode'"` // 现货商品代码
  240. Qty float64 `json:"qty" xorm:"'qty'"` // 数量
  241. Strtime string `json:"strtime" xorm:"'strtime'"` // 时间
  242. Enumdicname string `json:"enumdicname"` // 现货商品单位名称
  243. Recordname string `json:"recordname"` // 类型名称
  244. Unitid int32 `json:"-" xorm:"'UNITID'"` // 单位ID
  245. UserId int `json:"-"` // 所属用户ID
  246. WrstandardId int32 `json:"-"` // 现货商品ID
  247. }
  248. // 组建查询SQL
  249. func (r *ErmcpAreaSpotDetailModel) buildSql() string {
  250. str := "select to_char(t.hedgeplanid) relatedid," +
  251. " t.hedgeplanno relatedno," +
  252. " 1 as logType," +
  253. " t.contracttype," +
  254. " w.wrstandardname," +
  255. " w.wrstandardcode," +
  256. " t.planqty qty," +
  257. " w.unitid," +
  258. " to_char(t.createtime, 'yyyy-mm-dd hh:mi:ss') strtime" +
  259. " from ermcp_hedgeplan t" +
  260. " left join wrstandard w" +
  261. " on t.wrstandardid = w.wrstandardid" +
  262. " where t.hedgeplanstatus in (2, 3, 5)" +
  263. " and t.areauserid = %v and t.wrstandardid = %v" +
  264. " union all " +
  265. "select to_char(t.spotcontractid)," +
  266. " t.contractno," +
  267. " 1 as logType," +
  268. " t.contracttype," +
  269. " w.wrstandardname," +
  270. " w.wrstandardcode," +
  271. " t.qty," +
  272. " w.unitid," +
  273. " to_char(t.createtime, 'yyyy-mm-dd hh:mi:ss') strtime" +
  274. " from ermcp_spotcontract t" +
  275. " left join wrstandard w" +
  276. " on t.wrstandardid = w.wrstandardid" +
  277. " where t.contractstatus in (2, 3, 5)" +
  278. " and t.userid = %v and t.wrstandardid = %v"
  279. return fmt.Sprintf(str, r.UserId, r.WrstandardId, r.UserId, r.WrstandardId)
  280. }
  281. // 现货头寸-明细:数据加工处理
  282. func (r *ErmcpAreaSpotDetailModel) Calc() {
  283. var logTypeName, contractTypeName string
  284. if r.LogType == 1 {
  285. logTypeName = "计划"
  286. } else {
  287. logTypeName = "合同"
  288. }
  289. if r.Contracttype == 1 {
  290. contractTypeName = "采购"
  291. } else {
  292. contractTypeName = "销售"
  293. }
  294. r.Recordname = contractTypeName + logTypeName
  295. r.Enumdicname = mtpcache.GetEnumDicitemName(r.Unitid)
  296. }
  297. // 现货头寸-明细:从数据库中查询敞口现货头寸明细数据
  298. func (r *ErmcpAreaSpotDetailModel) GetData() ([]interface{}, error) {
  299. sData := make([]ErmcpAreaSpotDetailModel, 0)
  300. err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
  301. iDatas := make([]interface{}, 0)
  302. for i := range sData {
  303. // 注意要传指针类型(&sData[i]),因为要接口转换
  304. iDatas = append(iDatas, &sData[i])
  305. }
  306. return iDatas, err
  307. }
  308. ///////////////////////////
  309. /*历史/历史敞口*/
  310. type ErmcpHisExposure struct {
  311. RECKONDATE string `json:"reckondate" xorm:"'RECKONDATE'"` // 日照时期(yyyyMMdd)
  312. MIDDLEGOODSID int32 `json:"middlegoodsid" xorm:"'MIDDLEGOODSID'"` // 套保品种ID
  313. AREAUSERID int32 `json:"areauserid" xorm:"'AREAUSERID'"` // 所属机构
  314. TOTALSPOTQTY float64 `json:"totalspotqty" xorm:"'TOTALSPOTQTY'"` // 现货头寸总量
  315. TOTALFUTUREQTY float64 `json:"totalfutureqty" xorm:"'TOTALFUTUREQTY'"` // 期货头寸总量
  316. TOTALEXPOSURE float64 `json:"totalexposure" xorm:"'TOTALEXPOSURE'"` // 总敞口
  317. TOTALHEDGERATIO float64 `json:"totalhedgeratio" xorm:"'TOTALHEDGERATIO'"` // 敞口比例
  318. TOTALNEEDHEDGEQTY float64 `json:"totalneedhedgeqty" xorm:"'TOTALNEEDHEDGEQTY'"` // 应套保总量
  319. NEEDHEDGEEXPOSOURE float64 `json:"needhedgeexposourE" xorm:"'NEEDHEDGEEXPOSOURE'"` // 应套保敞口
  320. NEEDHEDGERATIO float64 `json:"needhedgeratio" xorm:"'NEEDHEDGERATIO'"` // 应套保敞口比例
  321. MIDDLEGOODSNAME string `json:"middlegoodsname" xorm:"'MIDDLEGOODSNAME'"` // 套保品种名称
  322. MIDDLEGOODSCODE string `json:"middlegoodscode" xorm:"'MIDDLEGOODSCODE'"` // 套保品种代码
  323. LastNum int32 `json:"-"` // 查询条数
  324. }
  325. // 历史分品种嵌套结构
  326. type ErmcpHisExposureS struct {
  327. MIDDLEGOODSID int32 `json:"middlegoodsid"` // 套保品种ID
  328. MIDDLEGOODSNAME string `json:"middlegoodsname"` // 套保品种名称
  329. Data []ErmcpHisExposure `json:"data"` // 历史敞口
  330. }
  331. func (r *ErmcpHisExposure) buildSql() string {
  332. str := "select *" +
  333. " from (select t.RECKONDATE," +
  334. " t.MIDDLEGOODSID," +
  335. " t.AREAUSERID," +
  336. " t.TOTALSPOTQTY," +
  337. " t.TOTALFUTUREQTY," +
  338. " t.TOTALEXPOSURE," +
  339. " t.TOTALHEDGERATIO," +
  340. " t.TOTALNEEDHEDGEQTY," +
  341. " t.NEEDHEDGEEXPOSOURE," +
  342. " t.NEEDHEDGERATIO," +
  343. " g.MIDDLEGOODSNAME," +
  344. " g.MIDDLEGOODSCODE" +
  345. " from Reckon_ERMCP_AreaExposure t" +
  346. " left join erms_middlegoods g" +
  347. " on t.middlegoodsid = g.middlegoodsid" +
  348. " where t.areauserid = %v" +
  349. " order by t.middlegoodsid, t.reckondate desc) a" +
  350. " where rownum <= %v"
  351. if r.LastNum <= 0 {
  352. r.LastNum = 100000 //限制最多查10W条
  353. }
  354. return fmt.Sprintf(str, r.AREAUSERID, r.LastNum)
  355. }
  356. // 获取历史敞口
  357. func (r *ErmcpHisExposure) GetData() ([]ErmcpHisExposure, error) {
  358. e := db.GetEngine()
  359. sData := make([]ErmcpHisExposure, 0)
  360. if err := e.SQL(r.buildSql()).Find(&sData); err != nil {
  361. return nil, err
  362. }
  363. return sData, nil
  364. }
  365. // 套保品种关联交易商品
  366. type ErmcpTradeGoods struct {
  367. MIDDLEGOODSID int32 `json:"middlegoodsid" xorm:"'MIDDLEGOODSID'"` // 套保商品id
  368. MIDDLEGOODSNAME string `json:"middlegoodsname" xorm:"'MIDDLEGOODSNAME'"` // 套保商品名称
  369. MIDDLEGOODSCODE string `json:"middlegoodscode" xorm:"'MIDDLEGOODSCODE'"` // 套保商品代码
  370. SRCGOODSGROUPID int32 `json:"srcgoodsgroupid" xorm:"'SRCGOODSGROUPID'"` // 源期货品种id
  371. DESTGOODSGROUPID int32 `json:"destgoodsgroupid" xorm:"'DESTGOODSGROUPID'"` // 目标期货品种id
  372. CONVERTRATIO float64 `json:"convertratio" xorm:"'CONVERTRATIO'"` // 折算系数
  373. GOODSID int32 `json:"goodsid" xorm:"pk 'GOODSID'"` // 商品id
  374. GOODSCODE string `json:"goodscode" xorm:"'GOODSCODE'"` // 商品代码
  375. GOODSNAME string `json:"goodsname" xorm:"'GOODSNAME'"` // 商品名称
  376. GOODSGROUPID int32 `json:"goodsgroupid" xorm:"'GOODSGROUPID'"` // 商品组id
  377. GOODSUNITID int32 `json:"goodsunitid" xorm:"'GOODSUNITID'"` // 套保品种单位id
  378. AREAUSERID int32 `json:"areauserid" xorm:"'AREAUSERID'"` // 所属机构id
  379. AGREEUNIT float64 `json:"agreeunit" xorm:"'agreeunit'"` // 合约单位
  380. }
  381. func (r *ErmcpTradeGoods) buildSq() string {
  382. sqlId := "SELECT t.MIDDLEGOODSID," +
  383. " t.MIDDLEGOODSNAME," +
  384. " t.MIDDLEGOODSCODE," +
  385. " t.GOODSUNITID," +
  386. " t.AREAUSERID," +
  387. " c.SRCGOODSGROUPID," +
  388. " c.DESTGOODSGROUPID," +
  389. " c.CONVERTRATIO," +
  390. " g.GOODSID," +
  391. " g.GOODSCODE," +
  392. " g.GOODSNAME," +
  393. " g.GOODSGROUPID," +
  394. " g.AGREEUNIT" +
  395. " FROM ERMS_MIDDLEGOODS t" +
  396. " INNER JOIN ERMCP_GGCONVERTCONFIG c" +
  397. " ON t.GOODSGROUPID = c.DESTGOODSGROUPID" +
  398. " INNER JOIN GOODS g" +
  399. " ON c.SRCGOODSGROUPID = g.GOODSGROUPID" +
  400. " WHERE t.AREAUSERID = %v" +
  401. " AND t.MIDDLEGOODSID = %v"
  402. sqlId = fmt.Sprintf(sqlId, r.AREAUSERID, r.MIDDLEGOODSID)
  403. return sqlId
  404. }
  405. // 获取套保商品关联的交易商品
  406. func (r *ErmcpTradeGoods) GetData() (map[int32]*ErmcpTradeGoods, error) {
  407. mData := make(map[int32]*ErmcpTradeGoods, 0)
  408. err := db.GetEngine().SQL(r.buildSq()).Find(&mData)
  409. return mData, err
  410. }
  411. // 获取用户头寸
  412. type ErmcpTradePosition struct {
  413. USERID int32 `json:"userid" xorm:"'userid'"` // 用户id
  414. GOODSID int32 `json:"goodsid" xorm:"'goodsid'"` // 商品id
  415. BUYPOSITIONQTY int64 `json:"buypositionqty" xorm:"'Buypositionqty'"` // 买期初持仓
  416. BUYCURPOSITIONQTY int64 `json:"buycurpositionqty" xorm:"'Buycurpositionqty'"` // 买当前持仓
  417. SELLPOSITIONQTY int64 `json:"sellpositionqty" xorm:"'Sellpositionqty'"` // 卖期初持仓
  418. SELLCURPOSITIONQTY int64 `json:"sellcurpositionqty" xorm:"'Sellcurpositionqty'"` // 卖当前持仓
  419. }
  420. func (r *ErmcpTradePosition) buildSql() string {
  421. sqlId := "select a.userid," +
  422. " a.goodsid," +
  423. " sum(a.buypositionqty) buypositionqty," +
  424. " sum(a.buycurpositionqty) buycurpositionqty," +
  425. " sum(a.sellpositionqty) sellpositionqty," +
  426. " sum(a.sellcurpositionqty) sellcurpositionqty" +
  427. " from (select ta.userid, t.*" +
  428. " from tradeposition t" +
  429. " inner join taaccount ta" +
  430. " on t.accountid = ta.accountid" +
  431. " where ta.userid = %v" +
  432. " ) a" +
  433. " group by a.userid, a.goodsid"
  434. sqlId = fmt.Sprintf(sqlId, r.USERID)
  435. return sqlId
  436. }
  437. // 获取用户持仓头寸
  438. func (r *ErmcpTradePosition) GetData() ([]ErmcpTradePosition, error) {
  439. sData := make([]ErmcpTradePosition, 0)
  440. err := db.GetEngine().SQL(r.buildSql()).Find(&sData)
  441. return sData, err
  442. }
  443. // 实时敞口\现货明细(头寸)
  444. type ErmcpExposurePostion struct {
  445. AREAUSERID int32 `json:"areauserid" xorm:"'AREAUSERID'"` // 所属机构id
  446. MIDDLEGOODSID int32 `json:"middlegoodsid" xorm:"'MIDDLEGOODSID'"` // 套保商品id
  447. GOODSID int32 `json:"goodsid" xorm:"'GOODSID'"` // 商品id
  448. GOODSCODE string `json:"goodscode" xorm:"'GOODSCODE'"` // 商品代码
  449. GOODSNAME string `json:"goodsname" xorm:"'GOODSNAME'"` // 商品名称
  450. YdQty int64 `json:"ydqty" xorm:"'YdQty'"` // 昨日持仓
  451. CurQty int64 `json:"curqty" xorm:"'CurQty'"` // 当前持仓
  452. DiffQty int64 `json:"diffqty" xorm:"'DiffQty'"` // 持仓变动量
  453. DiffHedgeQty float64 `json:"diffhedgeqty" xorm:"'DiffHedgeQty'"` // 套保品种变动量
  454. }
  455. // 获取敞口明细期货头寸
  456. func (r *ErmcpExposurePostion) GetDataEx() (interface{}, error) {
  457. // 查询交易商品
  458. mg := ErmcpTradeGoods{AREAUSERID: r.AREAUSERID, MIDDLEGOODSID: r.MIDDLEGOODSID}
  459. sGoods, err := mg.GetData()
  460. if err != nil || sGoods == nil || len(sGoods) == 0 {
  461. return nil, err
  462. }
  463. // 查询头寸
  464. mp := ErmcpTradePosition{USERID: r.AREAUSERID}
  465. sPostion, err1 := mp.GetData()
  466. if err1 != nil || sPostion == nil || len(sPostion) == 0 {
  467. return nil, err1
  468. }
  469. // 合并处理
  470. sData := make([]ErmcpExposurePostion, 0)
  471. for i := range sPostion {
  472. if val, ok := sGoods[sPostion[i].GOODSID]; ok {
  473. d := ErmcpExposurePostion{
  474. AREAUSERID: val.AREAUSERID,
  475. MIDDLEGOODSID: val.MIDDLEGOODSID,
  476. GOODSID: val.MIDDLEGOODSID,
  477. GOODSCODE: val.GOODSCODE,
  478. GOODSNAME: val.GOODSNAME,
  479. }
  480. //相关计算
  481. d.YdQty = sPostion[i].BUYPOSITIONQTY - sPostion[i].SELLPOSITIONQTY
  482. d.CurQty = sPostion[i].BUYCURPOSITIONQTY - sPostion[i].SELLCURPOSITIONQTY
  483. d.DiffQty = d.CurQty - d.YdQty
  484. d.DiffHedgeQty = float64(d.DiffQty) * float64(val.AGREEUNIT) * val.CONVERTRATIO
  485. sData = append(sData, d)
  486. }
  487. }
  488. return sData, nil
  489. }