erms3.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. package erms3
  2. import (
  3. "encoding/json"
  4. "math"
  5. "mtp2_if/db"
  6. "mtp2_if/global/app"
  7. "mtp2_if/global/e"
  8. "mtp2_if/logger"
  9. "mtp2_if/models"
  10. "net/http"
  11. "time"
  12. "github.com/gin-gonic/gin"
  13. )
  14. // RecordUtcCount UTC计数(毫秒)
  15. var RecordUtcCount int = 0
  16. // SecondCount 秒计数
  17. var SecondCount int = 0
  18. // SpotPriceOrder 定价明细
  19. type SpotPriceOrder struct {
  20. Price float64 `json:"price" binding:"required"` // 价格
  21. Qty float64 `json:"qty" binding:"required"` // 数量
  22. Amount float64 `json:"amount" binding:"required"` // 金额
  23. }
  24. // SpotPointOrder 点价明细
  25. type SpotPointOrder struct {
  26. GoodsID int32 `json:"goodsid" binding:"required"` // 商品ID
  27. GoodsName string `json:"goodsname"` // 商品名称
  28. Qty float64 `json:"qty" binding:"required"` // 数量
  29. Basic float64 `json:"basic" binding:"required"` // 基差
  30. StartDate string `json:"startdate" binding:"required"` // 点价开始日期
  31. EndDate string `json:"enddate" binding:"required"` // 点价结束日期
  32. }
  33. // SoptContractDetail 合同明细信息
  34. type SoptContractDetail struct {
  35. WrStandardID int64 `json:"wrstandardid" binding:"required"` // 交易标的ID
  36. WrStandardName string `json:"wrstandardname" binding:"required"` // 交易标的名称
  37. ProductType int32 `json:"producttype" binding:"required"` // 产品类型 1:标准仓单 2:等标 3:非标
  38. ProductTypeName string `json:"producttypename"` // 产品类型名称
  39. DeliveryGoodsID int32 `json:"deliverygoodsid" binding:"required"` // 现货品种ID
  40. DeliveryGoodsName string `json:"deliverygoodsname"` // 现货品种名称
  41. DeliveryGoodsDesc string `json:"deliverygoodsdesc"` // 现货品种说明
  42. WarehouseID int32 `json:"warehouseid" binding:"required"` // 仓库ID
  43. WarehouseName int32 `json:"warehousename"` // 仓库名称
  44. UnitName string `json:"unitname" binding:"required"` // 单位名称
  45. PointDesc string `json:"pointdesc"` // 点价描述
  46. SpotPriceOrderList []SpotPriceOrder `json:"spotPriceOrderList"` // 定价列表
  47. SpotPointOrderVoList []SpotPointOrder `json:"spotPointOrderVoList"` // 点价列表
  48. }
  49. // SoptContractDetailSum 合同明细信息汇总(组织JSON使用)
  50. type SoptContractDetailSum struct {
  51. WrStandardID int64 `json:"wrstandardid" binding:"required"` // 交易标的ID
  52. WrStandardName string `json:"wrstandardname" binding:"required"` // 交易标的名称
  53. ProductType int32 `json:"producttype" binding:"required"` // 产品类型 1:标准仓单 2:等标 3:非标
  54. ProductTypeName string `json:"producttypename"` // 产品类型名称
  55. DeliveryGoodsID int32 `json:"deliverygoodsid" binding:"required"` // 现货品种ID
  56. DeliveryGoodsName string `json:"deliverygoodsname"` // 现货品种名称
  57. DeliveryGoodsDesc string `json:"deliverygoodsdesc"` // 现货品种说明
  58. WarehouseID int32 `json:"warehouseid" binding:"required"` // 仓库ID
  59. WarehouseName int32 `json:"warehousename"` // 仓库名称
  60. UnitName string `json:"unitname" binding:"required"` // 单位名称
  61. PointDesc string `json:"pointdesc"` // 点价描述
  62. SpotPriceOrderList []SpotPriceOrder `json:"spotPriceOrderList"` // 定价列表
  63. SpotPointOrderVoList []SpotPointOrder `json:"spotPointOrderVoList"` // 点价列表
  64. TotalPriceOrderQty float64 `json:"totalPriceOrderQty"` // 定价总数量
  65. TotalPriceOrderPrice float64 `json:"totalPriceOrderPrice"` // 定价总价格
  66. TotalPriceOrderAmount float64 `json:"totalPriceOrderAmount"` // 定价总金额
  67. TotalPointOrderQty float64 `json:"totalPointOrderQty"` // 点价总数量
  68. TotalQty float64 `json:"totalQty"` // 总数量
  69. }
  70. // AddSpotContractApplyReq 新增现货合同申请请求
  71. type AddSpotContractApplyReq struct {
  72. ContractNo string `json:"contractno" binding:"required"` // 现货合同编号
  73. ContractType int32 `json:"contracttype" binding:"required"` // 现货合同类型 - 1:采购 -1:销售
  74. AreaUserID int32 `json:"areauserid" binding:"required"` // 所属机构
  75. AccountID int64 `json:"accountid" binding:"required"` // 资金账户ID
  76. CustomerUserID int32 `json:"customeruserid" binding:"required"` // 客户ID
  77. CustomerAccountID int64 `json:"customeraccountid" binding:"required"` // 客户资金账户ID
  78. SignDate time.Time `json:"signdate" binding:"required"` // 签订日期
  79. LastDate time.Time `json:"lastdate" binding:"required"` // 交货时间
  80. ContractAttachment string `json:"contractattachment"` // 合同附件
  81. OriMarginPayer int32 `json:"orimarginpayer" binding:"required"` // 初始保证金支付方 -1:买方 2:卖方
  82. OriMargin float64 `json:"orimargin" binding:"required"` // 初始保证金
  83. Remark string `json:"remark"` // 备注
  84. MarketID int32 `json:"marketid" binding:"required"` // 市场ID
  85. CreatorID int32 `json:"creatorid"` // 申请人
  86. Details []SoptContractDetail `json:"details" binding:"required"` // 明细
  87. }
  88. // AddSpotContractApplyRsp 新增现货合同申请响应
  89. type AddSpotContractApplyRsp struct {
  90. SpotContractID int64 `json:"spotcontractid" binging:"required"` // 现货合同ID(345+Unix秒时间戳(10位)+xxxxxx)
  91. ContractNo string `json:"contractno" binding:"required""` // 现货合同编号
  92. }
  93. // AddSpotContractApply 新增现货合同申请
  94. // @Summary 新增现货合同申请
  95. // @Produce json
  96. // @Security ApiKeyAuth
  97. // @Param contractno query string true "现货合同编号"
  98. // @Param contracttype query int true "现货合同类型, 1:采购 -1:销售"
  99. // @Param areauserid query int true "所属机构"
  100. // @Param accountid query int true "资金账户ID"
  101. // @Param customeruserid query int true "客户ID"
  102. // @Param customeraccountid query int true "客户资金账户ID"
  103. // @Param signdate query string true "签订日期, 格式:yyyy-MM-dd HH:mm:ss"
  104. // @Param lastdate query string true "交货时间, 格式:yyyy-MM-dd HH:mm:ss"
  105. // @Param contractattachment query string true "合同附件"
  106. // @Param orimarginpayer query int true "初始保证金支付方, 1:买方 2:卖方"
  107. // @Param orimargin query float true "初始保证金"
  108. // @Param remark query string true "备注"
  109. // @Param marketid query int true "市场ID"
  110. // @Param creatorid query int true "申请人"
  111. // @Param details query []SoptContractDetail true "明细"
  112. // @Success 200 {object} AddSpotContractApplyRsp
  113. // @Failure 500 {object} app.Response
  114. // @Router /Erms3/AddSpotContractApply [post]
  115. // @Tags 风险管理
  116. func AddSpotContractApply(c *gin.Context) {
  117. appG := app.Gin{C: c}
  118. // 获取请求参数
  119. var req AddSpotContractApplyReq
  120. err := appG.C.ShouldBindQuery(&req)
  121. if err != nil {
  122. logger.GetLogger().Errorf("AddSpotContractApply failed: %s", err.Error())
  123. appG.Response(http.StatusBadRequest, e.INVALID_PARAMS, nil)
  124. return
  125. }
  126. // 生成申请ID
  127. spotcontractid := GenSpotContractID()
  128. // 获取当前交易日
  129. tradedate, err := GetMarketTradeDate(int(req.MarketID))
  130. if err != nil {
  131. // 返回失败
  132. logger.GetLogger().Errorf("AddSpotContractApply get market trade date failed: %s", err.Error())
  133. appG.Response(http.StatusBadRequest, e.ERROR_OPERATION_FAILED, nil)
  134. return
  135. }
  136. // 根据明细,生成JSON信息
  137. detailjson, err := BuildDetailJSON(req.Details)
  138. if err != nil {
  139. // 返回失败
  140. logger.GetLogger().Errorf("AddSpotContractApply build detail json failed: %s", err.Error())
  141. appG.Response(http.StatusBadRequest, e.ERROR_OPERATION_FAILED, nil)
  142. return
  143. }
  144. // 组织sql,插入现货合同申请信息
  145. sql := `INSERT INTO ERMS3_SPOTCONTRACTAPPLY(SPOTCONTRACTID,
  146. TRADEDATE,
  147. CONTRACTNO,
  148. CONTRACTTYPE,
  149. AREAUSERID,
  150. ACCOUNTID,
  151. CUSTOMERUSERID,
  152. CUSTOMERACCOUNTID,
  153. SIGNDATE,
  154. LASTDATE,
  155. CONTRACTATTACHMENT,
  156. ORIMARGINPAYER,
  157. ORIMARGIN,
  158. REMARK,
  159. DETAILJSON,
  160. APPLYSTATUS,
  161. APPLYSRC,
  162. MARKETID,
  163. CREATORID,
  164. CREATETIME)
  165. VALUES(
  166. ?,
  167. ?,
  168. ?,
  169. ?,
  170. ?,
  171. ?,
  172. ?,
  173. ?,
  174. to_date(?, 'YYYY-MM-DD HH24:MI:SS'),
  175. to_date(?, 'YYYY-MM-DD HH24:MI:SS'),
  176. ?,
  177. ?,
  178. ?,
  179. ?,
  180. ?,
  181. 0,
  182. 2,
  183. ?,
  184. ?,
  185. sysdate)`
  186. engine := db.GetEngine()
  187. if _, err := engine.Exec(sql,
  188. spotcontractid,
  189. tradedate,
  190. req.ContractNo,
  191. req.ContractType,
  192. req.AreaUserID,
  193. req.AccountID,
  194. req.CustomerUserID,
  195. req.CustomerAccountID,
  196. req.SignDate,
  197. req.LastDate,
  198. req.ContractAttachment,
  199. req.OriMarginPayer,
  200. req.OriMargin,
  201. req.Remark,
  202. detailjson,
  203. req.MarketID,
  204. req.CreatorID); err != nil {
  205. // 插入失败
  206. logger.GetLogger().Errorf("AddSpotContractApply failed: %s", err.Error())
  207. appG.Response(http.StatusBadRequest, e.ERROR_OPERATION_FAILED, nil)
  208. return
  209. }
  210. rsp := AddSpotContractApplyRsp{
  211. SpotContractID: spotcontractid,
  212. ContractNo: req.ContractNo,
  213. }
  214. // 查询成功
  215. logger.GetLogger().Debugln("AddSpotContractApply successed: %v", rsp)
  216. appG.Response(http.StatusOK, e.SUCCESS, rsp)
  217. }
  218. // GenSpotContractID 生成现货合同ID
  219. func GenSpotContractID() int64 {
  220. // 获取当前时间
  221. cur := time.Now()
  222. // UnitNano获取的是纳秒,除以1000000获取毫秒级的时间戳
  223. timestamp := cur.UnixNano() / 1000000
  224. // 除以1000获取秒级的时间戳
  225. var curutc int = int(timestamp / 1000)
  226. if RecordUtcCount == curutc {
  227. SecondCount = SecondCount + 1
  228. } else {
  229. RecordUtcCount = curutc
  230. SecondCount = 1
  231. }
  232. var id int64 = int64(345)*int64(math.Pow(10, 16)) + int64(RecordUtcCount)*int64(math.Pow(10, 6)) + int64(SecondCount)
  233. return id
  234. }
  235. // GetMarketTradeDate 获取市场交易日
  236. func GetMarketTradeDate(marketid int) (string, error) {
  237. marketrun, err := models.GetMarketRun(marketid)
  238. if err != nil {
  239. return "", err
  240. }
  241. return marketrun.Tradedate, nil
  242. }
  243. // BuildDetailJSON 组件合同明细JSON
  244. func BuildDetailJSON(details []SoptContractDetail) (string, error) {
  245. detailsums := make([]SoptContractDetailSum, 0)
  246. for _, detail := range details {
  247. var totalpriceorderqty float64 = 0
  248. var totalpriceorderprice float64 = 0
  249. var totalpriceorderamount float64 = 0
  250. var totalpointorderqty float64 = 0
  251. var totalqty float64 = 0
  252. for _, spotpriceorder := range detail.SpotPriceOrderList {
  253. totalpriceorderqty = totalpriceorderqty + spotpriceorder.Qty
  254. totalpriceorderprice = totalpriceorderprice + spotpriceorder.Price
  255. totalpriceorderamount = totalpriceorderamount + spotpriceorder.Amount
  256. }
  257. for _, spotpointorder := range detail.SpotPointOrderVoList {
  258. totalpointorderqty = totalpointorderqty + spotpointorder.Qty
  259. }
  260. totalqty = totalpriceorderqty + totalpointorderqty
  261. var detailsum SoptContractDetailSum
  262. detailsum = SoptContractDetailSum{
  263. WrStandardID: detail.WrStandardID,
  264. WrStandardName: detail.WrStandardName,
  265. ProductType: detail.ProductType,
  266. ProductTypeName: detail.ProductTypeName,
  267. DeliveryGoodsID: detail.DeliveryGoodsID,
  268. DeliveryGoodsName: detail.DeliveryGoodsName,
  269. DeliveryGoodsDesc: detail.DeliveryGoodsDesc,
  270. WarehouseID: detail.WarehouseID,
  271. WarehouseName: detail.WarehouseName,
  272. UnitName: detail.UnitName,
  273. PointDesc: detail.PointDesc,
  274. SpotPriceOrderList: detail.SpotPriceOrderList,
  275. SpotPointOrderVoList: detail.SpotPointOrderVoList,
  276. TotalPriceOrderQty: totalpriceorderqty,
  277. TotalPriceOrderPrice: totalpriceorderprice,
  278. TotalPriceOrderAmount: totalpriceorderamount,
  279. TotalPointOrderQty: totalpointorderqty,
  280. TotalQty: totalqty,
  281. }
  282. detailsums = append(detailsums, detailsum)
  283. }
  284. jsoninfo, err := json.Marshal(detailsums)
  285. if err != nil {
  286. return "", err
  287. }
  288. return string(jsoninfo), nil
  289. }